RISC-V Port: gcc
gcc/ChangeLog: 2017-02-06 Palmer Dabbelt <palmer@dabbelt.com> * config/riscv/riscv.c: New file. * gcc/common/config/riscv/riscv-common.c: Likewise. * config.gcc: Likewise. * config/riscv/constraints.md: Likewise. * config/riscv/elf.h: Likewise. * config/riscv/generic.md: Likewise. * config/riscv/linux.h: Likewise. * config/riscv/multilib-generator: Likewise. * config/riscv/peephole.md: Likewise. * config/riscv/pic.md: Likewise. * config/riscv/predicates.md: Likewise. * config/riscv/riscv-builtins.c: Likewise. * config/riscv/riscv-c.c: Likewise. * config/riscv/riscv-ftypes.def: Likewise. * config/riscv/riscv-modes.def: Likewise. * config/riscv/riscv-opts.h: Likewise. * config/riscv/riscv-protos.h: Likewise. * config/riscv/riscv.h: Likewise. * config/riscv/riscv.md: Likewise. * config/riscv/riscv.opt: Likewise. * config/riscv/sync.md: Likewise. * config/riscv/t-elf-multilib: Likewise. * config/riscv/t-linux: Likewise. * config/riscv/t-linux-multilib: Likewise. * config/riscv/t-riscv: Likewise. * configure.ac: Likewise. * doc/contrib.texi: Add Kito Cheng, Palmer Dabbelt, and Andrew Waterman as RISC-V maintainers. * doc/install.texi: Add RISC-V entries. * doc/invoke.texi: Add RISC-V options section. * doc/md.texi: Add RISC-V constraints section. From-SVN: r245224
This commit is contained in:
parent
44a6da7bac
commit
09cae7507d
31 changed files with 9091 additions and 2 deletions
|
@ -1,3 +1,37 @@
|
|||
2017-02-06 Palmer Dabbelt <palmer@dabbelt.com>
|
||||
|
||||
* config/riscv/riscv.c: New file.
|
||||
* gcc/common/config/riscv/riscv-common.c: Likewise.
|
||||
* config.gcc: Likewise.
|
||||
* config/riscv/constraints.md: Likewise.
|
||||
* config/riscv/elf.h: Likewise.
|
||||
* config/riscv/generic.md: Likewise.
|
||||
* config/riscv/linux.h: Likewise.
|
||||
* config/riscv/multilib-generator: Likewise.
|
||||
* config/riscv/peephole.md: Likewise.
|
||||
* config/riscv/pic.md: Likewise.
|
||||
* config/riscv/predicates.md: Likewise.
|
||||
* config/riscv/riscv-builtins.c: Likewise.
|
||||
* config/riscv/riscv-c.c: Likewise.
|
||||
* config/riscv/riscv-ftypes.def: Likewise.
|
||||
* config/riscv/riscv-modes.def: Likewise.
|
||||
* config/riscv/riscv-opts.h: Likewise.
|
||||
* config/riscv/riscv-protos.h: Likewise.
|
||||
* config/riscv/riscv.h: Likewise.
|
||||
* config/riscv/riscv.md: Likewise.
|
||||
* config/riscv/riscv.opt: Likewise.
|
||||
* config/riscv/sync.md: Likewise.
|
||||
* config/riscv/t-elf-multilib: Likewise.
|
||||
* config/riscv/t-linux: Likewise.
|
||||
* config/riscv/t-linux-multilib: Likewise.
|
||||
* config/riscv/t-riscv: Likewise.
|
||||
* configure.ac: Likewise.
|
||||
* doc/contrib.texi: Add Kito Cheng, Palmer Dabbelt, and Andrew
|
||||
Waterman as RISC-V maintainers.
|
||||
* doc/install.texi: Add RISC-V entries.
|
||||
* doc/invoke.texi: Add RISC-V options section.
|
||||
* doc/md.texi: Add RISC-V constraints section.
|
||||
|
||||
2017-02-06 Michael Meissner <meissner@linux.vnet.ibm.com>
|
||||
|
||||
PR target/66144
|
||||
|
|
131
gcc/common/config/riscv/riscv-common.c
Normal file
131
gcc/common/config/riscv/riscv-common.c
Normal file
|
@ -0,0 +1,131 @@
|
|||
/* Common hooks for RISC-V.
|
||||
Copyright (C) 2016 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"
|
||||
|
||||
/* Parse a RISC-V ISA string into an option mask. */
|
||||
|
||||
static void
|
||||
riscv_parse_arch_string (const char *isa, int *flags, location_t loc)
|
||||
{
|
||||
const char *p = isa;
|
||||
|
||||
if (strncmp (p, "rv32", 4) == 0)
|
||||
*flags &= ~MASK_64BIT, p += 4;
|
||||
else if (strncmp (p, "rv64", 4) == 0)
|
||||
*flags |= MASK_64BIT, p += 4;
|
||||
else
|
||||
{
|
||||
error_at (loc, "-march=%s: ISA string must begin with rv32 or rv64", isa);
|
||||
return;
|
||||
}
|
||||
|
||||
if (*p == 'g')
|
||||
{
|
||||
p++;
|
||||
|
||||
*flags |= MASK_MUL;
|
||||
*flags |= MASK_ATOMIC;
|
||||
*flags |= MASK_HARD_FLOAT;
|
||||
*flags |= MASK_DOUBLE_FLOAT;
|
||||
}
|
||||
else if (*p == 'i')
|
||||
{
|
||||
p++;
|
||||
|
||||
*flags &= ~MASK_MUL;
|
||||
if (*p == 'm')
|
||||
*flags |= MASK_MUL, p++;
|
||||
|
||||
*flags &= ~MASK_ATOMIC;
|
||||
if (*p == 'a')
|
||||
*flags |= MASK_ATOMIC, p++;
|
||||
|
||||
*flags &= ~(MASK_HARD_FLOAT | MASK_DOUBLE_FLOAT);
|
||||
if (*p == 'f')
|
||||
{
|
||||
*flags |= MASK_HARD_FLOAT, p++;
|
||||
|
||||
if (*p == 'd')
|
||||
{
|
||||
*flags |= MASK_DOUBLE_FLOAT;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error_at (loc, "-march=%s: invalid ISA string", isa);
|
||||
return;
|
||||
}
|
||||
|
||||
*flags &= ~MASK_RVC;
|
||||
if (*p == 'c')
|
||||
*flags |= MASK_RVC, p++;
|
||||
|
||||
if (*p)
|
||||
{
|
||||
error_at (loc, "-march=%s: unsupported ISA substring %qs", isa, p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Implement TARGET_HANDLE_OPTION. */
|
||||
|
||||
static bool
|
||||
riscv_handle_option (struct gcc_options *opts,
|
||||
struct gcc_options *opts_set ATTRIBUTE_UNUSED,
|
||||
const struct cl_decoded_option *decoded,
|
||||
location_t loc)
|
||||
{
|
||||
switch (decoded->opt_index)
|
||||
{
|
||||
case OPT_march_:
|
||||
riscv_parse_arch_string (decoded->arg, &opts->x_target_flags, loc);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */
|
||||
static const struct default_options riscv_option_optimization_table[] =
|
||||
{
|
||||
{ OPT_LEVELS_1_PLUS, OPT_fsection_anchors, NULL, 1 },
|
||||
{ OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
|
||||
{ OPT_LEVELS_2_PLUS, OPT_free, NULL, 1 },
|
||||
{ OPT_LEVELS_NONE, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
#undef TARGET_OPTION_OPTIMIZATION_TABLE
|
||||
#define TARGET_OPTION_OPTIMIZATION_TABLE riscv_option_optimization_table
|
||||
|
||||
#undef TARGET_HANDLE_OPTION
|
||||
#define TARGET_HANDLE_OPTION riscv_handle_option
|
||||
|
||||
struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
|
|
@ -451,6 +451,10 @@ powerpc*-*-*)
|
|||
esac
|
||||
extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt"
|
||||
;;
|
||||
riscv*)
|
||||
cpu_type=riscv
|
||||
extra_objs="riscv-builtins.o riscv-c.o"
|
||||
;;
|
||||
rs6000*-*-*)
|
||||
extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt"
|
||||
;;
|
||||
|
@ -2016,6 +2020,34 @@ microblaze*-*-elf)
|
|||
cxx_target_objs="${cxx_target_objs} microblaze-c.o"
|
||||
tmake_file="${tmake_file} microblaze/t-microblaze"
|
||||
;;
|
||||
riscv*-*-linux*)
|
||||
tm_file="elfos.h gnu-user.h linux.h glibc-stdint.h ${tm_file} riscv/linux.h"
|
||||
case "x${enable_multilib}" in
|
||||
xno) ;;
|
||||
xyes) tmake_file="${tmake_file} riscv/t-linux-multilib" ;;
|
||||
*) echo "Unknown value for enable_multilib"; exit 1
|
||||
esac
|
||||
tmake_file="${tmake_file} riscv/t-riscv riscv/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
|
||||
;;
|
||||
riscv*-*-elf*)
|
||||
tm_file="elfos.h newlib-stdint.h ${tm_file} riscv/elf.h"
|
||||
case "x${enable_multilib}" in
|
||||
xno) ;;
|
||||
xyes) tmake_file="${tmake_file} riscv/t-elf-multilib" ;;
|
||||
*) echo "Unknown value for enable_multilib"; exit 1
|
||||
esac
|
||||
tmake_file="${tmake_file} riscv/t-riscv"
|
||||
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 netbsd.h netbsd-elf.h mips/netbsd.h"
|
||||
|
@ -3939,6 +3971,70 @@ case "${target}" in
|
|||
done
|
||||
;;
|
||||
|
||||
riscv*-*-*)
|
||||
supported_defaults="abi arch tune"
|
||||
|
||||
case "${target}" in
|
||||
riscv32*) xlen=32 ;;
|
||||
riscv64*) xlen=64 ;;
|
||||
*) echo "Unsupported RISC-V target ${target}" 1>&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
# Infer arch from --with-arch, --target, and --with-abi.
|
||||
case "${with_arch}" in
|
||||
rv32i* | rv32g* | rv64i* | rv64g*)
|
||||
# OK.
|
||||
;;
|
||||
"")
|
||||
# Infer XLEN, but otherwise assume GC.
|
||||
case "${with_abi}" in
|
||||
ilp32 | ilp32f | ilp32d) with_arch="rv32gc" ;;
|
||||
lp64 | lp64f | lp64d) with_arch="rv64gc" ;;
|
||||
*) with_arch="rv${xlen}gc" ;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
echo "--with-arch=${with_arch} is not supported. The argument must begin with rv32i, rv32g, rv64i, or rv64g." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Make sure --with-abi is valid. If it was not specified,
|
||||
# pick a default based on the ISA, preferring soft-float
|
||||
# unless the D extension is present.
|
||||
case "${with_abi}" in
|
||||
ilp32 | ilp32f | ilp32d | lp64 | lp64f | lp64d)
|
||||
;;
|
||||
"")
|
||||
case "${with_arch}" in
|
||||
rv32*d* | rv32g*) with_abi=ilp32d ;;
|
||||
rv32*) with_abi=ilp32 ;;
|
||||
rv64*d* | rv64g*) with_abi=lp64d ;;
|
||||
rv64*) with_abi=lp64 ;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
echo "--with-abi=${with_abi} is not supported" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Make sure ABI and ISA are compatible.
|
||||
case "${with_abi},${with_arch}" in
|
||||
ilp32,rv32* \
|
||||
| ilp32f,rv32*f* | ilp32f,rv32g* \
|
||||
| ilp32d,rv32*d* | ilp32d,rv32g* \
|
||||
| lp64,rv64* \
|
||||
| lp64f,rv64*f* | lp64f,rv64g* \
|
||||
| lp64d,rv64*d* | lp64d,rv64g*)
|
||||
;;
|
||||
*)
|
||||
echo "--with-abi=${with_abi} is not supported for ISA ${with_arch}" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
mips*-*-*)
|
||||
supported_defaults="abi arch arch_32 arch_64 float fpu nan fp_32 odd_spreg_32 tune tune_32 tune_64 divide llsc mips-plt synci lxc1-sxc1 madd4"
|
||||
|
||||
|
|
78
gcc/config/riscv/constraints.md
Normal file
78
gcc/config/riscv/constraints.md
Normal file
|
@ -0,0 +1,78 @@
|
|||
;; Constraint definitions for RISC-V target.
|
||||
;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
|
||||
;; Contributed by Andrew Waterman (andrew@sifive.com).
|
||||
;; 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
|
||||
;; <http://www.gnu.org/licenses/>.
|
||||
|
||||
;; Register constraints
|
||||
|
||||
(define_register_constraint "f" "TARGET_HARD_FLOAT ? FP_REGS : NO_REGS"
|
||||
"A floating-point register (if available).")
|
||||
|
||||
(define_register_constraint "j" "SIBCALL_REGS"
|
||||
"@internal")
|
||||
|
||||
;; Avoid using register t0 for JALR's argument, because for some
|
||||
;; microarchitectures that is a return-address stack hint.
|
||||
(define_register_constraint "l" "JALR_REGS"
|
||||
"@internal")
|
||||
|
||||
;; General constraints
|
||||
|
||||
(define_constraint "I"
|
||||
"An I-type 12-bit signed immediate."
|
||||
(and (match_code "const_int")
|
||||
(match_test "SMALL_OPERAND (ival)")))
|
||||
|
||||
(define_constraint "J"
|
||||
"Integer zero."
|
||||
(and (match_code "const_int")
|
||||
(match_test "ival == 0")))
|
||||
|
||||
(define_constraint "K"
|
||||
"A 5-bit unsigned immediate for CSR access instructions."
|
||||
(and (match_code "const_int")
|
||||
(match_test "IN_RANGE (ival, 0, 31)")))
|
||||
|
||||
;; Floating-point constant +0.0, used for FCVT-based moves when FMV is
|
||||
;; not available in RV32.
|
||||
(define_constraint "G"
|
||||
"@internal"
|
||||
(and (match_code "const_double")
|
||||
(match_test "op == CONST0_RTX (mode)")))
|
||||
|
||||
(define_memory_constraint "A"
|
||||
"An address that is held in a general-purpose register."
|
||||
(and (match_code "mem")
|
||||
(match_test "GET_CODE(XEXP(op,0)) == REG")))
|
||||
|
||||
(define_constraint "S"
|
||||
"@internal
|
||||
A constant call address."
|
||||
(match_operand 0 "absolute_symbolic_operand"))
|
||||
|
||||
(define_constraint "U"
|
||||
"@internal
|
||||
A PLT-indirect call address."
|
||||
(match_operand 0 "plt_symbolic_operand"))
|
||||
|
||||
(define_constraint "T"
|
||||
"@internal
|
||||
A constant @code{move_operand}."
|
||||
(and (match_operand 0 "move_operand")
|
||||
(match_test "CONSTANT_P (op)")))
|
35
gcc/config/riscv/elf.h
Normal file
35
gcc/config/riscv/elf.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/* Target macros for riscv*-elf targets.
|
||||
Copyright (C) 1994-2017 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 LINK_SPEC "\
|
||||
-melf" XLEN_SPEC "lriscv \
|
||||
%{shared}"
|
||||
|
||||
/* Link against Newlib libraries, because the ELF backend assumes Newlib.
|
||||
Handle the circular dependence between libc and libgloss. */
|
||||
#undef LIB_SPEC
|
||||
#define LIB_SPEC "--start-group -lc -lgloss --end-group"
|
||||
|
||||
#undef STARTFILE_SPEC
|
||||
#define STARTFILE_SPEC "crt0%O%s crtbegin%O%s"
|
||||
|
||||
#undef ENDFILE_SPEC
|
||||
#define ENDFILE_SPEC "crtend%O%s"
|
||||
|
||||
#define NO_IMPLICIT_EXTERN_C 1
|
78
gcc/config/riscv/generic.md
Normal file
78
gcc/config/riscv/generic.md
Normal file
|
@ -0,0 +1,78 @@
|
|||
;; Generic DFA-based pipeline description for RISC-V targets.
|
||||
;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
|
||||
;; Contributed by Andrew Waterman (andrew@sifive.com).
|
||||
;; 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
|
||||
;; <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
(define_automaton "pipe0")
|
||||
(define_cpu_unit "alu" "pipe0")
|
||||
(define_cpu_unit "imuldiv" "pipe0")
|
||||
(define_cpu_unit "fdivsqrt" "pipe0")
|
||||
|
||||
(define_insn_reservation "generic_alu" 1
|
||||
(eq_attr "type" "unknown,const,arith,shift,slt,multi,nop,logical,move")
|
||||
"alu")
|
||||
|
||||
(define_insn_reservation "generic_load" 3
|
||||
(eq_attr "type" "load,fpload")
|
||||
"alu")
|
||||
|
||||
(define_insn_reservation "generic_store" 1
|
||||
(eq_attr "type" "store,fpstore")
|
||||
"alu")
|
||||
|
||||
(define_insn_reservation "generic_xfer" 3
|
||||
(eq_attr "type" "mfc,mtc,fcvt,fmove,fcmp")
|
||||
"alu")
|
||||
|
||||
(define_insn_reservation "generic_branch" 1
|
||||
(eq_attr "type" "branch,jump,call")
|
||||
"alu")
|
||||
|
||||
(define_insn_reservation "generic_imul" 10
|
||||
(eq_attr "type" "imul")
|
||||
"imuldiv*10")
|
||||
|
||||
(define_insn_reservation "generic_idivsi" 34
|
||||
(and (eq_attr "type" "idiv")
|
||||
(eq_attr "mode" "SI"))
|
||||
"imuldiv*34")
|
||||
|
||||
(define_insn_reservation "generic_idivdi" 66
|
||||
(and (eq_attr "type" "idiv")
|
||||
(eq_attr "mode" "DI"))
|
||||
"imuldiv*66")
|
||||
|
||||
(define_insn_reservation "generic_fmul_single" 5
|
||||
(and (eq_attr "type" "fadd,fmul,fmadd")
|
||||
(eq_attr "mode" "SF"))
|
||||
"alu")
|
||||
|
||||
(define_insn_reservation "generic_fmul_double" 7
|
||||
(and (eq_attr "type" "fadd,fmul,fmadd")
|
||||
(eq_attr "mode" "DF"))
|
||||
"alu")
|
||||
|
||||
(define_insn_reservation "generic_fdiv" 20
|
||||
(eq_attr "type" "fdiv")
|
||||
"fdivsqrt*20")
|
||||
|
||||
(define_insn_reservation "generic_fsqrt" 25
|
||||
(eq_attr "type" "fsqrt")
|
||||
"fdivsqrt*25")
|
44
gcc/config/riscv/linux.h
Normal file
44
gcc/config/riscv/linux.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/* Definitions for RISC-V GNU/Linux systems with ELF format.
|
||||
Copyright (C) 1998-2017 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 TARGET_OS_CPP_BUILTINS() \
|
||||
do { \
|
||||
GNU_USER_TARGET_OS_CPP_BUILTINS(); \
|
||||
} while (0)
|
||||
|
||||
#define GLIBC_DYNAMIC_LINKER "/lib/ld-linux-riscv" XLEN_SPEC "-" ABI_SPEC ".so.1"
|
||||
|
||||
/* Because RISC-V only has word-sized atomics, it requries libatomic where
|
||||
others do not. So link libatomic by default, as needed. */
|
||||
#undef LIB_SPEC
|
||||
#ifdef LD_AS_NEEDED_OPTION
|
||||
#define LIB_SPEC GNU_USER_TARGET_LIB_SPEC \
|
||||
" %{pthread:" LD_AS_NEEDED_OPTION " -latomic " LD_NO_AS_NEEDED_OPTION "}"
|
||||
#else
|
||||
#define LIB_SPEC GNU_USER_TARGET_LIB_SPEC " -latomic "
|
||||
#endif
|
||||
|
||||
#define LINK_SPEC "\
|
||||
-melf" XLEN_SPEC "lriscv \
|
||||
%{shared} \
|
||||
%{!shared: \
|
||||
%{!static: \
|
||||
%{rdynamic:-export-dynamic} \
|
||||
-dynamic-linker " GNU_USER_DYNAMIC_LINKER "} \
|
||||
%{static:-static}}"
|
65
gcc/config/riscv/multilib-generator
Executable file
65
gcc/config/riscv/multilib-generator
Executable file
|
@ -0,0 +1,65 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# RISC-V multilib list generator.
|
||||
# Copyright (C) 2011-2017 Free Software Foundation, Inc.
|
||||
# Contributed by Andrew Waterman (andrew@sifive.com).
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
# Each argument to this script is of the form
|
||||
# <primary arch>-<abi>-<additional arches>-<extensions>
|
||||
# For example,
|
||||
# rv32imafd-ilp32d-rv32g-c,v
|
||||
# means that, in addition to rv32imafd, these configurations can also use the
|
||||
# rv32imafd-ilp32d libraries: rv32imafdc, rv32imafdv, rv32g, rv32gc, rv32gv
|
||||
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
import collections
|
||||
|
||||
arches = collections.OrderedDict()
|
||||
abis = collections.OrderedDict()
|
||||
required = []
|
||||
reuse = []
|
||||
|
||||
for cfg in sys.argv[1:]:
|
||||
(arch, abi, extra, ext) = cfg.split('-')
|
||||
arches[arch] = 1
|
||||
abis[abi] = 1
|
||||
extra = list(filter(None, extra.split(',')))
|
||||
ext = list(filter(None, ext.split(',')))
|
||||
alts = sum([[x] + [x + y for y in ext] for x in [arch] + extra], [])
|
||||
alts = alts + [x.replace('imafd', 'g') for x in alts if 'imafd' in x]
|
||||
for alt in alts[1:]:
|
||||
arches[alt] = 1
|
||||
reuse.append('march.%s/mabi.%s=march.%s/mabi.%s' % (arch, abi, alt, abi))
|
||||
required.append('march=%s/mabi=%s' % (arch, abi))
|
||||
|
||||
arch_options = '/'.join(['march=%s' % x for x in arches.keys()])
|
||||
arch_dirnames = ' \\\n'.join(arches.keys())
|
||||
|
||||
abi_options = '/'.join(['mabi=%s' % x for x in abis.keys()])
|
||||
abi_dirnames = ' \\\n'.join(abis.keys())
|
||||
|
||||
prog = sys.argv[0].split('/')[-1]
|
||||
print('# This file was generated by %s with the command:' % prog)
|
||||
print('# %s' % ' '.join(sys.argv))
|
||||
|
||||
print('MULTILIB_OPTIONS = %s %s' % (arch_options, abi_options))
|
||||
print('MULTILIB_DIRNAMES = %s %s' % (arch_dirnames, abi_dirnames))
|
||||
print('MULTILIB_REQUIRED = %s' % ' \\\n'.join(required))
|
||||
print('MULTILIB_REUSE = %s' % ' \\\n'.join(reuse))
|
40
gcc/config/riscv/peephole.md
Normal file
40
gcc/config/riscv/peephole.md
Normal file
|
@ -0,0 +1,40 @@
|
|||
;; Peephole optimizations for RISC-V for GNU compiler.
|
||||
;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
|
||||
;; Contributed by Andrew Waterman (andrew@sifive.com).
|
||||
|
||||
;; 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/>.
|
||||
|
||||
;; Simplify (unsigned long)(unsigned int)a << const
|
||||
(define_peephole2
|
||||
[(set (match_operand:DI 0 "register_operand")
|
||||
(ashift:DI (match_operand:DI 1 "register_operand")
|
||||
(match_operand 2 "const_int_operand")))
|
||||
(set (match_operand:DI 3 "register_operand")
|
||||
(lshiftrt:DI (match_dup 0) (match_dup 2)))
|
||||
(set (match_operand:DI 4 "register_operand")
|
||||
(ashift:DI (match_dup 3) (match_operand 5 "const_int_operand")))]
|
||||
"TARGET_64BIT
|
||||
&& INTVAL (operands[5]) < INTVAL (operands[2])
|
||||
&& (REGNO (operands[3]) == REGNO (operands[4])
|
||||
|| peep2_reg_dead_p (3, operands[3]))"
|
||||
[(set (match_dup 0)
|
||||
(ashift:DI (match_dup 1) (match_dup 2)))
|
||||
(set (match_dup 4)
|
||||
(lshiftrt:DI (match_dup 0) (match_operand 5)))]
|
||||
{
|
||||
operands[5] = GEN_INT (INTVAL (operands[2]) - INTVAL (operands[5]));
|
||||
})
|
85
gcc/config/riscv/pic.md
Normal file
85
gcc/config/riscv/pic.md
Normal file
|
@ -0,0 +1,85 @@
|
|||
;; PIC codegen for RISC-V for GNU compiler.
|
||||
;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
|
||||
;; Contributed by Andrew Waterman (andrew@sifive.com).
|
||||
|
||||
;; 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/>.
|
||||
|
||||
|
||||
;; Simplify PIC loads to static variables.
|
||||
;; These should go away once we figure out how to emit auipc discretely.
|
||||
|
||||
(define_insn "*local_pic_load<mode>"
|
||||
[(set (match_operand:ANYI 0 "register_operand" "=r")
|
||||
(mem:ANYI (match_operand 1 "absolute_symbolic_operand" "")))]
|
||||
"USE_LOAD_ADDRESS_MACRO (operands[1])"
|
||||
"<load>\t%0,%1"
|
||||
[(set (attr "length") (const_int 8))])
|
||||
|
||||
(define_insn "*local_pic_load<mode>"
|
||||
[(set (match_operand:ANYF 0 "register_operand" "=f")
|
||||
(mem:ANYF (match_operand 1 "absolute_symbolic_operand" "")))
|
||||
(clobber (match_scratch:DI 2 "=r"))]
|
||||
"TARGET_HARD_FLOAT && TARGET_64BIT && USE_LOAD_ADDRESS_MACRO (operands[1])"
|
||||
"<load>\t%0,%1,%2"
|
||||
[(set (attr "length") (const_int 8))])
|
||||
|
||||
(define_insn "*local_pic_load<mode>"
|
||||
[(set (match_operand:ANYF 0 "register_operand" "=f")
|
||||
(mem:ANYF (match_operand 1 "absolute_symbolic_operand" "")))
|
||||
(clobber (match_scratch:SI 2 "=r"))]
|
||||
"TARGET_HARD_FLOAT && !TARGET_64BIT && USE_LOAD_ADDRESS_MACRO (operands[1])"
|
||||
"<load>\t%0,%1,%2"
|
||||
[(set (attr "length") (const_int 8))])
|
||||
|
||||
(define_insn "*local_pic_loadu<mode>"
|
||||
[(set (match_operand:SUPERQI 0 "register_operand" "=r")
|
||||
(zero_extend:SUPERQI (mem:SUBX (match_operand 1 "absolute_symbolic_operand" ""))))]
|
||||
"USE_LOAD_ADDRESS_MACRO (operands[1])"
|
||||
"<load>u\t%0,%1"
|
||||
[(set (attr "length") (const_int 8))])
|
||||
|
||||
(define_insn "*local_pic_storedi<mode>"
|
||||
[(set (mem:ANYI (match_operand 0 "absolute_symbolic_operand" ""))
|
||||
(match_operand:ANYI 1 "reg_or_0_operand" "rJ"))
|
||||
(clobber (match_scratch:DI 2 "=&r"))]
|
||||
"TARGET_64BIT && USE_LOAD_ADDRESS_MACRO (operands[0])"
|
||||
"<store>\t%z1,%0,%2"
|
||||
[(set (attr "length") (const_int 8))])
|
||||
|
||||
(define_insn "*local_pic_storesi<mode>"
|
||||
[(set (mem:ANYI (match_operand 0 "absolute_symbolic_operand" ""))
|
||||
(match_operand:ANYI 1 "reg_or_0_operand" "rJ"))
|
||||
(clobber (match_scratch:SI 2 "=&r"))]
|
||||
"!TARGET_64BIT && USE_LOAD_ADDRESS_MACRO (operands[0])"
|
||||
"<store>\t%z1,%0,%2"
|
||||
[(set (attr "length") (const_int 8))])
|
||||
|
||||
(define_insn "*local_pic_storedi<mode>"
|
||||
[(set (mem:ANYF (match_operand 0 "absolute_symbolic_operand" ""))
|
||||
(match_operand:ANYF 1 "register_operand" "f"))
|
||||
(clobber (match_scratch:DI 2 "=r"))]
|
||||
"TARGET_HARD_FLOAT && TARGET_64BIT && USE_LOAD_ADDRESS_MACRO (operands[0])"
|
||||
"<store>\t%1,%0,%2"
|
||||
[(set (attr "length") (const_int 8))])
|
||||
|
||||
(define_insn "*local_pic_storesi<mode>"
|
||||
[(set (mem:ANYF (match_operand 0 "absolute_symbolic_operand" ""))
|
||||
(match_operand:ANYF 1 "register_operand" "f"))
|
||||
(clobber (match_scratch:SI 2 "=r"))]
|
||||
"TARGET_HARD_FLOAT && !TARGET_64BIT && USE_LOAD_ADDRESS_MACRO (operands[0])"
|
||||
"<store>\t%1,%0,%2"
|
||||
[(set (attr "length") (const_int 8))])
|
180
gcc/config/riscv/predicates.md
Normal file
180
gcc/config/riscv/predicates.md
Normal file
|
@ -0,0 +1,180 @@
|
|||
;; Predicate description for RISC-V target.
|
||||
;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
|
||||
;; Contributed by Andrew Waterman (andrew@sifive.com).
|
||||
;; 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
|
||||
;; <http://www.gnu.org/licenses/>.
|
||||
|
||||
(define_predicate "const_arith_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "SMALL_OPERAND (INTVAL (op))")))
|
||||
|
||||
(define_predicate "arith_operand"
|
||||
(ior (match_operand 0 "const_arith_operand")
|
||||
(match_operand 0 "register_operand")))
|
||||
|
||||
(define_predicate "const_csr_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "IN_RANGE (INTVAL (op), 0, 31)")))
|
||||
|
||||
(define_predicate "csr_operand"
|
||||
(ior (match_operand 0 "const_csr_operand")
|
||||
(match_operand 0 "register_operand")))
|
||||
|
||||
(define_predicate "sle_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "SMALL_OPERAND (INTVAL (op) + 1)")))
|
||||
|
||||
(define_predicate "sleu_operand"
|
||||
(and (match_operand 0 "sle_operand")
|
||||
(match_test "INTVAL (op) + 1 != 0")))
|
||||
|
||||
(define_predicate "const_0_operand"
|
||||
(and (match_code "const_int,const_wide_int,const_double,const_vector")
|
||||
(match_test "op == CONST0_RTX (GET_MODE (op))")))
|
||||
|
||||
(define_predicate "reg_or_0_operand"
|
||||
(ior (match_operand 0 "const_0_operand")
|
||||
(match_operand 0 "register_operand")))
|
||||
|
||||
;; Only use branch-on-bit sequences when the mask is not an ANDI immediate.
|
||||
(define_predicate "branch_on_bit_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "INTVAL (op) >= IMM_BITS - 1")))
|
||||
|
||||
;; A legitimate CONST_INT operand that takes more than one instruction
|
||||
;; to load.
|
||||
(define_predicate "splittable_const_int_operand"
|
||||
(match_code "const_int")
|
||||
{
|
||||
/* Don't handle multi-word moves this way; we don't want to introduce
|
||||
the individual word-mode moves until after reload. */
|
||||
if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
|
||||
return false;
|
||||
|
||||
/* Otherwise check whether the constant can be loaded in a single
|
||||
instruction. */
|
||||
return !LUI_OPERAND (INTVAL (op)) && !SMALL_OPERAND (INTVAL (op));
|
||||
})
|
||||
|
||||
(define_predicate "move_operand"
|
||||
(match_operand 0 "general_operand")
|
||||
{
|
||||
enum riscv_symbol_type symbol_type;
|
||||
|
||||
/* The thinking here is as follows:
|
||||
|
||||
(1) The move expanders should split complex load sequences into
|
||||
individual instructions. Those individual instructions can
|
||||
then be optimized by all rtl passes.
|
||||
|
||||
(2) The target of pre-reload load sequences should not be used
|
||||
to store temporary results. If the target register is only
|
||||
assigned one value, reload can rematerialize that value
|
||||
on demand, rather than spill it to the stack.
|
||||
|
||||
(3) If we allowed pre-reload passes like combine and cse to recreate
|
||||
complex load sequences, we would want to be able to split the
|
||||
sequences before reload as well, so that the pre-reload scheduler
|
||||
can see the individual instructions. This falls foul of (2);
|
||||
the splitter would be forced to reuse the target register for
|
||||
intermediate results.
|
||||
|
||||
(4) We want to define complex load splitters for combine. These
|
||||
splitters can request a temporary scratch register, which avoids
|
||||
the problem in (2). They allow things like:
|
||||
|
||||
(set (reg T1) (high SYM))
|
||||
(set (reg T2) (low (reg T1) SYM))
|
||||
(set (reg X) (plus (reg T2) (const_int OFFSET)))
|
||||
|
||||
to be combined into:
|
||||
|
||||
(set (reg T3) (high SYM+OFFSET))
|
||||
(set (reg X) (lo_sum (reg T3) SYM+OFFSET))
|
||||
|
||||
if T2 is only used this once. */
|
||||
switch (GET_CODE (op))
|
||||
{
|
||||
case CONST_INT:
|
||||
return !splittable_const_int_operand (op, mode);
|
||||
|
||||
case CONST:
|
||||
case SYMBOL_REF:
|
||||
case LABEL_REF:
|
||||
return riscv_symbolic_constant_p (op, &symbol_type)
|
||||
&& !riscv_split_symbol_type (symbol_type);
|
||||
|
||||
case HIGH:
|
||||
op = XEXP (op, 0);
|
||||
return riscv_symbolic_constant_p (op, &symbol_type)
|
||||
&& riscv_split_symbol_type (symbol_type)
|
||||
&& symbol_type != SYMBOL_PCREL;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
})
|
||||
|
||||
(define_predicate "symbolic_operand"
|
||||
(match_code "const,symbol_ref,label_ref")
|
||||
{
|
||||
enum riscv_symbol_type type;
|
||||
return riscv_symbolic_constant_p (op, &type);
|
||||
})
|
||||
|
||||
(define_predicate "absolute_symbolic_operand"
|
||||
(match_code "const,symbol_ref,label_ref")
|
||||
{
|
||||
enum riscv_symbol_type type;
|
||||
return (riscv_symbolic_constant_p (op, &type)
|
||||
&& (type == SYMBOL_ABSOLUTE || type == SYMBOL_PCREL));
|
||||
})
|
||||
|
||||
(define_predicate "plt_symbolic_operand"
|
||||
(match_code "const,symbol_ref,label_ref")
|
||||
{
|
||||
enum riscv_symbol_type type;
|
||||
return (riscv_symbolic_constant_p (op, &type)
|
||||
&& type == SYMBOL_GOT_DISP && !SYMBOL_REF_WEAK (op) && TARGET_PLT);
|
||||
})
|
||||
|
||||
(define_predicate "call_insn_operand"
|
||||
(ior (match_operand 0 "absolute_symbolic_operand")
|
||||
(match_operand 0 "plt_symbolic_operand")
|
||||
(match_operand 0 "register_operand")))
|
||||
|
||||
(define_predicate "modular_operator"
|
||||
(match_code "plus,minus,mult,ashift"))
|
||||
|
||||
(define_predicate "equality_operator"
|
||||
(match_code "eq,ne"))
|
||||
|
||||
(define_predicate "order_operator"
|
||||
(match_code "eq,ne,lt,ltu,le,leu,ge,geu,gt,gtu"))
|
||||
|
||||
(define_predicate "signed_order_operator"
|
||||
(match_code "eq,ne,lt,le,ge,gt"))
|
||||
|
||||
(define_predicate "fp_native_comparison"
|
||||
(match_code "eq,lt,le,gt,ge"))
|
||||
|
||||
(define_predicate "fp_scc_comparison"
|
||||
(match_code "unordered,ordered,unlt,unge,unle,ungt,ltgt,ne,eq,lt,le,gt,ge"))
|
||||
|
||||
(define_predicate "fp_branch_comparison"
|
||||
(match_code "unordered,ordered,unlt,unge,unle,ungt,uneq,ltgt,ne,eq,lt,le,gt,ge"))
|
287
gcc/config/riscv/riscv-builtins.c
Normal file
287
gcc/config/riscv/riscv-builtins.c
Normal file
|
@ -0,0 +1,287 @@
|
|||
/* Subroutines used for expanding RISC-V builtins.
|
||||
Copyright (C) 2011-2017 Free Software Foundation, Inc.
|
||||
Contributed by Andrew Waterman (andrew@sifive.com).
|
||||
|
||||
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 "rtl.h"
|
||||
#include "tree.h"
|
||||
#include "gimple-expr.h"
|
||||
#include "memmodel.h"
|
||||
#include "expmed.h"
|
||||
#include "optabs.h"
|
||||
#include "recog.h"
|
||||
#include "diagnostic-core.h"
|
||||
#include "stor-layout.h"
|
||||
#include "expr.h"
|
||||
#include "langhooks.h"
|
||||
|
||||
/* Macros to create an enumeration identifier for a function prototype. */
|
||||
#define RISCV_FTYPE_NAME1(A, B) RISCV_##A##_FTYPE_##B
|
||||
|
||||
/* Classifies the prototype of a built-in function. */
|
||||
enum riscv_function_type {
|
||||
#define DEF_RISCV_FTYPE(NARGS, LIST) RISCV_FTYPE_NAME##NARGS LIST,
|
||||
#include "config/riscv/riscv-ftypes.def"
|
||||
#undef DEF_RISCV_FTYPE
|
||||
RISCV_MAX_FTYPE_MAX
|
||||
};
|
||||
|
||||
/* Specifies how a built-in function should be converted into rtl. */
|
||||
enum riscv_builtin_type {
|
||||
/* The function corresponds directly to an .md pattern. */
|
||||
RISCV_BUILTIN_DIRECT,
|
||||
|
||||
/* Likewise, but with return type VOID. */
|
||||
RISCV_BUILTIN_DIRECT_NO_TARGET
|
||||
};
|
||||
|
||||
/* Declare an availability predicate for built-in functions. */
|
||||
#define AVAIL(NAME, COND) \
|
||||
static unsigned int \
|
||||
riscv_builtin_avail_##NAME (void) \
|
||||
{ \
|
||||
return (COND); \
|
||||
}
|
||||
|
||||
/* This structure describes a single built-in function. */
|
||||
struct riscv_builtin_description {
|
||||
/* The code of the main .md file instruction. See riscv_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 riscv_builtin_type builtin_type;
|
||||
|
||||
/* The function's prototype. */
|
||||
enum riscv_function_type prototype;
|
||||
|
||||
/* Whether the function is available. */
|
||||
unsigned int (*avail) (void);
|
||||
};
|
||||
|
||||
AVAIL (hard_float, TARGET_HARD_FLOAT)
|
||||
|
||||
/* Construct a riscv_builtin_description from the given arguments.
|
||||
|
||||
INSN is the name of the associated instruction pattern, without the
|
||||
leading CODE_FOR_riscv_.
|
||||
|
||||
NAME is the name of the function itself, without the leading
|
||||
"__builtin_riscv_".
|
||||
|
||||
BUILTIN_TYPE and FUNCTION_TYPE are riscv_builtin_description fields.
|
||||
|
||||
AVAIL is the name of the availability predicate, without the leading
|
||||
riscv_builtin_avail_. */
|
||||
#define RISCV_BUILTIN(INSN, NAME, BUILTIN_TYPE, FUNCTION_TYPE, AVAIL) \
|
||||
{ CODE_FOR_riscv_ ## INSN, "__builtin_riscv_" NAME, \
|
||||
BUILTIN_TYPE, FUNCTION_TYPE, riscv_builtin_avail_ ## AVAIL }
|
||||
|
||||
/* Define __builtin_riscv_<INSN>, which is a RISCV_BUILTIN_DIRECT function
|
||||
mapped to instruction CODE_FOR_riscv_<INSN>, FUNCTION_TYPE and AVAIL
|
||||
are as for RISCV_BUILTIN. */
|
||||
#define DIRECT_BUILTIN(INSN, FUNCTION_TYPE, AVAIL) \
|
||||
RISCV_BUILTIN (INSN, #INSN, RISCV_BUILTIN_DIRECT, FUNCTION_TYPE, AVAIL)
|
||||
|
||||
/* Define __builtin_riscv_<INSN>, which is a RISCV_BUILTIN_DIRECT_NO_TARGET
|
||||
function mapped to instruction CODE_FOR_riscv_<INSN>, FUNCTION_TYPE
|
||||
and AVAIL are as for RISCV_BUILTIN. */
|
||||
#define DIRECT_NO_TARGET_BUILTIN(INSN, FUNCTION_TYPE, AVAIL) \
|
||||
RISCV_BUILTIN (INSN, #INSN, RISCV_BUILTIN_DIRECT_NO_TARGET, \
|
||||
FUNCTION_TYPE, AVAIL)
|
||||
|
||||
/* Argument types. */
|
||||
#define RISCV_ATYPE_VOID void_type_node
|
||||
#define RISCV_ATYPE_USI unsigned_intSI_type_node
|
||||
|
||||
/* RISCV_FTYPE_ATYPESN takes N RISCV_FTYPES-like type codes and lists
|
||||
their associated RISCV_ATYPEs. */
|
||||
#define RISCV_FTYPE_ATYPES1(A, B) \
|
||||
RISCV_ATYPE_##A, RISCV_ATYPE_##B
|
||||
|
||||
static const struct riscv_builtin_description riscv_builtins[] = {
|
||||
DIRECT_BUILTIN (frflags, RISCV_USI_FTYPE_VOID, hard_float),
|
||||
DIRECT_NO_TARGET_BUILTIN (fsflags, RISCV_VOID_FTYPE_USI, hard_float)
|
||||
};
|
||||
|
||||
/* Index I is the function declaration for riscv_builtins[I], or null if the
|
||||
function isn't defined on this target. */
|
||||
static GTY(()) tree riscv_builtin_decls[ARRAY_SIZE (riscv_builtins)];
|
||||
|
||||
/* Get the index I of the function declaration for riscv_builtin_decls[I]
|
||||
using the instruction code or return null if not defined for the target. */
|
||||
static GTY(()) int riscv_builtin_decl_index[NUM_INSN_CODES];
|
||||
|
||||
#define GET_BUILTIN_DECL(CODE) \
|
||||
riscv_builtin_decls[riscv_builtin_decl_index[(CODE)]]
|
||||
|
||||
/* Return the function type associated with function prototype TYPE. */
|
||||
|
||||
static tree
|
||||
riscv_build_function_type (enum riscv_function_type type)
|
||||
{
|
||||
static tree types[(int) RISCV_MAX_FTYPE_MAX];
|
||||
|
||||
if (types[(int) type] == NULL_TREE)
|
||||
switch (type)
|
||||
{
|
||||
#define DEF_RISCV_FTYPE(NUM, ARGS) \
|
||||
case RISCV_FTYPE_NAME##NUM ARGS: \
|
||||
types[(int) type] \
|
||||
= build_function_type_list (RISCV_FTYPE_ATYPES##NUM ARGS, \
|
||||
NULL_TREE); \
|
||||
break;
|
||||
#include "config/riscv/riscv-ftypes.def"
|
||||
#undef DEF_RISCV_FTYPE
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
return types[(int) type];
|
||||
}
|
||||
|
||||
/* Implement TARGET_INIT_BUILTINS. */
|
||||
|
||||
void
|
||||
riscv_init_builtins (void)
|
||||
{
|
||||
for (size_t i = 0; i < ARRAY_SIZE (riscv_builtins); i++)
|
||||
{
|
||||
const struct riscv_builtin_description *d = &riscv_builtins[i];
|
||||
if (d->avail ())
|
||||
{
|
||||
tree type = riscv_build_function_type (d->prototype);
|
||||
riscv_builtin_decls[i]
|
||||
= add_builtin_function (d->name, type, i, BUILT_IN_MD, NULL, NULL);
|
||||
riscv_builtin_decl_index[d->icode] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Implement TARGET_BUILTIN_DECL. */
|
||||
|
||||
tree
|
||||
riscv_builtin_decl (unsigned int code, bool initialize_p ATTRIBUTE_UNUSED)
|
||||
{
|
||||
if (code >= ARRAY_SIZE (riscv_builtins))
|
||||
return error_mark_node;
|
||||
return riscv_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
|
||||
riscv_prepare_builtin_arg (struct expand_operand *op, tree exp, unsigned argno)
|
||||
{
|
||||
tree arg = CALL_EXPR_ARG (exp, argno);
|
||||
create_input_operand (op, expand_normal (arg), 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
|
||||
riscv_expand_builtin_insn (enum insn_code icode, unsigned int n_ops,
|
||||
struct expand_operand *ops, bool has_target_p)
|
||||
{
|
||||
if (!maybe_expand_insn (icode, n_ops, 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 RISCV_BUILTIN_DIRECT or RISCV_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
|
||||
riscv_expand_builtin_direct (enum insn_code icode, rtx target, tree exp,
|
||||
bool has_target_p)
|
||||
{
|
||||
struct expand_operand ops[MAX_RECOG_OPERANDS];
|
||||
|
||||
/* Map any target to operand 0. */
|
||||
int 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 (int argno = 0; argno < call_expr_nargs (exp); argno++)
|
||||
riscv_prepare_builtin_arg (&ops[opno++], exp, argno);
|
||||
|
||||
return riscv_expand_builtin_insn (icode, opno, ops, has_target_p);
|
||||
}
|
||||
|
||||
/* Implement TARGET_EXPAND_BUILTIN. */
|
||||
|
||||
rtx
|
||||
riscv_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
|
||||
machine_mode mode ATTRIBUTE_UNUSED,
|
||||
int ignore ATTRIBUTE_UNUSED)
|
||||
{
|
||||
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
|
||||
unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
|
||||
const struct riscv_builtin_description *d = &riscv_builtins[fcode];
|
||||
|
||||
switch (d->builtin_type)
|
||||
{
|
||||
case RISCV_BUILTIN_DIRECT:
|
||||
return riscv_expand_builtin_direct (d->icode, target, exp, true);
|
||||
|
||||
case RISCV_BUILTIN_DIRECT_NO_TARGET:
|
||||
return riscv_expand_builtin_direct (d->icode, target, exp, false);
|
||||
}
|
||||
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
/* Implement TARGET_ATOMIC_ASSIGN_EXPAND_FENV. */
|
||||
|
||||
void
|
||||
riscv_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
|
||||
{
|
||||
if (!TARGET_HARD_FLOAT)
|
||||
return;
|
||||
|
||||
tree frflags = GET_BUILTIN_DECL (CODE_FOR_riscv_frflags);
|
||||
tree fsflags = GET_BUILTIN_DECL (CODE_FOR_riscv_fsflags);
|
||||
tree old_flags = create_tmp_var_raw (RISCV_ATYPE_USI);
|
||||
|
||||
*hold = build2 (MODIFY_EXPR, RISCV_ATYPE_USI, old_flags,
|
||||
build_call_expr (frflags, 0));
|
||||
*clear = build_call_expr (fsflags, 1, old_flags);
|
||||
*update = NULL_TREE;
|
||||
}
|
92
gcc/config/riscv/riscv-c.c
Normal file
92
gcc/config/riscv/riscv-c.c
Normal file
|
@ -0,0 +1,92 @@
|
|||
/* RISC-V-specific code for C family languages.
|
||||
Copyright (C) 2011-2017 Free Software Foundation, Inc.
|
||||
Contributed by Andrew Waterman (andrew@sifive.com).
|
||||
|
||||
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 "c-family/c-common.h"
|
||||
#include "cpplib.h"
|
||||
|
||||
#define builtin_define(TXT) cpp_define (pfile, TXT)
|
||||
|
||||
/* Implement TARGET_CPU_CPP_BUILTINS. */
|
||||
|
||||
void
|
||||
riscv_cpu_cpp_builtins (cpp_reader *pfile)
|
||||
{
|
||||
builtin_define ("__riscv");
|
||||
|
||||
if (TARGET_RVC)
|
||||
builtin_define ("__riscv_compressed");
|
||||
|
||||
if (TARGET_ATOMIC)
|
||||
builtin_define ("__riscv_atomic");
|
||||
|
||||
if (TARGET_MUL)
|
||||
builtin_define ("__riscv_mul");
|
||||
if (TARGET_DIV)
|
||||
builtin_define ("__riscv_div");
|
||||
if (TARGET_DIV && TARGET_MUL)
|
||||
builtin_define ("__riscv_muldiv");
|
||||
|
||||
builtin_define_with_int_value ("__riscv_xlen", UNITS_PER_WORD * 8);
|
||||
if (TARGET_HARD_FLOAT)
|
||||
builtin_define_with_int_value ("__riscv_flen", UNITS_PER_FP_REG * 8);
|
||||
|
||||
if (TARGET_HARD_FLOAT && TARGET_FDIV)
|
||||
{
|
||||
builtin_define ("__riscv_fdiv");
|
||||
builtin_define ("__riscv_fsqrt");
|
||||
}
|
||||
|
||||
switch (riscv_abi)
|
||||
{
|
||||
case ABI_ILP32:
|
||||
case ABI_LP64:
|
||||
builtin_define ("__riscv_float_abi_soft");
|
||||
break;
|
||||
|
||||
case ABI_ILP32F:
|
||||
case ABI_LP64F:
|
||||
builtin_define ("__riscv_float_abi_single");
|
||||
break;
|
||||
|
||||
case ABI_ILP32D:
|
||||
case ABI_LP64D:
|
||||
builtin_define ("__riscv_float_abi_double");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (riscv_cmodel)
|
||||
{
|
||||
case CM_MEDLOW:
|
||||
builtin_define ("__riscv_cmodel_medlow");
|
||||
break;
|
||||
|
||||
case CM_MEDANY:
|
||||
builtin_define ("__riscv_cmodel_medany");
|
||||
break;
|
||||
|
||||
case CM_PIC:
|
||||
builtin_define ("__riscv_cmodel_pic");
|
||||
break;
|
||||
}
|
||||
}
|
30
gcc/config/riscv/riscv-ftypes.def
Normal file
30
gcc/config/riscv/riscv-ftypes.def
Normal file
|
@ -0,0 +1,30 @@
|
|||
/* Definitions of prototypes for RISC-V built-in functions. -*- C -*-
|
||||
Copyright (C) 2011-2017 Free Software Foundation, Inc.
|
||||
Contributed by Andrew Waterman (andrew@sifive.com).
|
||||
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
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Invoke DEF_RISCV_FTYPE (NARGS, LIST) for each prototype used by
|
||||
RISCV built-in functions, where:
|
||||
|
||||
NARGS is the number of arguments.
|
||||
LIST contains the return-type code followed by the codes for each
|
||||
argument type. */
|
||||
|
||||
DEF_RISCV_FTYPE (1, (USI, VOID))
|
||||
DEF_RISCV_FTYPE (1, (VOID, USI))
|
22
gcc/config/riscv/riscv-modes.def
Normal file
22
gcc/config/riscv/riscv-modes.def
Normal file
|
@ -0,0 +1,22 @@
|
|||
/* Extra machine modes for RISC-V target.
|
||||
Copyright (C) 2011-2017 Free Software Foundation, Inc.
|
||||
Contributed by Andrew Waterman (andrew@sifive.com).
|
||||
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
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
FLOAT_MODE (TF, 16, ieee_quad_format);
|
41
gcc/config/riscv/riscv-opts.h
Normal file
41
gcc/config/riscv/riscv-opts.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/* Definition of RISC-V target for GNU compiler.
|
||||
Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||||
Contributed by Andrew Waterman (andrew@sifive.com).
|
||||
|
||||
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 GCC_RISCV_OPTS_H
|
||||
#define GCC_RISCV_OPTS_H
|
||||
|
||||
enum riscv_abi_type {
|
||||
ABI_ILP32,
|
||||
ABI_ILP32F,
|
||||
ABI_ILP32D,
|
||||
ABI_LP64,
|
||||
ABI_LP64F,
|
||||
ABI_LP64D
|
||||
};
|
||||
extern enum riscv_abi_type riscv_abi;
|
||||
|
||||
enum riscv_code_model {
|
||||
CM_MEDLOW,
|
||||
CM_MEDANY,
|
||||
CM_PIC
|
||||
};
|
||||
extern enum riscv_code_model riscv_cmodel;
|
||||
|
||||
#endif /* ! GCC_RISCV_OPTS_H */
|
83
gcc/config/riscv/riscv-protos.h
Normal file
83
gcc/config/riscv/riscv-protos.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
/* Definition of RISC-V target for GNU compiler.
|
||||
Copyright (C) 2011-2017 Free Software Foundation, Inc.
|
||||
Contributed by Andrew Waterman (andrew@sifive.com).
|
||||
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
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef GCC_RISCV_PROTOS_H
|
||||
#define GCC_RISCV_PROTOS_H
|
||||
|
||||
/* Symbol types we understand. The order of this list must match that of
|
||||
the unspec enum in riscv.md, subsequent to UNSPEC_ADDRESS_FIRST. */
|
||||
enum riscv_symbol_type {
|
||||
SYMBOL_ABSOLUTE,
|
||||
SYMBOL_PCREL,
|
||||
SYMBOL_GOT_DISP,
|
||||
SYMBOL_TLS,
|
||||
SYMBOL_TLS_LE,
|
||||
SYMBOL_TLS_IE,
|
||||
SYMBOL_TLS_GD
|
||||
};
|
||||
#define NUM_SYMBOL_TYPES (SYMBOL_TLS_GD + 1)
|
||||
|
||||
/* Routines implemented in riscv.c. */
|
||||
extern enum riscv_symbol_type riscv_classify_symbolic_expression (rtx);
|
||||
extern bool riscv_symbolic_constant_p (rtx, enum riscv_symbol_type *);
|
||||
extern int riscv_regno_mode_ok_for_base_p (int, enum machine_mode, bool);
|
||||
extern bool riscv_hard_regno_mode_ok_p (unsigned int, enum machine_mode);
|
||||
extern int riscv_address_insns (rtx, enum machine_mode, bool);
|
||||
extern int riscv_const_insns (rtx);
|
||||
extern int riscv_split_const_insns (rtx);
|
||||
extern int riscv_load_store_insns (rtx, rtx_insn *);
|
||||
extern rtx riscv_emit_move (rtx, rtx);
|
||||
extern bool riscv_split_symbol (rtx, rtx, enum machine_mode, rtx *);
|
||||
extern bool riscv_split_symbol_type (enum riscv_symbol_type);
|
||||
extern rtx riscv_unspec_address (rtx, enum riscv_symbol_type);
|
||||
extern void riscv_move_integer (rtx, rtx, HOST_WIDE_INT);
|
||||
extern bool riscv_legitimize_move (enum machine_mode, rtx, rtx);
|
||||
extern rtx riscv_subword (rtx, bool);
|
||||
extern bool riscv_split_64bit_move_p (rtx, rtx);
|
||||
extern void riscv_split_doubleword_move (rtx, rtx);
|
||||
extern const char *riscv_output_move (rtx, rtx);
|
||||
extern const char *riscv_output_gpr_save (unsigned);
|
||||
#ifdef RTX_CODE
|
||||
extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx);
|
||||
extern void riscv_expand_float_scc (rtx, enum rtx_code, rtx, rtx);
|
||||
extern void riscv_expand_conditional_branch (rtx, enum rtx_code, rtx, rtx);
|
||||
#endif
|
||||
extern rtx riscv_legitimize_call_address (rtx);
|
||||
extern void riscv_set_return_address (rtx, rtx);
|
||||
extern bool riscv_expand_block_move (rtx, rtx, rtx);
|
||||
extern rtx riscv_return_addr (int, rtx);
|
||||
extern HOST_WIDE_INT riscv_initial_elimination_offset (int, int);
|
||||
extern void riscv_expand_prologue (void);
|
||||
extern void riscv_expand_epilogue (bool);
|
||||
extern bool riscv_can_use_return_insn (void);
|
||||
extern rtx riscv_function_value (const_tree, const_tree, enum machine_mode);
|
||||
extern unsigned int riscv_hard_regno_nregs (int, enum machine_mode);
|
||||
|
||||
/* Routines implemented in riscv-c.c. */
|
||||
void riscv_cpu_cpp_builtins (cpp_reader *);
|
||||
|
||||
/* Routines implemented in riscv-builtins.c. */
|
||||
extern void riscv_atomic_assign_expand_fenv (tree *, tree *, tree *);
|
||||
extern rtx riscv_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
|
||||
extern tree riscv_builtin_decl (unsigned int, bool);
|
||||
extern void riscv_init_builtins (void);
|
||||
|
||||
#endif /* ! GCC_RISCV_PROTOS_H */
|
4138
gcc/config/riscv/riscv.c
Normal file
4138
gcc/config/riscv/riscv.c
Normal file
File diff suppressed because it is too large
Load diff
906
gcc/config/riscv/riscv.h
Normal file
906
gcc/config/riscv/riscv.h
Normal file
|
@ -0,0 +1,906 @@
|
|||
/* Definition of RISC-V target for GNU compiler.
|
||||
Copyright (C) 2011-2017 Free Software Foundation, Inc.
|
||||
Contributed by Andrew Waterman (andrew@sifive.com).
|
||||
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
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef GCC_RISCV_H
|
||||
#define GCC_RISCV_H
|
||||
|
||||
#include "config/riscv/riscv-opts.h"
|
||||
|
||||
/* Target CPU builtins. */
|
||||
#define TARGET_CPU_CPP_BUILTINS() riscv_cpu_cpp_builtins (pfile)
|
||||
|
||||
/* Default target_flags if no switches are specified */
|
||||
|
||||
#ifndef TARGET_DEFAULT
|
||||
#define TARGET_DEFAULT 0
|
||||
#endif
|
||||
|
||||
#ifndef RISCV_TUNE_STRING_DEFAULT
|
||||
#define RISCV_TUNE_STRING_DEFAULT "rocket"
|
||||
#endif
|
||||
|
||||
/* Support for a compile-time default CPU, et cetera. The rules are:
|
||||
--with-arch is ignored if -march is specified.
|
||||
--with-abi is ignored if -mabi is specified.
|
||||
--with-tune is ignored if -mtune is specified. */
|
||||
#define OPTION_DEFAULT_SPECS \
|
||||
{"tune", "%{!mtune=*:-mtune=%(VALUE)}" }, \
|
||||
{"arch", "%{!march=*:-march=%(VALUE)}" }, \
|
||||
{"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \
|
||||
|
||||
#ifdef IN_LIBGCC2
|
||||
#undef TARGET_64BIT
|
||||
/* Make this compile time constant for libgcc2 */
|
||||
#define TARGET_64BIT (__riscv_xlen == 64)
|
||||
#endif /* IN_LIBGCC2 */
|
||||
|
||||
#undef ASM_SPEC
|
||||
#define ASM_SPEC "\
|
||||
%(subtarget_asm_debugging_spec) \
|
||||
%{" FPIE_OR_FPIC_SPEC ":-fpic} \
|
||||
%{march=*} \
|
||||
%{mabi=*} \
|
||||
%(subtarget_asm_spec)"
|
||||
|
||||
#define TARGET_DEFAULT_CMODEL CM_MEDLOW
|
||||
|
||||
#define LOCAL_LABEL_PREFIX "."
|
||||
#define USER_LABEL_PREFIX ""
|
||||
|
||||
/* Offsets recorded in opcodes are a multiple of this alignment factor.
|
||||
The default for this in 64-bit mode is 8, which causes problems with
|
||||
SFmode register saves. */
|
||||
#define DWARF_CIE_DATA_ALIGNMENT -4
|
||||
|
||||
/* The mapping from gcc register number to DWARF 2 CFA column number. */
|
||||
#define DWARF_FRAME_REGNUM(REGNO) \
|
||||
(GP_REG_P (REGNO) || FP_REG_P (REGNO) ? REGNO : INVALID_REGNUM)
|
||||
|
||||
/* The DWARF 2 CFA column which tracks the return address. */
|
||||
#define DWARF_FRAME_RETURN_COLUMN RETURN_ADDR_REGNUM
|
||||
#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (VOIDmode, RETURN_ADDR_REGNUM)
|
||||
|
||||
/* Describe how we implement __builtin_eh_return. */
|
||||
#define EH_RETURN_DATA_REGNO(N) \
|
||||
((N) < 4 ? (N) + GP_ARG_FIRST : INVALID_REGNUM)
|
||||
|
||||
#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, GP_ARG_FIRST + 4)
|
||||
|
||||
/* Target machine storage layout */
|
||||
|
||||
#define BITS_BIG_ENDIAN 0
|
||||
#define BYTES_BIG_ENDIAN 0
|
||||
#define WORDS_BIG_ENDIAN 0
|
||||
|
||||
#define MAX_BITS_PER_WORD 64
|
||||
|
||||
/* Width of a word, in units (bytes). */
|
||||
#define UNITS_PER_WORD (TARGET_64BIT ? 8 : 4)
|
||||
#ifndef IN_LIBGCC2
|
||||
#define MIN_UNITS_PER_WORD 4
|
||||
#endif
|
||||
|
||||
/* The `Q' extension is not yet supported. */
|
||||
#define UNITS_PER_FP_REG (TARGET_DOUBLE_FLOAT ? 8 : 4)
|
||||
|
||||
/* The largest type that can be passed in floating-point registers. */
|
||||
#define UNITS_PER_FP_ARG \
|
||||
(riscv_abi == ABI_ILP32 || riscv_abi == ABI_LP64 ? 0 : \
|
||||
riscv_abi == ABI_ILP32F || riscv_abi == ABI_LP64F ? 4 : 8) \
|
||||
|
||||
/* Set the sizes of the core types. */
|
||||
#define SHORT_TYPE_SIZE 16
|
||||
#define INT_TYPE_SIZE 32
|
||||
#define LONG_LONG_TYPE_SIZE 64
|
||||
#define POINTER_SIZE (riscv_abi >= ABI_LP64 ? 64 : 32)
|
||||
#define LONG_TYPE_SIZE POINTER_SIZE
|
||||
|
||||
#define FLOAT_TYPE_SIZE 32
|
||||
#define DOUBLE_TYPE_SIZE 64
|
||||
#define LONG_DOUBLE_TYPE_SIZE 128
|
||||
|
||||
/* Allocation boundary (in *bits*) for storing arguments in argument list. */
|
||||
#define PARM_BOUNDARY BITS_PER_WORD
|
||||
|
||||
/* Allocation boundary (in *bits*) for the code of a function. */
|
||||
#define FUNCTION_BOUNDARY (TARGET_RVC ? 16 : 32)
|
||||
|
||||
/* There is no point aligning anything to a rounder boundary than this. */
|
||||
#define BIGGEST_ALIGNMENT 128
|
||||
|
||||
/* The user-level ISA permits misaligned accesses, but they may execute
|
||||
extremely slowly and non-atomically. Some privileged architectures
|
||||
do not permit them at all. It is best to enforce strict alignment. */
|
||||
#define STRICT_ALIGNMENT 1
|
||||
|
||||
/* Define this if you wish to imitate the way many other C compilers
|
||||
handle alignment of bitfields and the structures that contain
|
||||
them.
|
||||
|
||||
The behavior is that the type written for a bit-field (`int',
|
||||
`short', or other integer type) imposes an alignment for the
|
||||
entire structure, as if the structure really did contain an
|
||||
ordinary field of that type. In addition, the bit-field is placed
|
||||
within the structure so that it would fit within such a field,
|
||||
not crossing a boundary for it.
|
||||
|
||||
Thus, on most machines, a bit-field whose type is written as `int'
|
||||
would not cross a four-byte boundary, and would force four-byte
|
||||
alignment for the whole structure. (The alignment used may not
|
||||
be four bytes; it is controlled by the other alignment
|
||||
parameters.)
|
||||
|
||||
If the macro is defined, its definition should be a C expression;
|
||||
a nonzero value for the expression enables this behavior. */
|
||||
|
||||
#define PCC_BITFIELD_TYPE_MATTERS 1
|
||||
|
||||
/* If defined, a C expression to compute the alignment given to a
|
||||
constant that is being placed in memory. CONSTANT is the constant
|
||||
and ALIGN is the alignment that the object would ordinarily have.
|
||||
The value of this macro is used instead of that alignment to align
|
||||
the object.
|
||||
|
||||
If this macro is not defined, then ALIGN is used.
|
||||
|
||||
The typical use of this macro is to increase alignment for string
|
||||
constants to be word aligned so that `strcpy' calls that copy
|
||||
constants can be done inline. */
|
||||
|
||||
#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
|
||||
((TREE_CODE (EXP) == STRING_CST || TREE_CODE (EXP) == CONSTRUCTOR) \
|
||||
&& (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
|
||||
|
||||
/* If defined, a C expression to compute the alignment for a static
|
||||
variable. TYPE is the data type, and ALIGN is the alignment that
|
||||
the object would ordinarily have. The value of this macro is used
|
||||
instead of that alignment to align the object.
|
||||
|
||||
If this macro is not defined, then ALIGN is used.
|
||||
|
||||
One use of this macro is to increase alignment of medium-size
|
||||
data to make it all fit in fewer cache lines. Another is to
|
||||
cause character arrays to be word-aligned so that `strcpy' calls
|
||||
that copy constants to character arrays can be done inline. */
|
||||
|
||||
#define DATA_ALIGNMENT(TYPE, ALIGN) \
|
||||
((((ALIGN) < BITS_PER_WORD) \
|
||||
&& (TREE_CODE (TYPE) == ARRAY_TYPE \
|
||||
|| TREE_CODE (TYPE) == UNION_TYPE \
|
||||
|| TREE_CODE (TYPE) == RECORD_TYPE)) ? BITS_PER_WORD : (ALIGN))
|
||||
|
||||
/* We need this for the same reason as DATA_ALIGNMENT, namely to cause
|
||||
character arrays to be word-aligned so that `strcpy' calls that copy
|
||||
constants to character arrays can be done inline, and 'strcmp' can be
|
||||
optimised to use word loads. */
|
||||
#define LOCAL_ALIGNMENT(TYPE, ALIGN) \
|
||||
DATA_ALIGNMENT (TYPE, ALIGN)
|
||||
|
||||
/* Define if operations between registers always perform the operation
|
||||
on the full register even if a narrower mode is specified. */
|
||||
#define WORD_REGISTER_OPERATIONS 1
|
||||
|
||||
/* When in 64-bit mode, move insns will sign extend SImode and CCmode
|
||||
moves. All other references are zero extended. */
|
||||
#define LOAD_EXTEND_OP(MODE) \
|
||||
(TARGET_64BIT && (MODE) == SImode ? SIGN_EXTEND : ZERO_EXTEND)
|
||||
|
||||
/* Define this macro if it is advisable to hold scalars in registers
|
||||
in a wider mode than that declared by the program. In such cases,
|
||||
the value is constrained to be within the bounds of the declared
|
||||
type, but kept valid in the wider mode. The signedness of the
|
||||
extension may differ from that of the type. */
|
||||
|
||||
#define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \
|
||||
if (GET_MODE_CLASS (MODE) == MODE_INT \
|
||||
&& GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \
|
||||
{ \
|
||||
if ((MODE) == SImode) \
|
||||
(UNSIGNEDP) = 0; \
|
||||
(MODE) = word_mode; \
|
||||
}
|
||||
|
||||
/* Pmode is always the same as ptr_mode, but not always the same as word_mode.
|
||||
Extensions of pointers to word_mode must be signed. */
|
||||
#define POINTERS_EXTEND_UNSIGNED false
|
||||
|
||||
/* When floating-point registers are wider than integer ones, moves between
|
||||
them must go through memory. */
|
||||
#define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE) \
|
||||
(GET_MODE_SIZE (MODE) > UNITS_PER_WORD \
|
||||
&& ((CLASS1) == FP_REGS) != ((CLASS2) == FP_REGS))
|
||||
|
||||
/* Define if loading short immediate values into registers sign extends. */
|
||||
#define SHORT_IMMEDIATES_SIGN_EXTEND 1
|
||||
|
||||
/* Standard register usage. */
|
||||
|
||||
/* Number of hardware registers. We have:
|
||||
|
||||
- 32 integer registers
|
||||
- 32 floating point registers
|
||||
- 2 fake registers:
|
||||
- ARG_POINTER_REGNUM
|
||||
- FRAME_POINTER_REGNUM */
|
||||
|
||||
#define FIRST_PSEUDO_REGISTER 66
|
||||
|
||||
/* x0, sp, gp, and tp are fixed. */
|
||||
|
||||
#define FIXED_REGISTERS \
|
||||
{ /* General registers. */ \
|
||||
1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
/* Floating-point registers. */ \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
/* Others. */ \
|
||||
1, 1 \
|
||||
}
|
||||
|
||||
/* a0-a7, t0-a6, fa0-fa7, and ft0-ft11 are volatile across calls.
|
||||
The call RTLs themselves clobber ra. */
|
||||
|
||||
#define CALL_USED_REGISTERS \
|
||||
{ /* General registers. */ \
|
||||
1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, \
|
||||
/* Floating-point registers. */ \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, \
|
||||
/* Others. */ \
|
||||
1, 1 \
|
||||
}
|
||||
|
||||
/* Internal macros to classify an ISA register's type. */
|
||||
|
||||
#define GP_REG_FIRST 0
|
||||
#define GP_REG_LAST 31
|
||||
#define GP_REG_NUM (GP_REG_LAST - GP_REG_FIRST + 1)
|
||||
|
||||
#define FP_REG_FIRST 32
|
||||
#define FP_REG_LAST 63
|
||||
#define FP_REG_NUM (FP_REG_LAST - FP_REG_FIRST + 1)
|
||||
|
||||
/* The DWARF 2 CFA column which tracks the return address from a
|
||||
signal handler context. This means that to maintain backwards
|
||||
compatibility, no hard register can be assigned this column if it
|
||||
would need to be handled by the DWARF unwinder. */
|
||||
#define DWARF_ALT_FRAME_RETURN_COLUMN 64
|
||||
|
||||
#define GP_REG_P(REGNO) \
|
||||
((unsigned int) ((int) (REGNO) - GP_REG_FIRST) < GP_REG_NUM)
|
||||
#define FP_REG_P(REGNO) \
|
||||
((unsigned int) ((int) (REGNO) - FP_REG_FIRST) < FP_REG_NUM)
|
||||
|
||||
#define FP_REG_RTX_P(X) (REG_P (X) && FP_REG_P (REGNO (X)))
|
||||
|
||||
#define HARD_REGNO_NREGS(REGNO, MODE) riscv_hard_regno_nregs (REGNO, MODE)
|
||||
|
||||
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
|
||||
riscv_hard_regno_mode_ok_p (REGNO, MODE)
|
||||
|
||||
/* Don't allow floating-point modes to be tied, since type punning of
|
||||
single-precision and double-precision is implementation defined. */
|
||||
#define MODES_TIEABLE_P(MODE1, MODE2) \
|
||||
((MODE1) == (MODE2) \
|
||||
|| !(GET_MODE_CLASS (MODE1) == MODE_FLOAT \
|
||||
&& GET_MODE_CLASS (MODE2) == MODE_FLOAT))
|
||||
|
||||
/* Use s0 as the frame pointer if it is so requested. */
|
||||
#define HARD_FRAME_POINTER_REGNUM 8
|
||||
#define STACK_POINTER_REGNUM 2
|
||||
#define THREAD_POINTER_REGNUM 4
|
||||
|
||||
/* These two registers don't really exist: they get eliminated to either
|
||||
the stack or hard frame pointer. */
|
||||
#define ARG_POINTER_REGNUM 64
|
||||
#define FRAME_POINTER_REGNUM 65
|
||||
|
||||
/* Register in which static-chain is passed to a function. */
|
||||
#define STATIC_CHAIN_REGNUM (GP_TEMP_FIRST + 2)
|
||||
|
||||
/* Registers used as temporaries in prologue/epilogue code.
|
||||
|
||||
The prologue registers mustn't conflict with any
|
||||
incoming arguments, the static chain pointer, or the frame pointer.
|
||||
The epilogue temporary mustn't conflict with the return registers,
|
||||
the frame pointer, the EH stack adjustment, or the EH data registers. */
|
||||
|
||||
#define RISCV_PROLOGUE_TEMP_REGNUM (GP_TEMP_FIRST + 1)
|
||||
#define RISCV_PROLOGUE_TEMP(MODE) gen_rtx_REG (MODE, RISCV_PROLOGUE_TEMP_REGNUM)
|
||||
|
||||
#define MCOUNT_NAME "_mcount"
|
||||
|
||||
#define NO_PROFILE_COUNTERS 1
|
||||
|
||||
/* Emit rtl for profiling. Output assembler code to FILE
|
||||
to call "_mcount" for profiling a function entry. */
|
||||
#define PROFILE_HOOK(LABEL) \
|
||||
{ \
|
||||
rtx fun, ra; \
|
||||
ra = get_hard_reg_initial_val (Pmode, RETURN_ADDR_REGNUM); \
|
||||
fun = gen_rtx_SYMBOL_REF (Pmode, MCOUNT_NAME); \
|
||||
emit_library_call (fun, LCT_NORMAL, VOIDmode, 1, ra, Pmode); \
|
||||
}
|
||||
|
||||
/* All the work done in PROFILE_HOOK, but still required. */
|
||||
#define FUNCTION_PROFILER(STREAM, LABELNO) do { } while (0)
|
||||
|
||||
/* Define this macro if it is as good or better to call a constant
|
||||
function address than to call an address kept in a register. */
|
||||
#define NO_FUNCTION_CSE 1
|
||||
|
||||
/* Define the classes of registers for register constraints in the
|
||||
machine description. Also define ranges of constants.
|
||||
|
||||
One of the classes must always be named ALL_REGS and include all hard regs.
|
||||
If there is more than one class, another class must be named NO_REGS
|
||||
and contain no registers.
|
||||
|
||||
The name GENERAL_REGS must be the name of a class (or an alias for
|
||||
another name such as ALL_REGS). This is the class of registers
|
||||
that is allowed by "g" or "r" in a register constraint.
|
||||
Also, registers outside this class are allocated only when
|
||||
instructions express preferences for them.
|
||||
|
||||
The classes must be numbered in nondecreasing order; that is,
|
||||
a larger-numbered class must never be contained completely
|
||||
in a smaller-numbered class.
|
||||
|
||||
For any two classes, it is very desirable that there be another
|
||||
class that represents their union. */
|
||||
|
||||
enum reg_class
|
||||
{
|
||||
NO_REGS, /* no registers in set */
|
||||
SIBCALL_REGS, /* registers used by indirect sibcalls */
|
||||
JALR_REGS, /* registers used by indirect calls */
|
||||
GR_REGS, /* integer registers */
|
||||
FP_REGS, /* floating-point registers */
|
||||
FRAME_REGS, /* arg pointer and frame pointer */
|
||||
ALL_REGS, /* all registers */
|
||||
LIM_REG_CLASSES /* max value + 1 */
|
||||
};
|
||||
|
||||
#define N_REG_CLASSES (int) LIM_REG_CLASSES
|
||||
|
||||
#define GENERAL_REGS GR_REGS
|
||||
|
||||
/* An initializer containing the names of the register classes as C
|
||||
string constants. These names are used in writing some of the
|
||||
debugging dumps. */
|
||||
|
||||
#define REG_CLASS_NAMES \
|
||||
{ \
|
||||
"NO_REGS", \
|
||||
"SIBCALL_REGS", \
|
||||
"JALR_REGS", \
|
||||
"GR_REGS", \
|
||||
"FP_REGS", \
|
||||
"FRAME_REGS", \
|
||||
"ALL_REGS" \
|
||||
}
|
||||
|
||||
/* An initializer containing the contents of the register classes,
|
||||
as integers which are bit masks. The Nth integer specifies the
|
||||
contents of class N. The way the integer MASK is interpreted is
|
||||
that register R is in the class if `MASK & (1 << R)' is 1.
|
||||
|
||||
When the machine has more than 32 registers, an integer does not
|
||||
suffice. Then the integers are replaced by sub-initializers,
|
||||
braced groupings containing several integers. Each
|
||||
sub-initializer must be suitable as an initializer for the type
|
||||
`HARD_REG_SET' which is defined in `hard-reg-set.h'. */
|
||||
|
||||
#define REG_CLASS_CONTENTS \
|
||||
{ \
|
||||
{ 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */ \
|
||||
{ 0xf00000c0, 0x00000000, 0x00000000 }, /* SIBCALL_REGS */ \
|
||||
{ 0xffffffc0, 0x00000000, 0x00000000 }, /* JALR_REGS */ \
|
||||
{ 0xffffffff, 0x00000000, 0x00000000 }, /* GR_REGS */ \
|
||||
{ 0x00000000, 0xffffffff, 0x00000000 }, /* FP_REGS */ \
|
||||
{ 0x00000000, 0x00000000, 0x00000003 }, /* FRAME_REGS */ \
|
||||
{ 0xffffffff, 0xffffffff, 0x00000003 } /* ALL_REGS */ \
|
||||
}
|
||||
|
||||
/* A C expression whose value is a register class containing hard
|
||||
register REGNO. In general there is more that one such class;
|
||||
choose a class which is "minimal", meaning that no smaller class
|
||||
also contains the register. */
|
||||
|
||||
#define REGNO_REG_CLASS(REGNO) riscv_regno_to_class[ (REGNO) ]
|
||||
|
||||
/* A macro whose definition is the name of the class to which a
|
||||
valid base register must belong. A base register is one used in
|
||||
an address which is the register value plus a displacement. */
|
||||
|
||||
#define BASE_REG_CLASS GR_REGS
|
||||
|
||||
/* A macro whose definition is the name of the class to which a
|
||||
valid index register must belong. An index register is one used
|
||||
in an address where its value is either multiplied by a scale
|
||||
factor or added to another register (as well as added to a
|
||||
displacement). */
|
||||
|
||||
#define INDEX_REG_CLASS NO_REGS
|
||||
|
||||
/* We generally want to put call-clobbered registers ahead of
|
||||
call-saved ones. (IRA expects this.) */
|
||||
|
||||
#define REG_ALLOC_ORDER \
|
||||
{ \
|
||||
/* Call-clobbered GPRs. */ \
|
||||
15, 14, 13, 12, 11, 10, 16, 17, 6, 28, 29, 30, 31, 5, 7, 1, \
|
||||
/* Call-saved GPRs. */ \
|
||||
8, 9, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, \
|
||||
/* GPRs that can never be exposed to the register allocator. */ \
|
||||
0, 2, 3, 4, \
|
||||
/* Call-clobbered FPRs. */ \
|
||||
47, 46, 45, 44, 43, 42, 32, 33, 34, 35, 36, 37, 38, 39, 48, 49, \
|
||||
60, 61, 62, 63, \
|
||||
/* Call-saved FPRs. */ \
|
||||
40, 41, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, \
|
||||
/* None of the remaining classes have defined call-saved \
|
||||
registers. */ \
|
||||
64, 65 \
|
||||
}
|
||||
|
||||
/* True if VALUE is a signed 12-bit number. */
|
||||
|
||||
#define SMALL_OPERAND(VALUE) \
|
||||
((unsigned HOST_WIDE_INT) (VALUE) + IMM_REACH/2 < IMM_REACH)
|
||||
|
||||
/* True if VALUE can be loaded into a register using LUI. */
|
||||
|
||||
#define LUI_OPERAND(VALUE) \
|
||||
(((VALUE) | ((1UL<<31) - IMM_REACH)) == ((1UL<<31) - IMM_REACH) \
|
||||
|| ((VALUE) | ((1UL<<31) - IMM_REACH)) + IMM_REACH == 0)
|
||||
|
||||
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
|
||||
reg_classes_intersect_p (FP_REGS, CLASS)
|
||||
|
||||
/* Stack layout; function entry, exit and calling. */
|
||||
|
||||
#define STACK_GROWS_DOWNWARD 1
|
||||
|
||||
#define FRAME_GROWS_DOWNWARD 1
|
||||
|
||||
#define STARTING_FRAME_OFFSET 0
|
||||
|
||||
#define RETURN_ADDR_RTX riscv_return_addr
|
||||
|
||||
#define ELIMINABLE_REGS \
|
||||
{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
|
||||
{ ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
|
||||
{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
|
||||
{ FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}} \
|
||||
|
||||
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
|
||||
(OFFSET) = riscv_initial_elimination_offset (FROM, TO)
|
||||
|
||||
/* Allocate stack space for arguments at the beginning of each function. */
|
||||
#define ACCUMULATE_OUTGOING_ARGS 1
|
||||
|
||||
/* The argument pointer always points to the first argument. */
|
||||
#define FIRST_PARM_OFFSET(FNDECL) 0
|
||||
|
||||
#define REG_PARM_STACK_SPACE(FNDECL) 0
|
||||
|
||||
/* Define this if it is the responsibility of the caller to
|
||||
allocate the area reserved for arguments passed in registers.
|
||||
If `ACCUMULATE_OUTGOING_ARGS' is also defined, the only effect
|
||||
of this macro is to determine whether the space is included in
|
||||
`crtl->outgoing_args_size'. */
|
||||
#define OUTGOING_REG_PARM_STACK_SPACE(FNTYPE) 1
|
||||
|
||||
#define STACK_BOUNDARY 128
|
||||
|
||||
/* Symbolic macros for the registers used to return integer and floating
|
||||
point values. */
|
||||
|
||||
#define GP_RETURN GP_ARG_FIRST
|
||||
#define FP_RETURN (UNITS_PER_FP_ARG == 0 ? GP_RETURN : FP_ARG_FIRST)
|
||||
|
||||
#define MAX_ARGS_IN_REGISTERS 8
|
||||
|
||||
/* Symbolic macros for the first/last argument registers. */
|
||||
|
||||
#define GP_ARG_FIRST (GP_REG_FIRST + 10)
|
||||
#define GP_ARG_LAST (GP_ARG_FIRST + MAX_ARGS_IN_REGISTERS - 1)
|
||||
#define GP_TEMP_FIRST (GP_REG_FIRST + 5)
|
||||
#define FP_ARG_FIRST (FP_REG_FIRST + 10)
|
||||
#define FP_ARG_LAST (FP_ARG_FIRST + MAX_ARGS_IN_REGISTERS - 1)
|
||||
|
||||
#define CALLEE_SAVED_REG_NUMBER(REGNO) \
|
||||
((REGNO) >= 8 && (REGNO) <= 9 ? (REGNO) - 8 : \
|
||||
(REGNO) >= 18 && (REGNO) <= 27 ? (REGNO) - 16 : -1)
|
||||
|
||||
#define LIBCALL_VALUE(MODE) \
|
||||
riscv_function_value (NULL_TREE, NULL_TREE, MODE)
|
||||
|
||||
#define FUNCTION_VALUE(VALTYPE, FUNC) \
|
||||
riscv_function_value (VALTYPE, FUNC, VOIDmode)
|
||||
|
||||
#define FUNCTION_VALUE_REGNO_P(N) ((N) == GP_RETURN || (N) == FP_RETURN)
|
||||
|
||||
/* 1 if N is a possible register number for function argument passing.
|
||||
We have no FP argument registers when soft-float. When FP registers
|
||||
are 32 bits, we can't directly reference the odd numbered ones. */
|
||||
|
||||
/* Accept arguments in a0-a7, and in fa0-fa7 if permitted by the ABI. */
|
||||
#define FUNCTION_ARG_REGNO_P(N) \
|
||||
(IN_RANGE ((N), GP_ARG_FIRST, GP_ARG_LAST) \
|
||||
|| (UNITS_PER_FP_ARG && IN_RANGE ((N), FP_ARG_FIRST, FP_ARG_LAST)))
|
||||
|
||||
typedef struct {
|
||||
/* Number of integer registers used so far, up to MAX_ARGS_IN_REGISTERS. */
|
||||
unsigned int num_gprs;
|
||||
|
||||
/* Number of floating-point registers used so far, likewise. */
|
||||
unsigned int num_fprs;
|
||||
} CUMULATIVE_ARGS;
|
||||
|
||||
/* Initialize a variable CUM of type CUMULATIVE_ARGS
|
||||
for a call to a function whose data type is FNTYPE.
|
||||
For a library call, FNTYPE is 0. */
|
||||
|
||||
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
|
||||
memset (&(CUM), 0, sizeof (CUM))
|
||||
|
||||
#define EPILOGUE_USES(REGNO) ((REGNO) == RETURN_ADDR_REGNUM)
|
||||
|
||||
/* ABI requires 16-byte alignment, even on RV32. */
|
||||
#define RISCV_STACK_ALIGN(LOC) (((LOC) + 15) & -16)
|
||||
|
||||
/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
|
||||
the stack pointer does not matter. The value is tested only in
|
||||
functions that have frame pointers.
|
||||
No definition is equivalent to always zero. */
|
||||
|
||||
#define EXIT_IGNORE_STACK 1
|
||||
|
||||
|
||||
/* Trampolines are a block of code followed by two pointers. */
|
||||
|
||||
#define TRAMPOLINE_CODE_SIZE 16
|
||||
#define TRAMPOLINE_SIZE \
|
||||
((Pmode == SImode) \
|
||||
? TRAMPOLINE_CODE_SIZE \
|
||||
: (TRAMPOLINE_CODE_SIZE + POINTER_SIZE * 2))
|
||||
#define TRAMPOLINE_ALIGNMENT POINTER_SIZE
|
||||
|
||||
/* Addressing modes, and classification of registers for them. */
|
||||
|
||||
#define REGNO_OK_FOR_INDEX_P(REGNO) 0
|
||||
#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \
|
||||
riscv_regno_mode_ok_for_base_p (REGNO, MODE, 1)
|
||||
|
||||
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
|
||||
and check its validity for a certain class.
|
||||
We have two alternate definitions for each of them.
|
||||
The usual definition accepts all pseudo regs; the other rejects them all.
|
||||
The symbol REG_OK_STRICT causes the latter definition to be used.
|
||||
|
||||
Most source files want to accept pseudo regs in the hope that
|
||||
they will get allocated to the class that the insn wants them to be in.
|
||||
Some source files that are used after register allocation
|
||||
need to be strict. */
|
||||
|
||||
#ifndef REG_OK_STRICT
|
||||
#define REG_MODE_OK_FOR_BASE_P(X, MODE) \
|
||||
riscv_regno_mode_ok_for_base_p (REGNO (X), MODE, 0)
|
||||
#else
|
||||
#define REG_MODE_OK_FOR_BASE_P(X, MODE) \
|
||||
riscv_regno_mode_ok_for_base_p (REGNO (X), MODE, 1)
|
||||
#endif
|
||||
|
||||
#define REG_OK_FOR_INDEX_P(X) 0
|
||||
|
||||
/* Maximum number of registers that can appear in a valid memory address. */
|
||||
|
||||
#define MAX_REGS_PER_ADDRESS 1
|
||||
|
||||
#define CONSTANT_ADDRESS_P(X) \
|
||||
(CONSTANT_P (X) && memory_address_p (SImode, X))
|
||||
|
||||
/* This handles the magic '..CURRENT_FUNCTION' symbol, which means
|
||||
'the start of the function that this code is output in'. */
|
||||
|
||||
#define ASM_OUTPUT_LABELREF(FILE,NAME) \
|
||||
if (strcmp (NAME, "..CURRENT_FUNCTION") == 0) \
|
||||
asm_fprintf ((FILE), "%U%s", \
|
||||
XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); \
|
||||
else \
|
||||
asm_fprintf ((FILE), "%U%s", (NAME))
|
||||
|
||||
#define JUMP_TABLES_IN_TEXT_SECTION 0
|
||||
#define CASE_VECTOR_MODE SImode
|
||||
#define CASE_VECTOR_PC_RELATIVE (riscv_cmodel != CM_MEDLOW)
|
||||
|
||||
/* The load-address macro is used for PC-relative addressing of symbols
|
||||
that bind locally. Don't use it for symbols that should be addressed
|
||||
via the GOT. Also, avoid it for CM_MEDLOW, where LUI addressing
|
||||
currently results in more opportunities for linker relaxation. */
|
||||
#define USE_LOAD_ADDRESS_MACRO(sym) \
|
||||
(!TARGET_EXPLICIT_RELOCS && \
|
||||
((flag_pic \
|
||||
&& ((SYMBOL_REF_P (sym) && SYMBOL_REF_LOCAL_P (sym)) \
|
||||
|| ((GET_CODE (sym) == CONST) \
|
||||
&& SYMBOL_REF_P (XEXP (XEXP (sym, 0),0)) \
|
||||
&& SYMBOL_REF_LOCAL_P (XEXP (XEXP (sym, 0),0))))) \
|
||||
|| riscv_cmodel == CM_MEDANY))
|
||||
|
||||
/* Define this as 1 if `char' should by default be signed; else as 0. */
|
||||
#define DEFAULT_SIGNED_CHAR 0
|
||||
|
||||
#define MOVE_MAX UNITS_PER_WORD
|
||||
#define MAX_MOVE_MAX 8
|
||||
|
||||
#define SLOW_BYTE_ACCESS 0
|
||||
|
||||
#define SHIFT_COUNT_TRUNCATED 1
|
||||
|
||||
#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
|
||||
|
||||
/* Specify the machine mode that pointers have.
|
||||
After generation of rtl, the compiler makes no further distinction
|
||||
between pointers and any other objects of this machine mode. */
|
||||
|
||||
#define Pmode word_mode
|
||||
|
||||
/* Give call MEMs SImode since it is the "most permissive" mode
|
||||
for both 32-bit and 64-bit targets. */
|
||||
|
||||
#define FUNCTION_MODE SImode
|
||||
|
||||
/* A C expression for the cost of a branch instruction. A value of 2
|
||||
seems to minimize code size. */
|
||||
|
||||
#define BRANCH_COST(speed_p, predictable_p) \
|
||||
((!(speed_p) || (predictable_p)) ? 2 : riscv_branch_cost)
|
||||
|
||||
#define LOGICAL_OP_NON_SHORT_CIRCUIT 0
|
||||
|
||||
/* Control the assembler format that we output. */
|
||||
|
||||
/* Output to assembler file text saying following lines
|
||||
may contain character constants, extra white space, comments, etc. */
|
||||
|
||||
#ifndef ASM_APP_ON
|
||||
#define ASM_APP_ON " #APP\n"
|
||||
#endif
|
||||
|
||||
/* Output to assembler file text saying following lines
|
||||
no longer contain unusual constructs. */
|
||||
|
||||
#ifndef ASM_APP_OFF
|
||||
#define ASM_APP_OFF " #NO_APP\n"
|
||||
#endif
|
||||
|
||||
#define REGISTER_NAMES \
|
||||
{ "zero","ra", "sp", "gp", "tp", "t0", "t1", "t2", \
|
||||
"s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", \
|
||||
"a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", \
|
||||
"s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", \
|
||||
"ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7", \
|
||||
"fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5", \
|
||||
"fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7", \
|
||||
"fs8", "fs9", "fs10","fs11","ft8", "ft9", "ft10","ft11", \
|
||||
"arg", "frame", }
|
||||
|
||||
#define ADDITIONAL_REGISTER_NAMES \
|
||||
{ \
|
||||
{ "x0", 0 + GP_REG_FIRST }, \
|
||||
{ "x1", 1 + GP_REG_FIRST }, \
|
||||
{ "x2", 2 + GP_REG_FIRST }, \
|
||||
{ "x3", 3 + GP_REG_FIRST }, \
|
||||
{ "x4", 4 + GP_REG_FIRST }, \
|
||||
{ "x5", 5 + GP_REG_FIRST }, \
|
||||
{ "x6", 6 + GP_REG_FIRST }, \
|
||||
{ "x7", 7 + GP_REG_FIRST }, \
|
||||
{ "x8", 8 + GP_REG_FIRST }, \
|
||||
{ "x9", 9 + GP_REG_FIRST }, \
|
||||
{ "x10", 10 + GP_REG_FIRST }, \
|
||||
{ "x11", 11 + GP_REG_FIRST }, \
|
||||
{ "x12", 12 + GP_REG_FIRST }, \
|
||||
{ "x13", 13 + GP_REG_FIRST }, \
|
||||
{ "x14", 14 + GP_REG_FIRST }, \
|
||||
{ "x15", 15 + GP_REG_FIRST }, \
|
||||
{ "x16", 16 + GP_REG_FIRST }, \
|
||||
{ "x17", 17 + GP_REG_FIRST }, \
|
||||
{ "x18", 18 + GP_REG_FIRST }, \
|
||||
{ "x19", 19 + GP_REG_FIRST }, \
|
||||
{ "x20", 20 + GP_REG_FIRST }, \
|
||||
{ "x21", 21 + GP_REG_FIRST }, \
|
||||
{ "x22", 22 + GP_REG_FIRST }, \
|
||||
{ "x23", 23 + GP_REG_FIRST }, \
|
||||
{ "x24", 24 + GP_REG_FIRST }, \
|
||||
{ "x25", 25 + GP_REG_FIRST }, \
|
||||
{ "x26", 26 + GP_REG_FIRST }, \
|
||||
{ "x27", 27 + GP_REG_FIRST }, \
|
||||
{ "x28", 28 + GP_REG_FIRST }, \
|
||||
{ "x29", 29 + GP_REG_FIRST }, \
|
||||
{ "x30", 30 + GP_REG_FIRST }, \
|
||||
{ "x31", 31 + GP_REG_FIRST }, \
|
||||
{ "f0", 0 + FP_REG_FIRST }, \
|
||||
{ "f1", 1 + FP_REG_FIRST }, \
|
||||
{ "f2", 2 + FP_REG_FIRST }, \
|
||||
{ "f3", 3 + FP_REG_FIRST }, \
|
||||
{ "f4", 4 + FP_REG_FIRST }, \
|
||||
{ "f5", 5 + FP_REG_FIRST }, \
|
||||
{ "f6", 6 + FP_REG_FIRST }, \
|
||||
{ "f7", 7 + FP_REG_FIRST }, \
|
||||
{ "f8", 8 + FP_REG_FIRST }, \
|
||||
{ "f9", 9 + FP_REG_FIRST }, \
|
||||
{ "f10", 10 + FP_REG_FIRST }, \
|
||||
{ "f11", 11 + FP_REG_FIRST }, \
|
||||
{ "f12", 12 + FP_REG_FIRST }, \
|
||||
{ "f13", 13 + FP_REG_FIRST }, \
|
||||
{ "f14", 14 + FP_REG_FIRST }, \
|
||||
{ "f15", 15 + FP_REG_FIRST }, \
|
||||
{ "f16", 16 + FP_REG_FIRST }, \
|
||||
{ "f17", 17 + FP_REG_FIRST }, \
|
||||
{ "f18", 18 + FP_REG_FIRST }, \
|
||||
{ "f19", 19 + FP_REG_FIRST }, \
|
||||
{ "f20", 20 + FP_REG_FIRST }, \
|
||||
{ "f21", 21 + FP_REG_FIRST }, \
|
||||
{ "f22", 22 + FP_REG_FIRST }, \
|
||||
{ "f23", 23 + FP_REG_FIRST }, \
|
||||
{ "f24", 24 + FP_REG_FIRST }, \
|
||||
{ "f25", 25 + FP_REG_FIRST }, \
|
||||
{ "f26", 26 + FP_REG_FIRST }, \
|
||||
{ "f27", 27 + FP_REG_FIRST }, \
|
||||
{ "f28", 28 + FP_REG_FIRST }, \
|
||||
{ "f29", 29 + FP_REG_FIRST }, \
|
||||
{ "f30", 30 + FP_REG_FIRST }, \
|
||||
{ "f31", 31 + FP_REG_FIRST }, \
|
||||
}
|
||||
|
||||
/* Globalizing directive for a label. */
|
||||
#define GLOBAL_ASM_OP "\t.globl\t"
|
||||
|
||||
/* This is how to store into the string LABEL
|
||||
the symbol_ref name of an internal numbered label where
|
||||
PREFIX is the class of label and NUM is the number within the class.
|
||||
This is suitable for output with `assemble_name'. */
|
||||
|
||||
#undef ASM_GENERATE_INTERNAL_LABEL
|
||||
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
|
||||
sprintf ((LABEL), "*%s%s%ld", (LOCAL_LABEL_PREFIX), (PREFIX), (long)(NUM))
|
||||
|
||||
/* This is how to output an element of a case-vector that is absolute. */
|
||||
|
||||
#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
|
||||
fprintf (STREAM, "\t.word\t%sL%d\n", LOCAL_LABEL_PREFIX, VALUE)
|
||||
|
||||
/* This is how to output an element of a PIC case-vector. */
|
||||
|
||||
#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \
|
||||
fprintf (STREAM, "\t.word\t%sL%d-%sL%d\n", \
|
||||
LOCAL_LABEL_PREFIX, VALUE, LOCAL_LABEL_PREFIX, REL)
|
||||
|
||||
/* This is how to output an assembler line
|
||||
that says to advance the location counter
|
||||
to a multiple of 2**LOG bytes. */
|
||||
|
||||
#define ASM_OUTPUT_ALIGN(STREAM,LOG) \
|
||||
fprintf (STREAM, "\t.align\t%d\n", (LOG))
|
||||
|
||||
/* Define the strings to put out for each section in the object file. */
|
||||
#define TEXT_SECTION_ASM_OP "\t.text" /* instructions */
|
||||
#define DATA_SECTION_ASM_OP "\t.data" /* large data */
|
||||
#define READONLY_DATA_SECTION_ASM_OP "\t.section\t.rodata"
|
||||
#define BSS_SECTION_ASM_OP "\t.bss"
|
||||
#define SBSS_SECTION_ASM_OP "\t.section\t.sbss,\"aw\",@nobits"
|
||||
#define SDATA_SECTION_ASM_OP "\t.section\t.sdata,\"aw\",@progbits"
|
||||
|
||||
#define ASM_OUTPUT_REG_PUSH(STREAM,REGNO) \
|
||||
do \
|
||||
{ \
|
||||
fprintf (STREAM, "\taddi\t%s,%s,-8\n\t%s\t%s,0(%s)\n", \
|
||||
reg_names[STACK_POINTER_REGNUM], \
|
||||
reg_names[STACK_POINTER_REGNUM], \
|
||||
TARGET_64BIT ? "sd" : "sw", \
|
||||
reg_names[REGNO], \
|
||||
reg_names[STACK_POINTER_REGNUM]); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define ASM_OUTPUT_REG_POP(STREAM,REGNO) \
|
||||
do \
|
||||
{ \
|
||||
fprintf (STREAM, "\t%s\t%s,0(%s)\n\taddi\t%s,%s,8\n", \
|
||||
TARGET_64BIT ? "ld" : "lw", \
|
||||
reg_names[REGNO], \
|
||||
reg_names[STACK_POINTER_REGNUM], \
|
||||
reg_names[STACK_POINTER_REGNUM], \
|
||||
reg_names[STACK_POINTER_REGNUM]); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define ASM_COMMENT_START "#"
|
||||
|
||||
#undef SIZE_TYPE
|
||||
#define SIZE_TYPE (POINTER_SIZE == 64 ? "long unsigned int" : "unsigned int")
|
||||
|
||||
#undef PTRDIFF_TYPE
|
||||
#define PTRDIFF_TYPE (POINTER_SIZE == 64 ? "long int" : "int")
|
||||
|
||||
/* If a memory-to-memory move would take MOVE_RATIO or more simple
|
||||
move-instruction pairs, we will do a movmem or libcall instead. */
|
||||
|
||||
#define MOVE_RATIO(speed) (CLEAR_RATIO (speed) / 2)
|
||||
|
||||
/* For CLEAR_RATIO, when optimizing for size, give a better estimate
|
||||
of the length of a memset call, but use the default otherwise. */
|
||||
|
||||
#define CLEAR_RATIO(speed) ((speed) ? 16 : 6)
|
||||
|
||||
/* This is similar to CLEAR_RATIO, but for a non-zero constant, so when
|
||||
optimizing for size adjust the ratio to account for the overhead of
|
||||
loading the constant and replicating it across the word. */
|
||||
|
||||
#define SET_RATIO(speed) (CLEAR_RATIO (speed) - ((speed) ? 0 : 2))
|
||||
|
||||
#ifndef USED_FOR_TARGET
|
||||
extern const enum reg_class riscv_regno_to_class[];
|
||||
extern bool riscv_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
|
||||
#endif
|
||||
|
||||
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
|
||||
(((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4)
|
||||
|
||||
#define XLEN_SPEC \
|
||||
"%{march=rv32*:32}" \
|
||||
"%{march=rv64*:64}" \
|
||||
|
||||
#define ABI_SPEC \
|
||||
"%{mabi=ilp32:ilp32}" \
|
||||
"%{mabi=ilp32f:ilp32f}" \
|
||||
"%{mabi=ilp32d:ilp32d}" \
|
||||
"%{mabi=lp64:lp64}" \
|
||||
"%{mabi=lp64f:lp64f}" \
|
||||
"%{mabi=lp64d:lp64d}" \
|
||||
|
||||
#define STARTFILE_PREFIX_SPEC \
|
||||
"/lib" XLEN_SPEC "/" ABI_SPEC "/ " \
|
||||
"/usr/lib" XLEN_SPEC "/" ABI_SPEC "/ " \
|
||||
"/lib/ " \
|
||||
"/usr/lib/ "
|
||||
|
||||
/* ISA constants needed for code generation. */
|
||||
#define OPCODE_LW 0x2003
|
||||
#define OPCODE_LD 0x3003
|
||||
#define OPCODE_AUIPC 0x17
|
||||
#define OPCODE_JALR 0x67
|
||||
#define OPCODE_LUI 0x37
|
||||
#define OPCODE_ADDI 0x13
|
||||
#define SHIFT_RD 7
|
||||
#define SHIFT_RS1 15
|
||||
#define SHIFT_IMM 20
|
||||
#define IMM_BITS 12
|
||||
|
||||
#define IMM_REACH (1LL << IMM_BITS)
|
||||
#define CONST_HIGH_PART(VALUE) (((VALUE) + (IMM_REACH/2)) & ~(IMM_REACH-1))
|
||||
#define CONST_LOW_PART(VALUE) ((VALUE) - CONST_HIGH_PART (VALUE))
|
||||
|
||||
#endif /* ! GCC_RISCV_H */
|
2079
gcc/config/riscv/riscv.md
Normal file
2079
gcc/config/riscv/riscv.md
Normal file
File diff suppressed because it is too large
Load diff
111
gcc/config/riscv/riscv.opt
Normal file
111
gcc/config/riscv/riscv.opt
Normal file
|
@ -0,0 +1,111 @@
|
|||
; Options for the RISC-V port of the compiler
|
||||
;
|
||||
; Copyright (C) 2011-2017 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/>.
|
||||
|
||||
HeaderInclude
|
||||
config/riscv/riscv-opts.h
|
||||
|
||||
mbranch-cost=
|
||||
Target RejectNegative Joined UInteger Var(riscv_branch_cost)
|
||||
-mbranch-cost=N Set the cost of branches to roughly N instructions.
|
||||
|
||||
mplt
|
||||
Target Report Var(TARGET_PLT) Init(1)
|
||||
When generating -fpic code, allow the use of PLTs. Ignored for fno-pic.
|
||||
|
||||
mabi=
|
||||
Target Report RejectNegative Joined Enum(abi_type) Var(riscv_abi) Init(ABI_ILP32)
|
||||
Specify integer and floating-point calling convention.
|
||||
|
||||
Enum
|
||||
Name(abi_type) Type(enum riscv_abi_type)
|
||||
Supported ABIs (for use with the -mabi= option):
|
||||
|
||||
EnumValue
|
||||
Enum(abi_type) String(ilp32) Value(ABI_ILP32)
|
||||
|
||||
EnumValue
|
||||
Enum(abi_type) String(ilp32f) Value(ABI_ILP32F)
|
||||
|
||||
EnumValue
|
||||
Enum(abi_type) String(ilp32d) Value(ABI_ILP32D)
|
||||
|
||||
EnumValue
|
||||
Enum(abi_type) String(lp64) Value(ABI_LP64)
|
||||
|
||||
EnumValue
|
||||
Enum(abi_type) String(lp64f) Value(ABI_LP64F)
|
||||
|
||||
EnumValue
|
||||
Enum(abi_type) String(lp64d) Value(ABI_LP64D)
|
||||
|
||||
mfdiv
|
||||
Target Report Mask(FDIV)
|
||||
Use hardware floating-point divide and square root instructions.
|
||||
|
||||
mdiv
|
||||
Target Report Mask(DIV)
|
||||
Use hardware instructions for integer division.
|
||||
|
||||
march=
|
||||
Target Report RejectNegative Joined
|
||||
-march= Generate code for given RISC-V ISA (e.g. RV64IM). ISA strings must be
|
||||
lower-case.
|
||||
|
||||
mtune=
|
||||
Target RejectNegative Joined Var(riscv_tune_string)
|
||||
-mtune=PROCESSOR Optimize the output for PROCESSOR.
|
||||
|
||||
msmall-data-limit=
|
||||
Target Joined Separate UInteger Var(g_switch_value) Init(8)
|
||||
-msmall-data-limit=N Put global and static data smaller than <number> bytes into a special section (on some targets).
|
||||
|
||||
msave-restore
|
||||
Target Report Mask(SAVE_RESTORE)
|
||||
Use smaller but slower prologue and epilogue code.
|
||||
|
||||
mcmodel=
|
||||
Target Report RejectNegative Joined Enum(code_model) Var(riscv_cmodel) Init(TARGET_DEFAULT_CMODEL)
|
||||
Specify the code model.
|
||||
|
||||
Enum
|
||||
Name(code_model) Type(enum riscv_code_model)
|
||||
Known code models (for use with the -mcmodel= option):
|
||||
|
||||
EnumValue
|
||||
Enum(code_model) String(medlow) Value(CM_MEDLOW)
|
||||
|
||||
EnumValue
|
||||
Enum(code_model) String(medany) Value(CM_MEDANY)
|
||||
|
||||
mexplicit-relocs
|
||||
Target Report Mask(EXPLICIT_RELOCS)
|
||||
Use %reloc() operators, rather than assembly macros, to load addresses.
|
||||
|
||||
Mask(64BIT)
|
||||
|
||||
Mask(MUL)
|
||||
|
||||
Mask(ATOMIC)
|
||||
|
||||
Mask(HARD_FLOAT)
|
||||
|
||||
Mask(DOUBLE_FLOAT)
|
||||
|
||||
Mask(RVC)
|
194
gcc/config/riscv/sync.md
Normal file
194
gcc/config/riscv/sync.md
Normal file
|
@ -0,0 +1,194 @@
|
|||
;; Machine description for RISC-V atomic operations.
|
||||
;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
|
||||
;; Contributed by Andrew Waterman (andrew@sifive.com).
|
||||
;; 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
|
||||
;; <http://www.gnu.org/licenses/>.
|
||||
|
||||
(define_c_enum "unspec" [
|
||||
UNSPEC_COMPARE_AND_SWAP
|
||||
UNSPEC_SYNC_OLD_OP
|
||||
UNSPEC_SYNC_EXCHANGE
|
||||
UNSPEC_ATOMIC_STORE
|
||||
UNSPEC_MEMORY_BARRIER
|
||||
])
|
||||
|
||||
(define_code_iterator any_atomic [plus ior xor and])
|
||||
(define_code_attr atomic_optab
|
||||
[(plus "add") (ior "or") (xor "xor") (and "and")])
|
||||
|
||||
;; Memory barriers.
|
||||
|
||||
(define_expand "mem_thread_fence"
|
||||
[(match_operand:SI 0 "const_int_operand" "")] ;; model
|
||||
""
|
||||
{
|
||||
if (INTVAL (operands[0]) != MEMMODEL_RELAXED)
|
||||
{
|
||||
rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
|
||||
MEM_VOLATILE_P (mem) = 1;
|
||||
emit_insn (gen_mem_thread_fence_1 (mem, operands[0]));
|
||||
}
|
||||
DONE;
|
||||
})
|
||||
|
||||
;; Until the RISC-V memory model (hence its mapping from C++) is finalized,
|
||||
;; conservatively emit a full FENCE.
|
||||
(define_insn "mem_thread_fence_1"
|
||||
[(set (match_operand:BLK 0 "" "")
|
||||
(unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))
|
||||
(match_operand:SI 1 "const_int_operand" "")] ;; model
|
||||
""
|
||||
"fence\trw,rw")
|
||||
|
||||
;; Atomic memory operations.
|
||||
|
||||
;; Implement atomic stores with amoswap. Fall back to fences for atomic loads.
|
||||
(define_insn "atomic_store<mode>"
|
||||
[(set (match_operand:GPR 0 "memory_operand" "=A")
|
||||
(unspec_volatile:GPR
|
||||
[(match_operand:GPR 1 "reg_or_0_operand" "rJ")
|
||||
(match_operand:SI 2 "const_int_operand")] ;; model
|
||||
UNSPEC_ATOMIC_STORE))]
|
||||
"TARGET_ATOMIC"
|
||||
"%F2amoswap.<amo>%A2 zero,%z1,%0"
|
||||
[(set (attr "length") (const_int 8))])
|
||||
|
||||
(define_insn "atomic_<atomic_optab><mode>"
|
||||
[(set (match_operand:GPR 0 "memory_operand" "+A")
|
||||
(unspec_volatile:GPR
|
||||
[(any_atomic:GPR (match_dup 0)
|
||||
(match_operand:GPR 1 "reg_or_0_operand" "rJ"))
|
||||
(match_operand:SI 2 "const_int_operand")] ;; model
|
||||
UNSPEC_SYNC_OLD_OP))]
|
||||
"TARGET_ATOMIC"
|
||||
"%F2amo<insn>.<amo>%A2 zero,%z1,%0"
|
||||
[(set (attr "length") (const_int 8))])
|
||||
|
||||
(define_insn "atomic_fetch_<atomic_optab><mode>"
|
||||
[(set (match_operand:GPR 0 "register_operand" "=&r")
|
||||
(match_operand:GPR 1 "memory_operand" "+A"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:GPR
|
||||
[(any_atomic:GPR (match_dup 1)
|
||||
(match_operand:GPR 2 "reg_or_0_operand" "rJ"))
|
||||
(match_operand:SI 3 "const_int_operand")] ;; model
|
||||
UNSPEC_SYNC_OLD_OP))]
|
||||
"TARGET_ATOMIC"
|
||||
"%F3amo<insn>.<amo>%A3 %0,%z2,%1"
|
||||
[(set (attr "length") (const_int 8))])
|
||||
|
||||
(define_insn "atomic_exchange<mode>"
|
||||
[(set (match_operand:GPR 0 "register_operand" "=&r")
|
||||
(unspec_volatile:GPR
|
||||
[(match_operand:GPR 1 "memory_operand" "+A")
|
||||
(match_operand:SI 3 "const_int_operand")] ;; model
|
||||
UNSPEC_SYNC_EXCHANGE))
|
||||
(set (match_dup 1)
|
||||
(match_operand:GPR 2 "register_operand" "0"))]
|
||||
"TARGET_ATOMIC"
|
||||
"%F3amoswap.<amo>%A3 %0,%z2,%1"
|
||||
[(set (attr "length") (const_int 8))])
|
||||
|
||||
(define_insn "atomic_cas_value_strong<mode>"
|
||||
[(set (match_operand:GPR 0 "register_operand" "=&r")
|
||||
(match_operand:GPR 1 "memory_operand" "+A"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:GPR [(match_operand:GPR 2 "reg_or_0_operand" "rJ")
|
||||
(match_operand:GPR 3 "reg_or_0_operand" "rJ")
|
||||
(match_operand:SI 4 "const_int_operand") ;; mod_s
|
||||
(match_operand:SI 5 "const_int_operand")] ;; mod_f
|
||||
UNSPEC_COMPARE_AND_SWAP))
|
||||
(clobber (match_scratch:GPR 6 "=&r"))]
|
||||
"TARGET_ATOMIC"
|
||||
"%F5 1: lr.<amo>%A5 %0,%1; bne %0,%z2,1f; sc.<amo>%A4 %6,%z3,%1; bnez %6,1b; 1:"
|
||||
[(set (attr "length") (const_int 20))])
|
||||
|
||||
(define_expand "atomic_compare_and_swap<mode>"
|
||||
[(match_operand:SI 0 "register_operand" "") ;; bool output
|
||||
(match_operand:GPR 1 "register_operand" "") ;; val output
|
||||
(match_operand:GPR 2 "memory_operand" "") ;; memory
|
||||
(match_operand:GPR 3 "reg_or_0_operand" "") ;; expected value
|
||||
(match_operand:GPR 4 "reg_or_0_operand" "") ;; desired value
|
||||
(match_operand:SI 5 "const_int_operand" "") ;; is_weak
|
||||
(match_operand:SI 6 "const_int_operand" "") ;; mod_s
|
||||
(match_operand:SI 7 "const_int_operand" "")] ;; mod_f
|
||||
"TARGET_ATOMIC"
|
||||
{
|
||||
emit_insn (gen_atomic_cas_value_strong<mode> (operands[1], operands[2],
|
||||
operands[3], operands[4],
|
||||
operands[6], operands[7]));
|
||||
|
||||
rtx compare = operands[1];
|
||||
if (operands[3] != const0_rtx)
|
||||
{
|
||||
rtx difference = gen_rtx_MINUS (<MODE>mode, operands[1], operands[3]);
|
||||
compare = gen_reg_rtx (<MODE>mode);
|
||||
emit_insn (gen_rtx_SET (compare, difference));
|
||||
}
|
||||
|
||||
if (word_mode != <MODE>mode)
|
||||
{
|
||||
rtx reg = gen_reg_rtx (word_mode);
|
||||
emit_insn (gen_rtx_SET (reg, gen_rtx_SIGN_EXTEND (word_mode, compare)));
|
||||
compare = reg;
|
||||
}
|
||||
|
||||
emit_insn (gen_rtx_SET (operands[0], gen_rtx_EQ (SImode, compare, const0_rtx)));
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "atomic_test_and_set"
|
||||
[(match_operand:QI 0 "register_operand" "") ;; bool output
|
||||
(match_operand:QI 1 "memory_operand" "+A") ;; memory
|
||||
(match_operand:SI 2 "const_int_operand" "")] ;; model
|
||||
"TARGET_ATOMIC"
|
||||
{
|
||||
/* We have no QImode atomics, so use the address LSBs to form a mask,
|
||||
then use an aligned SImode atomic. */
|
||||
rtx result = operands[0];
|
||||
rtx mem = operands[1];
|
||||
rtx model = operands[2];
|
||||
rtx addr = force_reg (Pmode, XEXP (mem, 0));
|
||||
|
||||
rtx aligned_addr = gen_reg_rtx (Pmode);
|
||||
emit_move_insn (aligned_addr, gen_rtx_AND (Pmode, addr, GEN_INT (-4)));
|
||||
|
||||
rtx aligned_mem = change_address (mem, SImode, aligned_addr);
|
||||
set_mem_alias_set (aligned_mem, 0);
|
||||
|
||||
rtx offset = gen_reg_rtx (SImode);
|
||||
emit_move_insn (offset, gen_rtx_AND (SImode, gen_lowpart (SImode, addr),
|
||||
GEN_INT (3)));
|
||||
|
||||
rtx tmp = gen_reg_rtx (SImode);
|
||||
emit_move_insn (tmp, GEN_INT (1));
|
||||
|
||||
rtx shmt = gen_reg_rtx (SImode);
|
||||
emit_move_insn (shmt, gen_rtx_ASHIFT (SImode, offset, GEN_INT (3)));
|
||||
|
||||
rtx word = gen_reg_rtx (SImode);
|
||||
emit_move_insn (word, gen_rtx_ASHIFT (SImode, tmp, shmt));
|
||||
|
||||
tmp = gen_reg_rtx (SImode);
|
||||
emit_insn (gen_atomic_fetch_orsi (tmp, aligned_mem, word, model));
|
||||
|
||||
emit_move_insn (gen_lowpart (SImode, result),
|
||||
gen_rtx_LSHIFTRT (SImode, tmp,
|
||||
gen_lowpart (SImode, shmt)));
|
||||
DONE;
|
||||
})
|
30
gcc/config/riscv/t-elf-multilib
Normal file
30
gcc/config/riscv/t-elf-multilib
Normal file
|
@ -0,0 +1,30 @@
|
|||
# This file was generated by multilib-generator with the command:
|
||||
# ./multilib-generator rv32i-ilp32--c rv32im-ilp32--c rv32iac-ilp32-- rv32imac-ilp32-- rv32imafc-ilp32f-rv32imafdc- rv64imac-lp64-- rv64imafdc-lp64d--
|
||||
MULTILIB_OPTIONS = march=rv32i/march=rv32ic/march=rv32im/march=rv32imc/march=rv32iac/march=rv32imac/march=rv32imafc/march=rv32imafdc/march=rv32gc/march=rv64imac/march=rv64imafdc/march=rv64gc mabi=ilp32/mabi=ilp32f/mabi=lp64/mabi=lp64d
|
||||
MULTILIB_DIRNAMES = rv32i \
|
||||
rv32ic \
|
||||
rv32im \
|
||||
rv32imc \
|
||||
rv32iac \
|
||||
rv32imac \
|
||||
rv32imafc \
|
||||
rv32imafdc \
|
||||
rv32gc \
|
||||
rv64imac \
|
||||
rv64imafdc \
|
||||
rv64gc ilp32 \
|
||||
ilp32f \
|
||||
lp64 \
|
||||
lp64d
|
||||
MULTILIB_REQUIRED = march=rv32i/mabi=ilp32 \
|
||||
march=rv32im/mabi=ilp32 \
|
||||
march=rv32iac/mabi=ilp32 \
|
||||
march=rv32imac/mabi=ilp32 \
|
||||
march=rv32imafc/mabi=ilp32f \
|
||||
march=rv64imac/mabi=lp64 \
|
||||
march=rv64imafdc/mabi=lp64d
|
||||
MULTILIB_REUSE = march.rv32i/mabi.ilp32=march.rv32ic/mabi.ilp32 \
|
||||
march.rv32im/mabi.ilp32=march.rv32imc/mabi.ilp32 \
|
||||
march.rv32imafc/mabi.ilp32f=march.rv32imafdc/mabi.ilp32f \
|
||||
march.rv32imafc/mabi.ilp32f=march.rv32gc/mabi.ilp32f \
|
||||
march.rv64imafdc/mabi.lp64d=march.rv64gc/mabi.lp64d
|
3
gcc/config/riscv/t-linux
Normal file
3
gcc/config/riscv/t-linux
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Only XLEN and ABI affect Linux multilib dir names, e.g. /lib32/ilp32d/
|
||||
MULTILIB_DIRNAMES := $(patsubst rv32%,lib32,$(patsubst rv64%,lib64,$(MULTILIB_DIRNAMES)))
|
||||
MULTILIB_OSDIRNAMES := $(patsubst lib%,../lib%,$(MULTILIB_DIRNAMES))
|
46
gcc/config/riscv/t-linux-multilib
Normal file
46
gcc/config/riscv/t-linux-multilib
Normal file
|
@ -0,0 +1,46 @@
|
|||
# This file was generated by multilib-generator with the command:
|
||||
# ./multilib-generator rv32imac-ilp32-rv32ima,rv32imaf,rv32imafd,rv32imafc,rv32imafdc- rv32imafdc-ilp32d-rv32imafd- rv64imac-lp64-rv64ima,rv64imaf,rv64imafd,rv64imafc,rv64imafdc- rv64imafdc-lp64d-rv64imafd-
|
||||
MULTILIB_OPTIONS = march=rv32imac/march=rv32ima/march=rv32imaf/march=rv32imafd/march=rv32imafc/march=rv32imafdc/march=rv32g/march=rv32gc/march=rv64imac/march=rv64ima/march=rv64imaf/march=rv64imafd/march=rv64imafc/march=rv64imafdc/march=rv64g/march=rv64gc mabi=ilp32/mabi=ilp32d/mabi=lp64/mabi=lp64d
|
||||
MULTILIB_DIRNAMES = rv32imac \
|
||||
rv32ima \
|
||||
rv32imaf \
|
||||
rv32imafd \
|
||||
rv32imafc \
|
||||
rv32imafdc \
|
||||
rv32g \
|
||||
rv32gc \
|
||||
rv64imac \
|
||||
rv64ima \
|
||||
rv64imaf \
|
||||
rv64imafd \
|
||||
rv64imafc \
|
||||
rv64imafdc \
|
||||
rv64g \
|
||||
rv64gc ilp32 \
|
||||
ilp32d \
|
||||
lp64 \
|
||||
lp64d
|
||||
MULTILIB_REQUIRED = march=rv32imac/mabi=ilp32 \
|
||||
march=rv32imafdc/mabi=ilp32d \
|
||||
march=rv64imac/mabi=lp64 \
|
||||
march=rv64imafdc/mabi=lp64d
|
||||
MULTILIB_REUSE = march.rv32imac/mabi.ilp32=march.rv32ima/mabi.ilp32 \
|
||||
march.rv32imac/mabi.ilp32=march.rv32imaf/mabi.ilp32 \
|
||||
march.rv32imac/mabi.ilp32=march.rv32imafd/mabi.ilp32 \
|
||||
march.rv32imac/mabi.ilp32=march.rv32imafc/mabi.ilp32 \
|
||||
march.rv32imac/mabi.ilp32=march.rv32imafdc/mabi.ilp32 \
|
||||
march.rv32imac/mabi.ilp32=march.rv32g/mabi.ilp32 \
|
||||
march.rv32imac/mabi.ilp32=march.rv32gc/mabi.ilp32 \
|
||||
march.rv32imafdc/mabi.ilp32d=march.rv32imafd/mabi.ilp32d \
|
||||
march.rv32imafdc/mabi.ilp32d=march.rv32gc/mabi.ilp32d \
|
||||
march.rv32imafdc/mabi.ilp32d=march.rv32g/mabi.ilp32d \
|
||||
march.rv64imac/mabi.lp64=march.rv64ima/mabi.lp64 \
|
||||
march.rv64imac/mabi.lp64=march.rv64imaf/mabi.lp64 \
|
||||
march.rv64imac/mabi.lp64=march.rv64imafd/mabi.lp64 \
|
||||
march.rv64imac/mabi.lp64=march.rv64imafc/mabi.lp64 \
|
||||
march.rv64imac/mabi.lp64=march.rv64imafdc/mabi.lp64 \
|
||||
march.rv64imac/mabi.lp64=march.rv64g/mabi.lp64 \
|
||||
march.rv64imac/mabi.lp64=march.rv64gc/mabi.lp64 \
|
||||
march.rv64imafdc/mabi.lp64d=march.rv64imafd/mabi.lp64d \
|
||||
march.rv64imafdc/mabi.lp64d=march.rv64gc/mabi.lp64d \
|
||||
march.rv64imafdc/mabi.lp64d=march.rv64g/mabi.lp64d
|
11
gcc/config/riscv/t-riscv
Normal file
11
gcc/config/riscv/t-riscv
Normal file
|
@ -0,0 +1,11 @@
|
|||
riscv-builtins.o: $(srcdir)/config/riscv/riscv-builtins.c $(CONFIG_H) \
|
||||
$(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) $(RECOG_H) langhooks.h \
|
||||
$(DIAGNOSTIC_CORE_H) $(OPTABS_H) $(srcdir)/config/riscv/riscv-ftypes.def \
|
||||
$(srcdir)/config/riscv/riscv-modes.def
|
||||
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
|
||||
$(srcdir)/config/riscv/riscv-builtins.c
|
||||
|
||||
riscv-c.o: $(srcdir)/config/riscv/riscv-c.c $(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/riscv/riscv-c.c
|
|
@ -3393,6 +3393,17 @@ x3: .space 4
|
|||
tls_first_minor=14
|
||||
tls_as_opt="-a32 --fatal-warnings"
|
||||
;;
|
||||
riscv*-*-*)
|
||||
conftest_s='
|
||||
.section .tdata,"awT",@progbits
|
||||
x: .word 2
|
||||
.text
|
||||
la.tls.gd a0,x
|
||||
call __tls_get_addr'
|
||||
tls_first_major=2
|
||||
tls_first_minor=21
|
||||
tls_as_opt='--fatal-warnings'
|
||||
;;
|
||||
s390-*-*)
|
||||
conftest_s='
|
||||
.section ".tdata","awT",@progbits
|
||||
|
@ -4744,8 +4755,8 @@ esac
|
|||
# version to the per-target configury.
|
||||
case "$cpu_type" in
|
||||
aarch64 | alpha | arm | avr | bfin | cris | i386 | m32c | m68k | microblaze \
|
||||
| mips | nios2 | pa | rs6000 | score | sparc | spu | tilegx | tilepro \
|
||||
| visium | xstormy16 | xtensa)
|
||||
| mips | nios2 | pa | riscv | rs6000 | score | sparc | spu | tilegx \
|
||||
| tilepro | visium | xstormy16 | xtensa)
|
||||
insn="nop"
|
||||
;;
|
||||
ia64 | s390)
|
||||
|
|
|
@ -172,6 +172,10 @@ John-Marc Chandonia for various libgcj patches.
|
|||
Denis Chertykov for contributing and maintaining the AVR port, the first GCC port
|
||||
for an 8-bit architecture.
|
||||
|
||||
@item
|
||||
Kito Cheng for his work on the RISC-V port, including bringing up the test
|
||||
suite and maintenance.
|
||||
|
||||
@item
|
||||
Scott Christley for his Objective-C contributions.
|
||||
|
||||
|
@ -216,6 +220,9 @@ Ian Dall for major improvements to the NS32k port.
|
|||
Paul Dale for his work to add uClinux platform support to the
|
||||
m68k backend.
|
||||
|
||||
@item
|
||||
Palmer Dabbelt for his work maintaining the RISC-V port.
|
||||
|
||||
@item
|
||||
Dario Dariol contributed the four varieties of sample programs
|
||||
that print a copy of their source.
|
||||
|
@ -1034,6 +1041,9 @@ associated configure steps.
|
|||
@item
|
||||
Todd Vierling for contributions for NetBSD ports.
|
||||
|
||||
@item
|
||||
Andrew Waterman for contributing the RISC-V port, as well as maintaining it.
|
||||
|
||||
@item
|
||||
Jonathan Wakely for contributing libstdc++ Doxygen notes and XHTML
|
||||
guidance.
|
||||
|
|
|
@ -4294,6 +4294,36 @@ Embedded PowerPC system in little endian mode.
|
|||
The Renesas RL78 processor.
|
||||
This configuration is intended for embedded systems.
|
||||
|
||||
@html
|
||||
<hr />
|
||||
@end html
|
||||
@anchor{riscv32-x-elf}
|
||||
@heading riscv32-*-elf
|
||||
The RISC-V RV32 instruction set.
|
||||
This configuration is intended for embedded systems.
|
||||
|
||||
@html
|
||||
<hr />
|
||||
@end html
|
||||
@anchor{riscv64-x-elf}
|
||||
@heading riscv64-*-elf
|
||||
The RISC-V RV64 instruction set.
|
||||
This configuration is intended for embedded systems.
|
||||
|
||||
@html
|
||||
<hr />
|
||||
@end html
|
||||
@anchor{riscv32-x-linux}
|
||||
@heading riscv32-*-linux
|
||||
The RISC-V RV32 instruction set running GNU/Linux.
|
||||
|
||||
@html
|
||||
<hr />
|
||||
@end html
|
||||
@anchor{riscv64-x-linux}
|
||||
@heading riscv64-*-linux
|
||||
The RISC-V RV64 instruction set running GNU/Linux.
|
||||
|
||||
@html
|
||||
<hr />
|
||||
@end html
|
||||
|
|
|
@ -1026,6 +1026,20 @@ See RS/6000 and PowerPC Options.
|
|||
-mstack-protector-guard-offset=@var{offset} @gol
|
||||
-mlra -mno-lra}
|
||||
|
||||
@emph{RISC-V Options}
|
||||
@gccoptlist{-mbranch-cost=@var{N-instruction} @gol
|
||||
-mmemcpy -mno-memcpy @gol
|
||||
-mplt -mno-plt @gol
|
||||
-mabi=@var{ABI-string} @gol
|
||||
-mfdiv -mno-fdiv @gol
|
||||
-mdiv -mno-div @gol
|
||||
-march=@var{ISA-string} @gol
|
||||
-mtune=@var{processor-string} @gol
|
||||
-msmall-data-limit=@var{N-bytes} @gol
|
||||
-msave-restore -mno-save-restore @gol
|
||||
-mcmodel=@var{code-model} @gol
|
||||
-mexplicit-relocs -mno-explicit-relocs @gol}
|
||||
|
||||
@emph{RX Options}
|
||||
@gccoptlist{-m64bit-doubles -m32bit-doubles -fpu -nofpu@gol
|
||||
-mcpu=@gol
|
||||
|
@ -13744,6 +13758,7 @@ platform.
|
|||
* PowerPC Options::
|
||||
* RL78 Options::
|
||||
* RS/6000 and PowerPC Options::
|
||||
* RISC-V Options::
|
||||
* RX Options::
|
||||
* S/390 and zSeries Options::
|
||||
* Score Options::
|
||||
|
@ -22137,6 +22152,70 @@ offset from that base register. The default for those is as specified in the
|
|||
relevant ABI.
|
||||
@end table
|
||||
|
||||
@node RISC-V Options
|
||||
@subsection RISC-V Options
|
||||
@cindex RISC-V Options
|
||||
|
||||
These command-line options are defined for RISC-V targets:
|
||||
|
||||
@table @gcctabopt
|
||||
@item -mbranch-cost=@var{n}
|
||||
@opindex mbranch-cost
|
||||
Set the cost of branches to roughly @var{n} instructions.
|
||||
|
||||
@item -mmemcpy
|
||||
@itemx -mno-memcpy
|
||||
@opindex mmemcpy
|
||||
Don't optimize block moves.
|
||||
|
||||
@item -mplt
|
||||
@itemx -mno-plt
|
||||
@opindex plt
|
||||
When generating PIC code, allow the use of PLTs. Ignored for non-PIC.
|
||||
|
||||
@item -mabi=@var{ABI-string}
|
||||
@opindex mabi
|
||||
Specify integer and floating-point calling convention. This defaults to the
|
||||
natural calling convention: e.g.@ LP64 for RV64I, ILP32 for RV32I, LP64D for
|
||||
RV64G.
|
||||
|
||||
@item -mfdiv
|
||||
@itemx -mno-fdiv
|
||||
@opindex mfdiv
|
||||
Use hardware floating-point divide and square root instructions. This requires
|
||||
the F or D extensions for floating-point registers.
|
||||
|
||||
@item -mdiv
|
||||
@itemx -mno-div
|
||||
@opindex mdiv
|
||||
Use hardware instructions for integer division. This requires the M extension.
|
||||
|
||||
@item -march=@var{ISA-string}
|
||||
@opindex march
|
||||
Generate code for given RISC-V ISA (e.g.@ @samp{rv64im}). ISA strings must be
|
||||
lower-case. Examples include @samp{rv64i}, @samp{rv32g}, and @samp{rv32imaf}.
|
||||
|
||||
@item -mtune=@var{processor-string}
|
||||
@opindex mtune
|
||||
Optimize the output for the given processor, specified by microarchitecture
|
||||
name.
|
||||
|
||||
@item -msmall-data-limit=@var{n}
|
||||
@opindex msmall-data-limit
|
||||
Put global and static data smaller than @var{n} bytes into a special section
|
||||
(on some targets).
|
||||
|
||||
@item -msave-restore
|
||||
@itemx -mno-save-restore
|
||||
@opindex msave-restore
|
||||
Use smaller but slower prologue and epilogue code.
|
||||
|
||||
@item -mcmodel=@var{code-model}
|
||||
@opindex mcmodel
|
||||
Specify the code model.
|
||||
|
||||
@end table
|
||||
|
||||
@node RX Options
|
||||
@subsection RX Options
|
||||
@cindex RX Options
|
||||
|
|
|
@ -3362,6 +3362,26 @@ The @code{X} register.
|
|||
|
||||
@end table
|
||||
|
||||
@item RISC-V---@file{config/riscv/constraints.md}
|
||||
@table @code
|
||||
|
||||
@item f
|
||||
A floating-point register (if availiable).
|
||||
|
||||
@item I
|
||||
An I-type 12-bit signed immediate.
|
||||
|
||||
@item J
|
||||
Integer zero.
|
||||
|
||||
@item K
|
||||
A 5-bit unsigned immediate for CSR access instructions.
|
||||
|
||||
@item A
|
||||
An address that is held in a general-purpose register.
|
||||
|
||||
@end table
|
||||
|
||||
@item RX---@file{config/rx/constraints.md}
|
||||
@table @code
|
||||
@item Q
|
||||
|
|
Loading…
Add table
Reference in a new issue