diff options
author | chenglulu <chenglulu@loongson.cn> | 2021-11-27 14:42:57 +0800 |
---|---|---|
committer | Chenghua Xu <paul.hua.gm@gmail.com> | 2022-03-29 17:43:32 +0800 |
commit | b44786f64019e7164cab687b19914e7e13c949a4 (patch) | |
tree | e76d6abd59f7213457cf95d3a8cfb5ee7d945e3a | |
parent | c6c0594ef8382754f9cd8869a0cfb2aa2dcc0f43 (diff) | |
download | gcc-b44786f64019e7164cab687b19914e7e13c949a4.tar.gz |
LoongArch Port: gcc build
2022-03-29 Chenghua Xu <xuchenghua@loongson.cn>
Lulu Cheng <chenglulu@loongson.cn>
gcc/ChangeLog:
* common/config/loongarch/loongarch-common.cc: New file.
* config/loongarch/genopts/genstr.sh: New file.
* config/loongarch/genopts/loongarch-strings: New file.
* config/loongarch/genopts/loongarch.opt.in: New file.
* config/loongarch/loongarch-str.h: New file.
* config/loongarch/gnu-user.h: New file.
* config/loongarch/linux.h: New file.
* config/loongarch/loongarch-cpu.cc: New file.
* config/loongarch/loongarch-cpu.h: New file.
* config/loongarch/loongarch-def.c: New file.
* config/loongarch/loongarch-def.h: New file.
* config/loongarch/loongarch-driver.cc: New file.
* config/loongarch/loongarch-driver.h: New file.
* config/loongarch/loongarch-opts.cc: New file.
* config/loongarch/loongarch-opts.h: New file.
* config/loongarch/loongarch.opt: New file.
* config/loongarch/t-linux: New file.
* config/loongarch/t-loongarch: New file.
* config.gcc: Add LoongArch support.
* configure.ac: Add LoongArch support.
contrib/ChangeLog:
* gcc_update (files_and_dependencies): Add
config/loongarch/loongarch.opt and config/loongarch/loongarch-str.h.
-rwxr-xr-x | contrib/gcc_update | 2 | ||||
-rw-r--r-- | gcc/common/config/loongarch/loongarch-common.cc | 43 | ||||
-rw-r--r-- | gcc/config.gcc | 435 | ||||
-rwxr-xr-x | gcc/config/loongarch/genopts/genstr.sh | 104 | ||||
-rw-r--r-- | gcc/config/loongarch/genopts/loongarch-strings | 58 | ||||
-rw-r--r-- | gcc/config/loongarch/genopts/loongarch.opt.in | 179 | ||||
-rw-r--r-- | gcc/config/loongarch/gnu-user.h | 80 | ||||
-rw-r--r-- | gcc/config/loongarch/linux.h | 50 | ||||
-rw-r--r-- | gcc/config/loongarch/loongarch-cpu.cc | 206 | ||||
-rw-r--r-- | gcc/config/loongarch/loongarch-cpu.h | 30 | ||||
-rw-r--r-- | gcc/config/loongarch/loongarch-def.c | 179 | ||||
-rw-r--r-- | gcc/config/loongarch/loongarch-def.h | 151 | ||||
-rw-r--r-- | gcc/config/loongarch/loongarch-driver.cc | 187 | ||||
-rw-r--r-- | gcc/config/loongarch/loongarch-driver.h | 68 | ||||
-rw-r--r-- | gcc/config/loongarch/loongarch-opts.cc | 577 | ||||
-rw-r--r-- | gcc/config/loongarch/loongarch-opts.h | 90 | ||||
-rw-r--r-- | gcc/config/loongarch/loongarch-str.h | 59 | ||||
-rw-r--r-- | gcc/config/loongarch/loongarch.opt | 186 | ||||
-rw-r--r-- | gcc/config/loongarch/t-linux | 53 | ||||
-rw-r--r-- | gcc/config/loongarch/t-loongarch | 71 | ||||
-rw-r--r-- | gcc/configure.ac | 33 |
21 files changed, 2836 insertions, 5 deletions
diff --git a/contrib/gcc_update b/contrib/gcc_update index 1cf15f9b3c2..641ce164775 100755 --- a/contrib/gcc_update +++ b/contrib/gcc_update @@ -86,6 +86,8 @@ gcc/config/arm/arm-tables.opt: gcc/config/arm/arm-cpus.in gcc/config/arm/parsecp gcc/config/c6x/c6x-tables.opt: gcc/config/c6x/c6x-isas.def gcc/config/c6x/genopt.sh gcc/config/c6x/c6x-sched.md: gcc/config/c6x/c6x-sched.md.in gcc/config/c6x/gensched.sh gcc/config/c6x/c6x-mult.md: gcc/config/c6x/c6x-mult.md.in gcc/config/c6x/genmult.sh +gcc/config/loongarch/loongarch-str.h: gcc/config/loongarch/genopts/genstr.sh gcc/config/loongarch/genopts/loongarch-string +gcc/config/loongarch/loongarch.opt: gcc/config/loongarch/genopts/genstr.sh gcc/config/loongarch/genopts/loongarch.opt.in gcc/config/m68k/m68k-tables.opt: gcc/config/m68k/m68k-devices.def gcc/config/m68k/m68k-isas.def gcc/config/m68k/m68k-microarchs.def gcc/config/m68k/genopt.sh gcc/config/mips/mips-tables.opt: gcc/config/mips/mips-cpus.def gcc/config/mips/genopt.sh gcc/config/rs6000/rs6000-tables.opt: gcc/config/rs6000/rs6000-cpus.def gcc/config/rs6000/genopt.sh diff --git a/gcc/common/config/loongarch/loongarch-common.cc b/gcc/common/config/loongarch/loongarch-common.cc new file mode 100644 index 00000000000..085d3d98f1c --- /dev/null +++ b/gcc/common/config/loongarch/loongarch-common.cc @@ -0,0 +1,43 @@ +/* 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 +<http://www.gnu.org/licenses/>. */ + +#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_NONE, 0, NULL, 0 } +}; + +#undef TARGET_DEFAULT_TARGET_FLAGS +#define TARGET_DEFAULT_TARGET_FLAGS MASK_CHECK_ZERO_DIV + +struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER; diff --git a/gcc/config.gcc b/gcc/config.gcc index 3833bfa16a9..7b58e1314ff 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -454,6 +454,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" @@ -2495,6 +2502,20 @@ riscv*-*-freebsd*) # automatically detect that GAS supports it, yet we require it. gcc_cv_initfini_array=yes ;; + +loongarch*-*-linux*) + 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" @@ -3601,7 +3622,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 @@ -4933,6 +4954,373 @@ 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 \ + triplet_os triplet_abi + + # Infer ABI from the triplet. + case ${target} in + loongarch64-*-*-*f64) + abi_pattern="lp64d" + triplet_abi="f64" + ;; + loongarch64-*-*-*f32) + abi_pattern="lp64f" + triplet_abi="f32" + ;; + loongarch64-*-*-*sf) + abi_pattern="lp64s" + triplet_abi="sf" + ;; + loongarch64-*-*-*) + abi_pattern="lp64[dfs]" + abi_default="lp64d" + triplet_abi="" + ;; + *) + echo "Unsupported target ${target}." 1>&2 + exit 1 + ;; + esac + + abiext_pattern="*" + abiext_default="base" + + # Get the canonical triplet (multiarch specifier). + case ${target} in + *-linux-gnu*) triplet_os="linux-gnu";; + *-linux-musl*) triplet_os="linux-musl";; + *) + echo "Unsupported target ${target}." 1>&2 + exit 1 + ;; + esac + + la_canonical_triplet="loongarch64-${triplet_os}${triplet_abi}" + + + # Perform initial sanity checks on --with-* options. + 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. + 0) + # Convert "0" to "none" for upcoming checks. + with_fpu="none" + ;; + *) + echo "Unknown fpu type in --with-fpu=$with_fpu" 1>&2 + exit 1 + ;; + esac + + + # Set 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}$" > /dev/null; then + : # OK + else + echo "Incompatible options:" \ + "--with-abi=${with_abi} and --target=${target}." 1>&2 + exit 1 + fi + ;; + esac + + # Set 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}$" > /dev/null; then + : # OK + else + echo "The ABI extension type \"${with_abiext}\"" \ + "is incompatible with --target=${target}." 1>&2 + exit 1 + fi + + ;; + esac + + # Infer 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 + + # Infer 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 + + ## Set 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}$" > /dev/null; then + : # OK + else + echo "${with_abi}/${with_abiext} ABI cannot be implemented with" \ + "--with-arch=${with_arch}." 1>&2 + exit 1 + fi + ;; + esac + + ## Set default value for with_fpu. + 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}$" > /dev/null; then + : # OK + else + echo "${with_abi}/${with_abiext} ABI cannot be implemented with" \ + "--with-fpu=${with_fpu}." 1>&2 + exit 1 + fi + ;; + esac + + + # Infer 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 + + ## Set 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}$" > /dev/null; then + : # OK + else + echo "Incompatible options: --with-tune=${with_tune}" \ + "and --with-arch=${with_arch}." 1>&2 + exit 1 + fi + ;; + 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="" + + # ${with_multilib_list} should not contain whitespaces, + # consecutive commas or slashes. + if echo "${with_multilib_list}" \ + | grep -E -e "[[:space:]]" -e '[,/][,/]' -e '[,/]$' -e '^[,/]' > /dev/null; then + echo "Invalid argument to --with-multilib-list." 1>&2 + exit 1 + fi + + unset component idx elem_abi_base elem_abi_ext elem_tmp + for elem in $(echo "${with_multilib_list}" | tr ',' ' '); do + idx=0 + while true; do + idx=$((idx + 1)) + component=$(echo "${elem}" | awk -F'/' '{print $'"${idx}"'}') + + case ${idx} in + 1) + # Component 1: Base ABI type + case ${component} in + lp64d) elem_tmp="ABI_BASE_LP64D,";; + lp64f) elem_tmp="ABI_BASE_LP64F,";; + lp64s) elem_tmp="ABI_BASE_LP64S,";; + *) + echo "Unknown base ABI \"${component}\" in --with-multilib-list." 1>&2 + exit 1 + ;; + esac + loongarch_multilib_list_c="${loongarch_multilib_list_c}${elem_tmp}" + loongarch_multilib_list_make="${loongarch_multilib_list_make}mabi=${component}" + elem_abi_base="${component}" + ;; + + 2) + # Component 2: ABI extension type + case ${component} in + "" | base) + component="base" + elem_tmp="ABI_EXT_BASE," + ;; + *) + echo "Unknown ABI extension \"${component}\" in --with-multilib-list." 1>&2 + exit 1 + ;; + esac + loongarch_multilib_list_c="${loongarch_multilib_list_c}${elem_tmp}" + loongarch_multilib_list_make="${loongarch_multilib_list_make}" # Add nothing for now. + elem_abi_ext="${component}" + ;; + + *) + # Component 3 and on: optional stuff + case ${component} in + "") + # End of component list. + break + ;; + *) + echo "Unknown ABI \"${elem}\" in --with-multilib-list." 1>&2 + exit 1 + ;; + esac + ;; + esac + done + + if test x${elem_abi_base} = x${with_abi} \ + && test x${elem_abi_ext} = x${with_abiext}; then + loongarch_multilib_list_sane=yes + fi + loongarch_multilib_list_make="${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%,} + loongarch_multilib_list_make=${loongarch_multilib_list_make%,} + ;; + nds32*-*-*) supported_defaults="arch cpu nds32_lib float fpu_config" @@ -5370,6 +5758,51 @@ case ${target} in tmake_file="mips/t-mips $tmake_file" ;; + loongarch*-*-*) + # Export canonical triplet. + tm_defines="${tm_defines} LA_MULTIARCH_TRIPLET=${la_canonical_triplet}" + + # Define macro LA_DISABLE_MULTILIB if --disable-multilib + tm_defines="${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="${tm_defines} LA_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="${tm_defines} DEFAULT_CPU_ARCH=CPU_NATIVE" ;; + la464) tm_defines="${tm_defines} DEFAULT_CPU_ARCH=CPU_LA464" ;; + loongarch64) tm_defines="${tm_defines} DEFAULT_CPU_ARCH=CPU_LOONGARCH64" ;; + esac + + case ${with_tune} in + native) tm_defines="${tm_defines} DEFAULT_CPU_TUNE=CPU_NATIVE" ;; + la464) tm_defines="${tm_defines} DEFAULT_CPU_TUNE=CPU_LA464" ;; + loongarch64) tm_defines="${tm_defines} DEFAULT_CPU_TUNE=CPU_LOONGARCH64" ;; + esac + + case ${with_abi} in + lp64d) tm_defines="${tm_defines} DEFAULT_ABI_BASE=ABI_BASE_LP64D" ;; + lp64f) tm_defines="${tm_defines} DEFAULT_ABI_BASE=ABI_BASE_LP64F" ;; + lp64s) tm_defines="${tm_defines} DEFAULT_ABI_BASE=ABI_BASE_LP64S" ;; + esac + + case ${with_abiext} in + base) tm_defines="${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. diff --git a/gcc/config/loongarch/genopts/genstr.sh b/gcc/config/loongarch/genopts/genstr.sh new file mode 100755 index 00000000000..972ef125ff9 --- /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 +# <http://www.gnu.org/licenses/>. + +cd "$(dirname "$0")" + +# Generate a header containing definitions from the string table. +gen_defines() { + cat <<EOF +/* Generated automatically by "genstr" from "loongarch-strings". + Please do not edit this file directly. + + 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 +<http://www.gnu.org/licenses/>. */ + +#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 "@@<KEY>@@" to "<VALUE>" 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 00000000000..cb88ed56b68 --- /dev/null +++ b/gcc/config/loongarch/genopts/loongarch-strings @@ -0,0 +1,58 @@ +# 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 +# <http://www.gnu.org/licenses/>. + +# -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_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 00000000000..61e7d72a0a1 --- /dev/null +++ b/gcc/config/loongarch/genopts/loongarch.opt.in @@ -0,0 +1,179 @@ +; 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 +; <http://www.gnu.org/licenses/>. +; + +; 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. + +; 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_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. diff --git a/gcc/config/loongarch/gnu-user.h b/gcc/config/loongarch/gnu-user.h new file mode 100644 index 00000000000..664dc9206ad --- /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 +<http://www.gnu.org/licenses/>. */ + +/* 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/linux.h b/gcc/config/loongarch/linux.h new file mode 100644 index 00000000000..110d0fab93d --- /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 +<http://www.gnu.org/licenses/>. */ + +/* 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-cpu.cc b/gcc/config/loongarch/loongarch-cpu.cc new file mode 100644 index 00000000000..a886dd9323b --- /dev/null +++ b/gcc/config/loongarch/loongarch-cpu.cc @@ -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 +<http://www.gnu.org/licenses/>. */ + +#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 00000000000..93d656f70f5 --- /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 +<http://www.gnu.org/licenses/>. */ + +#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 00000000000..c8769b7d65e --- /dev/null +++ b/gcc/config/loongarch/loongarch-def.c @@ -0,0 +1,179 @@ +/* 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 +<http://www.gnu.org/licenses/>. */ + +#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_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 00000000000..c2c35b6ba5c --- /dev/null +++ b/gcc/config/loongarch/loongarch-def.h @@ -0,0 +1,151 @@ +/* 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 +<http://www.gnu.org/licenses/>. */ + +/* 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_LARGE 3 +#define CMODEL_EXTREME 4 +#define N_CMODEL_TYPES 5 + +/* 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.cc b/gcc/config/loongarch/loongarch-driver.cc new file mode 100644 index 00000000000..0adcc923b7d --- /dev/null +++ b/gcc/config/loongarch/loongarch-driver.cc @@ -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 +<http://www.gnu.org/licenses/>. */ + +#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 "<option>=". */ +#undef MATCH_OPT +#define MATCH_OPT(NAME) \ + (strncmp (argv[0], OPTSTR_##NAME "=", \ + (parm_off = sizeof (OPTSTR_##NAME))) == 0) + + if (strcmp (argv[0], "no_link") == 0) + { + no_link = 1; + } + else if (MATCH_OPT (ABI_BASE)) + { + LARCH_DRIVER_SET_M_FLAG ( + loongarch_abi_base_strings, N_ABI_BASE_TYPES, + opt_abi_base_driver, PARM) + } + else if (MATCH_OPT (ISA_EXT_FPU)) + { + LARCH_DRIVER_SET_M_FLAG (loongarch_isa_ext_strings, N_ISA_EXT_FPU_TYPES, + opt_fpu_driver, PARM) + } + else if (MATCH_OPT (ARCH)) + { + LARCH_DRIVER_SET_M_FLAG (loongarch_cpu_strings, N_ARCH_TYPES, + opt_arch_driver, PARM) + } + else if (MATCH_OPT (TUNE)) + { + LARCH_DRIVER_SET_M_FLAG (loongarch_cpu_strings, N_TUNE_TYPES, + opt_tune_driver, PARM) + } + else if (MATCH_OPT (CMODEL)) + { + LARCH_DRIVER_SET_M_FLAG (loongarch_cmodel_strings, N_CMODEL_TYPES, + opt_cmodel_driver, PARM) + } + else /* switches */ + { + int switch_idx = M_OPTION_NOT_SEEN; + + LARCH_DRIVER_SET_M_FLAG (loongarch_switch_strings, N_SWITCH_TYPES, + switch_idx, argv[0]) + + if (switch_idx != M_OPTION_NOT_SEEN) + opt_switches |= loongarch_switch_mask[switch_idx]; + } + return ""; +} + +const char* +driver_get_normalized_m_opts (int argc, const char **argv) +{ + if (argc != 0) + { + (void) argv; /* To make compiler shut up about unused argument. */ + return " %eget_normalized_m_opts requires no argument.\n"; + } + + loongarch_config_target (& la_target, + opt_switches, + opt_arch_driver, + opt_tune_driver, + opt_fpu_driver, + opt_abi_base_driver, + opt_abi_ext_driver, + opt_cmodel_driver, + !no_link /* follow_multilib_list */); + + /* Output normalized option strings. */ + obstack_blank (&opts_obstack, 0); + +#undef APPEND_LTR +#define APPEND_LTR(S) \ + obstack_grow (&opts_obstack, (const void*) (S), \ + sizeof ((S)) / sizeof (char) -1) + +#undef APPEND_VAL +#define APPEND_VAL(S) \ + obstack_grow (&opts_obstack, (const void*) (S), strlen ((S))) + +#undef APPEND_OPT +#define APPEND_OPT(NAME) \ + APPEND_LTR (" %<m" OPTSTR_##NAME "=* " \ + " -m" OPTSTR_##NAME "=") + + for (int i = 0; i < N_SWITCH_TYPES; i++) + { + APPEND_LTR (" %<m"); + APPEND_VAL (loongarch_switch_strings[i]); + } + + APPEND_OPT (ABI_BASE); + APPEND_VAL (loongarch_abi_base_strings[la_target.abi.base]); + + APPEND_OPT (ARCH); + APPEND_VAL (loongarch_cpu_strings[la_target.cpu_arch]); + + APPEND_OPT (ISA_EXT_FPU); + APPEND_VAL (loongarch_isa_ext_strings[la_target.isa.fpu]); + + APPEND_OPT (CMODEL); + APPEND_VAL (loongarch_cmodel_strings[la_target.cmodel]); + + APPEND_OPT (TUNE); + APPEND_VAL (loongarch_cpu_strings[la_target.cpu_tune]); + + obstack_1grow (&opts_obstack, '\0'); + + return XOBFINISH (&opts_obstack, const char *); +} diff --git a/gcc/config/loongarch/loongarch-driver.h b/gcc/config/loongarch/loongarch-driver.h new file mode 100644 index 00000000000..2e4a7a9c870 --- /dev/null +++ b/gcc/config/loongarch/loongarch-driver.h @@ -0,0 +1,68 @@ +/* Subroutine headers 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 +<http://www.gnu.org/licenses/>. */ + +#ifndef LOONGARCH_DRIVER_H +#define LOONGARCH_DRIVER_H + +#include "loongarch-str.h" + +extern const char* +driver_set_m_flag (int argc, const char **argv); + +extern const char* +driver_get_normalized_m_opts (int argc, const char **argv); + +#define EXTRA_SPEC_FUNCTIONS \ + { "set_m_flag", driver_set_m_flag }, \ + { "get_normalized_m_opts", driver_get_normalized_m_opts }, + +/* Pre-process ABI-related options. */ +#define LA_SET_PARM_SPEC(NAME) \ + " %{m" OPTSTR_##NAME "=*: %:set_m_flag(" OPTSTR_##NAME "=%*)}" \ + +#define LA_SET_FLAG_SPEC(NAME) \ + " %{m" OPTSTR_##NAME ": %:set_m_flag(" OPTSTR_##NAME ")}" \ + +#define DRIVER_HANDLE_MACHINE_OPTIONS \ + " %{c|S|E|nostdlib: %:set_m_flag(no_link)}" \ + " %{nostartfiles: %{nodefaultlibs: %:set_m_flag(no_link)}}" \ + LA_SET_PARM_SPEC (ABI_BASE) \ + LA_SET_PARM_SPEC (ARCH) \ + LA_SET_PARM_SPEC (TUNE) \ + LA_SET_PARM_SPEC (ISA_EXT_FPU) \ + LA_SET_PARM_SPEC (CMODEL) \ + LA_SET_FLAG_SPEC (SOFT_FLOAT) \ + LA_SET_FLAG_SPEC (SINGLE_FLOAT) \ + LA_SET_FLAG_SPEC (DOUBLE_FLOAT) \ + " %:get_normalized_m_opts()" + +#define DRIVER_SELF_SPECS \ + DRIVER_HANDLE_MACHINE_OPTIONS + +/* ABI spec strings. */ +#define ABI_GRLEN_SPEC \ + "%{mabi=lp64*:64}" \ + +#define ABI_SPEC \ + "%{mabi=lp64d:lp64d}" \ + "%{mabi=lp64f:lp64f}" \ + "%{mabi=lp64s:lp64s}" \ + +#endif /* LOONGARCH_DRIVER_H */ diff --git a/gcc/config/loongarch/loongarch-opts.cc b/gcc/config/loongarch/loongarch-opts.cc new file mode 100644 index 00000000000..eb9c2a52f9e --- /dev/null +++ b/gcc/config/loongarch/loongarch-opts.cc @@ -0,0 +1,577 @@ +/* Subroutines for loongarch-specific option handling. + 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 +<http://www.gnu.org/licenses/>. */ + +#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-cpu.h" +#include "loongarch-opts.h" +#include "loongarch-str.h" + +struct loongarch_target la_target; + +/* ABI-related configuration. */ +#define ABI_COUNT (sizeof(abi_priority_list)/sizeof(struct loongarch_abi)) +static const struct loongarch_abi +abi_priority_list[] = { + {ABI_BASE_LP64D, ABI_EXT_BASE}, + {ABI_BASE_LP64F, ABI_EXT_BASE}, + {ABI_BASE_LP64S, ABI_EXT_BASE}, +}; + +/* Initialize enabled_abi_types from TM_MULTILIB_LIST. */ +#ifdef LA_DISABLE_MULTILIB +#define MULTILIB_LIST_LEN 1 +#else +#define MULTILIB_LIST_LEN (sizeof (tm_multilib_list) / sizeof (int) / 2) +static const int tm_multilib_list[] = { TM_MULTILIB_LIST }; +#endif +static int enabled_abi_types[N_ABI_BASE_TYPES][N_ABI_EXT_TYPES] = { 0 }; + +#define isa_required(ABI) (abi_minimal_isa[(ABI).base][(ABI).ext]) +extern "C" const struct loongarch_isa +abi_minimal_isa[N_ABI_BASE_TYPES][N_ABI_EXT_TYPES]; + +static inline int +is_multilib_enabled (struct loongarch_abi abi) +{ + return enabled_abi_types[abi.base][abi.ext]; +} + +static void +init_enabled_abi_types () +{ +#ifdef LA_DISABLE_MULTILIB + enabled_abi_types[DEFAULT_ABI_BASE][DEFAULT_ABI_EXT] = 1; +#else + int abi_base, abi_ext; + for (unsigned int i = 0; i < MULTILIB_LIST_LEN; i++) + { + abi_base = tm_multilib_list[i << 1]; + abi_ext = tm_multilib_list[(i << 1) + 1]; + enabled_abi_types[abi_base][abi_ext] = 1; + } +#endif +} + +/* Switch masks. */ +#undef M +#define M(NAME) OPTION_MASK_##NAME +const int loongarch_switch_mask[N_SWITCH_TYPES] = { + /* SW_SOFT_FLOAT */ M(FORCE_SOFTF), + /* SW_SINGLE_FLOAT */ M(FORCE_F32), + /* SW_DOUBLE_FLOAT */ M(FORCE_F64), +}; +#undef M + +/* String processing. */ +static struct obstack msg_obstack; +#define APPEND_STRING(STR) obstack_grow (&msg_obstack, STR, strlen(STR)); +#define APPEND1(CH) obstack_1grow(&msg_obstack, CH); + +static const char* abi_str (struct loongarch_abi abi); +static const char* isa_str (const struct loongarch_isa *isa, char separator); +static const char* arch_str (const struct loongarch_target *target); +static const char* multilib_enabled_abi_list (); + +/* Misc */ +static struct loongarch_abi isa_default_abi (const struct loongarch_isa *isa); +static int isa_base_compat_p (const struct loongarch_isa *set1, + const struct loongarch_isa *set2); +static int isa_fpu_compat_p (const struct loongarch_isa *set1, + const struct loongarch_isa *set2); +static int abi_compat_p (const struct loongarch_isa *isa, + struct loongarch_abi abi); +static int abi_default_cpu_arch (struct loongarch_abi abi); + +/* Checking configure-time defaults. */ +#ifndef DEFAULT_ABI_BASE +#error missing definition of DEFAULT_ABI_BASE in ${tm_defines}. +#endif + +#ifndef DEFAULT_ABI_EXT +#error missing definition of DEFAULT_ABI_EXT in ${tm_defines}. +#endif + +#ifndef DEFAULT_CPU_ARCH +#error missing definition of DEFAULT_CPU_ARCH in ${tm_defines}. +#endif + +#ifndef DEFAULT_ISA_EXT_FPU +#error missing definition of DEFAULT_ISA_EXT_FPU in ${tm_defines}. +#endif + +/* Handle combinations of -m machine option values + (see loongarch.opt and loongarch-opts.h). */ +void +loongarch_config_target (struct loongarch_target *target, + HOST_WIDE_INT opt_switches, + int opt_arch, int opt_tune, int opt_fpu, + int opt_abi_base, int opt_abi_ext, + int opt_cmodel, int follow_multilib_list) +{ + struct loongarch_target t; + + if (!target) + return; + + /* Initialization */ + init_enabled_abi_types (); + obstack_init (&msg_obstack); + + struct { + int arch, tune, fpu, abi_base, abi_ext, cmodel; + } constrained = { + M_OPT_ABSENT(opt_arch) ? 0 : 1, + M_OPT_ABSENT(opt_tune) ? 0 : 1, + M_OPT_ABSENT(opt_fpu) ? 0 : 1, + M_OPT_ABSENT(opt_abi_base) ? 0 : 1, + M_OPT_ABSENT(opt_abi_ext) ? 0 : 1, + M_OPT_ABSENT(opt_cmodel) ? 0 : 1, + }; + +#define on(NAME) ((loongarch_switch_mask[(SW_##NAME)] & opt_switches) \ + && (on_switch = (SW_##NAME), 1)) + int on_switch; + + /* 1. Target ABI */ + t.abi.base = constrained.abi_base ? opt_abi_base : DEFAULT_ABI_BASE; + + t.abi.ext = constrained.abi_ext ? opt_abi_ext : DEFAULT_ABI_EXT; + + /* Extra switch handling. */ + if (on (SOFT_FLOAT) || on (SINGLE_FLOAT) || on (DOUBLE_FLOAT)) + { + switch (on_switch) + { + case SW_SOFT_FLOAT: + opt_fpu = ISA_EXT_NOFPU; + break; + + case SW_SINGLE_FLOAT: + opt_fpu = ISA_EXT_FPU32; + break; + + case SW_DOUBLE_FLOAT: + opt_fpu = ISA_EXT_FPU64; + break; + + default: + gcc_unreachable(); + } + constrained.fpu = 1; + + /* The target ISA is not ready yet, but (isa_required (t.abi) + + forced fpu) is enough for computing the forced base ABI. */ + struct loongarch_isa default_isa = isa_required (t.abi); + struct loongarch_isa force_isa = default_isa; + struct loongarch_abi force_abi = t.abi; + force_isa.fpu = opt_fpu; + force_abi.base = isa_default_abi (&force_isa).base; + + if (constrained.abi_base && (t.abi.base != force_abi.base)) + inform (UNKNOWN_LOCATION, + "%<-m%s%> overrides %<-m%s=%s%>, adjusting ABI to %qs", + loongarch_switch_strings[on_switch], + OPTSTR_ABI_BASE, loongarch_abi_base_strings[t.abi.base], + abi_str (force_abi)); + + t.abi.base = force_abi.base; + } + +#ifdef LA_DISABLE_MULTILIB + if (follow_multilib_list) + if (t.abi.base != DEFAULT_ABI_BASE || t.abi.ext != DEFAULT_ABI_EXT) + { + static const struct loongarch_abi default_abi + = {DEFAULT_ABI_BASE, DEFAULT_ABI_EXT}; + + warning (0, "ABI changed (%qs to %qs) while multilib is disabled", + abi_str (default_abi), abi_str (t.abi)); + } +#endif + + /* 2. Target CPU */ + t.cpu_arch = constrained.arch ? opt_arch : DEFAULT_CPU_ARCH; + + t.cpu_tune = constrained.tune ? opt_tune + : (constrained.arch ? DEFAULT_CPU_ARCH : DEFAULT_CPU_TUNE); + +#ifdef __loongarch__ + /* For native compilers, gather local CPU information + and fill the "CPU_NATIVE" index of arrays defined in + loongarch-cpu.c. */ + + t.cpu_native = fill_native_cpu_config (t.cpu_arch == CPU_NATIVE, + t.cpu_tune == CPU_NATIVE); + +#else + if (t.cpu_arch == CPU_NATIVE) + fatal_error (UNKNOWN_LOCATION, + "%qs does not work on a cross compiler", + "-m" OPTSTR_ARCH "=" STR_CPU_NATIVE); + + else if (t.cpu_tune == CPU_NATIVE) + fatal_error (UNKNOWN_LOCATION, + "%qs does not work on a cross compiler", + "-m" OPTSTR_TUNE "=" STR_CPU_NATIVE); +#endif + + /* 3. Target ISA */ +config_target_isa: + + /* Get default ISA from "-march" or its default value. */ + t.isa = loongarch_cpu_default_isa[LARCH_ACTUAL_ARCH]; + + /* Apply incremental changes. */ + /* "-march=native" overrides the default FPU type. */ + t.isa.fpu = constrained.fpu ? opt_fpu : + ((t.cpu_arch == CPU_NATIVE && constrained.arch) ? + t.isa.fpu : DEFAULT_ISA_EXT_FPU); + + + /* 4. ABI-ISA compatibility */ + /* Note: + - There IS a unique default -march value for each ABI type + (config.gcc: triplet -> abi -> default arch). + + - If the base ABI is incompatible with the default arch, + try using the default -march it implies (and mark it + as "constrained" this time), then re-apply step 3. */ + + struct loongarch_abi abi_tmp; + const struct loongarch_isa* isa_min; + + abi_tmp = t.abi; + isa_min = &isa_required (abi_tmp); + + if (isa_base_compat_p (&t.isa, isa_min)); /* OK. */ + else if (!constrained.arch) + { + /* Base architecture can only be implied by -march, + so we adjust that first if it is not constrained. */ + int fallback_arch = abi_default_cpu_arch (t.abi); + + if (t.cpu_arch == CPU_NATIVE) + warning (0, "your native CPU architecture (%qs) " + "does not support %qs ABI, falling back to %<-m%s=%s%>", + arch_str (&t), abi_str (t.abi), OPTSTR_ARCH, + loongarch_cpu_strings[fallback_arch]); + else + warning (0, "default CPU architecture (%qs) " + "does not support %qs ABI, falling back to %<-m%s=%s%>", + arch_str (&t), abi_str (t.abi), OPTSTR_ARCH, + loongarch_cpu_strings[fallback_arch]); + + t.cpu_arch = fallback_arch; + constrained.arch = 1; + goto config_target_isa; + } + else if (!constrained.abi_base) + { + /* If -march is given while -mabi is not, + try selecting another base ABI type. */ + abi_tmp.base = isa_default_abi (&t.isa).base; + } + else + goto fatal; + + if (isa_fpu_compat_p (&t.isa, isa_min)); /* OK. */ + else if (!constrained.fpu) + t.isa.fpu = isa_min->fpu; + else if (!constrained.abi_base) + /* If -march is compatible with the default ABI + while -mfpu is not. */ + abi_tmp.base = isa_default_abi (&t.isa).base; + else + goto fatal; + + if (0) +fatal: + fatal_error (UNKNOWN_LOCATION, + "unable to implement ABI %qs with instruction set %qs", + abi_str (t.abi), isa_str (&t.isa, '/')); + + + /* Using the fallback ABI. */ + if (abi_tmp.base != t.abi.base || abi_tmp.ext != t.abi.ext) + { + /* This flag is only set in the GCC driver. */ + if (follow_multilib_list) + { + + /* Continue falling back until we find a feasible ABI type + enabled by TM_MULTILIB_LIST. */ + if (!is_multilib_enabled (abi_tmp)) + { + for (unsigned int i = 0; i < ABI_COUNT; i++) + { + if (is_multilib_enabled (abi_priority_list[i]) + && abi_compat_p (&t.isa, abi_priority_list[i])) + { + abi_tmp = abi_priority_list[i]; + + warning (0, "ABI %qs cannot be implemented due to " + "limited instruction set %qs, " + "falling back to %qs", abi_str (t.abi), + isa_str (&t.isa, '/'), abi_str (abi_tmp)); + + goto fallback; + } + } + + /* Otherwise, keep using abi_tmp with a warning. */ +#ifdef LA_DISABLE_MULTILIB + warning (0, "instruction set %qs cannot implement " + "default ABI %qs, falling back to %qs", + isa_str (&t.isa, '/'), abi_str (t.abi), + abi_str (abi_tmp)); +#else + warning (0, "no multilib-enabled ABI (%qs) can be implemented " + "with instruction set %qs, falling back to %qs", + multilib_enabled_abi_list (), + isa_str (&t.isa, '/'), abi_str (abi_tmp)); +#endif + } + } + +fallback: + t.abi = abi_tmp; + } + else if (follow_multilib_list) + { + if (!is_multilib_enabled (t.abi)) + { + inform (UNKNOWN_LOCATION, + "ABI %qs is not enabled at configure-time, " + "the linker might report an error", abi_str (t.abi)); + + inform (UNKNOWN_LOCATION, "ABI with startfiles: %s", + multilib_enabled_abi_list ()); + } + } + + + /* 5. Target code model */ + t.cmodel = constrained.cmodel ? opt_cmodel : CMODEL_NORMAL; + + /* Cleanup and return. */ + obstack_free (&msg_obstack, NULL); + *target = t; +} + +/* Returns the default ABI for the given instruction set. */ +static inline struct loongarch_abi +isa_default_abi (const struct loongarch_isa *isa) +{ + struct loongarch_abi abi; + + switch (isa->fpu) + { + case ISA_EXT_FPU64: + if (isa->base == ISA_BASE_LA64V100) + abi.base = ABI_BASE_LP64D; + break; + + case ISA_EXT_FPU32: + if (isa->base == ISA_BASE_LA64V100) + abi.base = ABI_BASE_LP64F; + break; + + case ISA_EXT_NOFPU: + if (isa->base == ISA_BASE_LA64V100) + abi.base = ABI_BASE_LP64S; + break; + + default: + gcc_unreachable (); + } + + abi.ext = ABI_EXT_BASE; + return abi; +} + +/* Check if set2 is a subset of set1. */ +static inline int +isa_base_compat_p (const struct loongarch_isa *set1, + const struct loongarch_isa *set2) +{ + switch (set2->base) + { + case ISA_BASE_LA64V100: + return (set1->base == ISA_BASE_LA64V100); + + default: + gcc_unreachable (); + } +} + +static inline int +isa_fpu_compat_p (const struct loongarch_isa *set1, + const struct loongarch_isa *set2) +{ + switch (set2->fpu) + { + case ISA_EXT_FPU64: + return set1->fpu == ISA_EXT_FPU64; + + case ISA_EXT_FPU32: + return set1->fpu == ISA_EXT_FPU32 || set1->fpu == ISA_EXT_FPU64; + + case ISA_EXT_NOFPU: + return 1; + + default: + gcc_unreachable (); + } + +} + +static inline int +abi_compat_p (const struct loongarch_isa *isa, struct loongarch_abi abi) +{ + int compatible = 1; + const struct loongarch_isa *isa2 = &isa_required (abi); + + /* Append conditionals for new ISA components below. */ + compatible = compatible && isa_base_compat_p (isa, isa2); + compatible = compatible && isa_fpu_compat_p (isa, isa2); + return compatible; +} + +/* The behavior of this function should be consistent + with config.gcc. */ +static inline int +abi_default_cpu_arch (struct loongarch_abi abi) +{ + switch (abi.base) + { + case ABI_BASE_LP64D: + case ABI_BASE_LP64F: + case ABI_BASE_LP64S: + if (abi.ext == ABI_EXT_BASE) + return CPU_LOONGARCH64; + } + gcc_unreachable (); +} + +static const char* +abi_str (struct loongarch_abi abi) +{ + /* "/base" can be omitted. */ + if (abi.ext == ABI_EXT_BASE) + return (const char*) + obstack_copy0 (&msg_obstack, loongarch_abi_base_strings[abi.base], + strlen (loongarch_abi_base_strings[abi.base])); + else + { + APPEND_STRING (loongarch_abi_base_strings[abi.base]) + APPEND1 ('/') + APPEND_STRING (loongarch_abi_ext_strings[abi.ext]) + APPEND1 ('\0') + + return XOBFINISH (&msg_obstack, const char *); + } +} + +static const char* +isa_str (const struct loongarch_isa *isa, char separator) +{ + APPEND_STRING (loongarch_isa_base_strings[isa->base]) + APPEND1 (separator) + + if (isa->fpu == ISA_EXT_NOFPU) + { + APPEND_STRING ("no" OPTSTR_ISA_EXT_FPU) + } + else + { + APPEND_STRING (OPTSTR_ISA_EXT_FPU) + APPEND_STRING (loongarch_isa_ext_strings[isa->fpu]) + } + APPEND1 ('\0') + + /* Add more here. */ + + return XOBFINISH (&msg_obstack, const char *); +} + +static const char* +arch_str (const struct loongarch_target *target) +{ + if (target->cpu_arch == CPU_NATIVE) + { + if (target->cpu_native == CPU_NATIVE) + { + /* Describe a native CPU with unknown PRID. */ + const char* isa_string = isa_str (&target->isa, ','); + APPEND_STRING ("PRID: 0x") + APPEND_STRING (get_native_prid_str ()) + APPEND_STRING (", ISA features: ") + APPEND_STRING (isa_string) + APPEND1 ('\0') + } + else + APPEND_STRING (loongarch_cpu_strings[target->cpu_native]); + } + else + APPEND_STRING (loongarch_cpu_strings[target->cpu_arch]); + + APPEND1 ('\0') + return XOBFINISH (&msg_obstack, const char *); +} + +static const char* +multilib_enabled_abi_list () +{ + int enabled_abi_idx[MULTILIB_LIST_LEN] = { 0 }; + const char* enabled_abi_str[MULTILIB_LIST_LEN] = { NULL }; + unsigned int j = 0; + + for (unsigned int i = 0; i < ABI_COUNT && j < MULTILIB_LIST_LEN; i++) + { + if (enabled_abi_types[abi_priority_list[i].base] + [abi_priority_list[i].ext]) + { + enabled_abi_idx[j++] = i; + } + } + + for (unsigned int k = 0; k < j; k++) + { + enabled_abi_str[k] = abi_str (abi_priority_list[enabled_abi_idx[k]]); + } + + for (unsigned int k = 0; k < j - 1; k++) + { + APPEND_STRING (enabled_abi_str[k]) + APPEND1 (',') + APPEND1 (' ') + } + APPEND_STRING (enabled_abi_str[j - 1]) + APPEND1 ('\0') + + return XOBFINISH (&msg_obstack, const char *); +} diff --git a/gcc/config/loongarch/loongarch-opts.h b/gcc/config/loongarch/loongarch-opts.h new file mode 100644 index 00000000000..eaa6fc07448 --- /dev/null +++ b/gcc/config/loongarch/loongarch-opts.h @@ -0,0 +1,90 @@ +/* Definitions for loongarch-specific option handling. + 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 +<http://www.gnu.org/licenses/>. */ + +#ifndef LOONGARCH_OPTS_H +#define LOONGARCH_OPTS_H + + +/* Target configuration */ +extern struct loongarch_target la_target; + +/* Switch masks */ +extern const int loongarch_switch_mask[]; + +#include "loongarch-def.h" + +#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS) && !defined(IN_RTS) +/* Handler for "-m" option combinations, + shared by the driver and the compiler proper. */ +void +loongarch_config_target (struct loongarch_target *target, + HOST_WIDE_INT opt_switches, + int opt_arch, int opt_tune, int opt_fpu, + int opt_abi_base, int opt_abi_ext, + int opt_cmodel, int follow_multilib_list); +#endif + + +/* Macros for common conditional expressions used in loongarch.{c,h,md} */ +#define TARGET_CMODEL_NORMAL (la_target.cmodel == CMODEL_NORMAL) +#define TARGET_CMODEL_TINY (la_target.cmodel == CMODEL_TINY) +#define TARGET_CMODEL_TINY_STATIC (la_target.cmodel == CMODEL_TINY_STATIC) +#define TARGET_CMODEL_LARGE (la_target.cmodel == CMODEL_LARGE) +#define TARGET_CMODEL_EXTREME (la_target.cmodel == CMODEL_EXTREME) + +#define TARGET_HARD_FLOAT (la_target.isa.fpu != ISA_EXT_NOFPU) +#define TARGET_HARD_FLOAT_ABI (la_target.abi.base == ABI_BASE_LP64D \ + || la_target.abi.base == ABI_BASE_LP64F) + +#define TARGET_SOFT_FLOAT (la_target.isa.fpu == ISA_EXT_NOFPU) +#define TARGET_SOFT_FLOAT_ABI (la_target.abi.base == ABI_BASE_LP64S) +#define TARGET_SINGLE_FLOAT (la_target.isa.fpu == ISA_EXT_FPU32) +#define TARGET_SINGLE_FLOAT_ABI (la_target.abi.base == ABI_BASE_LP64F) +#define TARGET_DOUBLE_FLOAT (la_target.isa.fpu == ISA_EXT_FPU64) +#define TARGET_DOUBLE_FLOAT_ABI (la_target.abi.base == ABI_BASE_LP64D) + +#define TARGET_64BIT (la_target.isa.base == ISA_BASE_LA64V100) +#define TARGET_ABI_LP64 (la_target.abi.base == ABI_BASE_LP64D \ + || la_target.abi.base == ABI_BASE_LP64F \ + || la_target.abi.base == ABI_BASE_LP64S) + +#define TARGET_ARCH_NATIVE (la_target.cpu_arch == CPU_NATIVE) +#define LARCH_ACTUAL_ARCH (TARGET_ARCH_NATIVE \ + ? (la_target.cpu_native < N_ARCH_TYPES \ + ? (la_target.cpu_native) : (CPU_NATIVE)) \ + : (la_target.cpu_arch)) + +#define TARGET_TUNE_NATIVE (la_target.cpu_tune == CPU_NATIVE) +#define LARCH_ACTUAL_TUNE (TARGET_TUNE_NATIVE \ + ? (la_target.cpu_native < N_TUNE_TYPES \ + ? (la_target.cpu_native) : (CPU_NATIVE)) \ + : (la_target.cpu_tune)) + +#define TARGET_ARCH_LOONGARCH64 (LARCH_ACTUAL_ARCH == CPU_LOONGARCH64) +#define TARGET_ARCH_LA464 (LARCH_ACTUAL_ARCH == CPU_LA464) + +#define TARGET_TUNE_LOONGARCH64 (LARCH_ACTUAL_TUNE == CPU_LOONGARCH64) +#define TARGET_TUNE_LA464 (LARCH_ACTUAL_TUNE == CPU_LA464) + +/* Note: optimize_size may vary across functions, + while -m[no]-memcpy imposes a global constraint. */ +#define TARGET_DO_OPTIMIZE_BLOCK_MOVE_P loongarch_do_optimize_block_move_p() + +#endif /* LOONGARCH_OPTS_H */ diff --git a/gcc/config/loongarch/loongarch-str.h b/gcc/config/loongarch/loongarch-str.h new file mode 100644 index 00000000000..0e8889b8c96 --- /dev/null +++ b/gcc/config/loongarch/loongarch-str.h @@ -0,0 +1,59 @@ +/* Generated automatically by "genstr" from "loongarch-strings". + Please do not edit this file directly. + + 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 +<http://www.gnu.org/licenses/>. */ + +#ifndef LOONGARCH_STR_H +#define LOONGARCH_STR_H + +#define OPTSTR_ARCH "arch" +#define OPTSTR_TUNE "tune" + +#define STR_CPU_NATIVE "native" +#define STR_CPU_LOONGARCH64 "loongarch64" +#define STR_CPU_LA464 "la464" + +#define STR_ISA_BASE_LA64V100 "la64" + +#define OPTSTR_ISA_EXT_FPU "fpu" +#define STR_ISA_EXT_NOFPU "none" +#define STR_ISA_EXT_FPU0 "0" +#define STR_ISA_EXT_FPU32 "32" +#define STR_ISA_EXT_FPU64 "64" + +#define OPTSTR_SOFT_FLOAT "soft-float" +#define OPTSTR_SINGLE_FLOAT "single-float" +#define OPTSTR_DOUBLE_FLOAT "double-float" + +#define OPTSTR_ABI_BASE "abi" +#define STR_ABI_BASE_LP64D "lp64d" +#define STR_ABI_BASE_LP64F "lp64f" +#define STR_ABI_BASE_LP64S "lp64s" + +#define STR_ABI_EXT_BASE "base" + +#define OPTSTR_CMODEL "cmodel" +#define STR_CMODEL_NORMAL "normal" +#define STR_CMODEL_TINY "tiny" +#define STR_CMODEL_TS "tiny-static" +#define STR_CMODEL_LARGE "large" +#define STR_CMODEL_EXTREME "extreme" + +#endif /* LOONGARCH_STR_H */ diff --git a/gcc/config/loongarch/loongarch.opt b/gcc/config/loongarch/loongarch.opt new file mode 100644 index 00000000000..3ff0d860413 --- /dev/null +++ b/gcc/config/loongarch/loongarch.opt @@ -0,0 +1,186 @@ +; 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". +; +; 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 +; <http://www.gnu.org/licenses/>. +; + +; 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(la64) Value(ISA_BASE_LA64V100) + + +;; ISA extensions / adjustments +Enum +Name(isa_ext_fpu) Type(int) +FPU types of LoongArch: + +EnumValue +Enum(isa_ext_fpu) String(none) Value(ISA_EXT_NOFPU) + +EnumValue +Enum(isa_ext_fpu) String(32) Value(ISA_EXT_FPU32) + +EnumValue +Enum(isa_ext_fpu) String(64) Value(ISA_EXT_FPU64) + +mfpu= +Target RejectNegative Joined ToLower Enum(isa_ext_fpu) Var(la_opt_fpu) Init(M_OPTION_NOT_SEEN) +-mfpu=FPU Generate code for the given FPU. + +mfpu=0 +Target RejectNegative Alias(mfpu=,none) + +msoft-float +Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_SOFTF) Negative(msingle-float) +Prevent the use of all hardware floating-point instructions. + +msingle-float +Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_F32) Negative(mdouble-float) +Restrict the use of hardware floating-point instructions to 32-bit operations. + +mdouble-float +Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_F64) Negative(msoft-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(native) Value(CPU_NATIVE) + +EnumValue +Enum(cpu_type) String(loongarch64) Value(CPU_LOONGARCH64) + +EnumValue +Enum(cpu_type) String(la464) Value(CPU_LA464) + +march= +Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_arch) Init(M_OPTION_NOT_SEEN) +-march=PROCESSOR Generate code for the given PROCESSOR ISA. + +mtune= +Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_tune) Init(M_OPTION_NOT_SEEN) +-mtune=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(lp64d) Value(ABI_BASE_LP64D) + +EnumValue +Enum(abi_base) String(lp64f) Value(ABI_BASE_LP64F) + +EnumValue +Enum(abi_base) String(lp64s) Value(ABI_BASE_LP64S) + +mabi= +Target RejectNegative Joined ToLower Enum(abi_base) Var(la_opt_abi_base) Init(M_OPTION_NOT_SEEN) +-mabi=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. + +; The code model option names for -mcmodel. +Enum +Name(cmodel) Type(int) +The code model option names for -mcmodel: + +EnumValue +Enum(cmodel) String(normal) Value(CMODEL_NORMAL) + +EnumValue +Enum(cmodel) String(tiny) Value(CMODEL_TINY) + +EnumValue +Enum(cmodel) String(tiny-static) Value(CMODEL_TINY_STATIC) + +EnumValue +Enum(cmodel) String(large) Value(CMODEL_LARGE) + +EnumValue +Enum(cmodel) String(extreme) Value(CMODEL_EXTREME) + +mcmodel= +Target RejectNegative Joined Enum(cmodel) Var(la_opt_cmodel) Init(CMODEL_NORMAL) +Specify the code model. diff --git a/gcc/config/loongarch/t-linux b/gcc/config/loongarch/t-linux new file mode 100644 index 00000000000..5b9796aea2b --- /dev/null +++ b/gcc/config/loongarch/t-linux @@ -0,0 +1,53 @@ +# 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 +# <http://www.gnu.org/licenses/>. + +# Multilib +MULTILIB_OPTIONS = mabi=lp64d/mabi=lp64f/mabi=lp64s +MULTILIB_DIRNAMES = base/lp64d base/lp64f base/lp64s + +# The GCC driver always gets all abi-related options on the command line. +# (see loongarch-driver.c:driver_get_normalized_m_opts) +comma=, +MULTILIB_REQUIRED = $(subst $(comma), ,$(TM_MULTILIB_CONFIG)) + +# Multiarch +ifneq ($(call if_multiarch,yes),yes) + # Define LA_DISABLE_MULTIARCH if multiarch is disabled. + tm_defines += LA_DISABLE_MULTIARCH +else + # Only define MULTIARCH_DIRNAME when multiarch is enabled, + # or it would always introduce ${target} into the search path. + MULTIARCH_DIRNAME = $(LA_MULTIARCH_TRIPLET) +endif + +# Don't define MULTILIB_OSDIRNAMES if multilib is disabled. +ifeq ($(filter LA_DISABLE_MULTILIB,$(tm_defines)),) + + MULTILIB_OSDIRNAMES = \ + mabi.lp64d=../lib64$\ + $(call if_multiarch,:loongarch64-linux-gnuf64) + + MULTILIB_OSDIRNAMES += \ + mabi.lp64f=../lib64/f32$\ + $(call if_multiarch,:loongarch64-linux-gnuf32) + + MULTILIB_OSDIRNAMES += \ + mabi.lp64s=../lib64/sf$\ + $(call if_multiarch,:loongarch64-linux-gnusf) + +endif diff --git a/gcc/config/loongarch/t-loongarch b/gcc/config/loongarch/t-loongarch new file mode 100644 index 00000000000..6d6e3435d59 --- /dev/null +++ b/gcc/config/loongarch/t-loongarch @@ -0,0 +1,71 @@ +# 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 +# <http://www.gnu.org/licenses/>. + +# Canonical target triplet from config.gcc +LA_MULTIARCH_TRIPLET = $(patsubst LA_MULTIARCH_TRIPLET=%,%,$\ +$(filter LA_MULTIARCH_TRIPLET=%,$(tm_defines))) + +# String definition header +LA_STR_H = $(srcdir)/config/loongarch/loongarch-str.h + +# String definition header +$(LA_STR_H): s-loongarch-str ; @true +s-loongarch-str: $(srcdir)/config/loongarch/genopts/genstr.sh \ + $(srcdir)/config/loongarch/genopts/loongarch-strings + $(SHELL) $(srcdir)/config/loongarch/genopts/genstr.sh header \ + $(srcdir)/config/loongarch/genopts/loongarch-strings > \ + tmp-loongarch-str.h + $(SHELL) $(srcdir)/../move-if-change tmp-loongarch-str.h \ + $(LA_STR_H) + $(STAMP) s-loongarch-str + +loongarch-c.o: $(srcdir)/config/loongarch/loongarch-c.cc $(CONFIG_H) $(SYSTEM_H) \ + coretypes.h $(TM_H) $(TREE_H) output.h $(C_COMMON_H) $(TARGET_H) + $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ + $(srcdir)/config/loongarch/loongarch-c.cc + +loongarch-builtins.o: $(srcdir)/config/loongarch/loongarch-builtins.cc $(CONFIG_H) \ + $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) $(RECOG_H) langhooks.h \ + $(DIAGNOSTIC_CORE_H) $(OPTABS_H) $(srcdir)/config/loongarch/loongarch-ftypes.def \ + $(srcdir)/config/loongarch/loongarch-modes.def + $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ + $(srcdir)/config/loongarch/loongarch-builtins.cc + +loongarch-driver.o : $(srcdir)/config/loongarch/loongarch-driver.cc $(LA_STR_H) \ + $(CONFIG_H) $(SYSTEM_H) + $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< + +loongarch-opts.o: $(srcdir)/config/loongarch/loongarch-opts.cc $(LA_STR_H) + $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< + +loongarch-cpu.o: $(srcdir)/config/loongarch/loongarch-cpu.cc $(LA_STR_H) + $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< + +loongarch-def.o: $(srcdir)/config/loongarch/loongarch-def.c $(LA_STR_H) + $(CC) -c $(ALL_CFLAGS) $(INCLUDES) $< + +$(srcdir)/config/loongarch/loongarch.opt: s-loongarch-opt ; @true +s-loongarch-opt: $(srcdir)/config/loongarch/genopts/genstr.sh \ + $(srcdir)/config/loongarch/genopts/loongarch.opt.in \ + $(srcdir)/config/loongarch/genopts/loongarch-strings $(LA_STR_H) + $(SHELL) $(srcdir)/config/loongarch/genopts/genstr.sh opt \ + $(srcdir)/config/loongarch/genopts/loongarch.opt.in \ + > tmp-loongarch.opt + $(SHELL) $(srcdir)/../move-if-change tmp-loongarch.opt \ + $(srcdir)/config/loongarch/loongarch.opt + $(STAMP) s-loongarch-opt diff --git a/gcc/configure.ac b/gcc/configure.ac index 90cad309762..ea67fb62292 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -951,6 +951,9 @@ AC_ARG_ENABLE(fixed-point, mips*-*-*) enable_fixed_point=yes ;; + loongarch*-*-*) + enable_fixed_point=yes + ;; *) AC_MSG_WARN([fixed-point is not supported for this target, ignored]) enable_fixed_point=no @@ -3838,6 +3841,17 @@ foo: data8 25 movl r24 = @tprel(foo#)' tls_as_opt=--fatal-warnings ;; + loongarch*-*-*) + conftest_s=' + .section .tdata,"awT",@progbits +x: .word 2 + .text + la.tls.gd $a0,x + bl __tls_get_addr' + tls_first_major=0 + tls_first_minor=0 + tls_as_opt='--fatal-warnings' + ;; microblaze*-*-*) conftest_s=' .section .tdata,"awT",@progbits @@ -5300,6 +5314,17 @@ configured with --enable-newlib-nano-formatted-io.]) [AC_DEFINE(HAVE_AS_MARCH_ZIFENCEI, 1, [Define if the assembler understands -march=rv*_zifencei.])]) ;; + loongarch*-*-*) + gcc_GAS_CHECK_FEATURE([.dtprelword support], + gcc_cv_as_loongarch_dtprelword, [2,18,0],, + [.section .tdata,"awT",@progbits +x: + .word 2 + .text + .dtprelword x+0x8000],, + [AC_DEFINE(HAVE_AS_DTPRELWORD, 1, + [Define if your assembler supports .dtprelword.])]) + ;; s390*-*-*) gcc_GAS_CHECK_FEATURE([.gnu_attribute support], gcc_cv_as_s390_gnu_attribute,, @@ -5333,11 +5358,11 @@ configured with --enable-newlib-nano-formatted-io.]) ;; esac -# Mips and HP-UX need the GNU assembler. +# Mips, LoongArch and HP-UX need the GNU assembler. # Linux on IA64 might be able to use the Intel assembler. case "$target" in - mips*-*-* | *-*-hpux* ) + mips*-*-* | loongarch*-*-* | *-*-hpux* ) if test x$gas_flag = xyes \ || test x"$host" != x"$build" \ || test ! -x "$gcc_cv_as" \ @@ -5494,8 +5519,8 @@ esac # ??? Once 2.11 is released, probably need to add first known working # version to the per-target configury. case "$cpu_type" in - aarch64 | alpha | arc | arm | avr | bfin | cris | csky | i386 | m32c | m68k \ - | microblaze | mips | nds32 | nios2 | pa | riscv | rs6000 | score | sparc \ + aarch64 | alpha | arc | arm | avr | bfin | cris | csky | i386 | loongarch | m32c \ + | m68k | microblaze | mips | nds32 | nios2 | pa | riscv | rs6000 | score | sparc \ | tilegx | tilepro | visium | xstormy16 | xtensa) insn="nop" ;; |