From c1d38abc9d6c478017e35dc756ef2658d2684875 Mon Sep 17 00:00:00 2001 From: yangchenguang Date: Mon, 24 Apr 2023 15:51:58 +0800 Subject: [PATCH] Sync 2203 support loongarch64 patch file Signed-off-by: yangchenguang --- ...sn_recog_data-after-simplifying-a-me.patch | 57 + 0036-Add-LoongArch-ABI-2.01-support.patch | 20155 ++++++++++++++++ ...heck_effective_target_exceptions_ena.patch | 36 + 0038-libsanitizer-Add-LoongArch-support.patch | 1401 ++ ...sanitizer-Fixup-pr59063-2-link-error.patch | 32 + ...hread_join-weak-define-after-glibc-2.patch | 28 + 0041-add-missed-headers.patch | 55 + gcc.spec | 50 +- 8 files changed, 21807 insertions(+), 7 deletions(-) create mode 100644 0035-lra-clear-lra_insn_recog_data-after-simplifying-a-me.patch create mode 100644 0036-Add-LoongArch-ABI-2.01-support.patch create mode 100644 0037-Testsuite-Mark-check_effective_target_exceptions_ena.patch create mode 100644 0038-libsanitizer-Add-LoongArch-support.patch create mode 100644 0039-libsanitizer-Fixup-pr59063-2-link-error.patch create mode 100644 0040-libstdc-Fixup-pthread_join-weak-define-after-glibc-2.patch create mode 100644 0041-add-missed-headers.patch diff --git a/0035-lra-clear-lra_insn_recog_data-after-simplifying-a-me.patch b/0035-lra-clear-lra_insn_recog_data-after-simplifying-a-me.patch new file mode 100644 index 0000000..a30761b --- /dev/null +++ b/0035-lra-clear-lra_insn_recog_data-after-simplifying-a-me.patch @@ -0,0 +1,57 @@ +From 6dc82826ba61b25855e5a79f4479d009395a7299 Mon Sep 17 00:00:00 2001 +From: Ilya Leoshkevich +Date: Wed, 13 Jan 2021 13:59:10 +0100 +Subject: [PATCH 0001/6575] lra: clear lra_insn_recog_data after simplifying a + mem subreg + +Suppose we have: + + (insn (set (reg:FPRX2 70) (subreg:FPRX2 (reg/v:TF 63) 0))) + +where operand_loc[0] points to r70 and operand_loc[1] points to r63. +If r63 is spilled, remove_pseudos() will change this insn to: + + (insn (set (reg:FPRX2 70) + (subreg:FPRX2 (mem/c:TF (plus:DI (reg:DI %fp) + (const_int 144)))))) + +This is fine so far: rtx pointed to by operand_loc[1] has been changed +from (reg) to (mem), but its slot is still under (subreg). However, +alter_subreg() will simplify this insn to: + + (insn (set (reg:FPRX2 70) + (mem/c:FPRX2 (plus:DI (reg:DI %fp) (const_int 144))))) + +The (subreg) is gone, and therefore operand_loc[1] is no longer valid. +This will prevent process_insn_for_elimination() from updating the spill +slot offset, causing miscompilation: different instructions will refer +to the same spill slot using different offsets. + +Fix by clearing all the cached data, and not just used_insn_alternative. + +gcc/ChangeLog: + +2021-01-13 Ilya Leoshkevich + + * lra-spills.c (remove_pseudos): Call lra_update_insn_recog_data() + after calling alter_subreg() on a (mem). +--- + gcc/lra-spills.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/gcc/lra-spills.c b/gcc/lra-spills.c +index 26f56b2df02..01bd82574e7 100644 +--- a/gcc/lra-spills.c ++++ b/gcc/lra-spills.c +@@ -431,7 +431,7 @@ remove_pseudos (rtx *loc, rtx_insn *insn) + alter_subreg (loc, false); + if (GET_CODE (*loc) == MEM) + { +- lra_get_insn_recog_data (insn)->used_insn_alternative = -1; ++ lra_update_insn_recog_data (insn); + if (lra_dump_file != NULL) + fprintf (lra_dump_file, + "Memory subreg was simplified in insn #%u\n", +-- +2.27.0 + diff --git a/0036-Add-LoongArch-ABI-2.01-support.patch b/0036-Add-LoongArch-ABI-2.01-support.patch new file mode 100644 index 0000000..6168230 --- /dev/null +++ b/0036-Add-LoongArch-ABI-2.01-support.patch @@ -0,0 +1,20155 @@ +From ee3e15a8409439c44ffd686c9a99800b88a722f1 Mon Sep 17 00:00:00 2001 +From: Xing Li +Date: Tue, 20 Dec 2022 15:00:29 +0800 +Subject: [PATCH 2/4] Add LoongArch ABI 2.01 support + +--- + config.guess | 3 + + config.sub | 1 + + config/picflag.m4 | 3 + + configure | 10 +- + configure.ac | 10 +- + contrib/config-list.mk | 5 +- + .../config/loongarch/loongarch-common.c | 41 + + gcc/config.gcc | 404 +- + gcc/config.in | 6 + + gcc/config/host-linux.c | 2 + + gcc/config/loongarch/constraints.md | 192 + + gcc/config/loongarch/generic.md | 118 + + gcc/config/loongarch/genopts/genstr.sh | 104 + + .../loongarch/genopts/loongarch-strings | 59 + + gcc/config/loongarch/genopts/loongarch.opt.in | 190 + + gcc/config/loongarch/gnu-user.h | 80 + + gcc/config/loongarch/la464.md | 132 + + gcc/config/loongarch/larchintrin.h | 355 + + gcc/config/loongarch/linux.h | 50 + + gcc/config/loongarch/loongarch-builtins.c | 424 ++ + gcc/config/loongarch/loongarch-c.c | 109 + + gcc/config/loongarch/loongarch-cpu.c | 206 + + gcc/config/loongarch/loongarch-cpu.h | 30 + + gcc/config/loongarch/loongarch-def.c | 180 + + gcc/config/loongarch/loongarch-def.h | 152 + + gcc/config/loongarch/loongarch-driver.c | 187 + + gcc/config/loongarch/loongarch-driver.h | 68 + + gcc/config/loongarch/loongarch-ftypes.def | 65 + + gcc/config/loongarch/loongarch-modes.def | 25 + + gcc/config/loongarch/loongarch-opts.c | 595 ++ + gcc/config/loongarch/loongarch-opts.h | 95 + + gcc/config/loongarch/loongarch-protos.h | 183 + + gcc/config/loongarch/loongarch-str.h | 60 + + gcc/config/loongarch/loongarch-tune.h | 50 + + gcc/config/loongarch/loongarch.c | 6676 +++++++++++++++++ + gcc/config/loongarch/loongarch.h | 1155 +++ + gcc/config/loongarch/loongarch.md | 3375 +++++++++ + gcc/config/loongarch/loongarch.opt | 197 + + gcc/config/loongarch/predicates.md | 277 + + gcc/config/loongarch/sync.md | 597 ++ + gcc/config/loongarch/t-linux | 53 + + gcc/config/loongarch/t-loongarch | 71 + + gcc/configure | 129 +- + gcc/configure.ac | 47 +- + gcc/doc/extend.texi | 17 + + gcc/doc/install.texi | 41 +- + gcc/doc/invoke.texi | 188 + + gcc/doc/md.texi | 55 + + gcc/testsuite/g++.dg/cpp0x/constexpr-rom.C | 2 +- + gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C | 2 +- + gcc/testsuite/g++.old-deja/g++.pt/ptrmem6.C | 2 +- + gcc/testsuite/g++.target/loongarch/pr106828.C | 4 + + .../gcc.c-torture/execute/20101011-1.c | 1 + + .../gcc.c-torture/execute/mul-sext.c | 20 + + gcc/testsuite/gcc.dg/20020312-2.c | 2 + + gcc/testsuite/gcc.dg/builtin-apply2.c | 2 +- + gcc/testsuite/gcc.dg/loop-8.c | 2 +- + gcc/testsuite/gcc.dg/stack-usage-1.c | 5 + + .../torture/stackalign/builtin-apply-2.c | 2 +- + gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-3.c | 2 +- + .../gcc.target/loongarch/attr-model-1.c | 6 + + .../gcc.target/loongarch/attr-model-2.c | 6 + + .../gcc.target/loongarch/attr-model-diag.c | 7 + + .../gcc.target/loongarch/attr-model-test.c | 25 + + .../gcc.target/loongarch/direct-extern-1.c | 6 + + .../gcc.target/loongarch/direct-extern-2.c | 6 + + gcc/testsuite/gcc.target/loongarch/div-1.c | 9 + + gcc/testsuite/gcc.target/loongarch/div-2.c | 9 + + gcc/testsuite/gcc.target/loongarch/div-3.c | 9 + + gcc/testsuite/gcc.target/loongarch/div-4.c | 9 + + .../gcc.target/loongarch/fmax-fmin.c | 30 + + .../gcc.target/loongarch/func-call-1.c | 33 + + .../gcc.target/loongarch/func-call-2.c | 32 + + .../gcc.target/loongarch/func-call-3.c | 32 + + .../gcc.target/loongarch/func-call-4.c | 32 + + .../gcc.target/loongarch/func-call-5.c | 33 + + .../gcc.target/loongarch/func-call-6.c | 33 + + .../gcc.target/loongarch/func-call-7.c | 34 + + .../gcc.target/loongarch/func-call-8.c | 33 + + .../loongarch/func-call-extreme-1.c | 32 + + .../loongarch/func-call-extreme-2.c | 33 + + .../gcc.target/loongarch/func-call-medium-1.c | 41 + + .../gcc.target/loongarch/func-call-medium-2.c | 41 + + .../gcc.target/loongarch/func-call-medium-3.c | 41 + + .../gcc.target/loongarch/func-call-medium-4.c | 41 + + .../gcc.target/loongarch/func-call-medium-5.c | 42 + + .../gcc.target/loongarch/func-call-medium-6.c | 42 + + .../gcc.target/loongarch/func-call-medium-7.c | 43 + + .../gcc.target/loongarch/func-call-medium-8.c | 42 + + .../gcc.target/loongarch/larch-builtin.c | 265 + + .../gcc.target/loongarch/loongarch.exp | 40 + + gcc/testsuite/gcc.target/loongarch/mulw_d_w.c | 10 + + gcc/testsuite/gcc.target/loongarch/pr106459.c | 13 + + .../gcc.target/loongarch/pr107713-1.c | 50 + + .../gcc.target/loongarch/pr107713-2.c | 9 + + .../gcc.target/loongarch/prolog-opt.c | 15 + + .../loongarch/relocs-symbol-noaddend.c | 23 + + .../gcc.target/loongarch/tls-gd-noplt.c | 11 + + .../gcc.target/loongarch/tst-asm-const.c | 16 + + .../loongarch/zero-size-field-pass.c | 30 + + .../loongarch/zero-size-field-ret.c | 28 + + gcc/testsuite/go.test/go-test.exp | 3 + + gcc/testsuite/lib/target-supports.exp | 16 + + libgcc/config.host | 26 + + libgcc/config/loongarch/crtfastmath.c | 52 + + libgcc/config/loongarch/crti.S | 43 + + libgcc/config/loongarch/crtn.S | 39 + + libgcc/config/loongarch/lib2funcs.c | 0 + libgcc/config/loongarch/linux-unwind.h | 80 + + libgcc/config/loongarch/sfp-machine.h | 152 + + libgcc/config/loongarch/t-crtstuff | 5 + + libgcc/config/loongarch/t-elf | 3 + + libgcc/config/loongarch/t-loongarch | 7 + + libgcc/config/loongarch/t-loongarch64 | 1 + + libgcc/config/loongarch/t-softfp-tf | 3 + + libgcc/configure | 5 +- + libgcc/configure.ac | 2 +- + libgomp/configure.tgt | 4 + + 118 files changed, 18826 insertions(+), 25 deletions(-) + create mode 100644 gcc/common/config/loongarch/loongarch-common.c + create mode 100644 gcc/config/loongarch/constraints.md + create mode 100644 gcc/config/loongarch/generic.md + create mode 100644 gcc/config/loongarch/genopts/genstr.sh + create mode 100644 gcc/config/loongarch/genopts/loongarch-strings + create mode 100644 gcc/config/loongarch/genopts/loongarch.opt.in + create mode 100644 gcc/config/loongarch/gnu-user.h + create mode 100644 gcc/config/loongarch/la464.md + create mode 100644 gcc/config/loongarch/larchintrin.h + create mode 100644 gcc/config/loongarch/linux.h + create mode 100644 gcc/config/loongarch/loongarch-builtins.c + create mode 100644 gcc/config/loongarch/loongarch-c.c + create mode 100644 gcc/config/loongarch/loongarch-cpu.c + create mode 100644 gcc/config/loongarch/loongarch-cpu.h + create mode 100644 gcc/config/loongarch/loongarch-def.c + create mode 100644 gcc/config/loongarch/loongarch-def.h + create mode 100644 gcc/config/loongarch/loongarch-driver.c + create mode 100644 gcc/config/loongarch/loongarch-driver.h + create mode 100644 gcc/config/loongarch/loongarch-ftypes.def + create mode 100644 gcc/config/loongarch/loongarch-modes.def + create mode 100644 gcc/config/loongarch/loongarch-opts.c + create mode 100644 gcc/config/loongarch/loongarch-opts.h + create mode 100644 gcc/config/loongarch/loongarch-protos.h + create mode 100644 gcc/config/loongarch/loongarch-str.h + create mode 100644 gcc/config/loongarch/loongarch-tune.h + create mode 100644 gcc/config/loongarch/loongarch.c + create mode 100644 gcc/config/loongarch/loongarch.h + create mode 100644 gcc/config/loongarch/loongarch.md + create mode 100644 gcc/config/loongarch/loongarch.opt + create mode 100644 gcc/config/loongarch/predicates.md + create mode 100644 gcc/config/loongarch/sync.md + create mode 100644 gcc/config/loongarch/t-linux + create mode 100644 gcc/config/loongarch/t-loongarch + create mode 100644 gcc/testsuite/g++.target/loongarch/pr106828.C + create mode 100644 gcc/testsuite/gcc.c-torture/execute/mul-sext.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/attr-model-1.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/attr-model-2.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/attr-model-diag.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/attr-model-test.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/direct-extern-1.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/direct-extern-2.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/div-1.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/div-2.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/div-3.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/div-4.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/fmax-fmin.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-1.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-2.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-3.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-4.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-5.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-6.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-7.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-8.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-extreme-1.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-extreme-2.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-medium-1.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-medium-2.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-medium-3.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-medium-4.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-medium-5.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-medium-6.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-medium-7.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-medium-8.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/larch-builtin.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/loongarch.exp + create mode 100644 gcc/testsuite/gcc.target/loongarch/mulw_d_w.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/pr106459.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/pr107713-1.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/pr107713-2.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/prolog-opt.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/relocs-symbol-noaddend.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/tls-gd-noplt.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/tst-asm-const.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/zero-size-field-pass.c + create mode 100644 gcc/testsuite/gcc.target/loongarch/zero-size-field-ret.c + create mode 100644 libgcc/config/loongarch/crtfastmath.c + create mode 100644 libgcc/config/loongarch/crti.S + create mode 100644 libgcc/config/loongarch/crtn.S + create mode 100644 libgcc/config/loongarch/lib2funcs.c + create mode 100644 libgcc/config/loongarch/linux-unwind.h + create mode 100644 libgcc/config/loongarch/sfp-machine.h + create mode 100644 libgcc/config/loongarch/t-crtstuff + create mode 100644 libgcc/config/loongarch/t-elf + create mode 100644 libgcc/config/loongarch/t-loongarch + create mode 100644 libgcc/config/loongarch/t-loongarch64 + create mode 100644 libgcc/config/loongarch/t-softfp-tf + +diff --git a/config.guess b/config.guess +index 97ad07333..0739a4cce 100755 +--- a/config.guess ++++ b/config.guess +@@ -980,6 +980,9 @@ EOF + k1om:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; ++ loongarch*:Linux:*:*) ++ echo "$UNAME_MACHINE"-linux-"$LIBC" ++ exit ;; + m32r*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; +diff --git a/config.sub b/config.sub +index a318a4686..cb3b2f848 100755 +--- a/config.sub ++++ b/config.sub +@@ -1183,6 +1183,7 @@ case $cpu-$vendor in + | k1om \ + | le32 | le64 \ + | lm32 \ ++ | loongarch32 | loongarch64 | loongarchx32 \ + | m32c | m32r | m32rle \ + | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \ + | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \ +diff --git a/config/picflag.m4 b/config/picflag.m4 +index 8b106f9af..0aefcf619 100644 +--- a/config/picflag.m4 ++++ b/config/picflag.m4 +@@ -44,6 +44,9 @@ case "${$2}" in + # sets the default TLS model and affects inlining. + $1=-fPIC + ;; ++ loongarch*-*-*) ++ $1=-fpic ++ ;; + mips-sgi-irix6*) + # PIC is the default. + ;; +diff --git a/configure b/configure +index 97d5ca4fc..65d92742c 100755 +--- a/configure ++++ b/configure +@@ -3029,7 +3029,7 @@ case "${ENABLE_GOLD}" in + # Check for target supported by gold. + case "${target}" in + i?86-*-* | x86_64-*-* | sparc*-*-* | powerpc*-*-* | arm*-*-* \ +- | aarch64*-*-* | tilegx*-*-* | mips*-*-* | s390*-*-*) ++ | aarch64*-*-* | tilegx*-*-* | mips*-*-* | s390*-*-* | loongarch*-*-*) + configdirs="$configdirs gold" + if test x${ENABLE_GOLD} = xdefault; then + default_ld=gold +@@ -3641,6 +3641,9 @@ case "${target}" in + i[3456789]86-*-*) + libgloss_dir=i386 + ;; ++ loongarch*-*-*) ++ libgloss_dir=loongarch ++ ;; + m68hc11-*-*|m6811-*-*|m68hc12-*-*|m6812-*-*) + libgloss_dir=m68hc11 + ;; +@@ -4025,6 +4028,11 @@ case "${target}" in + wasm32-*-*) + noconfigdirs="$noconfigdirs ld" + ;; ++ loongarch*-*-linux*) ++ ;; ++ loongarch*-*-*) ++ noconfigdirs="$noconfigdirs gprof" ++ ;; + esac + + # If we aren't building newlib, then don't build libgloss, since libgloss +diff --git a/configure.ac b/configure.ac +index 90ccd5ef8..0e547c5b2 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -345,7 +345,7 @@ case "${ENABLE_GOLD}" in + # Check for target supported by gold. + case "${target}" in + i?86-*-* | x86_64-*-* | sparc*-*-* | powerpc*-*-* | arm*-*-* \ +- | aarch64*-*-* | tilegx*-*-* | mips*-*-* | s390*-*-*) ++ | aarch64*-*-* | tilegx*-*-* | mips*-*-* | s390*-*-* | loongarch*-*-*) + configdirs="$configdirs gold" + if test x${ENABLE_GOLD} = xdefault; then + default_ld=gold +@@ -914,6 +914,9 @@ case "${target}" in + i[[3456789]]86-*-*) + libgloss_dir=i386 + ;; ++ loongarch*-*-*) ++ libgloss_dir=loongarch ++ ;; + m68hc11-*-*|m6811-*-*|m68hc12-*-*|m6812-*-*) + libgloss_dir=m68hc11 + ;; +@@ -1298,6 +1301,11 @@ case "${target}" in + wasm32-*-*) + noconfigdirs="$noconfigdirs ld" + ;; ++ loongarch*-*-linux*) ++ ;; ++ loongarch*-*-*) ++ noconfigdirs="$noconfigdirs gprof" ++ ;; + esac + + # If we aren't building newlib, then don't build libgloss, since libgloss +diff --git a/contrib/config-list.mk b/contrib/config-list.mk +index d154286a4..c06e2b924 100644 +--- a/contrib/config-list.mk ++++ b/contrib/config-list.mk +@@ -57,7 +57,10 @@ LIST = aarch64-elf aarch64-linux-gnu aarch64-rtems \ + i686-wrs-vxworksae \ + i686-cygwinOPT-enable-threads=yes i686-mingw32crt ia64-elf \ + ia64-freebsd6 ia64-linux ia64-hpux ia64-hp-vms iq2000-elf lm32-elf \ +- lm32-rtems lm32-uclinux m32c-rtems m32c-elf m32r-elf m32rle-elf \ ++ lm32-rtems lm32-uclinux \ ++ loongarch64-linux-gnu loongarch64-linux-gnuf64 \ ++ loongarch64-linux-gnuf32 loongarch64-linux-gnusf \ ++ m32c-rtems m32c-elf m32r-elf m32rle-elf \ + m32r-linux m32rle-linux m68k-elf m68k-netbsdelf \ + m68k-openbsd m68k-uclinux m68k-linux m68k-rtems \ + mcore-elf microblaze-linux microblaze-elf \ +diff --git a/gcc/common/config/loongarch/loongarch-common.c b/gcc/common/config/loongarch/loongarch-common.c +new file mode 100644 +index 000000000..f8b4660fa +--- /dev/null ++++ b/gcc/common/config/loongarch/loongarch-common.c +@@ -0,0 +1,41 @@ ++/* Common hooks for LoongArch. ++ Copyright (C) 2021-2022 Free Software Foundation, Inc. ++ ++This file is part of GCC. ++ ++GCC is free software; you can redistribute it and/or modify ++it under the terms of the GNU General Public License as published by ++the Free Software Foundation; either version 3, or (at your option) ++any later version. ++ ++GCC 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 GCC; see the file COPYING3. If not see ++. */ ++ ++#include "config.h" ++#include "system.h" ++#include "coretypes.h" ++#include "tm.h" ++#include "common/common-target.h" ++#include "common/common-target-def.h" ++#include "opts.h" ++#include "flags.h" ++#include "diagnostic-core.h" ++ ++#undef TARGET_OPTION_OPTIMIZATION_TABLE ++#define TARGET_OPTION_OPTIMIZATION_TABLE loongarch_option_optimization_table ++ ++/* Set default optimization options. */ ++static const struct default_options loongarch_option_optimization_table[] = ++{ ++ { OPT_LEVELS_ALL, OPT_fasynchronous_unwind_tables, NULL, 1 }, ++ { OPT_LEVELS_1_PLUS, OPT_fsection_anchors, NULL, 1 }, ++ { OPT_LEVELS_NONE, 0, NULL, 0 } ++}; ++ ++struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER; +diff --git a/gcc/config.gcc b/gcc/config.gcc +index 6fcdd771d..63d1b47a4 100644 +--- a/gcc/config.gcc ++++ b/gcc/config.gcc +@@ -180,7 +180,7 @@ + # the --with-sysroot configure option or the + # --sysroot command line option is used this + # will be relative to the sysroot. +-# target_type_format_char ++# target_type_format_char + # The default character to be used for formatting + # the attribute in a + # .type symbol_name, ${t_t_f_c} +@@ -477,6 +477,13 @@ mips*-*-*) + extra_objs="frame-header-opt.o" + extra_options="${extra_options} g.opt fused-madd.opt mips/mips-tables.opt" + ;; ++loongarch*-*-*) ++ cpu_type=loongarch ++ extra_headers="larchintrin.h" ++ extra_objs="loongarch-c.o loongarch-builtins.o loongarch-cpu.o loongarch-opts.o loongarch-def.o" ++ extra_gcc_objs="loongarch-driver.o loongarch-cpu.o loongarch-opts.o loongarch-def.o" ++ extra_options="${extra_options} g.opt fused-madd.opt" ++ ;; + nds32*) + cpu_type=nds32 + extra_headers="nds32_intrinsic.h nds32_isr.h nds32_init.inc" +@@ -2503,6 +2510,20 @@ riscv*-*-freebsd*) + # automatically detect that GAS supports it, yet we require it. + gcc_cv_initfini_array=yes + ;; ++ ++loongarch*-*-linux-gnu*) ++ tm_file="dbxelf.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h ${tm_file}" ++ tm_file="${tm_file} loongarch/gnu-user.h loongarch/linux.h" ++ extra_options="${extra_options} linux-android.opt" ++ tmake_file="${tmake_file} loongarch/t-linux" ++ gnu_ld=yes ++ gas=yes ++ ++ # Force .init_array support. The configure script cannot always ++ # automatically detect that GAS supports it, yet we require it. ++ gcc_cv_initfini_array=yes ++ ;; ++ + mips*-*-netbsd*) # NetBSD/mips, either endian. + target_cpu_default="MASK_ABICALLS" + tm_file="elfos.h ${tm_file} mips/elf.h ${nbsd_tm_file} mips/netbsd.h" +@@ -3575,7 +3596,7 @@ case ${target} in + ;; + *-*-linux* | *-*-gnu*) + case ${target} in +- aarch64*-* | arm*-* | i[34567]86-* | powerpc*-* | s390*-* | sparc*-* | x86_64-*) ++ aarch64*-* | arm*-* | i[34567]86-* | powerpc*-* | s390*-* | sparc*-* | x86_64-* | loongarch*-*) + default_gnu_indirect_function=yes + ;; + esac +@@ -4854,6 +4875,338 @@ case "${target}" in + esac + ;; + ++ loongarch*-*-*) ++ supported_defaults="abi arch tune fpu" ++ ++ # Local variables ++ unset \ ++ abi_pattern abi_default \ ++ abiext_pattern abiext_default \ ++ arch_pattern arch_default \ ++ fpu_pattern fpu_default \ ++ tune_pattern tune_default ++ ++ # Inferring ABI from the triplet: pass 1 ++ case ${target} in ++ loongarch64-*) ++ abiext_pattern="*" ++ abiext_default="base" ++ ;; ++ esac ++ ++ # Inferring ABI from the triplet: pass 2 ++ case ${target} in ++ loongarch64-*-linux-gnuf64) ++ la_canonical_triplet="loongarch64-linux-gnuf64" ++ abi_pattern="lp64d" ++ ;; ++ loongarch64-*-linux-gnuf32) ++ la_canonical_triplet="loongarch64-linux-gnuf32" ++ abi_pattern="lp64f" ++ ;; ++ loongarch64-*-linux-gnusf) ++ la_canonical_triplet="loongarch64-linux-gnusf" ++ abi_pattern="lp64s" ++ ;; ++ loongarch64-*-linux-gnu) ++ la_canonical_triplet="loongarch64-linux-gnuf64" ++ abi_pattern="lp64[dfs]" ++ abi_default="lp64d" ++ ;; ++ *) ++ echo "Unsupported target ${target}." 1>&2 ++ exit 1 ++ esac ++ ++ ## Setting default value for with_abi. ++ case ${with_abi} in ++ "") ++ if test x${abi_default} != x; then ++ with_abi=${abi_default} ++ else ++ with_abi=${abi_pattern} ++ fi ++ ;; ++ ++ *) ++ if echo "${with_abi}" | grep -E "^${abi_pattern}$"; then ++ : # OK ++ else ++ echo "Incompatible options:" \ ++ "--with-abi=${with_abi} and --target=${target}." 1>&2 ++ exit 1 ++ fi ++ ;; ++ esac ++ ++ ## Setting default value for with_abiext (internal) ++ case ${with_abiext} in ++ "") ++ if test x${abiext_default} != x; then ++ with_abiext=${abiext_default} ++ else ++ with_abiext=${abiext_pattern} ++ fi ++ ;; ++ ++ *) ++ if echo "${with_abiext}" | grep -E "^${abiext_pattern}$"; then ++ : # OK ++ else ++ echo "The ABI extension type \"${with_abiext}\"" \ ++ "is incompatible with --target=${target}." 1>&2 ++ exit 1 ++ fi ++ ++ ;; ++ esac ++ ++ ++ # Inferring ISA-related default options from the ABI: pass 1 ++ case ${with_abi}/${with_abiext} in ++ lp64*/base) ++ # architectures that support lp64* ABI ++ arch_pattern="native|loongarch64|la464" ++ # default architecture for lp64* ABI ++ arch_default="loongarch64" ++ ;; ++ *) ++ echo "Unsupported ABI type ${with_abi}/${with_abiext}." 1>&2 ++ exit 1 ++ ;; ++ esac ++ ++ # Inferring ISA-related default options from the ABI: pass 2 ++ case ${with_abi}/${with_abiext} in ++ lp64d/base) ++ fpu_pattern="64" ++ ;; ++ lp64f/base) ++ fpu_pattern="32|64" ++ fpu_default="32" ++ ;; ++ lp64s/base) ++ fpu_pattern="none|32|64" ++ fpu_default="none" ++ ;; ++ *) ++ echo "Unsupported ABI type ${with_abi}/${with_abiext}." 1>&2 ++ exit 1 ++ ;; ++ esac ++ ++ ## Setting default value for with_arch. ++ case ${with_arch} in ++ "") ++ if test x${arch_default} != x; then ++ with_arch=${arch_default} ++ else ++ with_arch=${arch_pattern} ++ fi ++ ;; ++ ++ *) ++ if echo "${with_arch}" | grep -E "^${arch_pattern}$"; then ++ : # OK ++ else ++ echo "${with_abi}/${with_abiext} ABI cannot be implemented with" \ ++ "--with-arch=${with_arch}." 1>&2 ++ exit 1 ++ fi ++ ;; ++ esac ++ ++ ## Setting default value for with_fpu. ++ if test x${with_fpu} == xnone; then ++ with_fpu="0" ++ fi ++ ++ case ${with_fpu} in ++ "") ++ if test x${fpu_default} != x; then ++ with_fpu=${fpu_default} ++ else ++ with_fpu=${fpu_pattern} ++ fi ++ ;; ++ ++ *) ++ if echo "${with_fpu}" | grep -E "^${fpu_pattern}$"; then ++ : # OK ++ else ++ echo "${with_abi}/${with_abiext} ABI cannot be implemented with" \ ++ "--with-fpu=${with_fpu}." 1>&2 ++ exit 1 ++ fi ++ ;; ++ esac ++ ++ ++ # Inferring default with_tune from with_arch: pass 1 ++ case ${with_arch} in ++ native) ++ tune_pattern="*" ++ tune_default="native" ++ ;; ++ loongarch64) ++ tune_pattern="loongarch64 | la464" ++ tune_default="la464" ++ ;; ++ *) ++ # By default, $with_tune == $with_arch ++ tune_pattern="$with_arch" ++ ;; ++ esac ++ ++ ## Setting default value for with_tune. ++ case ${with_tune} in ++ "") ++ if test x${tune_default} != x; then ++ with_tune=${tune_default} ++ else ++ with_tune=${tune_pattern} ++ fi ++ ;; ++ ++ *) ++ if echo "${with_tune}" | grep -E "^${tune_pattern}$"; then ++ : # OK ++ else ++ echo "Incompatible options: --with-tune=${with_tune}" \ ++ "and --with-arch=${with_arch}." 1>&2 ++ exit 1 ++ fi ++ ;; ++ esac ++ ++ ++ # Perform final sanity checks. ++ case ${with_arch} in ++ loongarch64 | la464) ;; # OK, append here. ++ native) ++ if test x${host} != x${target}; then ++ echo "--with-arch=native is illegal for cross-compiler." 1>&2 ++ exit 1 ++ fi ++ ;; ++ "") ++ echo "Please set a default value for \${with_arch}" \ ++ "according to your target triplet \"${target}\"." 1>&2 ++ exit 1 ++ ;; ++ *) ++ echo "Unknown arch in --with-arch=$with_arch" 1>&2 ++ exit 1 ++ ;; ++ esac ++ ++ case ${with_abi} in ++ lp64d | lp64f | lp64s) ;; # OK, append here. ++ *) ++ echo "Unsupported ABI given in --with-abi=$with_abi" 1>&2 ++ exit 1 ++ ;; ++ esac ++ ++ case ${with_abiext} in ++ base) ;; # OK, append here. ++ *) ++ echo "Unsupported ABI extention type $with_abiext" 1>&2 ++ exit 1 ++ ;; ++ esac ++ ++ case ${with_fpu} in ++ none | 32 | 64) ;; # OK, append here. ++ *) ++ echo "Unknown fpu type in --with-fpu=$with_fpu" 1>&2 ++ exit 1 ++ ;; ++ esac ++ ++ # Handle --with-multilib-list. ++ if test x${with_multilib_list} == x \ ++ || test x${with_multilib_list} == xno \ ++ || test x${with_multilib_list} == xdefault \ ++ || test x${enable_multilib} != xyes; then ++ ++ with_multilib_list="${with_abi}/${with_abiext}" ++ fi ++ ++ # Check if the configured default ABI combination is included in ++ # ${with_multilib_list}. ++ loongarch_multilib_list_sane=no ++ ++ # This one goes to TM_MULTILIB_CONFIG, for use in t-linux. ++ loongarch_multilib_list_make="" ++ ++ # This one goes to tm_defines, for use in loongarch-driver.c. ++ loongarch_multilib_list_c="" ++ ++ for e in $(tr ',' ' ' <<< "${with_multilib_list}"); do ++ e=($(tr '/' ' ' <<< "$e")) ++ ++ # Base ABI type ++ case ${e[0]} in ++ lp64d) loongarch_multilib_list_c+="ABI_BASE_LP64D,";; ++ lp64f) loongarch_multilib_list_c+="ABI_BASE_LP64F,";; ++ lp64s) loongarch_multilib_list_c+="ABI_BASE_LP64S,";; ++ *) ++ echo "Unknown base ABI \"${e[0]}\" in --with-multilib-list." 1>&2 ++ exit 1 ++ ;; ++ esac ++ loongarch_multilib_list_make+="mabi=${e[0]}" ++ ++ # ABI extension type ++ case ${e[1]} in ++ "" | base) ++ loongarch_multilib_list_make+="" ++ loongarch_multilib_list_c+="ABI_EXT_BASE," ++ e[1]="base" ++ ;; ++ *) ++ echo "Unknown ABI extension \"${e[1]}\" in --with-multilib-list." 1>&2 ++ exit 1 ++ ;; ++ esac ++ ++ case ${e[2]} in ++ "") ;; # OK ++ *) ++ echo "Unknown ABI in --with-multilib-list." 1>&2 ++ exit 1 ++ ;; ++ esac ++ ++ if test x${with_abi} != x && test x${with_abiext} != x; then ++ if test x${e[0]} == x${with_abi} \ ++ && test x${e[1]} == x${with_abiext}; then ++ loongarch_multilib_list_sane=yes ++ fi ++ fi ++ ++ loongarch_multilib_list_make+="," ++ done ++ ++ # Check if the default ABI combination is in the default list. ++ if test x${loongarch_multilib_list_sane} == xno; then ++ if test x${with_abiext} == xbase; then ++ with_abiext="" ++ else ++ with_abiext="/${with_abiext}" ++ fi ++ ++ echo "Default ABI combination (${with_abi}${with_abiext})" \ ++ "not found in --with-multilib-list." 1>&2 ++ exit 1 ++ fi ++ ++ # Remove the excessive appending comma. ++ loongarch_multilib_list_c=${loongarch_multilib_list_c:0:-1} ++ loongarch_multilib_list_make=${loongarch_multilib_list_make:0:-1} ++ ;; ++ + nds32*-*-*) + supported_defaults="arch cpu nds32_lib float fpu_config" + +@@ -5301,6 +5654,51 @@ case ${target} in + tmake_file="mips/t-mips $tmake_file" + ;; + ++ loongarch*-*-*) ++ # Export canonical triplet. ++ tm_defines+=" LA_MULTIARCH_TRIPLET=${la_canonical_triplet}" ++ ++ # Define macro __DISABLE_MULTILIB if --disable-multilib ++ tm_defines+=" TM_MULTILIB_LIST=${loongarch_multilib_list_c}" ++ if test x$enable_multilib == xyes; then ++ TM_MULTILIB_CONFIG="${loongarch_multilib_list_make}" ++ else ++ tm_defines+=" __DISABLE_MULTILIB" ++ fi ++ ++ # Let --with- flags initialize the enum variables from loongarch.opt. ++ # See macro definitions from loongarch-opts.h and loongarch-cpu.h. ++ case ${with_arch} in ++ native) tm_defines+=" DEFAULT_CPU_ARCH=CPU_NATIVE" ;; ++ la464) tm_defines+=" DEFAULT_CPU_ARCH=CPU_LA464" ;; ++ loongarch64) tm_defines+=" DEFAULT_CPU_ARCH=CPU_LOONGARCH64" ;; ++ esac ++ ++ case ${with_tune} in ++ native) tm_defines+=" DEFAULT_CPU_TUNE=CPU_NATIVE" ;; ++ la464) tm_defines+=" DEFAULT_CPU_TUNE=CPU_LA464" ;; ++ loongarch64) tm_defines+=" DEFAULT_CPU_TUNE=CPU_LOONGARCH64" ;; ++ esac ++ ++ case ${with_abi} in ++ lp64d) tm_defines+=" DEFAULT_ABI_BASE=ABI_BASE_LP64D" ;; ++ lp64f) tm_defines+=" DEFAULT_ABI_BASE=ABI_BASE_LP64F" ;; ++ lp64s) tm_defines+=" DEFAULT_ABI_BASE=ABI_BASE_LP64S" ;; ++ esac ++ ++ case ${with_abiext} in ++ base) tm_defines+=" DEFAULT_ABI_EXT=ABI_EXT_BASE" ;; ++ esac ++ ++ case ${with_fpu} in ++ none) tm_defines="$tm_defines DEFAULT_ISA_EXT_FPU=ISA_EXT_NOFPU" ;; ++ 32) tm_defines="$tm_defines DEFAULT_ISA_EXT_FPU=ISA_EXT_FPU32" ;; ++ 64) tm_defines="$tm_defines DEFAULT_ISA_EXT_FPU=ISA_EXT_FPU64" ;; ++ esac ++ ++ tmake_file="loongarch/t-loongarch $tmake_file" ++ ;; ++ + powerpc*-*-* | rs6000-*-*) + # FIXME: The PowerPC port uses the value set at compile time, + # although it's only cosmetic. +@@ -5364,7 +5762,7 @@ case ${target} in + esac + + t= +-all_defaults="abi cpu cpu_32 cpu_64 arch arch_32 arch_64 tune tune_32 tune_64 schedule float mode fpu nan fp_32 odd_spreg_32 divide llsc mips-plt synci tls lxc1-sxc1 madd4" ++all_defaults="abi cpu cpu_32 cpu_64 arch arch_32 arch_64 tune tune_32 tune_64 schedule float mode fpu nan fp_32 odd_spreg_32 divide llsc mips-plt synci tls lxc1-sxc1 madd4 fix-loongson3-llsc" + for option in $all_defaults + do + eval "val=\$with_"`echo $option | sed s/-/_/g` +diff --git a/gcc/config.in b/gcc/config.in +index 80b421d99..d70653db0 100644 +--- a/gcc/config.in ++++ b/gcc/config.in +@@ -383,6 +383,12 @@ + #endif + + ++/* Define if your assembler supports eh_frame pcrel encoding. */ ++#ifndef USED_FOR_TARGET ++#undef HAVE_AS_EH_FRAME_PCREL_ENCODING_SUPPORT ++#endif ++ ++ + /* Define if your assembler supports the R_PPC64_ENTRY relocation. */ + #ifndef USED_FOR_TARGET + #undef HAVE_AS_ENTRY_MARKERS +diff --git a/gcc/config/host-linux.c b/gcc/config/host-linux.c +index 268725441..38f9d4ce7 100644 +--- a/gcc/config/host-linux.c ++++ b/gcc/config/host-linux.c +@@ -98,6 +98,8 @@ + # define TRY_EMPTY_VM_SPACE 0x60000000 + #elif defined(__riscv) && defined (__LP64__) + # define TRY_EMPTY_VM_SPACE 0x1000000000 ++#elif defined(__loongarch__) && defined(__LP64__) ++# define TRY_EMPTY_VM_SPACE 0x8000000000 + #else + # define TRY_EMPTY_VM_SPACE 0 + #endif +diff --git a/gcc/config/loongarch/constraints.md b/gcc/config/loongarch/constraints.md +new file mode 100644 +index 000000000..43cb7b5f0 +--- /dev/null ++++ b/gcc/config/loongarch/constraints.md +@@ -0,0 +1,192 @@ ++;; Constraint definitions for LoongArch. ++;; Copyright (C) 2021-2022 Free Software Foundation, Inc. ++;; Contributed by Loongson Ltd. ++;; ++;; This file is part of GCC. ++;; ++;; GCC is free software; you can redistribute it and/or modify ++;; it under the terms of the GNU General Public License as published by ++;; the Free Software Foundation; either version 3, or (at your option) ++;; any later version. ++;; ++;; GCC 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 GCC; see the file COPYING3. If not see ++;; . ++ ++;; Register constraints ++ ++;; "a" <-----unused ++;; "b" "A constant call not local address." ++;; "c" "A constant call local address." ++;; "d" <-----unused ++;; "e" JIRL_REGS ++;; "f" FP_REGS ++;; "g" <-----unused ++;; "h" <-----unused ++;; "i" "Matches a general integer constant." (Global non-architectural) ++;; "j" SIBCALL_REGS ++;; "k" "A memory operand whose address is formed by a base register and ++;; (optionally scaled) index register." ++;; "l" "A signed 16-bit constant." ++;; "m" "A memory operand whose address is formed by a base register and offset ++;; that is suitable for use in instructions with the same addressing mode ++;; as @code{st.w} and @code{ld.w}." ++;; "n" "Matches a non-symbolic integer constant." (Global non-architectural) ++;; "o" "Matches an offsettable memory reference." (Global non-architectural) ++;; "p" "Matches a general address." (Global non-architectural) ++;; "q" CSR_REGS ++;; "r" GENERAL_REGS (Global non-architectural) ++;; "s" "Matches a symbolic integer constant." (Global non-architectural) ++;; "t" <-----unused ++;; "u" "A signed 52bit constant and low 32-bit is zero (for logic instructions)" ++;; "v" "A signed 64-bit constant and low 44-bit is zero (for logic instructions)." ++;; "w" "Matches any valid memory." ++;; "x" <-----unused ++;; "y" <-----unused ++;; "z" FCC_REGS ++;; "A" <-----unused ++;; "B" <-----unused ++;; "C" <-----unused ++;; "D" <-----unused ++;; "E" "Matches a floating-point constant." (Global non-architectural) ++;; "F" "Matches a floating-point constant." (Global non-architectural) ++;; "G" "Floating-point zero." ++;; "H" <-----unused ++;; "I" "A signed 12-bit constant (for arithmetic instructions)." ++;; "J" "Integer zero." ++;; "K" "An unsigned 12-bit constant (for logic instructions)." ++;; "L" <-----unused ++;; "M" <-----unused ++;; "N" <-----unused ++;; "O" <-----unused ++;; "P" <-----unused ++;; "Q" <-----unused ++;; "R" <-----unused ++;; "S" <-----unused ++;; "T" <-----unused ++;; "U" <-----unused ++;; "V" "Matches a non-offsettable memory reference." (Global non-architectural) ++;; "W" <-----unused ++;; "X" "Matches anything." (Global non-architectural) ++;; "Y" - ++;; "Yd" ++;; "A constant @code{move_operand} that can be safely loaded using ++;; @code{la}." ++;; "Yx" ++;; "Z" - ++;; "ZC" ++;; "A memory operand whose address is formed by a base register and offset ++;; that is suitable for use in instructions with the same addressing mode ++;; as @code{ll.w} and @code{sc.w}." ++;; "ZB" ++;; "An address that is held in a general-purpose register. ++;; The offset is zero" ++;; "<" "Matches a pre-dec or post-dec operand." (Global non-architectural) ++;; ">" "Matches a pre-inc or post-inc operand." (Global non-architectural) ++ ++(define_constraint "b" ++ "@internal ++ A constant call no local address." ++ (match_operand 0 "is_const_call_no_local_symbol")) ++ ++(define_constraint "c" ++ "@internal ++ A constant call local address." ++ (match_operand 0 "is_const_call_local_symbol")) ++ ++(define_register_constraint "e" "JIRL_REGS" ++ "@internal") ++ ++(define_register_constraint "f" "TARGET_HARD_FLOAT ? FP_REGS : NO_REGS" ++ "A floating-point register (if available).") ++ ++(define_register_constraint "j" "SIBCALL_REGS" ++ "@internal") ++ ++(define_memory_constraint "k" ++ "A memory operand whose address is formed by a base register and (optionally scaled) ++ index register." ++ (and (match_code "mem") ++ (match_test "loongarch_base_index_address_p (XEXP (op, 0), mode)"))) ++ ++(define_constraint "l" ++"A signed 16-bit constant." ++(and (match_code "const_int") ++ (match_test "IMM16_OPERAND (ival)"))) ++ ++(define_memory_constraint "m" ++ "A memory operand whose address is formed by a base register and offset ++ that is suitable for use in instructions with the same addressing mode ++ as @code{st.w} and @code{ld.w}." ++ (and (match_code "mem") ++ (match_test "loongarch_12bit_offset_address_p (XEXP (op, 0), mode)"))) ++ ++(define_register_constraint "q" "CSR_REGS" ++ "A general-purpose register except for $r0 and $r1 for lcsr.") ++ ++(define_constraint "u" ++ "A signed 52bit constant and low 32-bit is zero (for logic instructions)." ++ (and (match_code "const_int") ++ (match_test "LU32I_OPERAND (ival)"))) ++ ++(define_constraint "v" ++ "A signed 64-bit constant and low 44-bit is zero (for logic instructions)." ++ (and (match_code "const_int") ++ (match_test "LU52I_OPERAND (ival)"))) ++ ++(define_register_constraint "z" "FCC_REGS" ++ "A floating-point condition code register.") ++ ++;; Floating-point constraints ++ ++(define_constraint "G" ++ "Floating-point zero." ++ (and (match_code "const_double") ++ (match_test "op == CONST0_RTX (mode)"))) ++ ++;; Integer constraints ++ ++(define_constraint "I" ++ "A signed 12-bit constant (for arithmetic instructions)." ++ (and (match_code "const_int") ++ (match_test "IMM12_OPERAND (ival)"))) ++ ++(define_constraint "J" ++ "Integer zero." ++ (and (match_code "const_int") ++ (match_test "ival == 0"))) ++ ++(define_constraint "K" ++ "An unsigned 12-bit constant (for logic instructions)." ++ (and (match_code "const_int") ++ (match_test "IMM12_OPERAND_UNSIGNED (ival)"))) ++ ++(define_constraint "Yd" ++ "@internal ++ A constant @code{move_operand} that can be safely loaded using ++ @code{la}." ++ (and (match_operand 0 "move_operand") ++ (match_test "CONSTANT_P (op)"))) ++ ++(define_constraint "Yx" ++ "@internal" ++ (match_operand 0 "low_bitmask_operand")) ++ ++(define_memory_constraint "ZC" ++ "A memory operand whose address is formed by a base register and offset ++ that is suitable for use in instructions with the same addressing mode ++ as @code{ll.w} and @code{sc.w}." ++ (and (match_code "mem") ++ (match_test "loongarch_14bit_shifted_offset_address_p (XEXP (op, 0), mode)"))) ++ ++(define_memory_constraint "ZB" ++ "@internal ++ An address that is held in a general-purpose register. ++ The offset is zero" ++ (and (match_code "mem") ++ (match_test "REG_P (XEXP (op, 0))"))) +diff --git a/gcc/config/loongarch/generic.md b/gcc/config/loongarch/generic.md +new file mode 100644 +index 000000000..6e5a0934d +--- /dev/null ++++ b/gcc/config/loongarch/generic.md +@@ -0,0 +1,118 @@ ++;; Generic DFA-based pipeline description for LoongArch targets ++;; Copyright (C) 2021-2022 Free Software Foundation, Inc. ++;; Contributed by Loongson Ltd. ++;; Based on MIPS target for GNU compiler. ++ ++;; This file is part of GCC. ++ ++;; GCC is free software; you can redistribute it and/or modify it ++;; under the terms of the GNU General Public License as published ++;; by the Free Software Foundation; either version 3, or (at your ++;; option) any later version. ++ ++;; GCC 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 GCC; see the file COPYING3. If not see ++;; . ++ ++(define_automaton "alu,imuldiv") ++ ++(define_cpu_unit "alu" "alu") ++(define_cpu_unit "imuldiv" "imuldiv") ++ ++;; Ghost instructions produce no real code. ++;; They exist purely to express an effect on dataflow. ++(define_insn_reservation "ghost" 0 ++ (eq_attr "type" "ghost") ++ "nothing") ++ ++(define_insn_reservation "generic_alu" 1 ++ (eq_attr "type" "unknown,prefetch,prefetchx,condmove,const,arith, ++ shift,slt,clz,trap,multi,nop,logical,signext,move") ++ "alu") ++ ++(define_insn_reservation "generic_load" 3 ++ (eq_attr "type" "load,fpload,fpidxload") ++ "alu") ++ ++(define_insn_reservation "generic_store" 1 ++ (eq_attr "type" "store,fpstore,fpidxstore") ++ "alu") ++ ++(define_insn_reservation "generic_xfer" 2 ++ (eq_attr "type" "mftg,mgtf") ++ "alu") ++ ++(define_insn_reservation "generic_branch" 1 ++ (eq_attr "type" "branch,jump,call") ++ "alu") ++ ++(define_insn_reservation "generic_imul" 17 ++ (eq_attr "type" "imul") ++ "imuldiv*17") ++ ++(define_insn_reservation "generic_fcvt" 1 ++ (eq_attr "type" "fcvt") ++ "alu") ++ ++(define_insn_reservation "generic_fmove" 2 ++ (eq_attr "type" "fabs,fneg,fmove") ++ "alu") ++ ++(define_insn_reservation "generic_fcmp" 3 ++ (eq_attr "type" "fcmp") ++ "alu") ++ ++(define_insn_reservation "generic_fadd" 4 ++ (eq_attr "type" "fadd") ++ "alu") ++ ++(define_insn_reservation "generic_fmul_single" 7 ++ (and (eq_attr "type" "fmul,fmadd") ++ (eq_attr "mode" "SF")) ++ "alu") ++ ++(define_insn_reservation "generic_fmul_double" 8 ++ (and (eq_attr "type" "fmul,fmadd") ++ (eq_attr "mode" "DF")) ++ "alu") ++ ++(define_insn_reservation "generic_fdiv_single" 23 ++ (and (eq_attr "type" "fdiv,frdiv") ++ (eq_attr "mode" "SF")) ++ "alu") ++ ++(define_insn_reservation "generic_fdiv_double" 36 ++ (and (eq_attr "type" "fdiv,frdiv") ++ (eq_attr "mode" "DF")) ++ "alu") ++ ++(define_insn_reservation "generic_fsqrt_single" 54 ++ (and (eq_attr "type" "fsqrt,frsqrt") ++ (eq_attr "mode" "SF")) ++ "alu") ++ ++(define_insn_reservation "generic_fsqrt_double" 112 ++ (and (eq_attr "type" "fsqrt,frsqrt") ++ (eq_attr "mode" "DF")) ++ "alu") ++ ++(define_insn_reservation "generic_atomic" 10 ++ (eq_attr "type" "atomic") ++ "alu") ++ ++;; Sync loop consists of (in order) ++;; (1) optional sync, ++;; (2) LL instruction, ++;; (3) branch and 1-2 ALU instructions, ++;; (4) SC instruction, ++;; (5) branch and ALU instruction. ++;; The net result of this reservation is a big delay with a flush of ++;; ALU pipeline. ++(define_insn_reservation "generic_sync_loop" 40 ++ (eq_attr "type" "syncloop") ++ "alu*39") +diff --git a/gcc/config/loongarch/genopts/genstr.sh b/gcc/config/loongarch/genopts/genstr.sh +new file mode 100644 +index 000000000..972ef125f +--- /dev/null ++++ b/gcc/config/loongarch/genopts/genstr.sh +@@ -0,0 +1,104 @@ ++#!/bin/sh ++# A simple script that generates loongarch-str.h and loongarch.opt ++# from genopt/loongarch-optstr. ++# ++# Copyright (C) 2021-2022 Free Software Foundation, Inc. ++# ++# This file is part of GCC. ++# ++# GCC is free software; you can redistribute it and/or modify it under ++# the terms of the GNU General Public License as published by the Free ++# Software Foundation; either version 3, or (at your option) any later ++# version. ++# ++# GCC 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 GCC; see the file COPYING3. If not see ++# . ++ ++cd "$(dirname "$0")" ++ ++# Generate a header containing definitions from the string table. ++gen_defines() { ++ cat <. */ ++ ++#ifndef LOONGARCH_STR_H ++#define LOONGARCH_STR_H ++EOF ++ ++ sed -e '/^$/n' -e 's@#.*$@@' -e '/^$/d' \ ++ -e 's@^\([^ \t]\+\)[ \t]*\([^ \t]*\)@#define \1 "\2"@' \ ++ loongarch-strings ++ ++ echo ++ echo "#endif /* LOONGARCH_STR_H */" ++} ++ ++ ++# Substitute all "@@@@" to "" in loongarch.opt.in ++# according to the key-value pairs defined in loongarch-strings. ++ ++gen_options() { ++ ++ sed -e '/^$/n' -e 's@#.*$@@' -e '/^$/d' \ ++ -e 's@^\([^ \t]\+\)[ \t]*\([^ \t]*\)@\1="\2"@' \ ++ loongarch-strings | { \ ++ ++ # read the definitions ++ while read -r line; do ++ eval "$line" ++ done ++ ++ # print a header ++ cat << EOF ++; Generated by "genstr" from the template "loongarch.opt.in" ++; and definitions from "loongarch-strings". ++; ++; Please do not edit this file directly. ++; It will be automatically updated during a gcc build ++; if you change "loongarch.opt.in" or "loongarch-strings". ++; ++EOF ++ ++ # make the substitutions ++ sed -e 's@"@\\"@g' -e 's/@@\([^@]\+\)@@/${\1}/g' loongarch.opt.in | \ ++ while read -r line; do ++ eval "echo \"$line\"" ++ done ++ } ++} ++ ++main() { ++ case "$1" in ++ header) gen_defines;; ++ opt) gen_options;; ++ *) echo "Unknown Command: \"$1\". Available: header, opt"; exit 1;; ++ esac ++} ++ ++main "$@" +diff --git a/gcc/config/loongarch/genopts/loongarch-strings b/gcc/config/loongarch/genopts/loongarch-strings +new file mode 100644 +index 000000000..44ebb7ab1 +--- /dev/null ++++ b/gcc/config/loongarch/genopts/loongarch-strings +@@ -0,0 +1,59 @@ ++# Defines the key strings for LoongArch compiler options. ++# ++# Copyright (C) 2021-2022 Free Software Foundation, Inc. ++# ++# This file is part of GCC. ++# ++# GCC is free software; you can redistribute it and/or modify it under ++# the terms of the GNU General Public License as published by the Free ++# Software Foundation; either version 3, or (at your option) any later ++# version. ++# ++# GCC 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 GCC; see the file COPYING3. If not see ++# . ++ ++# -march= / -mtune= ++OPTSTR_ARCH arch ++OPTSTR_TUNE tune ++ ++STR_CPU_NATIVE native ++STR_CPU_LOONGARCH64 loongarch64 ++STR_CPU_LA464 la464 ++ ++# Base architecture ++STR_ISA_BASE_LA64V100 la64 ++ ++# -mfpu ++OPTSTR_ISA_EXT_FPU fpu ++STR_ISA_EXT_NOFPU none ++STR_ISA_EXT_FPU0 0 ++STR_ISA_EXT_FPU32 32 ++STR_ISA_EXT_FPU64 64 ++ ++OPTSTR_SOFT_FLOAT soft-float ++OPTSTR_SINGLE_FLOAT single-float ++OPTSTR_DOUBLE_FLOAT double-float ++ ++# -mabi= ++OPTSTR_ABI_BASE abi ++STR_ABI_BASE_LP64D lp64d ++STR_ABI_BASE_LP64F lp64f ++STR_ABI_BASE_LP64S lp64s ++ ++# ABI extension types ++STR_ABI_EXT_BASE base ++ ++# -mcmodel= ++OPTSTR_CMODEL cmodel ++STR_CMODEL_NORMAL normal ++STR_CMODEL_TINY tiny ++STR_CMODEL_TS tiny-static ++STR_CMODEL_MEDIUM medium ++STR_CMODEL_LARGE large ++STR_CMODEL_EXTREME extreme +diff --git a/gcc/config/loongarch/genopts/loongarch.opt.in b/gcc/config/loongarch/genopts/loongarch.opt.in +new file mode 100644 +index 000000000..e10618777 +--- /dev/null ++++ b/gcc/config/loongarch/genopts/loongarch.opt.in +@@ -0,0 +1,190 @@ ++; Copyright (C) 2021-2022 Free Software Foundation, Inc. ++; ++; This file is part of GCC. ++; ++; GCC is free software; you can redistribute it and/or modify it under ++; the terms of the GNU General Public License as published by the Free ++; Software Foundation; either version 3, or (at your option) any later ++; version. ++; ++; GCC 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 GCC; see the file COPYING3. If not see ++; . ++; ++ ++; Variables (macros) that should be exported by loongarch.opt: ++; la_opt_switches, ++; la_opt_abi_base, la_opt_abi_ext, ++; la_opt_cpu_arch, la_opt_cpu_tune, ++; la_opt_fpu, ++; la_cmodel. ++ ++HeaderInclude ++config/loongarch/loongarch-opts.h ++ ++HeaderInclude ++config/loongarch/loongarch-str.h ++ ++Variable ++HOST_WIDE_INT la_opt_switches = 0 ++ ++; ISA related options ++;; Base ISA ++Enum ++Name(isa_base) Type(int) ++Basic ISAs of LoongArch: ++ ++EnumValue ++Enum(isa_base) String(@@STR_ISA_BASE_LA64V100@@) Value(ISA_BASE_LA64V100) ++ ++ ++;; ISA extensions / adjustments ++Enum ++Name(isa_ext_fpu) Type(int) ++FPU types of LoongArch: ++ ++EnumValue ++Enum(isa_ext_fpu) String(@@STR_ISA_EXT_NOFPU@@) Value(ISA_EXT_NOFPU) ++ ++EnumValue ++Enum(isa_ext_fpu) String(@@STR_ISA_EXT_FPU32@@) Value(ISA_EXT_FPU32) ++ ++EnumValue ++Enum(isa_ext_fpu) String(@@STR_ISA_EXT_FPU64@@) Value(ISA_EXT_FPU64) ++ ++m@@OPTSTR_ISA_EXT_FPU@@= ++Target RejectNegative Joined ToLower Enum(isa_ext_fpu) Var(la_opt_fpu) Init(M_OPTION_NOT_SEEN) ++-m@@OPTSTR_ISA_EXT_FPU@@=FPU Generate code for the given FPU. ++ ++m@@OPTSTR_ISA_EXT_FPU@@=@@STR_ISA_EXT_FPU0@@ ++Target RejectNegative Alias(m@@OPTSTR_ISA_EXT_FPU@@=,@@STR_ISA_EXT_NOFPU@@) ++ ++m@@OPTSTR_SOFT_FLOAT@@ ++Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_SOFTF) Negative(m@@OPTSTR_SINGLE_FLOAT@@) ++Prevent the use of all hardware floating-point instructions. ++ ++m@@OPTSTR_SINGLE_FLOAT@@ ++Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_F32) Negative(m@@OPTSTR_DOUBLE_FLOAT@@) ++Restrict the use of hardware floating-point instructions to 32-bit operations. ++ ++m@@OPTSTR_DOUBLE_FLOAT@@ ++Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_F64) Negative(m@@OPTSTR_SOFT_FLOAT@@) ++Allow hardware floating-point instructions to cover both 32-bit and 64-bit operations. ++ ++ ++;; Base target models (implies ISA & tune parameters) ++Enum ++Name(cpu_type) Type(int) ++LoongArch CPU types: ++ ++EnumValue ++Enum(cpu_type) String(@@STR_CPU_NATIVE@@) Value(CPU_NATIVE) ++ ++EnumValue ++Enum(cpu_type) String(@@STR_CPU_LOONGARCH64@@) Value(CPU_LOONGARCH64) ++ ++EnumValue ++Enum(cpu_type) String(@@STR_CPU_LA464@@) Value(CPU_LA464) ++ ++m@@OPTSTR_ARCH@@= ++Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_arch) Init(M_OPTION_NOT_SEEN) ++-m@@OPTSTR_ARCH@@=PROCESSOR Generate code for the given PROCESSOR ISA. ++ ++m@@OPTSTR_TUNE@@= ++Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_tune) Init(M_OPTION_NOT_SEEN) ++-m@@OPTSTR_TUNE@@=PROCESSOR Generate optimized code for PROCESSOR. ++ ++ ++; ABI related options ++; (ISA constraints on ABI are handled dynamically) ++ ++;; Base ABI ++Enum ++Name(abi_base) Type(int) ++Base ABI types for LoongArch: ++ ++EnumValue ++Enum(abi_base) String(@@STR_ABI_BASE_LP64D@@) Value(ABI_BASE_LP64D) ++ ++EnumValue ++Enum(abi_base) String(@@STR_ABI_BASE_LP64F@@) Value(ABI_BASE_LP64F) ++ ++EnumValue ++Enum(abi_base) String(@@STR_ABI_BASE_LP64S@@) Value(ABI_BASE_LP64S) ++ ++m@@OPTSTR_ABI_BASE@@= ++Target RejectNegative Joined ToLower Enum(abi_base) Var(la_opt_abi_base) Init(M_OPTION_NOT_SEEN) ++-m@@OPTSTR_ABI_BASE@@=BASEABI Generate code that conforms to the given BASEABI. ++ ++;; ABI Extension ++Variable ++int la_opt_abi_ext = M_OPTION_NOT_SEEN ++ ++ ++mbranch-cost= ++Target RejectNegative Joined UInteger Var(loongarch_branch_cost) ++-mbranch-cost=COST Set the cost of branches to roughly COST instructions. ++ ++mcheck-zero-division ++Target Mask(CHECK_ZERO_DIV) ++Trap on integer divide by zero. ++ ++mcond-move-int ++Target Var(TARGET_COND_MOVE_INT) Init(1) ++Conditional moves for integral are enabled. ++ ++mcond-move-float ++Target Var(TARGET_COND_MOVE_FLOAT) Init(1) ++Conditional moves for float are enabled. ++ ++mmemcpy ++Target Mask(MEMCPY) ++Prevent optimizing block moves, which is also the default behavior of -Os. ++ ++mstrict-align ++Target Var(TARGET_STRICT_ALIGN) Init(0) ++Do not generate unaligned memory accesses. ++ ++mmax-inline-memcpy-size= ++Target Joined RejectNegative UInteger Var(loongarch_max_inline_memcpy_size) Init(1024) ++-mmax-inline-memcpy-size=SIZE Set the max size of memcpy to inline, default is 1024. ++ ++mexplicit-relocs ++Target Var(TARGET_EXPLICIT_RELOCS) Init(HAVE_AS_EXPLICIT_RELOCS) ++Use %reloc() assembly operators. ++ ++; The code model option names for -mcmodel. ++Enum ++Name(cmodel) Type(int) ++The code model option names for -mcmodel: ++ ++EnumValue ++Enum(cmodel) String(@@STR_CMODEL_NORMAL@@) Value(CMODEL_NORMAL) ++ ++EnumValue ++Enum(cmodel) String(@@STR_CMODEL_TINY@@) Value(CMODEL_TINY) ++ ++EnumValue ++Enum(cmodel) String(@@STR_CMODEL_TS@@) Value(CMODEL_TINY_STATIC) ++ ++EnumValue ++Enum(cmodel) String(@@STR_CMODEL_MEDIUM@@) Value(CMODEL_MEDIUM) ++ ++EnumValue ++Enum(cmodel) String(@@STR_CMODEL_LARGE@@) Value(CMODEL_LARGE) ++ ++EnumValue ++Enum(cmodel) String(@@STR_CMODEL_EXTREME@@) Value(CMODEL_EXTREME) ++ ++mcmodel= ++Target RejectNegative Joined Enum(cmodel) Var(la_opt_cmodel) Init(CMODEL_NORMAL) ++Specify the code model. ++ ++mdirect-extern-access ++Target Var(TARGET_DIRECT_EXTERN_ACCESS) Init(0) ++Avoid using the GOT to access external symbols. +diff --git a/gcc/config/loongarch/gnu-user.h b/gcc/config/loongarch/gnu-user.h +new file mode 100644 +index 000000000..664dc9206 +--- /dev/null ++++ b/gcc/config/loongarch/gnu-user.h +@@ -0,0 +1,80 @@ ++/* Definitions for LoongArch systems using GNU (glibc-based) userspace, ++ or other userspace with libc derived from glibc. ++ Copyright (C) 2021-2022 Free Software Foundation, Inc. ++ ++This file is part of GCC. ++ ++GCC is free software; you can redistribute it and/or modify ++it under the terms of the GNU General Public License as published by ++the Free Software Foundation; either version 3, or (at your option) ++any later version. ++ ++GCC 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 GCC; see the file COPYING3. If not see ++. */ ++ ++/* Define the size of the wide character type. */ ++#undef WCHAR_TYPE ++#define WCHAR_TYPE "int" ++ ++#undef WCHAR_TYPE_SIZE ++#define WCHAR_TYPE_SIZE 32 ++ ++ ++/* GNU-specific SPEC definitions. */ ++#define GNU_USER_LINK_EMULATION "elf" ABI_GRLEN_SPEC "loongarch" ++ ++#undef GLIBC_DYNAMIC_LINKER ++#define GLIBC_DYNAMIC_LINKER \ ++ "/lib" ABI_GRLEN_SPEC "/ld-linux-loongarch-" ABI_SPEC ".so.1" ++ ++#undef MUSL_DYNAMIC_LINKER ++#define MUSL_DYNAMIC_LINKER \ ++ "/lib" ABI_GRLEN_SPEC "/ld-musl-loongarch-" ABI_SPEC ".so.1" ++ ++#undef GNU_USER_TARGET_LINK_SPEC ++#define GNU_USER_TARGET_LINK_SPEC \ ++ "%{G*} %{shared} -m " GNU_USER_LINK_EMULATION \ ++ "%{!shared: %{static} %{!static: %{rdynamic:-export-dynamic} " \ ++ "-dynamic-linker " GNU_USER_DYNAMIC_LINKER "}}" ++ ++ ++/* Similar to standard Linux, but adding -ffast-math support. */ ++#undef GNU_USER_TARGET_MATHFILE_SPEC ++#define GNU_USER_TARGET_MATHFILE_SPEC \ ++ "%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s}" ++ ++#undef LIB_SPEC ++#define LIB_SPEC GNU_USER_TARGET_LIB_SPEC ++ ++#undef LINK_SPEC ++#define LINK_SPEC GNU_USER_TARGET_LINK_SPEC ++ ++#undef ENDFILE_SPEC ++#define ENDFILE_SPEC \ ++ GNU_USER_TARGET_MATHFILE_SPEC " " \ ++ GNU_USER_TARGET_ENDFILE_SPEC ++ ++#undef SUBTARGET_CPP_SPEC ++#define SUBTARGET_CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}" ++ ++/* A standard GNU/Linux mapping. On most targets, it is included in ++ CC1_SPEC itself by config/linux.h, but loongarch.h overrides CC1_SPEC ++ and provides this hook instead. */ ++#undef SUBTARGET_CC1_SPEC ++#define SUBTARGET_CC1_SPEC GNU_USER_TARGET_CC1_SPEC ++ ++#define TARGET_OS_CPP_BUILTINS() \ ++ do \ ++ { \ ++ GNU_USER_TARGET_OS_CPP_BUILTINS (); \ ++ /* The GNU C++ standard library requires this. */ \ ++ if (c_dialect_cxx ()) \ ++ builtin_define ("_GNU_SOURCE"); \ ++ } \ ++ while (0) +diff --git a/gcc/config/loongarch/la464.md b/gcc/config/loongarch/la464.md +new file mode 100644 +index 000000000..0ae177610 +--- /dev/null ++++ b/gcc/config/loongarch/la464.md +@@ -0,0 +1,132 @@ ++;; Pipeline model for LoongArch LA464 cores. ++ ++;; Copyright (C) 2021-2022 Free Software Foundation, Inc. ++;; Contributed by Loongson Ltd. ++ ++;; This file is part of GCC. ++;; ++;; GCC is free software; you can redistribute it and/or modify it ++;; under the terms of the GNU General Public License as published ++;; by the Free Software Foundation; either version 3, or (at your ++;; option) any later version. ++;; ++;; GCC 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 GCC; see the file COPYING3. If not see ++;; . ++ ++;; Uncomment the following line to output automata for debugging. ++;; (automata_option "v") ++ ++;; Automaton for integer instructions. ++(define_automaton "la464_a_alu") ++ ++;; Automaton for floating-point instructions. ++(define_automaton "la464_a_falu") ++ ++;; Automaton for memory operations. ++(define_automaton "la464_a_mem") ++ ++;; Describe the resources. ++ ++(define_cpu_unit "la464_alu1" "la464_a_alu") ++(define_cpu_unit "la464_alu2" "la464_a_alu") ++(define_cpu_unit "la464_mem1" "la464_a_mem") ++(define_cpu_unit "la464_mem2" "la464_a_mem") ++(define_cpu_unit "la464_falu1" "la464_a_falu") ++(define_cpu_unit "la464_falu2" "la464_a_falu") ++ ++;; Describe instruction reservations. ++ ++(define_insn_reservation "la464_arith" 1 ++ (and (match_test "TARGET_TUNE_LA464") ++ (eq_attr "type" "arith,clz,const,logical, ++ move,nop,shift,signext,slt")) ++ "la464_alu1 | la464_alu2") ++ ++(define_insn_reservation "la464_branch" 1 ++ (and (match_test "TARGET_TUNE_LA464") ++ (eq_attr "type" "branch,jump,call,condmove,trap")) ++ "la464_alu1 | la464_alu2") ++ ++(define_insn_reservation "la464_imul" 7 ++ (and (match_test "TARGET_TUNE_LA464") ++ (eq_attr "type" "imul")) ++ "la464_alu1 | la464_alu2") ++ ++(define_insn_reservation "la464_idiv_si" 12 ++ (and (match_test "TARGET_TUNE_LA464") ++ (and (eq_attr "type" "idiv") ++ (eq_attr "mode" "SI"))) ++ "la464_alu1 | la464_alu2") ++ ++(define_insn_reservation "la464_idiv_di" 25 ++ (and (match_test "TARGET_TUNE_LA464") ++ (and (eq_attr "type" "idiv") ++ (eq_attr "mode" "DI"))) ++ "la464_alu1 | la464_alu2") ++ ++(define_insn_reservation "la464_load" 4 ++ (and (match_test "TARGET_TUNE_LA464") ++ (eq_attr "type" "load")) ++ "la464_mem1 | la464_mem2") ++ ++(define_insn_reservation "la464_gpr_fp" 16 ++ (and (match_test "TARGET_TUNE_LA464") ++ (eq_attr "type" "mftg,mgtf")) ++ "la464_mem1") ++ ++(define_insn_reservation "la464_fpload" 4 ++ (and (match_test "TARGET_TUNE_LA464") ++ (eq_attr "type" "fpload")) ++ "la464_mem1 | la464_mem2") ++ ++(define_insn_reservation "la464_prefetch" 0 ++ (and (match_test "TARGET_TUNE_LA464") ++ (eq_attr "type" "prefetch,prefetchx")) ++ "la464_mem1 | la464_mem2") ++ ++(define_insn_reservation "la464_store" 0 ++ (and (match_test "TARGET_TUNE_LA464") ++ (eq_attr "type" "store,fpstore,fpidxstore")) ++ "la464_mem1 | la464_mem2") ++ ++(define_insn_reservation "la464_fadd" 4 ++ (and (match_test "TARGET_TUNE_LA464") ++ (eq_attr "type" "fadd,fmul,fmadd")) ++ "la464_falu1 | la464_falu2") ++ ++(define_insn_reservation "la464_fcmp" 2 ++ (and (match_test "TARGET_TUNE_LA464") ++ (eq_attr "type" "fabs,fcmp,fmove,fneg")) ++ "la464_falu1 | la464_falu2") ++ ++(define_insn_reservation "la464_fcvt" 4 ++ (and (match_test "TARGET_TUNE_LA464") ++ (eq_attr "type" "fcvt")) ++ "la464_falu1 | la464_falu2") ++ ++(define_insn_reservation "la464_fdiv_sf" 12 ++ (and (match_test "TARGET_TUNE_LA464") ++ (and (eq_attr "type" "fdiv,frdiv,fsqrt,frsqrt") ++ (eq_attr "mode" "SF"))) ++ "la464_falu1 | la464_falu2") ++ ++(define_insn_reservation "la464_fdiv_df" 19 ++ (and (match_test "TARGET_TUNE_LA464") ++ (and (eq_attr "type" "fdiv,frdiv,fsqrt,frsqrt") ++ (eq_attr "mode" "DF"))) ++ "la464_falu1 | la464_falu2") ++ ++;; Force single-dispatch for unknown or multi. ++(define_insn_reservation "la464_unknown" 1 ++ (and (match_test "TARGET_TUNE_LA464") ++ (eq_attr "type" "unknown,multi,atomic,syncloop")) ++ "la464_alu1 + la464_alu2 + la464_falu1 ++ + la464_falu2 + la464_mem1 + la464_mem2") ++ ++;; End of DFA-based pipeline description for la464 +diff --git a/gcc/config/loongarch/larchintrin.h b/gcc/config/loongarch/larchintrin.h +new file mode 100644 +index 000000000..2833f1487 +--- /dev/null ++++ b/gcc/config/loongarch/larchintrin.h +@@ -0,0 +1,355 @@ ++/* Intrinsics for LoongArch BASE operations. ++ Copyright (C) 2021-2022 Free Software Foundation, Inc. ++ Contributed by Loongson Ltd. ++ ++This file is part of GCC. ++ ++GCC is free software; you can redistribute it and/or modify it ++under the terms of the GNU General Public License as published ++by the Free Software Foundation; either version 3, or (at your ++option) any later version. ++ ++GCC 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. ++ ++Under Section 7 of GPL version 3, you are granted additional ++permissions described in the GCC Runtime Library Exception, version ++3.1, as published by the Free Software Foundation. ++ ++You should have received a copy of the GNU General Public License and ++a copy of the GCC Runtime Library Exception along with this program; ++see the files COPYING3 and COPYING.RUNTIME respectively. If not, see ++. */ ++ ++#ifndef _GCC_LOONGARCH_BASE_INTRIN_H ++#define _GCC_LOONGARCH_BASE_INTRIN_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++typedef struct drdtime ++{ ++ unsigned long dvalue; ++ unsigned long dtimeid; ++} __drdtime_t; ++ ++typedef struct rdtime ++{ ++ unsigned int value; ++ unsigned int timeid; ++} __rdtime_t; ++ ++#ifdef __loongarch64 ++extern __inline __drdtime_t ++__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) ++__rdtime_d (void) ++{ ++ __drdtime_t __drdtime; ++ __asm__ volatile ( ++ "rdtime.d\t%[val],%[tid]\n\t" ++ : [val]"=&r"(__drdtime.dvalue),[tid]"=&r"(__drdtime.dtimeid) ++ :); ++ return __drdtime; ++} ++#endif ++ ++extern __inline __rdtime_t ++__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) ++__rdtimeh_w (void) ++{ ++ __rdtime_t __rdtime; ++ __asm__ volatile ( ++ "rdtimeh.w\t%[val],%[tid]\n\t" ++ : [val]"=&r"(__rdtime.value),[tid]"=&r"(__rdtime.timeid) ++ :); ++ return __rdtime; ++} ++ ++extern __inline __rdtime_t ++__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) ++__rdtimel_w (void) ++{ ++ __rdtime_t __rdtime; ++ __asm__ volatile ( ++ "rdtimel.w\t%[val],%[tid]\n\t" ++ : [val]"=&r"(__rdtime.value),[tid]"=&r"(__rdtime.timeid) ++ :); ++ return __rdtime; ++} ++ ++/* Assembly instruction format: rj, fcsr. */ ++/* Data types in instruction templates: USI, UQI. */ ++#define __movfcsr2gr(/*ui5*/ _1) __builtin_loongarch_movfcsr2gr ((_1)); ++ ++/* Assembly instruction format: fcsr, rj. */ ++/* Data types in instruction templates: VOID, UQI, USI. */ ++#define __movgr2fcsr(/*ui5*/ _1, _2) \ ++ __builtin_loongarch_movgr2fcsr ((_1), (unsigned int) _2); ++ ++#if defined __loongarch64 ++/* Assembly instruction format: ui5, rj, si12. */ ++/* Data types in instruction templates: VOID, USI, UDI, SI. */ ++#define __cacop_d(/*ui5*/ _1, /*unsigned long int*/ _2, /*si12*/ _3) \ ++ ((void) __builtin_loongarch_cacop_d ((_1), (unsigned long int) (_2), (_3))) ++#else ++#error "Unsupported ABI." ++#endif ++ ++/* Assembly instruction format: rd, rj. */ ++/* Data types in instruction templates: USI, USI. */ ++extern __inline unsigned int ++__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) ++__cpucfg (unsigned int _1) ++{ ++ return (unsigned int) __builtin_loongarch_cpucfg ((unsigned int) _1); ++} ++ ++#ifdef __loongarch64 ++/* Assembly instruction format: rj, rk. */ ++/* Data types in instruction templates: DI, DI. */ ++extern __inline void ++__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) ++__asrtle_d (long int _1, long int _2) ++{ ++ __builtin_loongarch_asrtle_d ((long int) _1, (long int) _2); ++} ++ ++/* Assembly instruction format: rj, rk. */ ++/* Data types in instruction templates: DI, DI. */ ++extern __inline void ++__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) ++__asrtgt_d (long int _1, long int _2) ++{ ++ __builtin_loongarch_asrtgt_d ((long int) _1, (long int) _2); ++} ++#endif ++ ++#if defined __loongarch64 ++/* Assembly instruction format: rd, rj, ui5. */ ++/* Data types in instruction templates: DI, DI, UQI. */ ++#define __lddir_d(/*long int*/ _1, /*ui5*/ _2) \ ++ ((long int) __builtin_loongarch_lddir_d ((long int) (_1), (_2))) ++#else ++#error "Unsupported ABI." ++#endif ++ ++#if defined __loongarch64 ++/* Assembly instruction format: rj, ui5. */ ++/* Data types in instruction templates: VOID, DI, UQI. */ ++#define __ldpte_d(/*long int*/ _1, /*ui5*/ _2) \ ++ ((void) __builtin_loongarch_ldpte_d ((long int) (_1), (_2))) ++#else ++#error "Unsupported ABI." ++#endif ++ ++/* Assembly instruction format: rd, rj, rk. */ ++/* Data types in instruction templates: SI, QI, SI. */ ++extern __inline int ++__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) ++__crc_w_b_w (char _1, int _2) ++{ ++ return (int) __builtin_loongarch_crc_w_b_w ((char) _1, (int) _2); ++} ++ ++/* Assembly instruction format: rd, rj, rk. */ ++/* Data types in instruction templates: SI, HI, SI. */ ++extern __inline int ++__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) ++__crc_w_h_w (short _1, int _2) ++{ ++ return (int) __builtin_loongarch_crc_w_h_w ((short) _1, (int) _2); ++} ++ ++/* Assembly instruction format: rd, rj, rk. */ ++/* Data types in instruction templates: SI, SI, SI. */ ++extern __inline int ++__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) ++__crc_w_w_w (int _1, int _2) ++{ ++ return (int) __builtin_loongarch_crc_w_w_w ((int) _1, (int) _2); ++} ++ ++#ifdef __loongarch64 ++/* Assembly instruction format: rd, rj, rk. */ ++/* Data types in instruction templates: SI, DI, SI. */ ++extern __inline int ++__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) ++__crc_w_d_w (long int _1, int _2) ++{ ++ return (int) __builtin_loongarch_crc_w_d_w ((long int) _1, (int) _2); ++} ++#endif ++ ++/* Assembly instruction format: rd, rj, rk. */ ++/* Data types in instruction templates: SI, QI, SI. */ ++extern __inline int ++__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) ++__crcc_w_b_w (char _1, int _2) ++{ ++ return (int) __builtin_loongarch_crcc_w_b_w ((char) _1, (int) _2); ++} ++ ++/* Assembly instruction format: rd, rj, rk. */ ++/* Data types in instruction templates: SI, HI, SI. */ ++extern __inline int ++__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) ++__crcc_w_h_w (short _1, int _2) ++{ ++ return (int) __builtin_loongarch_crcc_w_h_w ((short) _1, (int) _2); ++} ++ ++/* Assembly instruction format: rd, rj, rk. */ ++/* Data types in instruction templates: SI, SI, SI. */ ++extern __inline int ++__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) ++__crcc_w_w_w (int _1, int _2) ++{ ++ return (int) __builtin_loongarch_crcc_w_w_w ((int) _1, (int) _2); ++} ++ ++#ifdef __loongarch64 ++/* Assembly instruction format: rd, rj, rk. */ ++/* Data types in instruction templates: SI, DI, SI. */ ++extern __inline int ++__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) ++__crcc_w_d_w (long int _1, int _2) ++{ ++ return (int) __builtin_loongarch_crcc_w_d_w ((long int) _1, (int) _2); ++} ++#endif ++ ++/* Assembly instruction format: rd, ui14. */ ++/* Data types in instruction templates: USI, USI. */ ++#define __csrrd_w(/*ui14*/ _1) \ ++ ((unsigned int) __builtin_loongarch_csrrd_w ((_1))) ++ ++/* Assembly instruction format: rd, ui14. */ ++/* Data types in instruction templates: USI, USI, USI. */ ++#define __csrwr_w(/*unsigned int*/ _1, /*ui14*/ _2) \ ++ ((unsigned int) __builtin_loongarch_csrwr_w ((unsigned int) (_1), (_2))) ++ ++/* Assembly instruction format: rd, rj, ui14. */ ++/* Data types in instruction templates: USI, USI, USI, USI. */ ++#define __csrxchg_w(/*unsigned int*/ _1, /*unsigned int*/ _2, /*ui14*/ _3) \ ++ ((unsigned int) __builtin_loongarch_csrxchg_w ((unsigned int) (_1), \ ++ (unsigned int) (_2), (_3))) ++ ++#ifdef __loongarch64 ++/* Assembly instruction format: rd, ui14. */ ++/* Data types in instruction templates: UDI, USI. */ ++#define __csrrd_d(/*ui14*/ _1) \ ++ ((unsigned long int) __builtin_loongarch_csrrd_d ((_1))) ++ ++/* Assembly instruction format: rd, ui14. */ ++/* Data types in instruction templates: UDI, UDI, USI. */ ++#define __csrwr_d(/*unsigned long int*/ _1, /*ui14*/ _2) \ ++ ((unsigned long int) __builtin_loongarch_csrwr_d ((unsigned long int) (_1), \ ++ (_2))) ++ ++/* Assembly instruction format: rd, rj, ui14. */ ++/* Data types in instruction templates: UDI, UDI, UDI, USI. */ ++#define __csrxchg_d(/*unsigned long int*/ _1, /*unsigned long int*/ _2, \ ++ /*ui14*/ _3) \ ++ ((unsigned long int) __builtin_loongarch_csrxchg_d ( \ ++ (unsigned long int) (_1), (unsigned long int) (_2), (_3))) ++#endif ++ ++/* Assembly instruction format: rd, rj. */ ++/* Data types in instruction templates: UQI, USI. */ ++extern __inline unsigned char ++__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) ++__iocsrrd_b (unsigned int _1) ++{ ++ return (unsigned char) __builtin_loongarch_iocsrrd_b ((unsigned int) _1); ++} ++ ++/* Assembly instruction format: rd, rj. */ ++/* Data types in instruction templates: UHI, USI. */ ++extern __inline unsigned char ++__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) ++__iocsrrd_h (unsigned int _1) ++{ ++ return (unsigned short) __builtin_loongarch_iocsrrd_h ((unsigned int) _1); ++} ++ ++/* Assembly instruction format: rd, rj. */ ++/* Data types in instruction templates: USI, USI. */ ++extern __inline unsigned int ++__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) ++__iocsrrd_w (unsigned int _1) ++{ ++ return (unsigned int) __builtin_loongarch_iocsrrd_w ((unsigned int) _1); ++} ++ ++#ifdef __loongarch64 ++/* Assembly instruction format: rd, rj. */ ++/* Data types in instruction templates: UDI, USI. */ ++extern __inline unsigned long int ++__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) ++__iocsrrd_d (unsigned int _1) ++{ ++ return (unsigned long int) __builtin_loongarch_iocsrrd_d ((unsigned int) _1); ++} ++#endif ++ ++/* Assembly instruction format: rd, rj. */ ++/* Data types in instruction templates: VOID, UQI, USI. */ ++extern __inline void ++__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) ++__iocsrwr_b (unsigned char _1, unsigned int _2) ++{ ++ __builtin_loongarch_iocsrwr_b ((unsigned char) _1, (unsigned int) _2); ++} ++ ++/* Assembly instruction format: rd, rj. */ ++/* Data types in instruction templates: VOID, UHI, USI. */ ++extern __inline void ++__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) ++__iocsrwr_h (unsigned short _1, unsigned int _2) ++{ ++ __builtin_loongarch_iocsrwr_h ((unsigned short) _1, (unsigned int) _2); ++} ++ ++/* Assembly instruction format: rd, rj. */ ++/* Data types in instruction templates: VOID, USI, USI. */ ++extern __inline void ++__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) ++__iocsrwr_w (unsigned int _1, unsigned int _2) ++{ ++ __builtin_loongarch_iocsrwr_w ((unsigned int) _1, (unsigned int) _2); ++} ++ ++#ifdef __loongarch64 ++/* Assembly instruction format: rd, rj. */ ++/* Data types in instruction templates: VOID, UDI, USI. */ ++extern __inline void ++__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) ++__iocsrwr_d (unsigned long int _1, unsigned int _2) ++{ ++ __builtin_loongarch_iocsrwr_d ((unsigned long int) _1, (unsigned int) _2); ++} ++#endif ++ ++/* Assembly instruction format: ui15. */ ++/* Data types in instruction templates: USI. */ ++#define __dbar(/*ui15*/ _1) __builtin_loongarch_dbar ((_1)) ++ ++/* Assembly instruction format: ui15. */ ++/* Data types in instruction templates: USI. */ ++#define __ibar(/*ui15*/ _1) __builtin_loongarch_ibar ((_1)) ++ ++/* Assembly instruction format: ui15. */ ++/* Data types in instruction templates: USI. */ ++#define __syscall(/*ui15*/ _1) __builtin_loongarch_syscall ((_1)) ++ ++/* Assembly instruction format: ui15. */ ++/* Data types in instruction templates: USI. */ ++#define __break(/*ui15*/ _1) __builtin_loongarch_break ((_1)) ++ ++#ifdef __cplusplus ++} ++#endif ++#endif /* _GCC_LOONGARCH_BASE_INTRIN_H */ +diff --git a/gcc/config/loongarch/linux.h b/gcc/config/loongarch/linux.h +new file mode 100644 +index 000000000..110d0fab9 +--- /dev/null ++++ b/gcc/config/loongarch/linux.h +@@ -0,0 +1,50 @@ ++/* Definitions for Linux-based systems with libraries in ELF format. ++ Copyright (C) 2021-2022 Free Software Foundation, Inc. ++ ++This file is part of GCC. ++ ++GCC is free software; you can redistribute it and/or modify ++it under the terms of the GNU General Public License as published by ++the Free Software Foundation; either version 3, or (at your option) ++any later version. ++ ++GCC 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 GCC; see the file COPYING3. If not see ++. */ ++ ++/* Default system library search paths. ++ * This ensures that a compiler configured with --disable-multilib ++ * can work in a multilib environment. */ ++ ++#if defined(LA_DISABLE_MULTILIB) && defined(LA_DISABLE_MULTIARCH) ++ ++ #if DEFAULT_ABI_BASE == ABI_BASE_LP64D ++ #define ABI_LIBDIR "lib64" ++ #elif DEFAULT_ABI_BASE == ABI_BASE_LP64F ++ #define ABI_LIBDIR "lib64/f32" ++ #elif DEFAULT_ABI_BASE == ABI_BASE_LP64S ++ #define ABI_LIBDIR "lib64/sf" ++ #endif ++ ++#endif ++ ++#ifndef ABI_LIBDIR ++#define ABI_LIBDIR "lib" ++#endif ++ ++#define STANDARD_STARTFILE_PREFIX_1 "/" ABI_LIBDIR "/" ++#define STANDARD_STARTFILE_PREFIX_2 "/usr/" ABI_LIBDIR "/" ++ ++ ++/* Define this to be nonzero if static stack checking is supported. */ ++#define STACK_CHECK_STATIC_BUILTIN 1 ++ ++/* The default value isn't sufficient in 64-bit mode. */ ++#define STACK_CHECK_PROTECT (TARGET_64BIT ? 16 * 1024 : 12 * 1024) ++ ++#define TARGET_ASM_FILE_END file_end_indicate_exec_stack +diff --git a/gcc/config/loongarch/loongarch-builtins.c b/gcc/config/loongarch/loongarch-builtins.c +new file mode 100644 +index 000000000..64fe11168 +--- /dev/null ++++ b/gcc/config/loongarch/loongarch-builtins.c +@@ -0,0 +1,424 @@ ++/* Subroutines used for expanding LoongArch builtins. ++ Copyright (C) 2021-2022 Free Software Foundation, Inc. ++ Contributed by Loongson Ltd. ++ ++This file is part of GCC. ++ ++GCC is free software; you can redistribute it and/or modify ++it under the terms of the GNU General Public License as published by ++the Free Software Foundation; either version 3, or (at your option) ++any later version. ++ ++GCC 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 GCC; see the file COPYING3. If not see ++. */ ++ ++#define IN_TARGET_CODE 1 ++ ++#include "config.h" ++#include "system.h" ++#include "coretypes.h" ++#include "backend.h" ++#include "target.h" ++#include "rtl.h" ++#include "tree.h" ++#include "memmodel.h" ++#include "gimple.h" ++#include "tm_p.h" ++#include "optabs.h" ++#include "recog.h" ++#include "diagnostic.h" ++#include "fold-const.h" ++#include "expr.h" ++#include "langhooks.h" ++ ++/* Macros to create an enumeration identifier for a function prototype. */ ++#define LARCH_FTYPE_NAME1(A, B) LARCH_##A##_FTYPE_##B ++#define LARCH_FTYPE_NAME2(A, B, C) LARCH_##A##_FTYPE_##B##_##C ++#define LARCH_FTYPE_NAME3(A, B, C, D) LARCH_##A##_FTYPE_##B##_##C##_##D ++ ++/* Classifies the prototype of a built-in function. */ ++enum loongarch_function_type ++{ ++#define DEF_LARCH_FTYPE(NARGS, LIST) LARCH_FTYPE_NAME##NARGS LIST, ++#include "config/loongarch/loongarch-ftypes.def" ++#undef DEF_LARCH_FTYPE ++ LARCH_MAX_FTYPE_MAX ++}; ++ ++/* Specifies how a built-in function should be converted into rtl. */ ++enum loongarch_builtin_type ++{ ++ /* The function corresponds directly to an .md pattern. The return ++ value is mapped to operand 0 and the arguments are mapped to ++ operands 1 and above. */ ++ LARCH_BUILTIN_DIRECT, ++ ++ /* The function corresponds directly to an .md pattern. There is no return ++ value and the arguments are mapped to operands 0 and above. */ ++ LARCH_BUILTIN_DIRECT_NO_TARGET, ++ ++}; ++ ++/* Declare an availability predicate for built-in functions that require ++ * COND to be true. NAME is the main part of the predicate's name. */ ++#define AVAIL_ALL(NAME, COND) \ ++ static unsigned int \ ++ loongarch_builtin_avail_##NAME (void) \ ++ { \ ++ return (COND) ? 1 : 0; \ ++ } ++ ++static unsigned int ++loongarch_builtin_avail_default (void) ++{ ++ return 1; ++} ++/* This structure describes a single built-in function. */ ++struct loongarch_builtin_description ++{ ++ /* The code of the main .md file instruction. See loongarch_builtin_type ++ for more information. */ ++ enum insn_code icode; ++ ++ /* The name of the built-in function. */ ++ const char *name; ++ ++ /* Specifies how the function should be expanded. */ ++ enum loongarch_builtin_type builtin_type; ++ ++ /* The function's prototype. */ ++ enum loongarch_function_type function_type; ++ ++ /* Whether the function is available. */ ++ unsigned int (*avail) (void); ++}; ++ ++AVAIL_ALL (hard_float, TARGET_HARD_FLOAT_ABI) ++ ++/* Construct a loongarch_builtin_description from the given arguments. ++ ++ INSN is the name of the associated instruction pattern, without the ++ leading CODE_FOR_loongarch_. ++ ++ CODE is the floating-point condition code associated with the ++ function. It can be 'f' if the field is not applicable. ++ ++ NAME is the name of the function itself, without the leading ++ "__builtin_loongarch_". ++ ++ BUILTIN_TYPE and FUNCTION_TYPE are loongarch_builtin_description fields. ++ ++ AVAIL is the name of the availability predicate, without the leading ++ loongarch_builtin_avail_. */ ++#define LARCH_BUILTIN(INSN, NAME, BUILTIN_TYPE, FUNCTION_TYPE, AVAIL) \ ++ { \ ++ CODE_FOR_loongarch_##INSN, "__builtin_loongarch_" NAME, \ ++ BUILTIN_TYPE, FUNCTION_TYPE, \ ++ loongarch_builtin_avail_##AVAIL \ ++ } ++ ++/* Define __builtin_loongarch_, which is a LARCH_BUILTIN_DIRECT function ++ mapped to instruction CODE_FOR_loongarch_, FUNCTION_TYPE and AVAIL ++ are as for LARCH_BUILTIN. */ ++#define DIRECT_BUILTIN(INSN, FUNCTION_TYPE, AVAIL) \ ++ LARCH_BUILTIN (INSN, #INSN, LARCH_BUILTIN_DIRECT, FUNCTION_TYPE, AVAIL) ++ ++/* Define __builtin_loongarch_, which is a LARCH_BUILTIN_DIRECT_NO_TARGET ++ function mapped to instruction CODE_FOR_loongarch_, FUNCTION_TYPE ++ and AVAIL are as for LARCH_BUILTIN. */ ++#define DIRECT_NO_TARGET_BUILTIN(INSN, FUNCTION_TYPE, AVAIL) \ ++ LARCH_BUILTIN (INSN, #INSN, LARCH_BUILTIN_DIRECT_NO_TARGET, \ ++ FUNCTION_TYPE, AVAIL) ++ ++static const struct loongarch_builtin_description loongarch_builtins[] = { ++#define LARCH_MOVFCSR2GR 0 ++ DIRECT_BUILTIN (movfcsr2gr, LARCH_USI_FTYPE_UQI, hard_float), ++#define LARCH_MOVGR2FCSR 1 ++ DIRECT_NO_TARGET_BUILTIN (movgr2fcsr, LARCH_VOID_FTYPE_UQI_USI, hard_float), ++ ++ DIRECT_NO_TARGET_BUILTIN (cacop_w, LARCH_VOID_FTYPE_USI_USI_SI, default), ++ DIRECT_NO_TARGET_BUILTIN (cacop_d, LARCH_VOID_FTYPE_USI_UDI_SI, default), ++ DIRECT_NO_TARGET_BUILTIN (dbar, LARCH_VOID_FTYPE_USI, default), ++ DIRECT_NO_TARGET_BUILTIN (ibar, LARCH_VOID_FTYPE_USI, default), ++ ++ DIRECT_BUILTIN (lddir_d, LARCH_DI_FTYPE_DI_UQI, default), ++ DIRECT_BUILTIN (lddir_w, LARCH_SI_FTYPE_SI_UQI, default), ++ DIRECT_NO_TARGET_BUILTIN (ldpte_d, LARCH_VOID_FTYPE_DI_UQI, default), ++ DIRECT_NO_TARGET_BUILTIN (ldpte_w, LARCH_VOID_FTYPE_SI_UQI, default), ++ ++ /* CRC Instrinsic */ ++ ++ DIRECT_BUILTIN (crc_w_b_w, LARCH_SI_FTYPE_QI_SI, default), ++ DIRECT_BUILTIN (crc_w_h_w, LARCH_SI_FTYPE_HI_SI, default), ++ DIRECT_BUILTIN (crc_w_w_w, LARCH_SI_FTYPE_SI_SI, default), ++ DIRECT_BUILTIN (crc_w_d_w, LARCH_SI_FTYPE_DI_SI, default), ++ DIRECT_BUILTIN (crcc_w_b_w, LARCH_SI_FTYPE_QI_SI, default), ++ DIRECT_BUILTIN (crcc_w_h_w, LARCH_SI_FTYPE_HI_SI, default), ++ DIRECT_BUILTIN (crcc_w_w_w, LARCH_SI_FTYPE_SI_SI, default), ++ DIRECT_BUILTIN (crcc_w_d_w, LARCH_SI_FTYPE_DI_SI, default), ++ ++ DIRECT_BUILTIN (csrrd_w, LARCH_USI_FTYPE_USI, default), ++ DIRECT_BUILTIN (csrrd_d, LARCH_UDI_FTYPE_USI, default), ++ DIRECT_BUILTIN (csrwr_w, LARCH_USI_FTYPE_USI_USI, default), ++ DIRECT_BUILTIN (csrwr_d, LARCH_UDI_FTYPE_UDI_USI, default), ++ DIRECT_BUILTIN (csrxchg_w, LARCH_USI_FTYPE_USI_USI_USI, default), ++ DIRECT_BUILTIN (csrxchg_d, LARCH_UDI_FTYPE_UDI_UDI_USI, default), ++ DIRECT_BUILTIN (iocsrrd_b, LARCH_UQI_FTYPE_USI, default), ++ DIRECT_BUILTIN (iocsrrd_h, LARCH_UHI_FTYPE_USI, default), ++ DIRECT_BUILTIN (iocsrrd_w, LARCH_USI_FTYPE_USI, default), ++ DIRECT_BUILTIN (iocsrrd_d, LARCH_UDI_FTYPE_USI, default), ++ DIRECT_NO_TARGET_BUILTIN (iocsrwr_b, LARCH_VOID_FTYPE_UQI_USI, default), ++ DIRECT_NO_TARGET_BUILTIN (iocsrwr_h, LARCH_VOID_FTYPE_UHI_USI, default), ++ DIRECT_NO_TARGET_BUILTIN (iocsrwr_w, LARCH_VOID_FTYPE_USI_USI, default), ++ DIRECT_NO_TARGET_BUILTIN (iocsrwr_d, LARCH_VOID_FTYPE_UDI_USI, default), ++ ++ DIRECT_BUILTIN (cpucfg, LARCH_USI_FTYPE_USI, default), ++ DIRECT_NO_TARGET_BUILTIN (asrtle_d, LARCH_VOID_FTYPE_DI_DI, default), ++ DIRECT_NO_TARGET_BUILTIN (asrtgt_d, LARCH_VOID_FTYPE_DI_DI, default), ++ DIRECT_NO_TARGET_BUILTIN (syscall, LARCH_VOID_FTYPE_USI, default), ++ DIRECT_NO_TARGET_BUILTIN (break, LARCH_VOID_FTYPE_USI, default), ++}; ++ ++/* Index I is the function declaration for loongarch_builtins[I], or null if ++ the function isn't defined on this target. */ ++static GTY (()) tree loongarch_builtin_decls[ARRAY_SIZE (loongarch_builtins)]; ++/* Get the index I of the function declaration for loongarch_builtin_decls[I] ++ using the instruction code or return null if not defined for the target. */ ++static GTY (()) int loongarch_get_builtin_decl_index[NUM_INSN_CODES]; ++ ++/* Source-level argument types. */ ++#define LARCH_ATYPE_VOID void_type_node ++#define LARCH_ATYPE_INT integer_type_node ++#define LARCH_ATYPE_POINTER ptr_type_node ++ ++/* Standard mode-based argument types. */ ++#define LARCH_ATYPE_QI intQI_type_node ++#define LARCH_ATYPE_UQI unsigned_intQI_type_node ++#define LARCH_ATYPE_HI intHI_type_node ++#define LARCH_ATYPE_UHI unsigned_intHI_type_node ++#define LARCH_ATYPE_SI intSI_type_node ++#define LARCH_ATYPE_USI unsigned_intSI_type_node ++#define LARCH_ATYPE_DI intDI_type_node ++#define LARCH_ATYPE_UDI unsigned_intDI_type_node ++#define LARCH_ATYPE_SF float_type_node ++#define LARCH_ATYPE_DF double_type_node ++ ++/* LARCH_FTYPE_ATYPESN takes N LARCH_FTYPES-like type codes and lists ++ their associated LARCH_ATYPEs. */ ++#define LARCH_FTYPE_ATYPES1(A, B) LARCH_ATYPE_##A, LARCH_ATYPE_##B ++ ++#define LARCH_FTYPE_ATYPES2(A, B, C) \ ++ LARCH_ATYPE_##A, LARCH_ATYPE_##B, LARCH_ATYPE_##C ++ ++#define LARCH_FTYPE_ATYPES3(A, B, C, D) \ ++ LARCH_ATYPE_##A, LARCH_ATYPE_##B, LARCH_ATYPE_##C, LARCH_ATYPE_##D ++ ++#define LARCH_FTYPE_ATYPES4(A, B, C, D, E) \ ++ LARCH_ATYPE_##A, LARCH_ATYPE_##B, LARCH_ATYPE_##C, LARCH_ATYPE_##D, \ ++ LARCH_ATYPE_##E ++ ++/* Return the function type associated with function prototype TYPE. */ ++ ++static tree ++loongarch_build_function_type (enum loongarch_function_type type) ++{ ++ static tree types[(int) LARCH_MAX_FTYPE_MAX]; ++ ++ if (types[(int) type] == NULL_TREE) ++ switch (type) ++ { ++#define DEF_LARCH_FTYPE(NUM, ARGS) \ ++ case LARCH_FTYPE_NAME##NUM ARGS: \ ++ types[(int) type] \ ++ = build_function_type_list (LARCH_FTYPE_ATYPES##NUM ARGS, NULL_TREE); \ ++ break; ++#include "config/loongarch/loongarch-ftypes.def" ++#undef DEF_LARCH_FTYPE ++ default: ++ gcc_unreachable (); ++ } ++ ++ return types[(int) type]; ++} ++ ++/* Implement TARGET_INIT_BUILTINS. */ ++ ++void ++loongarch_init_builtins (void) ++{ ++ const struct loongarch_builtin_description *d; ++ unsigned int i; ++ tree type; ++ ++ /* Iterate through all of the bdesc arrays, initializing all of the ++ builtin functions. */ ++ for (i = 0; i < ARRAY_SIZE (loongarch_builtins); i++) ++ { ++ d = &loongarch_builtins[i]; ++ if (d->avail ()) ++ { ++ type = loongarch_build_function_type (d->function_type); ++ loongarch_builtin_decls[i] ++ = add_builtin_function (d->name, type, i, BUILT_IN_MD, NULL, ++ NULL); ++ loongarch_get_builtin_decl_index[d->icode] = i; ++ } ++ } ++} ++ ++/* Implement TARGET_BUILTIN_DECL. */ ++ ++tree ++loongarch_builtin_decl (unsigned int code, bool initialize_p ATTRIBUTE_UNUSED) ++{ ++ if (code >= ARRAY_SIZE (loongarch_builtins)) ++ return error_mark_node; ++ return loongarch_builtin_decls[code]; ++} ++ ++/* Take argument ARGNO from EXP's argument list and convert it into ++ an expand operand. Store the operand in *OP. */ ++ ++static void ++loongarch_prepare_builtin_arg (struct expand_operand *op, tree exp, ++ unsigned int argno) ++{ ++ tree arg; ++ rtx value; ++ ++ arg = CALL_EXPR_ARG (exp, argno); ++ value = expand_normal (arg); ++ create_input_operand (op, value, TYPE_MODE (TREE_TYPE (arg))); ++} ++ ++/* Expand instruction ICODE as part of a built-in function sequence. ++ Use the first NOPS elements of OPS as the instruction's operands. ++ HAS_TARGET_P is true if operand 0 is a target; it is false if the ++ instruction has no target. ++ ++ Return the target rtx if HAS_TARGET_P, otherwise return const0_rtx. */ ++ ++static rtx ++loongarch_expand_builtin_insn (enum insn_code icode, unsigned int nops, ++ struct expand_operand *ops, bool has_target_p) ++{ ++ if (!maybe_expand_insn (icode, nops, ops)) ++ { ++ error ("invalid argument to built-in function"); ++ return has_target_p ? gen_reg_rtx (ops[0].mode) : const0_rtx; ++ } ++ return has_target_p ? ops[0].value : const0_rtx; ++} ++ ++/* Expand a LARCH_BUILTIN_DIRECT or LARCH_BUILTIN_DIRECT_NO_TARGET function; ++ HAS_TARGET_P says which. EXP is the CALL_EXPR that calls the function ++ and ICODE is the code of the associated .md pattern. TARGET, if nonnull, ++ suggests a good place to put the result. */ ++ ++static rtx ++loongarch_expand_builtin_direct (enum insn_code icode, rtx target, tree exp, ++ bool has_target_p) ++{ ++ struct expand_operand ops[MAX_RECOG_OPERANDS]; ++ int opno, argno; ++ ++ /* Map any target to operand 0. */ ++ opno = 0; ++ if (has_target_p) ++ create_output_operand (&ops[opno++], target, TYPE_MODE (TREE_TYPE (exp))); ++ ++ /* Map the arguments to the other operands. */ ++ gcc_assert (opno + call_expr_nargs (exp) ++ == insn_data[icode].n_generator_args); ++ for (argno = 0; argno < call_expr_nargs (exp); argno++) ++ loongarch_prepare_builtin_arg (&ops[opno++], exp, argno); ++ ++ return loongarch_expand_builtin_insn (icode, opno, ops, has_target_p); ++} ++ ++/* Implement TARGET_EXPAND_BUILTIN. */ ++ ++rtx ++loongarch_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, ++ machine_mode mode ATTRIBUTE_UNUSED, ++ int ignore ATTRIBUTE_UNUSED) ++{ ++ tree fndecl; ++ unsigned int fcode, avail; ++ const struct loongarch_builtin_description *d; ++ ++ fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); ++ fcode = DECL_MD_FUNCTION_CODE (fndecl); ++ gcc_assert (fcode < ARRAY_SIZE (loongarch_builtins)); ++ d = &loongarch_builtins[fcode]; ++ avail = d->avail (); ++ gcc_assert (avail != 0); ++ switch (d->builtin_type) ++ { ++ case LARCH_BUILTIN_DIRECT: ++ return loongarch_expand_builtin_direct (d->icode, target, exp, true); ++ ++ case LARCH_BUILTIN_DIRECT_NO_TARGET: ++ return loongarch_expand_builtin_direct (d->icode, target, exp, false); ++ } ++ gcc_unreachable (); ++} ++ ++/* Implement TARGET_ATOMIC_ASSIGN_EXPAND_FENV. */ ++ ++void ++loongarch_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update) ++{ ++ if (!TARGET_HARD_FLOAT_ABI) ++ return; ++ tree exceptions_var = create_tmp_var_raw (LARCH_ATYPE_USI); ++ tree fcsr_orig_var = create_tmp_var_raw (LARCH_ATYPE_USI); ++ tree fcsr_mod_var = create_tmp_var_raw (LARCH_ATYPE_USI); ++ tree const0 = build_int_cst (LARCH_ATYPE_UQI, 0); ++ tree get_fcsr = loongarch_builtin_decls[LARCH_MOVFCSR2GR]; ++ tree set_fcsr = loongarch_builtin_decls[LARCH_MOVGR2FCSR]; ++ tree get_fcsr_hold_call = build_call_expr (get_fcsr, 1, const0); ++ tree hold_assign_orig = build4 (TARGET_EXPR, LARCH_ATYPE_USI, ++ fcsr_orig_var, get_fcsr_hold_call, ++ NULL, NULL); ++ tree hold_mod_val = build2 (BIT_AND_EXPR, LARCH_ATYPE_USI, fcsr_orig_var, ++ build_int_cst (LARCH_ATYPE_USI, 0xffe0ffe0)); ++ tree hold_assign_mod = build4 (TARGET_EXPR, LARCH_ATYPE_USI, ++ fcsr_mod_var, hold_mod_val, NULL, NULL); ++ tree set_fcsr_hold_call = build_call_expr (set_fcsr, 2, const0, ++ fcsr_mod_var); ++ tree hold_all = build2 (COMPOUND_EXPR, LARCH_ATYPE_USI, hold_assign_orig, ++ hold_assign_mod); ++ *hold = build2 (COMPOUND_EXPR, void_type_node, hold_all, set_fcsr_hold_call); ++ ++ *clear = build_call_expr (set_fcsr, 2, const0, fcsr_mod_var); ++ ++ tree get_fcsr_update_call = build_call_expr (get_fcsr, 1, const0); ++ *update = build4 (TARGET_EXPR, LARCH_ATYPE_USI, exceptions_var, ++ get_fcsr_update_call, NULL, NULL); ++ tree set_fcsr_update_call = build_call_expr (set_fcsr, 2, const0, ++ fcsr_orig_var); ++ *update = build2 (COMPOUND_EXPR, void_type_node, *update, ++ set_fcsr_update_call); ++ tree atomic_feraiseexcept ++ = builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT); ++ tree int_exceptions_var = fold_convert (integer_type_node, exceptions_var); ++ tree atomic_feraiseexcept_call = build_call_expr (atomic_feraiseexcept, 1, ++ int_exceptions_var); ++ *update = build2 (COMPOUND_EXPR, void_type_node, *update, ++ atomic_feraiseexcept_call); ++} ++ ++/* Implement TARGET_BUILTIN_VA_LIST. */ ++ ++tree ++loongarch_build_builtin_va_list (void) ++{ ++ return ptr_type_node; ++} +diff --git a/gcc/config/loongarch/loongarch-c.c b/gcc/config/loongarch/loongarch-c.c +new file mode 100644 +index 000000000..d6e3e19f0 +--- /dev/null ++++ b/gcc/config/loongarch/loongarch-c.c +@@ -0,0 +1,109 @@ ++/* LoongArch-specific code for C family languages. ++ Copyright (C) 2021-2022 Free Software Foundation, Inc. ++ Contributed by Loongson Ltd. ++ ++This file is part of GCC. ++ ++GCC is free software; you can redistribute it and/or modify ++it under the terms of the GNU General Public License as published by ++the Free Software Foundation; either version 3, or (at your option) ++any later version. ++ ++GCC 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 GCC; see the file COPYING3. If not see ++. */ ++ ++#define IN_TARGET_CODE 1 ++ ++#include "config.h" ++#include "system.h" ++#include "coretypes.h" ++#include "tm.h" ++#include "c-family/c-common.h" ++#include "cpplib.h" ++ ++#define preprocessing_asm_p() (cpp_get_options (pfile)->lang == CLK_ASM) ++#define builtin_define(TXT) cpp_define (pfile, TXT) ++#define builtin_assert(TXT) cpp_assert (pfile, TXT) ++ ++/* Define preprocessor macros for the -march and -mtune options. ++ PREFIX is either _LOONGARCH_ARCH or _LOONGARCH_TUNE, INFO is ++ the selected processor. If INFO's canonical name is "foo", ++ define PREFIX to be "foo", and define an additional macro ++ PREFIX_FOO. */ ++#define LARCH_CPP_SET_PROCESSOR(PREFIX, CPU_TYPE) \ ++ do \ ++ { \ ++ char *macro, *p; \ ++ int cpu_type = (CPU_TYPE); \ ++ \ ++ macro = concat ((PREFIX), "_", \ ++ loongarch_cpu_strings[cpu_type], NULL); \ ++ for (p = macro; *p != 0; p++) \ ++ *p = TOUPPER (*p); \ ++ \ ++ builtin_define (macro); \ ++ builtin_define_with_value ((PREFIX), \ ++ loongarch_cpu_strings[cpu_type], 1); \ ++ free (macro); \ ++ } \ ++ while (0) ++ ++void ++loongarch_cpu_cpp_builtins (cpp_reader *pfile) ++{ ++ builtin_assert ("machine=loongarch"); ++ builtin_assert ("cpu=loongarch"); ++ builtin_define ("__loongarch__"); ++ ++ LARCH_CPP_SET_PROCESSOR ("_LOONGARCH_ARCH", LARCH_ACTUAL_ARCH); ++ LARCH_CPP_SET_PROCESSOR ("_LOONGARCH_TUNE", LARCH_ACTUAL_TUNE); ++ ++ /* Base architecture / ABI. */ ++ if (TARGET_64BIT) ++ { ++ builtin_define ("__loongarch_grlen=64"); ++ builtin_define ("__loongarch64"); ++ } ++ ++ if (TARGET_ABI_LP64) ++ { ++ builtin_define ("_ABILP64=3"); ++ builtin_define ("_LOONGARCH_SIM=_ABILP64"); ++ builtin_define ("__loongarch_lp64"); ++ } ++ ++ /* These defines reflect the ABI in use, not whether the ++ FPU is directly accessible. */ ++ if (TARGET_DOUBLE_FLOAT_ABI) ++ builtin_define ("__loongarch_double_float=1"); ++ else if (TARGET_SINGLE_FLOAT_ABI) ++ builtin_define ("__loongarch_single_float=1"); ++ ++ if (TARGET_DOUBLE_FLOAT_ABI || TARGET_SINGLE_FLOAT_ABI) ++ builtin_define ("__loongarch_hard_float=1"); ++ else ++ builtin_define ("__loongarch_soft_float=1"); ++ ++ ++ /* ISA Extensions. */ ++ if (TARGET_DOUBLE_FLOAT) ++ builtin_define ("__loongarch_frlen=64"); ++ else if (TARGET_SINGLE_FLOAT) ++ builtin_define ("__loongarch_frlen=32"); ++ else ++ builtin_define ("__loongarch_frlen=0"); ++ ++ /* Native Data Sizes. */ ++ builtin_define_with_int_value ("_LOONGARCH_SZINT", INT_TYPE_SIZE); ++ builtin_define_with_int_value ("_LOONGARCH_SZLONG", LONG_TYPE_SIZE); ++ builtin_define_with_int_value ("_LOONGARCH_SZPTR", POINTER_SIZE); ++ builtin_define_with_int_value ("_LOONGARCH_FPSET", 32); ++ builtin_define_with_int_value ("_LOONGARCH_SPFPSET", 32); ++ ++} +diff --git a/gcc/config/loongarch/loongarch-cpu.c b/gcc/config/loongarch/loongarch-cpu.c +new file mode 100644 +index 000000000..a886dd932 +--- /dev/null ++++ b/gcc/config/loongarch/loongarch-cpu.c +@@ -0,0 +1,206 @@ ++/* Definitions for LoongArch CPU properties. ++ Copyright (C) 2021-2022 Free Software Foundation, Inc. ++ Contributed by Loongson Ltd. ++ ++This file is part of GCC. ++ ++GCC is free software; you can redistribute it and/or modify ++it under the terms of the GNU General Public License as published by ++the Free Software Foundation; either version 3, or (at your option) ++any later version. ++ ++GCC 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 GCC; see the file COPYING3. If not see ++. */ ++ ++#define IN_TARGET_CODE 1 ++ ++#include "config.h" ++#include "system.h" ++#include "coretypes.h" ++#include "tm.h" ++#include "diagnostic-core.h" ++ ++#include "loongarch-opts.h" ++#include "loongarch-cpu.h" ++#include "loongarch-str.h" ++ ++/* Native CPU detection with "cpucfg" */ ++#define N_CPUCFG_WORDS 0x15 ++static uint32_t cpucfg_cache[N_CPUCFG_WORDS] = { 0 }; ++static const int cpucfg_useful_idx[] = {0, 1, 2, 16, 17, 18, 19}; ++ ++static uint32_t ++read_cpucfg_word (int wordno) ++{ ++ /* To make cross-compiler shut up. */ ++ (void) wordno; ++ uint32_t ret = 0; ++ ++ #ifdef __loongarch__ ++ __asm__ __volatile__ ("cpucfg %0,%1\n\t" ++ :"=r"(ret) ++ :"r"(wordno) ++ :); ++ #endif ++ ++ return ret; ++} ++ ++void ++cache_cpucfg (void) ++{ ++ for (unsigned int i = 0; i < sizeof (cpucfg_useful_idx) / sizeof (int); i++) ++ { ++ cpucfg_cache[cpucfg_useful_idx[i]] ++ = read_cpucfg_word (cpucfg_useful_idx[i]); ++ } ++} ++ ++uint32_t ++get_native_prid (void) ++{ ++ /* Fill loongarch_cpu_default_config[CPU_NATIVE] with cpucfg data, ++ see "Loongson Architecture Reference Manual" ++ (Volume 1, Section 2.2.10.5) */ ++ return cpucfg_cache[0]; ++} ++ ++const char* ++get_native_prid_str (void) ++{ ++ static char prid_str[9]; ++ sprintf (prid_str, "%08x", cpucfg_cache[0]); ++ return (const char*) prid_str; ++} ++ ++/* Fill property tables for CPU_NATIVE. */ ++unsigned int ++fill_native_cpu_config (int p_arch_native, int p_tune_native) ++{ ++ int ret_cpu_type; ++ ++ /* Nothing needs to be done unless "-march/tune=native" ++ is given or implied. */ ++ if (!(p_arch_native || p_tune_native)) ++ return CPU_NATIVE; ++ ++ /* Fill cpucfg_cache with the "cpucfg" instruction. */ ++ cache_cpucfg (); ++ ++ ++ /* Fill: loongarch_cpu_default_isa[CPU_NATIVE].base ++ With: base architecture (ARCH) ++ At: cpucfg_words[1][1:0] */ ++ ++ #define NATIVE_BASE_ISA (loongarch_cpu_default_isa[CPU_NATIVE].base) ++ switch (cpucfg_cache[1] & 0x3) ++ { ++ case 0x02: ++ NATIVE_BASE_ISA = ISA_BASE_LA64V100; ++ break; ++ ++ default: ++ if (p_arch_native) ++ fatal_error (UNKNOWN_LOCATION, ++ "unknown base architecture %<0x%x%>, %qs failed", ++ (unsigned int) (cpucfg_cache[1] & 0x3), ++ "-m" OPTSTR_ARCH "=" STR_CPU_NATIVE); ++ } ++ ++ /* Fill: loongarch_cpu_default_isa[CPU_NATIVE].fpu ++ With: FPU type (FP, FP_SP, FP_DP) ++ At: cpucfg_words[2][2:0] */ ++ ++ #define NATIVE_FPU (loongarch_cpu_default_isa[CPU_NATIVE].fpu) ++ switch (cpucfg_cache[2] & 0x7) ++ { ++ case 0x07: ++ NATIVE_FPU = ISA_EXT_FPU64; ++ break; ++ ++ case 0x03: ++ NATIVE_FPU = ISA_EXT_FPU32; ++ break; ++ ++ case 0x00: ++ NATIVE_FPU = ISA_EXT_NOFPU; ++ break; ++ ++ default: ++ if (p_arch_native) ++ fatal_error (UNKNOWN_LOCATION, ++ "unknown FPU type %<0x%x%>, %qs failed", ++ (unsigned int) (cpucfg_cache[2] & 0x7), ++ "-m" OPTSTR_ARCH "=" STR_CPU_NATIVE); ++ } ++ ++ /* Fill: loongarch_cpu_cache[CPU_NATIVE] ++ With: cache size info ++ At: cpucfg_words[16:20][31:0] */ ++ ++ int l1d_present = 0, l1u_present = 0; ++ int l2d_present = 0; ++ uint32_t l1_szword, l2_szword; ++ ++ l1u_present |= cpucfg_cache[16] & 3; /* bit[1:0]: unified l1 cache */ ++ l1d_present |= cpucfg_cache[16] & 4; /* bit[2:2]: l1 dcache */ ++ l1_szword = l1d_present ? 18 : (l1u_present ? 17 : 0); ++ l1_szword = l1_szword ? cpucfg_cache[l1_szword]: 0; ++ ++ l2d_present |= cpucfg_cache[16] & 24; /* bit[4:3]: unified l2 cache */ ++ l2d_present |= cpucfg_cache[16] & 128; /* bit[7:7]: l2 dcache */ ++ l2_szword = l2d_present ? cpucfg_cache[19]: 0; ++ ++ loongarch_cpu_cache[CPU_NATIVE].l1d_line_size ++ = 1 << ((l1_szword & 0x7f000000) >> 24); /* bit[30:24]: log2(linesize) */ ++ ++ loongarch_cpu_cache[CPU_NATIVE].l1d_size ++ = (1 << ((l1_szword & 0x00ff0000) >> 16)) /* bit[23:16]: log2(idx) */ ++ * ((l1_szword & 0x0000ffff) + 1) /* bit[15:0]: sets - 1 */ ++ * (1 << ((l1_szword & 0x7f000000) >> 24)) /* bit[30:24]: log2(linesize) */ ++ >> 10; /* in kilobytes */ ++ ++ loongarch_cpu_cache[CPU_NATIVE].l2d_size ++ = (1 << ((l2_szword & 0x00ff0000) >> 16)) /* bit[23:16]: log2(idx) */ ++ * ((l2_szword & 0x0000ffff) + 1) /* bit[15:0]: sets - 1 */ ++ * (1 << ((l2_szword & 0x7f000000) >> 24)) /* bit[30:24]: log2(linesize) */ ++ >> 10; /* in kilobytes */ ++ ++ /* Fill: ret_cpu_type ++ With: processor ID (PRID) ++ At: cpucfg_words[0][31:0] */ ++ ++ switch (cpucfg_cache[0] & 0x00ffff00) ++ { ++ case 0x0014c000: /* LA464 */ ++ ret_cpu_type = CPU_LA464; ++ break; ++ ++ default: ++ /* Unknown PRID. This is generally harmless as long as ++ the properties above can be obtained via "cpucfg". */ ++ if (p_tune_native) ++ inform (UNKNOWN_LOCATION, "unknown processor ID %<0x%x%>, " ++ "some tuning parameters will fall back to default", ++ cpucfg_cache[0]); ++ break; ++ } ++ ++ /* Properties that cannot be looked up directly using cpucfg. */ ++ loongarch_cpu_issue_rate[CPU_NATIVE] ++ = loongarch_cpu_issue_rate[ret_cpu_type]; ++ ++ loongarch_cpu_multipass_dfa_lookahead[CPU_NATIVE] ++ = loongarch_cpu_multipass_dfa_lookahead[ret_cpu_type]; ++ ++ loongarch_cpu_rtx_cost_data[CPU_NATIVE] ++ = loongarch_cpu_rtx_cost_data[ret_cpu_type]; ++ ++ return ret_cpu_type; ++} +diff --git a/gcc/config/loongarch/loongarch-cpu.h b/gcc/config/loongarch/loongarch-cpu.h +new file mode 100644 +index 000000000..93d656f70 +--- /dev/null ++++ b/gcc/config/loongarch/loongarch-cpu.h +@@ -0,0 +1,30 @@ ++/* Definitions for loongarch native cpu property detection routines. ++ Copyright (C) 2020-2021 Free Software Foundation, Inc. ++ ++This file is part of GCC. ++ ++GCC is free software; you can redistribute it and/or modify ++it under the terms of the GNU General Public License as published by ++the Free Software Foundation; either version 3, or (at your option) ++any later version. ++ ++GCC 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 GCC; see the file COPYING3. If not see ++. */ ++ ++#ifndef LOONGARCH_CPU_H ++#define LOONGARCH_CPU_H ++ ++#include "system.h" ++ ++void cache_cpucfg (void); ++unsigned int fill_native_cpu_config (int p_arch_native, int p_tune_native); ++uint32_t get_native_prid (void); ++const char* get_native_prid_str (void); ++ ++#endif /* LOONGARCH_CPU_H */ +diff --git a/gcc/config/loongarch/loongarch-def.c b/gcc/config/loongarch/loongarch-def.c +new file mode 100644 +index 000000000..cbf995d81 +--- /dev/null ++++ b/gcc/config/loongarch/loongarch-def.c +@@ -0,0 +1,180 @@ ++/* LoongArch static properties. ++ Copyright (C) 2021-2022 Free Software Foundation, Inc. ++ Contributed by Loongson Ltd. ++ ++This file is part of GCC. ++ ++GCC is free software; you can redistribute it and/or modify ++it under the terms of the GNU General Public License as published by ++the Free Software Foundation; either version 3, or (at your option) ++any later version. ++ ++GCC 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 GCC; see the file COPYING3. If not see ++. */ ++ ++#include "loongarch-def.h" ++#include "loongarch-str.h" ++ ++/* Default RTX cost initializer. */ ++#define COSTS_N_INSNS(N) ((N) * 4) ++#define DEFAULT_COSTS \ ++ .fp_add = COSTS_N_INSNS (1), \ ++ .fp_mult_sf = COSTS_N_INSNS (2), \ ++ .fp_mult_df = COSTS_N_INSNS (4), \ ++ .fp_div_sf = COSTS_N_INSNS (6), \ ++ .fp_div_df = COSTS_N_INSNS (8), \ ++ .int_mult_si = COSTS_N_INSNS (1), \ ++ .int_mult_di = COSTS_N_INSNS (1), \ ++ .int_div_si = COSTS_N_INSNS (4), \ ++ .int_div_di = COSTS_N_INSNS (6), \ ++ .branch_cost = 2, \ ++ .memory_latency = 4 ++ ++/* CPU property tables. */ ++const char* ++loongarch_cpu_strings[N_TUNE_TYPES] = { ++ [CPU_NATIVE] = STR_CPU_NATIVE, ++ [CPU_LOONGARCH64] = STR_CPU_LOONGARCH64, ++ [CPU_LA464] = STR_CPU_LA464, ++}; ++ ++struct loongarch_isa ++loongarch_cpu_default_isa[N_ARCH_TYPES] = { ++ [CPU_LOONGARCH64] = { ++ .base = ISA_BASE_LA64V100, ++ .fpu = ISA_EXT_FPU64, ++ }, ++ [CPU_LA464] = { ++ .base = ISA_BASE_LA64V100, ++ .fpu = ISA_EXT_FPU64, ++ }, ++}; ++ ++struct loongarch_cache ++loongarch_cpu_cache[N_TUNE_TYPES] = { ++ [CPU_LOONGARCH64] = { ++ .l1d_line_size = 64, ++ .l1d_size = 64, ++ .l2d_size = 256, ++ }, ++ [CPU_LA464] = { ++ .l1d_line_size = 64, ++ .l1d_size = 64, ++ .l2d_size = 256, ++ }, ++}; ++ ++/* The following properties cannot be looked up directly using "cpucfg". ++ So it is necessary to provide a default value for "unknown native" ++ tune targets (i.e. -mtune=native while PRID does not correspond to ++ any known "-mtune" type). */ ++ ++struct loongarch_rtx_cost_data ++loongarch_cpu_rtx_cost_data[N_TUNE_TYPES] = { ++ [CPU_NATIVE] = { ++ DEFAULT_COSTS ++ }, ++ [CPU_LOONGARCH64] = { ++ DEFAULT_COSTS ++ }, ++ [CPU_LA464] = { ++ DEFAULT_COSTS ++ }, ++}; ++ ++/* RTX costs to use when optimizing for size. */ ++extern const struct loongarch_rtx_cost_data ++loongarch_rtx_cost_optimize_size = { ++ .fp_add = 4, ++ .fp_mult_sf = 4, ++ .fp_mult_df = 4, ++ .fp_div_sf = 4, ++ .fp_div_df = 4, ++ .int_mult_si = 4, ++ .int_mult_di = 4, ++ .int_div_si = 4, ++ .int_div_di = 4, ++ .branch_cost = 2, ++ .memory_latency = 4, ++}; ++ ++int ++loongarch_cpu_issue_rate[N_TUNE_TYPES] = { ++ [CPU_NATIVE] = 4, ++ [CPU_LOONGARCH64] = 4, ++ [CPU_LA464] = 4, ++}; ++ ++int ++loongarch_cpu_multipass_dfa_lookahead[N_TUNE_TYPES] = { ++ [CPU_NATIVE] = 4, ++ [CPU_LOONGARCH64] = 4, ++ [CPU_LA464] = 4, ++}; ++ ++/* Wiring string definitions from loongarch-str.h to global arrays ++ with standard index values from loongarch-opts.h, so we can ++ print config-related messages and do ABI self-spec filtering ++ from the driver in a self-consistent manner. */ ++ ++const char* ++loongarch_isa_base_strings[N_ISA_BASE_TYPES] = { ++ [ISA_BASE_LA64V100] = STR_ISA_BASE_LA64V100, ++}; ++ ++const char* ++loongarch_isa_ext_strings[N_ISA_EXT_TYPES] = { ++ [ISA_EXT_FPU64] = STR_ISA_EXT_FPU64, ++ [ISA_EXT_FPU32] = STR_ISA_EXT_FPU32, ++ [ISA_EXT_NOFPU] = STR_ISA_EXT_NOFPU, ++}; ++ ++const char* ++loongarch_abi_base_strings[N_ABI_BASE_TYPES] = { ++ [ABI_BASE_LP64D] = STR_ABI_BASE_LP64D, ++ [ABI_BASE_LP64F] = STR_ABI_BASE_LP64F, ++ [ABI_BASE_LP64S] = STR_ABI_BASE_LP64S, ++}; ++ ++const char* ++loongarch_abi_ext_strings[N_ABI_EXT_TYPES] = { ++ [ABI_EXT_BASE] = STR_ABI_EXT_BASE, ++}; ++ ++const char* ++loongarch_cmodel_strings[] = { ++ [CMODEL_NORMAL] = STR_CMODEL_NORMAL, ++ [CMODEL_TINY] = STR_CMODEL_TINY, ++ [CMODEL_TINY_STATIC] = STR_CMODEL_TS, ++ [CMODEL_MEDIUM] = STR_CMODEL_MEDIUM, ++ [CMODEL_LARGE] = STR_CMODEL_LARGE, ++ [CMODEL_EXTREME] = STR_CMODEL_EXTREME, ++}; ++ ++const char* ++loongarch_switch_strings[] = { ++ [SW_SOFT_FLOAT] = OPTSTR_SOFT_FLOAT, ++ [SW_SINGLE_FLOAT] = OPTSTR_SINGLE_FLOAT, ++ [SW_DOUBLE_FLOAT] = OPTSTR_DOUBLE_FLOAT, ++}; ++ ++ ++/* ABI-related definitions. */ ++const struct loongarch_isa ++abi_minimal_isa[N_ABI_BASE_TYPES][N_ABI_EXT_TYPES] = { ++ [ABI_BASE_LP64D] = { ++ [ABI_EXT_BASE] = {.base = ISA_BASE_LA64V100, .fpu = ISA_EXT_FPU64}, ++ }, ++ [ABI_BASE_LP64F] = { ++ [ABI_EXT_BASE] = {.base = ISA_BASE_LA64V100, .fpu = ISA_EXT_FPU32}, ++ }, ++ [ABI_BASE_LP64S] = { ++ [ABI_EXT_BASE] = {.base = ISA_BASE_LA64V100, .fpu = ISA_EXT_NOFPU}, ++ }, ++}; +diff --git a/gcc/config/loongarch/loongarch-def.h b/gcc/config/loongarch/loongarch-def.h +new file mode 100644 +index 000000000..b5985f070 +--- /dev/null ++++ b/gcc/config/loongarch/loongarch-def.h +@@ -0,0 +1,152 @@ ++/* LoongArch definitions. ++ Copyright (C) 2021-2022 Free Software Foundation, Inc. ++ Contributed by Loongson Ltd. ++ ++This file is part of GCC. ++ ++GCC is free software; you can redistribute it and/or modify ++it under the terms of the GNU General Public License as published by ++the Free Software Foundation; either version 3, or (at your option) ++any later version. ++ ++GCC 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 GCC; see the file COPYING3. If not see ++. */ ++ ++/* Definition of standard codes for: ++ - base architecture types (isa_base), ++ - ISA extensions (isa_ext), ++ - base ABI types (abi_base), ++ - ABI extension types (abi_ext). ++ ++ - code models (cmodel) ++ - other command-line switches (switch) ++ ++ These values are primarily used for implementing option handling ++ logic in "loongarch.opt", "loongarch-driver.c" and "loongarch-opt.c". ++ ++ As for the result of this option handling process, the following ++ scheme is adopted to represent the final configuration: ++ ++ - The target ABI is encoded with a tuple (abi_base, abi_ext) ++ using the code defined below. ++ ++ - The target ISA is encoded with a "struct loongarch_isa" defined ++ in loongarch-cpu.h. ++ ++ - The target microarchitecture is represented with a cpu model ++ index defined in loongarch-cpu.h. ++*/ ++ ++#ifndef LOONGARCH_DEF_H ++#define LOONGARCH_DEF_H ++ ++#include "loongarch-tune.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* enum isa_base */ ++extern const char* loongarch_isa_base_strings[]; ++#define ISA_BASE_LA64V100 0 ++#define N_ISA_BASE_TYPES 1 ++ ++/* enum isa_ext_* */ ++extern const char* loongarch_isa_ext_strings[]; ++#define ISA_EXT_NOFPU 0 ++#define ISA_EXT_FPU32 1 ++#define ISA_EXT_FPU64 2 ++#define N_ISA_EXT_FPU_TYPES 3 ++#define N_ISA_EXT_TYPES 3 ++ ++/* enum abi_base */ ++extern const char* loongarch_abi_base_strings[]; ++#define ABI_BASE_LP64D 0 ++#define ABI_BASE_LP64F 1 ++#define ABI_BASE_LP64S 2 ++#define N_ABI_BASE_TYPES 3 ++ ++/* enum abi_ext */ ++extern const char* loongarch_abi_ext_strings[]; ++#define ABI_EXT_BASE 0 ++#define N_ABI_EXT_TYPES 1 ++ ++/* enum cmodel */ ++extern const char* loongarch_cmodel_strings[]; ++#define CMODEL_NORMAL 0 ++#define CMODEL_TINY 1 ++#define CMODEL_TINY_STATIC 2 ++#define CMODEL_MEDIUM 3 ++#define CMODEL_LARGE 4 ++#define CMODEL_EXTREME 5 ++#define N_CMODEL_TYPES 6 ++ ++/* enum switches */ ++/* The "SW_" codes represent command-line switches (options that ++ accept no parameters). Definition for other switches that affects ++ the target ISA / ABI configuration will also be appended here ++ in the future. */ ++ ++extern const char* loongarch_switch_strings[]; ++#define SW_SOFT_FLOAT 0 ++#define SW_SINGLE_FLOAT 1 ++#define SW_DOUBLE_FLOAT 2 ++#define N_SWITCH_TYPES 3 ++ ++/* The common default value for variables whose assignments ++ are triggered by command-line options. */ ++ ++#define M_OPTION_NOT_SEEN -1 ++#define M_OPT_ABSENT(opt_enum) ((opt_enum) == M_OPTION_NOT_SEEN) ++ ++ ++/* Internal representation of the target. */ ++struct loongarch_isa ++{ ++ unsigned char base; /* ISA_BASE_ */ ++ unsigned char fpu; /* ISA_EXT_FPU_ */ ++}; ++ ++struct loongarch_abi ++{ ++ unsigned char base; /* ABI_BASE_ */ ++ unsigned char ext; /* ABI_EXT_ */ ++}; ++ ++struct loongarch_target ++{ ++ struct loongarch_isa isa; ++ struct loongarch_abi abi; ++ unsigned char cpu_arch; /* CPU_ */ ++ unsigned char cpu_tune; /* same */ ++ unsigned char cpu_native; /* same */ ++ unsigned char cmodel; /* CMODEL_ */ ++}; ++ ++/* CPU properties. */ ++/* index */ ++#define CPU_NATIVE 0 ++#define CPU_LOONGARCH64 1 ++#define CPU_LA464 2 ++#define N_ARCH_TYPES 3 ++#define N_TUNE_TYPES 3 ++ ++/* parallel tables. */ ++extern const char* loongarch_cpu_strings[]; ++extern struct loongarch_isa loongarch_cpu_default_isa[]; ++extern int loongarch_cpu_issue_rate[]; ++extern int loongarch_cpu_multipass_dfa_lookahead[]; ++ ++extern struct loongarch_cache loongarch_cpu_cache[]; ++extern struct loongarch_rtx_cost_data loongarch_cpu_rtx_cost_data[]; ++ ++#ifdef __cplusplus ++} ++#endif ++#endif /* LOONGARCH_DEF_H */ +diff --git a/gcc/config/loongarch/loongarch-driver.c b/gcc/config/loongarch/loongarch-driver.c +new file mode 100644 +index 000000000..0adcc923b +--- /dev/null ++++ b/gcc/config/loongarch/loongarch-driver.c +@@ -0,0 +1,187 @@ ++/* Subroutines for the gcc driver. ++ Copyright (C) 2021-2022 Free Software Foundation, Inc. ++ Contributed by Loongson Ltd. ++ ++This file is part of GCC. ++ ++GCC is free software; you can redistribute it and/or modify ++it under the terms of the GNU General Public License as published by ++the Free Software Foundation; either version 3, or (at your option) ++any later version. ++ ++GCC 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 GCC; see the file COPYING3. If not see ++. */ ++ ++#define IN_TARGET_CODE 1 ++ ++#include "config.h" ++#include "system.h" ++#include "coretypes.h" ++#include "tm.h" ++#include "obstack.h" ++#include "diagnostic-core.h" ++ ++#include "loongarch-opts.h" ++#include "loongarch-driver.h" ++ ++static int ++ opt_arch_driver = M_OPTION_NOT_SEEN, ++ opt_tune_driver = M_OPTION_NOT_SEEN, ++ opt_fpu_driver = M_OPTION_NOT_SEEN, ++ opt_abi_base_driver = M_OPTION_NOT_SEEN, ++ opt_abi_ext_driver = M_OPTION_NOT_SEEN, ++ opt_cmodel_driver = M_OPTION_NOT_SEEN; ++ ++int opt_switches = 0; ++ ++/* This flag is set to 1 if we believe that the user might be avoiding ++ linking (implicitly) against something from the startfile search paths. */ ++static int no_link = 0; ++ ++#define LARCH_DRIVER_SET_M_FLAG(OPTS_ARRAY, N_OPTS, FLAG, STR) \ ++ for (int i = 0; i < (N_OPTS); i++) \ ++ { \ ++ if ((OPTS_ARRAY)[i] != 0) \ ++ if (strcmp ((STR), (OPTS_ARRAY)[i]) == 0) \ ++ (FLAG) = i; \ ++ } ++ ++/* Use the public obstack from the gcc driver (defined in gcc.c). ++ This is for allocating space for the returned string. */ ++extern struct obstack opts_obstack; ++ ++#define APPEND_LTR(S) \ ++ obstack_grow (&opts_obstack, (const void*) (S), \ ++ sizeof ((S)) / sizeof (char) -1) ++ ++#define APPEND_VAL(S) \ ++ obstack_grow (&opts_obstack, (const void*) (S), strlen ((S))) ++ ++ ++const char* ++driver_set_m_flag (int argc, const char **argv) ++{ ++ int parm_off = 0; ++ ++ if (argc != 1) ++ return "%eset_m_flag requires exactly 1 argument."; ++ ++#undef PARM ++#define PARM (argv[0] + parm_off) ++ ++/* Note: sizeof (OPTSTR_##NAME) equals the length of "