• R/O
  • HTTP
  • SSH
  • HTTPS

gcc-fork: Commit


Commit MetaInfo

Revision9f4a68236290720f186c5fa461ecd61bae5c12dc (tree)
Time2014-05-18 11:48:17
AuthorMasaki Muranaka <monaka@pizz...>
CommiterMasaki Muranaka

Log Message

Add NIOS2 support. Code from SourceyG++.

Change Summary

Incremental Difference

--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -331,6 +331,10 @@ mips*-*-*)
331331 need_64bit_hwint=yes
332332 extra_headers="loongson.h"
333333 ;;
334+nios2-*-*)
335+ cpu_type=nios2
336+ extra_options="${extra_options} g.opt"
337+ ;;
334338 picochip-*-*)
335339 cpu_type=picochip
336340 ;;
@@ -1871,6 +1875,19 @@ mn10300-*-*)
18711875 use_collect2=no
18721876 use_gcc_stdint=wrap
18731877 ;;
1878+nios2-*-*)
1879+ tm_file="elfos.h ${tm_file}"
1880+ tmake_file="${tmake_file} nios2/t-nios2"
1881+ case ${target} in
1882+ nios2-*-linux*)
1883+ tm_file="${tm_file} gnu-user.h linux.h glibc-stdint.h nios2/linux.h "
1884+ ;;
1885+ nios2-*-elf*)
1886+ tm_file="${tm_file} newlib-stdint.h nios2/elf.h"
1887+ extra_options="${extra_options} nios2/elf.opt"
1888+ ;;
1889+ esac
1890+ ;;
18741891 pdp11-*-*)
18751892 tm_file="${tm_file} newlib-stdint.h"
18761893 use_gcc_stdint=wrap
--- /dev/null
+++ b/gcc/config/nios2/constraints.md
@@ -0,0 +1,120 @@
1+;; Constraint definitions for Altera Nios II.
2+;; Copyright (C) 2012 Free Software Foundation, Inc.
3+;; Contributed by Chung-Lin Tang <cltang@codesourcery.com>
4+;;
5+;; This file is part of GCC.
6+;;
7+;; GCC is free software; you can redistribute it and/or modify
8+;; it under the terms of the GNU General Public License as published by
9+;; the Free Software Foundation; either version 3, or (at your option)
10+;; any later version.
11+;;
12+;; GCC is distributed in the hope that it will be useful,
13+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+;; GNU General Public License for more details.
16+;;
17+;; You should have received a copy of the GNU General Public License
18+;; along with GCC; see the file COPYING3. If not see
19+;; <http://www.gnu.org/licenses/>.
20+
21+;; We use the following constraint letters for constants
22+;;
23+;; I: -32768 to -32767
24+;; J: 0 to 65535
25+;; K: $nnnn0000 for some nnnn
26+;; L: 0 to 31 (for shift counts)
27+;; M: 0
28+;; N: 0 to 255 (for custom instruction numbers)
29+;; O: 0 to 31 (for control register numbers)
30+;;
31+;; We use the following built-in register classes:
32+;;
33+;; r: general purpose register (r0..r31)
34+;; m: memory operand
35+;;
36+;; Plus, we define the following constraint strings:
37+;;
38+;; S: symbol that is in the "small data" area
39+;; Dnn: Dnn_REG (just rnn)
40+
41+;; Register constraints
42+
43+(define_register_constraint "j" "SIB_REGS"
44+ "A register suitable for an indirect sibcall.")
45+
46+;; These are documented for use in inline asm.
47+(define_register_constraint "D00" "D00_REG" "Hard register 0.")
48+(define_register_constraint "D01" "D01_REG" "Hard register 1.")
49+(define_register_constraint "D02" "D02_REG" "Hard register 2.")
50+(define_register_constraint "D03" "D03_REG" "Hard register 3.")
51+(define_register_constraint "D04" "D04_REG" "Hard register 4.")
52+(define_register_constraint "D05" "D05_REG" "Hard register 5.")
53+(define_register_constraint "D06" "D06_REG" "Hard register 6.")
54+(define_register_constraint "D07" "D07_REG" "Hard register 7.")
55+(define_register_constraint "D08" "D08_REG" "Hard register 8.")
56+(define_register_constraint "D09" "D09_REG" "Hard register 9.")
57+(define_register_constraint "D10" "D10_REG" "Hard register 10.")
58+(define_register_constraint "D11" "D11_REG" "Hard register 11.")
59+(define_register_constraint "D12" "D12_REG" "Hard register 12.")
60+(define_register_constraint "D13" "D13_REG" "Hard register 13.")
61+(define_register_constraint "D14" "D14_REG" "Hard register 14.")
62+(define_register_constraint "D15" "D15_REG" "Hard register 15.")
63+(define_register_constraint "D16" "D16_REG" "Hard register 16.")
64+(define_register_constraint "D17" "D17_REG" "Hard register 17.")
65+(define_register_constraint "D18" "D18_REG" "Hard register 18.")
66+(define_register_constraint "D19" "D19_REG" "Hard register 19.")
67+(define_register_constraint "D20" "D20_REG" "Hard register 20.")
68+(define_register_constraint "D21" "D21_REG" "Hard register 21.")
69+(define_register_constraint "D22" "D22_REG" "Hard register 22.")
70+(define_register_constraint "D23" "D23_REG" "Hard register 23.")
71+(define_register_constraint "D24" "D24_REG" "Hard register 24.")
72+(define_register_constraint "D25" "D25_REG" "Hard register 25.")
73+(define_register_constraint "D26" "D26_REG" "Hard register 26.")
74+(define_register_constraint "D27" "D27_REG" "Hard register 27.")
75+(define_register_constraint "D28" "D28_REG" "Hard register 28.")
76+(define_register_constraint "D29" "D29_REG" "Hard register 29.")
77+(define_register_constraint "D30" "D30_REG" "Hard register 30.")
78+(define_register_constraint "D31" "D31_REG" "Hard register 31.")
79+
80+;; Integer constraints
81+
82+(define_constraint "I"
83+ "A signed 16-bit constant (for arithmetic instructions)."
84+ (and (match_code "const_int")
85+ (match_test "SMALL_INT (ival)")))
86+
87+(define_constraint "J"
88+ "An unsigned 16-bit constant (for logical instructions)."
89+ (and (match_code "const_int")
90+ (match_test "SMALL_INT_UNSIGNED (ival)")))
91+
92+(define_constraint "K"
93+ "An unsigned 16-bit high constant (for logical instructions)."
94+ (and (match_code "const_int")
95+ (match_test "UPPER16_INT (ival)")))
96+
97+(define_constraint "L"
98+ "An unsigned 5-bit constant (for shift counts)."
99+ (and (match_code "const_int")
100+ (match_test "ival >= 0 && ival <= 31")))
101+
102+(define_constraint "M"
103+ "Integer zero."
104+ (and (match_code "const_int")
105+ (match_test "ival == 0")))
106+
107+(define_constraint "N"
108+ "An unsigned 8-bit constant (for custom instruction codes)."
109+ (and (match_code "const_int")
110+ (match_test "ival >= 0 && ival <= 255")))
111+
112+(define_constraint "O"
113+ "An unsigned 5-bit constant (for control register numbers)."
114+ (and (match_code "const_int")
115+ (match_test "ival >= 0 && ival <= 31")))
116+
117+(define_constraint "S"
118+ "An immediate stored in small data, accessible by GP."
119+ (and (match_code "symbol_ref")
120+ (match_test "SYMBOL_REF_IN_NIOS2_SMALL_DATA_P (op)")))
--- /dev/null
+++ b/gcc/config/nios2/elf.h
@@ -0,0 +1,52 @@
1+/* Definitions of ELF target support for Altera Nios II.
2+ Copyright (C) 2012 Free Software Foundation, Inc.
3+ Contributed by Jonah Graham (jgraham@altera.com),
4+ Will Reece (wreece@altera.com), and Jeff DaSilva (jdasilva@altera.com).
5+ Contributed by Mentor Graphics, Inc.
6+
7+ This file is part of GCC.
8+
9+ GCC is free software; you can redistribute it and/or modify it
10+ under the terms of the GNU General Public License as published
11+ by the Free Software Foundation; either version 3, or (at your
12+ option) any later version.
13+
14+ GCC is distributed in the hope that it will be useful, but WITHOUT
15+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17+ License for more details.
18+
19+ You should have received a copy of the GNU General Public License
20+ along with GCC; see the file COPYING3. If not see
21+ <http://www.gnu.org/licenses/>. */
22+
23+
24+/* Specs to support the additional command-line options for Nios II ELF
25+ toolchains. */
26+
27+/* -msmallc chooses an alternate C library.
28+ -msys-lib= specifies an additional low-level system/hosting library and
29+ is typically used to suck in a library provided by a HAL BSP. */
30+#undef LIB_SPEC
31+#define LIB_SPEC \
32+"--start-group %{msmallc: -lsmallc} %{!msmallc: -lc} -lgcc \
33+ %{msys-lib=*: -l%*} \
34+ --end-group \
35+"
36+
37+/* Linking with -mhal suppresses inclusion of the GCC-provided crt* begin/end
38+ code. Normally in this case you also link with -msys-crt0= to specify
39+ the startup code provided by the HAL BSP instead. */
40+#undef STARTFILE_SPEC
41+#define STARTFILE_SPEC \
42+ "%{mhal:" \
43+ "%{msys-crt0=*:%*} %{!msys-crt0=*:crt0%O%s} " \
44+ "%{msys-crt0=:%eYou need a C startup file for -msys-crt0=};" \
45+ ":crti%O%s crtbegin%O%s}"
46+
47+#undef ENDFILE_SPEC
48+#define ENDFILE_SPEC "%{!mhal:crtend%O%s crtn%O%s}"
49+
50+/* The ELF target doesn't support the Nios II Linux ABI. */
51+#define TARGET_LINUX_ABI 0
52+
--- /dev/null
+++ b/gcc/config/nios2/elf.opt
@@ -0,0 +1,38 @@
1+; Options for the Altera Nios II port of the compiler.
2+; Copyright (C) 2012 Free Software Foundation, Inc.
3+; Contributed by Altera and Mentor Graphics, Inc.
4+;
5+; This file is part of GCC.
6+;
7+; GCC is free software; you can redistribute it and/or modify
8+; it under the terms of the GNU General Public License as published by
9+; the Free Software Foundation; either version 3, or (at your option)
10+; any later version.
11+;
12+; GCC is distributed in the hope that it will be useful,
13+; but WITHOUT ANY WARRANTY; without even the implied warranty of
14+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+; GNU General Public License for more details.
16+;
17+; You should have received a copy of the GNU General Public License
18+; along with GCC; see the file COPYING3. If not see
19+; <http://www.gnu.org/licenses/>.
20+
21+; These additional options are supported for ELF (bare-metal) Nios II
22+; toolchains.
23+
24+msmallc
25+Target Report RejectNegative
26+Link with a limited version of the C library
27+
28+msys-lib=
29+Target RejectNegative Joined Var(nios2_sys_lib_string)
30+Name of system library to link against
31+
32+msys-crt0=
33+Target RejectNegative Joined Var(nios2_sys_crt0_string)
34+Name of the startfile
35+
36+mhal
37+Target Report RejectNegative
38+Link with HAL BSP
--- /dev/null
+++ b/gcc/config/nios2/linux.h
@@ -0,0 +1,55 @@
1+/* Definitions of target support for Altera Nios II systems
2+ running GNU/Linux with ELF format.
3+ Copyright (C) 2012 Free Software Foundation, Inc.
4+ Contributed by Mentor Graphics, Inc.
5+
6+ This file is part of GCC.
7+
8+ GCC is free software; you can redistribute it and/or modify it
9+ under the terms of the GNU General Public License as published
10+ by the Free Software Foundation; either version 3, or (at your
11+ option) any later version.
12+
13+ GCC is distributed in the hope that it will be useful, but WITHOUT
14+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16+ License for more details.
17+
18+ You should have received a copy of the GNU General Public License
19+ along with GCC; see the file COPYING3. If not see
20+ <http://www.gnu.org/licenses/>. */
21+
22+#undef LIB_SPEC
23+#define LIB_SPEC "-lc \
24+ %{pthread:-lpthread}"
25+
26+#undef STARTFILE_SPEC
27+#define STARTFILE_SPEC \
28+"%{!shared: crt1.o%s} \
29+ crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s}"
30+
31+#undef ENDFILE_SPEC
32+#define ENDFILE_SPEC \
33+"%{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s"
34+
35+#define TARGET_OS_CPP_BUILTINS() \
36+ do \
37+ { \
38+ GNU_USER_TARGET_OS_CPP_BUILTINS(); \
39+ } \
40+ while (0)
41+
42+#undef SYSROOT_SUFFIX_SPEC
43+#define SYSROOT_SUFFIX_SPEC \
44+ "%{EB:/EB}"
45+
46+#undef LINK_SPEC
47+#define LINK_SPEC LINK_SPEC_ENDIAN \
48+ " %{shared:-shared} \
49+ %{static:-Bstatic} \
50+ %{rdynamic:-export-dynamic}"
51+
52+/* This toolchain implements the ABI for Linux Systems documented in the
53+ Nios II Processor Reference Handbook. */
54+#define TARGET_LINUX_ABI 1
55+
--- /dev/null
+++ b/gcc/config/nios2/nios2-opts.h
@@ -0,0 +1,70 @@
1+/* Definitions for option handling for Nios II.
2+ Copyright (C) 2013
3+ Free Software Foundation, Inc.
4+
5+This file is part of GCC.
6+
7+GCC is free software; you can redistribute it and/or modify
8+it under the terms of the GNU General Public License as published by
9+the Free Software Foundation; either version 3, or (at your option)
10+any later version.
11+
12+GCC is distributed in the hope that it will be useful,
13+but WITHOUT ANY WARRANTY; without even the implied warranty of
14+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+GNU General Public License for more details.
16+
17+You should have received a copy of the GNU General Public License
18+along with GCC; see the file COPYING3. If not see
19+<http://www.gnu.org/licenses/>. */
20+
21+#ifndef NIOS2_OPTS_H
22+#define NIOS2_OPTS_H
23+
24+/* Enumeration of all FPU insn codes. */
25+#define N2FPU_ALL_CODES \
26+ N2FPU_CODE(fadds) N2FPU_CODE(fsubs) N2FPU_CODE(fmuls) N2FPU_CODE(fdivs) \
27+ N2FPU_CODE(fmins) N2FPU_CODE(fmaxs) \
28+ N2FPU_CODE(fnegs) N2FPU_CODE(fabss) N2FPU_CODE(fsqrts) \
29+ N2FPU_CODE(fsins) N2FPU_CODE(fcoss) N2FPU_CODE(ftans) N2FPU_CODE(fatans) \
30+ N2FPU_CODE(fexps) N2FPU_CODE(flogs) \
31+ N2FPU_CODE(fcmpeqs) N2FPU_CODE(fcmpnes) \
32+ N2FPU_CODE(fcmplts) N2FPU_CODE(fcmples) \
33+ N2FPU_CODE(fcmpgts) N2FPU_CODE(fcmpges) \
34+ \
35+ N2FPU_CODE(faddd) N2FPU_CODE(fsubd) N2FPU_CODE(fmuld) N2FPU_CODE(fdivd) \
36+ N2FPU_CODE(fmind) N2FPU_CODE(fmaxd) \
37+ N2FPU_CODE(fnegd) N2FPU_CODE(fabsd) N2FPU_CODE(fsqrtd) \
38+ N2FPU_CODE(fsind) N2FPU_CODE(fcosd) N2FPU_CODE(ftand) N2FPU_CODE(fatand) \
39+ N2FPU_CODE(fexpd) N2FPU_CODE(flogd) \
40+ N2FPU_CODE(fcmpeqd) N2FPU_CODE(fcmpned) \
41+ N2FPU_CODE(fcmpltd) N2FPU_CODE(fcmpled) \
42+ N2FPU_CODE(fcmpgtd) N2FPU_CODE(fcmpged) \
43+ \
44+ N2FPU_CODE(floatis) N2FPU_CODE(floatus) \
45+ N2FPU_CODE(floatid) N2FPU_CODE(floatud) \
46+ N2FPU_CODE(fixsi) N2FPU_CODE(fixsu) \
47+ N2FPU_CODE(fixdi) N2FPU_CODE(fixdu) \
48+ N2FPU_CODE(fextsd) N2FPU_CODE(ftruncds) \
49+ \
50+ N2FPU_CODE(fwrx) N2FPU_CODE(fwry) \
51+ N2FPU_CODE(frdxlo) N2FPU_CODE(frdxhi) N2FPU_CODE(frdy)
52+
53+enum n2fpu_code {
54+#define N2FPU_CODE(name) n2fpu_ ## name,
55+ N2FPU_ALL_CODES
56+#undef N2FPU_CODE
57+ n2fpu_code_num
58+};
59+
60+/* An enumeration to indicate the custom code status; if values within 0--255
61+ are registered to an FPU insn, or custom insn. */
62+enum nios2_ccs_code
63+{
64+ CCS_UNUSED,
65+ CCS_FPU,
66+ CCS_BUILTIN_CALL
67+};
68+
69+#endif
70+
--- /dev/null
+++ b/gcc/config/nios2/nios2-protos.h
@@ -0,0 +1,59 @@
1+/* Subroutine declarations for Altera Nios II target support.
2+ Copyright (C) 2012 Free Software Foundation, Inc.
3+ Contributed by Jonah Graham (jgraham@altera.com).
4+ Contributed by Mentor Graphics, Inc.
5+
6+ This file is part of GCC.
7+
8+ GCC is free software; you can redistribute it and/or modify it
9+ under the terms of the GNU General Public License as published
10+ by the Free Software Foundation; either version 3, or (at your
11+ option) any later version.
12+
13+ GCC is distributed in the hope that it will be useful, but WITHOUT
14+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16+ License for more details.
17+
18+ You should have received a copy of the GNU General Public License
19+ along with GCC; see the file COPYING3. If not see
20+ <http://www.gnu.org/licenses/>. */
21+
22+#ifndef GCC_NIOS2_PROTOS_H
23+#define GCC_NIOS2_PROTOS_H
24+
25+extern int nios2_initial_elimination_offset (int, int);
26+extern int nios2_can_use_return_insn (void);
27+extern void expand_prologue (void);
28+extern void expand_epilogue (bool);
29+extern void nios2_function_profiler (FILE *, int);
30+
31+#ifdef RTX_CODE
32+extern int nios2_emit_move_sequence (rtx *, enum machine_mode);
33+extern int nios2_emit_expensive_div (rtx *, enum machine_mode);
34+extern void nios2_adjust_call_address (rtx *);
35+
36+extern rtx nios2_get_return_address (int);
37+extern void nios2_set_return_address (rtx, rtx);
38+
39+extern bool nios2_supported_compare_p (enum machine_mode);
40+extern bool nios2_validate_compare (enum machine_mode, rtx*, rtx*, rtx*);
41+
42+extern bool nios2_fpu_insn_enabled (enum n2fpu_code);
43+extern const char* nios2_fpu_insn_asm (enum n2fpu_code);
44+
45+extern bool nios2_legitimate_pic_operand_p (rtx x);
46+
47+#ifdef TREE_CODE
48+#ifdef ARGS_SIZE_RTX
49+/* expr.h defines both ARGS_SIZE_RTX and `enum direction' */
50+extern enum direction nios2_function_arg_padding (enum machine_mode, const_tree);
51+extern enum direction nios2_block_reg_padding (enum machine_mode, tree, int);
52+#endif /* ARGS_SIZE_RTX */
53+
54+extern void nios2_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
55+
56+#endif /* TREE_CODE */
57+#endif /* RTX_CODE */
58+
59+#endif /* GCC_NIOS2_PROTOS_H */
--- /dev/null
+++ b/gcc/config/nios2/nios2.c
@@ -0,0 +1,3250 @@
1+/* Target machine subroutines for Altera Nios II.
2+ Copyright (C) 2012 Free Software Foundation, Inc.
3+ Contributed by Jonah Graham (jgraham@altera.com),
4+ Will Reece (wreece@altera.com), and Jeff DaSilva (jdasilva@altera.com).
5+ Contributed by Mentor Graphics, Inc.
6+
7+ This file is part of GCC.
8+
9+ GCC is free software; you can redistribute it and/or modify it
10+ under the terms of the GNU General Public License as published
11+ by the Free Software Foundation; either version 3, or (at your
12+ option) any later version.
13+
14+ GCC is distributed in the hope that it will be useful, but WITHOUT
15+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17+ License for more details.
18+
19+ You should have received a copy of the GNU General Public License
20+ along with GCC; see the file COPYING3. If not see
21+ <http://www.gnu.org/licenses/>. */
22+
23+#include <stdio.h>
24+#include "config.h"
25+#include "system.h"
26+#include "coretypes.h"
27+#include "tm.h"
28+#include "rtl.h"
29+#include "tree.h"
30+#include "regs.h"
31+#include "hard-reg-set.h"
32+#include "insn-config.h"
33+#include "conditions.h"
34+#include "output.h"
35+#include "insn-attr.h"
36+#include "flags.h"
37+#include "recog.h"
38+#include "expr.h"
39+#include "optabs.h"
40+#include "function.h"
41+#include "ggc.h"
42+#include "basic-block.h"
43+#include "diagnostic-core.h"
44+#include "toplev.h"
45+#include "target.h"
46+#include "target-def.h"
47+#include "tm_p.h"
48+#include "langhooks.h"
49+#include "df.h"
50+#include "debug.h"
51+#include "real.h"
52+#include "integrate.h"
53+#include "reload.h"
54+
55+/* Local prototypes. */
56+static bool nios2_rtx_costs (rtx, int, int, int, int *, bool);
57+static reg_class_t nios2_preferred_reload_class (rtx, reg_class_t);
58+static void nios2_print_operand (FILE *, rtx, int);
59+static void nios2_print_operand_address (FILE *, rtx);
60+static void nios2_asm_function_prologue (FILE *, HOST_WIDE_INT);
61+static int nios2_issue_rate (void);
62+static struct machine_function *nios2_init_machine_status (void);
63+static bool nios2_in_small_data_p (const_tree);
64+static void dump_frame_size (FILE *);
65+static HOST_WIDE_INT compute_frame_size (void);
66+static void save_reg (int, unsigned);
67+static void restore_reg (int, unsigned);
68+static unsigned int nios2_section_type_flags (tree, const char *, int);
69+static bool nios2_can_eliminate (const int, const int);
70+static void nios2_load_pic_register (void);
71+static bool nios2_cannot_force_const_mem (enum machine_mode, rtx);
72+static rtx nios2_legitimize_pic_address (rtx orig, enum machine_mode mode,
73+ rtx reg);
74+static bool nios2_legitimate_constant_p (enum machine_mode, rtx);
75+static rtx nios2_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode);
76+static bool nios2_legitimate_address_p (enum machine_mode mode, rtx, bool);
77+static void nios2_init_builtins (void);
78+static rtx nios2_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
79+static void nios2_init_libfuncs (void);
80+static rtx nios2_function_arg (cumulative_args_t, enum machine_mode,
81+ const_tree, bool);
82+static void nios2_function_arg_advance (cumulative_args_t, enum machine_mode,
83+ const_tree, bool);
84+static void nios2_setup_incoming_varargs (cumulative_args_t, enum machine_mode,
85+ tree, int *, int);
86+static int nios2_arg_partial_bytes (cumulative_args_t,
87+ enum machine_mode, tree, bool);
88+static void nios2_trampoline_init (rtx, tree, rtx);
89+static rtx nios2_function_value (const_tree, const_tree, bool);
90+static rtx nios2_libcall_value (enum machine_mode, const_rtx);
91+static bool nios2_function_value_regno_p (const unsigned int);
92+static bool nios2_return_in_memory (const_tree, const_tree);
93+static void nios2_encode_section_info (tree, rtx, int);
94+static void nios2_output_dwarf_dtprel (FILE *fuke, int size, rtx x);
95+static void nios2_option_override (void);
96+static void nios2_option_save (struct cl_target_option*);
97+static void nios2_option_restore (struct cl_target_option*);
98+static void nios2_set_current_function (tree);
99+static bool nios2_valid_target_attribute_p (tree, tree, tree, int);
100+static bool nios2_pragma_target_parse (tree, tree);
101+static tree nios2_merge_decl_attributes (tree, tree);
102+static void nios2_custom_check_insns (void);
103+static void nios2_handle_custom_fpu_cfg (const char*, bool);
104+static void nios2_handle_custom_fpu_insn_option (int);
105+static void nios2_register_custom_code (unsigned int, enum nios2_ccs_code, int);
106+static void nios2_deregister_custom_code (unsigned int);
107+
108+/* Initialize the GCC target structure. */
109+#undef TARGET_ASM_FUNCTION_PROLOGUE
110+#define TARGET_ASM_FUNCTION_PROLOGUE nios2_asm_function_prologue
111+
112+#undef TARGET_SCHED_ISSUE_RATE
113+#define TARGET_SCHED_ISSUE_RATE nios2_issue_rate
114+#undef TARGET_IN_SMALL_DATA_P
115+#define TARGET_IN_SMALL_DATA_P nios2_in_small_data_p
116+#undef TARGET_ENCODE_SECTION_INFO
117+#define TARGET_ENCODE_SECTION_INFO nios2_encode_section_info
118+#undef TARGET_SECTION_TYPE_FLAGS
119+#define TARGET_SECTION_TYPE_FLAGS nios2_section_type_flags
120+
121+#undef TARGET_INIT_BUILTINS
122+#define TARGET_INIT_BUILTINS nios2_init_builtins
123+#undef TARGET_EXPAND_BUILTIN
124+#define TARGET_EXPAND_BUILTIN nios2_expand_builtin
125+
126+#undef TARGET_INIT_LIBFUNCS
127+#define TARGET_INIT_LIBFUNCS nios2_init_libfuncs
128+
129+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
130+#define TARGET_FUNCTION_OK_FOR_SIBCALL hook_bool_tree_tree_true
131+
132+#undef TARGET_CAN_ELIMINATE
133+#define TARGET_CAN_ELIMINATE nios2_can_eliminate
134+
135+#undef TARGET_FUNCTION_ARG
136+#define TARGET_FUNCTION_ARG nios2_function_arg
137+
138+#undef TARGET_FUNCTION_ARG_ADVANCE
139+#define TARGET_FUNCTION_ARG_ADVANCE nios2_function_arg_advance
140+
141+#undef TARGET_ARG_PARTIAL_BYTES
142+#define TARGET_ARG_PARTIAL_BYTES nios2_arg_partial_bytes
143+
144+#undef TARGET_TRAMPOLINE_INIT
145+#define TARGET_TRAMPOLINE_INIT nios2_trampoline_init
146+
147+#undef TARGET_FUNCTION_VALUE
148+#define TARGET_FUNCTION_VALUE nios2_function_value
149+
150+#undef TARGET_LIBCALL_VALUE
151+#define TARGET_LIBCALL_VALUE nios2_libcall_value
152+
153+#undef TARGET_FUNCTION_VALUE_REGNO_P
154+#define TARGET_FUNCTION_VALUE_REGNO_P nios2_function_value_regno_p
155+
156+#undef TARGET_RETURN_IN_MEMORY
157+#define TARGET_RETURN_IN_MEMORY nios2_return_in_memory
158+
159+#undef TARGET_PROMOTE_PROTOTYPES
160+#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
161+
162+#undef TARGET_SETUP_INCOMING_VARARGS
163+#define TARGET_SETUP_INCOMING_VARARGS nios2_setup_incoming_varargs
164+
165+#undef TARGET_MUST_PASS_IN_STACK
166+#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
167+
168+#undef TARGET_LEGITIMATE_CONSTANT_P
169+#define TARGET_LEGITIMATE_CONSTANT_P nios2_legitimate_constant_p
170+
171+#undef TARGET_LEGITIMIZE_ADDRESS
172+#define TARGET_LEGITIMIZE_ADDRESS nios2_legitimize_address
173+
174+#undef TARGET_LEGITIMATE_ADDRESS_P
175+#define TARGET_LEGITIMATE_ADDRESS_P nios2_legitimate_address_p
176+
177+#undef TARGET_PREFERRED_RELOAD_CLASS
178+#define TARGET_PREFERRED_RELOAD_CLASS nios2_preferred_reload_class
179+
180+#undef TARGET_RTX_COSTS
181+#define TARGET_RTX_COSTS nios2_rtx_costs
182+
183+#undef TARGET_HAVE_TLS
184+#define TARGET_HAVE_TLS TARGET_LINUX_ABI
185+
186+#undef TARGET_CANNOT_FORCE_CONST_MEM
187+#define TARGET_CANNOT_FORCE_CONST_MEM nios2_cannot_force_const_mem
188+
189+#undef TARGET_ASM_OUTPUT_DWARF_DTPREL
190+#define TARGET_ASM_OUTPUT_DWARF_DTPREL nios2_output_dwarf_dtprel
191+
192+#undef TARGET_PRINT_OPERAND
193+#define TARGET_PRINT_OPERAND nios2_print_operand
194+
195+#undef TARGET_PRINT_OPERAND_ADDRESS
196+#define TARGET_PRINT_OPERAND_ADDRESS nios2_print_operand_address
197+
198+#undef TARGET_OPTION_OVERRIDE
199+#define TARGET_OPTION_OVERRIDE nios2_option_override
200+
201+#undef TARGET_OPTION_SAVE
202+#define TARGET_OPTION_SAVE nios2_option_save
203+
204+#undef TARGET_OPTION_RESTORE
205+#define TARGET_OPTION_RESTORE nios2_option_restore
206+
207+#undef TARGET_SET_CURRENT_FUNCTION
208+#define TARGET_SET_CURRENT_FUNCTION nios2_set_current_function
209+
210+#undef TARGET_OPTION_VALID_ATTRIBUTE_P
211+#define TARGET_OPTION_VALID_ATTRIBUTE_P nios2_valid_target_attribute_p
212+
213+#undef TARGET_OPTION_PRAGMA_PARSE
214+#define TARGET_OPTION_PRAGMA_PARSE nios2_pragma_target_parse
215+
216+#undef TARGET_MERGE_DECL_ATTRIBUTES
217+#define TARGET_MERGE_DECL_ATTRIBUTES nios2_merge_decl_attributes
218+
219+/* ??? Might want to redefine TARGET_RETURN_IN_MSB here to handle
220+ big-endian case; depends on what ABI we choose. */
221+
222+struct gcc_target targetm = TARGET_INITIALIZER;
223+
224+
225+/* Threshold for data being put into the small data/bss area, instead
226+ of the normal data area (references to the small data/bss area take
227+ 1 instruction, and use the global pointer, references to the normal
228+ data area takes 2 instructions). */
229+unsigned HOST_WIDE_INT nios2_section_threshold = NIOS2_DEFAULT_GVALUE;
230+
231+struct GTY (()) machine_function
232+{
233+ /* Current frame information, to be filled in by compute_frame_size
234+ with register save masks, and offsets for the current function. */
235+
236+ unsigned HOST_WIDE_INT save_mask; /* Mask of registers to save. */
237+ long total_size; /* # bytes that the entire frame takes up. */
238+ long var_size; /* # bytes that variables take up. */
239+ long args_size; /* # bytes that outgoing arguments take up. */
240+ int save_reg_size; /* # bytes needed to store gp regs. */
241+ long save_regs_offset; /* Offset from new sp to store gp registers. */
242+ int initialized; /* != 0 if frame size already calculated. */
243+};
244+
245+/* State to track the assignment of custom codes to FPU/custom builtins. */
246+static enum nios2_ccs_code custom_code_status[256];
247+static int custom_code_index[256];
248+/* Set to true if any conflicts (re-use of a code between 0-255) are found. */
249+static bool custom_code_conflict = false;
250+
251+
252+
253+/* Definition of builtin function types for nios2. */
254+
255+#define N2_FTYPES \
256+ N2_FTYPE(1, (SF)) \
257+ N2_FTYPE(1, (VOID)) \
258+ N2_FTYPE(2, (DF, DF)) \
259+ N2_FTYPE(3, (DF, DF, DF)) \
260+ N2_FTYPE(2, (DF, SF)) \
261+ N2_FTYPE(2, (DF, SI)) \
262+ N2_FTYPE(2, (DF, UI)) \
263+ N2_FTYPE(2, (SF, DF)) \
264+ N2_FTYPE(2, (SF, SF)) \
265+ N2_FTYPE(3, (SF, SF, SF)) \
266+ N2_FTYPE(2, (SF, SI)) \
267+ N2_FTYPE(2, (SF, UI)) \
268+ N2_FTYPE(2, (SI, CVPTR)) \
269+ N2_FTYPE(2, (SI, DF)) \
270+ N2_FTYPE(3, (SI, DF, DF)) \
271+ N2_FTYPE(2, (SI, SF)) \
272+ N2_FTYPE(3, (SI, SF, SF)) \
273+ N2_FTYPE(2, (SI, SI)) \
274+ N2_FTYPE(2, (UI, CVPTR)) \
275+ N2_FTYPE(2, (UI, DF)) \
276+ N2_FTYPE(2, (UI, SF)) \
277+ N2_FTYPE(2, (VOID, DF)) \
278+ N2_FTYPE(2, (VOID, SF)) \
279+ N2_FTYPE(3, (VOID, SI, SI)) \
280+ N2_FTYPE(3, (VOID, VPTR, SI))
281+
282+#define N2_FTYPE_OP1(R) N2_FTYPE_ ## R ## _VOID
283+#define N2_FTYPE_OP2(R, A1) N2_FTYPE_ ## R ## _ ## A1
284+#define N2_FTYPE_OP3(R, A1, A2) N2_FTYPE_ ## R ## _ ## A1 ## _ ## A2
285+
286+/* Expand ftcode enumeration. */
287+enum nios2_ftcode {
288+#define N2_FTYPE(N,ARGS) N2_FTYPE_OP ## N ARGS,
289+N2_FTYPES
290+#undef N2_FTYPE
291+N2_FTYPE_MAX
292+};
293+
294+/* Return the tree function type, based on the ftcode. */
295+static tree
296+nios2_ftype (enum nios2_ftcode ftcode)
297+{
298+ static tree types[(int) N2_FTYPE_MAX];
299+
300+ tree N2_TYPE_SF = float_type_node;
301+ tree N2_TYPE_DF = double_type_node;
302+ tree N2_TYPE_SI = integer_type_node;
303+ tree N2_TYPE_UI = unsigned_type_node;
304+ tree N2_TYPE_VOID = void_type_node;
305+
306+ static const_tree N2_TYPE_CVPTR, N2_TYPE_VPTR;
307+ if (!N2_TYPE_CVPTR)
308+ {
309+ /* const volatile void * */
310+ N2_TYPE_CVPTR
311+ = build_pointer_type (build_qualified_type (void_type_node,
312+ (TYPE_QUAL_CONST
313+ | TYPE_QUAL_VOLATILE)));
314+ /* volatile void * */
315+ N2_TYPE_VPTR
316+ = build_pointer_type (build_qualified_type (void_type_node,
317+ TYPE_QUAL_VOLATILE));
318+ }
319+ if (types[(int) ftcode] == NULL_TREE)
320+ switch (ftcode)
321+ {
322+#define N2_FTYPE_ARGS1(R) N2_TYPE_ ## R
323+#define N2_FTYPE_ARGS2(R,A1) N2_TYPE_ ## R, N2_TYPE_ ## A1
324+#define N2_FTYPE_ARGS3(R,A1,A2) N2_TYPE_ ## R, N2_TYPE_ ## A1, N2_TYPE_ ## A2
325+#define N2_FTYPE(N,ARGS) \
326+ case N2_FTYPE_OP ## N ARGS: \
327+ types[(int) ftcode] \
328+ = build_function_type_list (N2_FTYPE_ARGS ## N ARGS, NULL_TREE); \
329+ break;
330+ N2_FTYPES
331+#undef N2_FTYPE
332+ default: gcc_unreachable ();
333+ }
334+ return types[(int) ftcode];
335+}
336+
337+
338+
339+/* Definition of FPU instruction descriptions. */
340+
341+struct nios2_fpu_insn_info
342+{
343+ const char *name;
344+ int num_operands, *optvar;
345+ int opt, no_opt;
346+#define N2F_DF 0x1
347+#define N2F_DFREQ 0x2
348+#define N2F_UNSAFE 0x4
349+#define N2F_FINITE 0x8
350+ unsigned int flags;
351+ enum insn_code icode;
352+ enum nios2_ftcode ftcode;
353+};
354+
355+/* Base macro for defining FPU instructions. */
356+#define N2FPU_INSN_DEF_BASE(insn, nop, flags, icode, args) \
357+ { #insn, nop, &nios2_custom_ ## insn, OPT_mcustom_##insn##_, \
358+ OPT_mno_custom_##insn, flags, CODE_FOR_ ## icode, \
359+ N2_FTYPE_OP ## nop args }
360+
361+/* Arithmetic and math functions; 2 or 3 operand FP operations. */
362+#define N2FPU_OP2(mode) (mode, mode)
363+#define N2FPU_OP3(mode) (mode, mode, mode)
364+#define N2FPU_INSN_DEF(code, icode, nop, flags, m, M) \
365+ N2FPU_INSN_DEF_BASE (f ## code ## m, nop, flags, \
366+ icode ## m ## f ## nop, N2FPU_OP ## nop (M ## F))
367+#define N2FPU_INSN_SF(code, nop, flags) \
368+ N2FPU_INSN_DEF (code, code, nop, flags, s, S)
369+#define N2FPU_INSN_DF(code, nop, flags) \
370+ N2FPU_INSN_DEF (code, code, nop, flags | N2F_DF, d, D)
371+
372+/* Compare instructions, 3 operand FP operation with a SI result. */
373+#define N2FPU_CMP_DEF(code, flags, m, M) \
374+ N2FPU_INSN_DEF_BASE (fcmp ## code ## m, 3, flags, \
375+ nios2_s ## code ## m ## f, (SI, M ## F, M ## F))
376+#define N2FPU_CMP_SF(code) N2FPU_CMP_DEF (code, 0, s, S)
377+#define N2FPU_CMP_DF(code) N2FPU_CMP_DEF (code, N2F_DF, d, D)
378+
379+/* The order of definition needs to be maintained consistent with
380+ enum n2fpu_code in nios2-opts.h. */
381+struct nios2_fpu_insn_info nios2_fpu_insn[] =
382+ {
383+ /* Single precision instructions. */
384+ N2FPU_INSN_SF (add, 3, 0),
385+ N2FPU_INSN_SF (sub, 3, 0),
386+ N2FPU_INSN_SF (mul, 3, 0),
387+ N2FPU_INSN_SF (div, 3, 0),
388+ /* Due to textual difference between min/max and smin/smax. */
389+ N2FPU_INSN_DEF (min, smin, 3, N2F_FINITE, s, S),
390+ N2FPU_INSN_DEF (max, smax, 3, N2F_FINITE, s, S),
391+ N2FPU_INSN_SF (neg, 2, 0),
392+ N2FPU_INSN_SF (abs, 2, 0),
393+ N2FPU_INSN_SF (sqrt, 2, 0),
394+ N2FPU_INSN_SF (sin, 2, N2F_UNSAFE),
395+ N2FPU_INSN_SF (cos, 2, N2F_UNSAFE),
396+ N2FPU_INSN_SF (tan, 2, N2F_UNSAFE),
397+ N2FPU_INSN_SF (atan, 2, N2F_UNSAFE),
398+ N2FPU_INSN_SF (exp, 2, N2F_UNSAFE),
399+ N2FPU_INSN_SF (log, 2, N2F_UNSAFE),
400+ /* Single precision compares. */
401+ N2FPU_CMP_SF (eq), N2FPU_CMP_SF (ne),
402+ N2FPU_CMP_SF (lt), N2FPU_CMP_SF (le),
403+ N2FPU_CMP_SF (gt), N2FPU_CMP_SF (ge),
404+
405+ /* Double precision instructions. */
406+ N2FPU_INSN_DF (add, 3, 0),
407+ N2FPU_INSN_DF (sub, 3, 0),
408+ N2FPU_INSN_DF (mul, 3, 0),
409+ N2FPU_INSN_DF (div, 3, 0),
410+ /* Due to textual difference between min/max and smin/smax. */
411+ N2FPU_INSN_DEF (min, smin, 3, N2F_FINITE, d, D),
412+ N2FPU_INSN_DEF (max, smax, 3, N2F_FINITE, d, D),
413+ N2FPU_INSN_DF (neg, 2, 0),
414+ N2FPU_INSN_DF (abs, 2, 0),
415+ N2FPU_INSN_DF (sqrt, 2, 0),
416+ N2FPU_INSN_DF (sin, 2, N2F_UNSAFE),
417+ N2FPU_INSN_DF (cos, 2, N2F_UNSAFE),
418+ N2FPU_INSN_DF (tan, 2, N2F_UNSAFE),
419+ N2FPU_INSN_DF (atan, 2, N2F_UNSAFE),
420+ N2FPU_INSN_DF (exp, 2, N2F_UNSAFE),
421+ N2FPU_INSN_DF (log, 2, N2F_UNSAFE),
422+ /* Double precision compares. */
423+ N2FPU_CMP_DF (eq), N2FPU_CMP_DF (ne),
424+ N2FPU_CMP_DF (lt), N2FPU_CMP_DF (le),
425+ N2FPU_CMP_DF (gt), N2FPU_CMP_DF (ge),
426+
427+ /* Conversion instructions. */
428+ N2FPU_INSN_DEF_BASE (floatis, 2, 0, floatsisf2, (SF, SI)),
429+ N2FPU_INSN_DEF_BASE (floatus, 2, 0, floatunssisf2, (SF, UI)),
430+ N2FPU_INSN_DEF_BASE (floatid, 2, 0, floatsidf2, (DF, SI)),
431+ N2FPU_INSN_DEF_BASE (floatud, 2, 0, floatunssidf2, (DF, UI)),
432+ N2FPU_INSN_DEF_BASE (fixsi, 2, 0, fix_truncsfsi2, (SI, SF)),
433+ N2FPU_INSN_DEF_BASE (fixsu, 2, 0, fixuns_truncsfsi2, (UI, SF)),
434+ N2FPU_INSN_DEF_BASE (fixdi, 2, 0, fix_truncdfsi2, (SI, DF)),
435+ N2FPU_INSN_DEF_BASE (fixdu, 2, 0, fixuns_truncdfsi2, (UI, DF)),
436+ N2FPU_INSN_DEF_BASE (fextsd, 2, 0, extendsfdf2, (DF, SF)),
437+ N2FPU_INSN_DEF_BASE (ftruncds, 2, 0, truncdfsf2, (SF, DF)),
438+
439+ /* X, Y access instructions. */
440+ N2FPU_INSN_DEF_BASE (fwrx, 2, N2F_DFREQ, nios2_fwrx, (VOID, DF)),
441+ N2FPU_INSN_DEF_BASE (fwry, 2, N2F_DFREQ, nios2_fwry, (VOID, SF)),
442+ N2FPU_INSN_DEF_BASE (frdxlo, 1, N2F_DFREQ, nios2_frdxlo, (SF)),
443+ N2FPU_INSN_DEF_BASE (frdxhi, 1, N2F_DFREQ, nios2_frdxhi, (SF)),
444+ N2FPU_INSN_DEF_BASE (frdy, 1, N2F_DFREQ, nios2_frdy, (SF))
445+ };
446+
447+/* Some macros for ease of access. */
448+#define N2FPU(code) nios2_fpu_insn[(int) code]
449+#define N2FPU_ENABLED_P(code) (N2FPU_N(code) >= 0)
450+#define N2FPU_N(code) (*N2FPU(code).optvar)
451+#define N2FPU_NAME(code) (N2FPU(code).name)
452+#define N2FPU_ICODE(code) (N2FPU(code).icode)
453+#define N2FPU_FTCODE(code) (N2FPU(code).ftcode)
454+#define N2FPU_FINITE_P(code) (N2FPU(code).flags & N2F_FINITE)
455+#define N2FPU_UNSAFE_P(code) (N2FPU(code).flags & N2F_UNSAFE)
456+#define N2FPU_DOUBLE_P(code) (N2FPU(code).flags & N2F_DF)
457+#define N2FPU_DOUBLE_REQUIRED_P(code) (N2FPU(code).flags & N2F_DFREQ)
458+
459+/* Same as above, but for cases where using only the op part is shorter. */
460+#define N2FPU_OP(op) N2FPU(n2fpu_ ## op)
461+#define N2FPU_OP_NAME(op) N2FPU_NAME(n2fpu_ ## op)
462+#define N2FPU_OP_ENABLED_P(op) N2FPU_ENABLED_P(n2fpu_ ## op)
463+
464+/* Export the FPU insn enabled predicate to nios2.md. */
465+bool
466+nios2_fpu_insn_enabled (enum n2fpu_code code)
467+{
468+ return N2FPU_ENABLED_P (code);
469+}
470+
471+static bool
472+nios2_fpu_compare_enabled (enum rtx_code cond, enum machine_mode mode)
473+{
474+ if (mode == SFmode)
475+ switch (cond)
476+ {
477+ case EQ: return N2FPU_OP_ENABLED_P (fcmpeqs);
478+ case NE: return N2FPU_OP_ENABLED_P (fcmpnes);
479+ case GT: return N2FPU_OP_ENABLED_P (fcmpgts);
480+ case GE: return N2FPU_OP_ENABLED_P (fcmpges);
481+ case LT: return N2FPU_OP_ENABLED_P (fcmplts);
482+ case LE: return N2FPU_OP_ENABLED_P (fcmples);
483+ default: break;
484+ }
485+ else if (mode == DFmode)
486+ switch (cond)
487+ {
488+ case EQ: return N2FPU_OP_ENABLED_P (fcmpeqd);
489+ case NE: return N2FPU_OP_ENABLED_P (fcmpned);
490+ case GT: return N2FPU_OP_ENABLED_P (fcmpgtd);
491+ case GE: return N2FPU_OP_ENABLED_P (fcmpged);
492+ case LT: return N2FPU_OP_ENABLED_P (fcmpltd);
493+ case LE: return N2FPU_OP_ENABLED_P (fcmpled);
494+ default: break;
495+ }
496+ return false;
497+}
498+
499+#define IS_UNSPEC_TLS(x) ((x) >= UNSPEC_TLS && (x) <= UNSPEC_ADD_TLS_LDO)
500+
501+
502+/* Stack Layout and Calling Conventions */
503+
504+#define TOO_BIG_OFFSET(X) ((X) > ((1 << 15) - 1))
505+#define TEMP_REG_NUM 8
506+
507+static void
508+save_reg (int regno, unsigned offset)
509+{
510+ rtx reg = gen_rtx_REG (SImode, regno);
511+ rtx addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
512+ gen_int_mode (offset, Pmode));
513+
514+ rtx pattern = gen_rtx_SET (SImode, gen_frame_mem (Pmode, addr), reg);
515+ rtx insn = emit_insn (pattern);
516+ RTX_FRAME_RELATED_P (insn) = 1;
517+}
518+
519+static void
520+restore_reg (int regno, unsigned offset)
521+{
522+ rtx reg = gen_rtx_REG (SImode, regno);
523+ rtx addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
524+ gen_int_mode (offset, Pmode));
525+
526+ rtx pattern = gen_rtx_SET (SImode, reg, gen_frame_mem (Pmode, addr));
527+ emit_insn (pattern);
528+}
529+
530+void
531+expand_prologue (void)
532+{
533+ int ix;
534+ HOST_WIDE_INT total_frame_size = compute_frame_size ();
535+ int sp_offset; /* offset from base_reg to final stack value. */
536+ int fp_offset; /* offset from base_reg to final fp value. */
537+ int save_offset;
538+ rtx insn;
539+ unsigned HOST_WIDE_INT save_mask;
540+
541+ total_frame_size = compute_frame_size ();
542+ if (flag_stack_usage_info)
543+ current_function_static_stack_size = total_frame_size;
544+
545+ /* Decrement the stack pointer */
546+ if (TOO_BIG_OFFSET (total_frame_size))
547+ {
548+ /* We need an intermediary point, this will point at the spill
549+ block. */
550+ insn = emit_insn
551+ (gen_add3_insn (stack_pointer_rtx,
552+ stack_pointer_rtx,
553+ gen_int_mode (cfun->machine->save_regs_offset
554+ - total_frame_size, Pmode)));
555+ RTX_FRAME_RELATED_P (insn) = 1;
556+
557+ fp_offset = 0;
558+ sp_offset = -cfun->machine->save_regs_offset;
559+ }
560+ else if (total_frame_size)
561+ {
562+ insn = emit_insn (gen_add3_insn (stack_pointer_rtx,
563+ stack_pointer_rtx,
564+ gen_int_mode (-total_frame_size,
565+ Pmode)));
566+ RTX_FRAME_RELATED_P (insn) = 1;
567+ fp_offset = cfun->machine->save_regs_offset;
568+ sp_offset = 0;
569+ }
570+ else
571+ fp_offset = sp_offset = 0;
572+
573+ if (crtl->limit_stack)
574+ emit_insn (gen_stack_overflow_detect_and_trap ());
575+
576+ save_offset = fp_offset + cfun->machine->save_reg_size;
577+ save_mask = cfun->machine->save_mask;
578+
579+ for (ix = 32; ix--;)
580+ if (save_mask & ((unsigned HOST_WIDE_INT)1 << ix))
581+ {
582+ save_offset -= 4;
583+ save_reg (ix, save_offset);
584+ }
585+
586+ if (frame_pointer_needed)
587+ {
588+ insn = emit_insn (gen_add3_insn (hard_frame_pointer_rtx,
589+ stack_pointer_rtx,
590+ gen_int_mode (fp_offset, Pmode)));
591+ RTX_FRAME_RELATED_P (insn) = 1;
592+ }
593+
594+ if (sp_offset)
595+ {
596+ rtx sp_adjust
597+ = gen_rtx_SET (Pmode, stack_pointer_rtx,
598+ gen_rtx_PLUS (Pmode, stack_pointer_rtx,
599+ gen_int_mode (sp_offset, Pmode)));
600+ if (SMALL_INT (sp_offset))
601+ insn = emit_insn (sp_adjust);
602+ else
603+ {
604+ rtx tmp = gen_rtx_REG (Pmode, TEMP_REG_NUM);
605+ emit_insn (gen_rtx_SET (Pmode, tmp, gen_int_mode (sp_offset, Pmode)));
606+ insn = emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
607+ tmp));
608+ /* Attach the sp_adjust as a note indicating what happened. */
609+ REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR,
610+ sp_adjust, REG_NOTES (insn));
611+ }
612+ RTX_FRAME_RELATED_P (insn) = 1;
613+
614+ if (crtl->limit_stack)
615+ emit_insn (gen_stack_overflow_detect_and_trap ());
616+ }
617+
618+ /* Load the PIC register if needed. */
619+ if (crtl->uses_pic_offset_table)
620+ nios2_load_pic_register ();
621+
622+ /* If we are profiling, make sure no instructions are scheduled before
623+ the call to mcount. */
624+ if (crtl->profile)
625+ emit_insn (gen_blockage ());
626+}
627+
628+void
629+expand_epilogue (bool sibcall_p)
630+{
631+ int ix;
632+ HOST_WIDE_INT total_frame_size = compute_frame_size ();
633+ unsigned HOST_WIDE_INT save_mask;
634+ int sp_adjust;
635+ int save_offset;
636+
637+ if (!sibcall_p && nios2_can_use_return_insn ())
638+ {
639+ emit_jump_insn (gen_return ());
640+ return;
641+ }
642+
643+ emit_insn (gen_blockage ());
644+
645+ if (frame_pointer_needed)
646+ {
647+ /* Recover the stack pointer. */
648+ emit_insn (gen_rtx_SET (Pmode, stack_pointer_rtx,
649+ hard_frame_pointer_rtx));
650+ save_offset = 0;
651+ sp_adjust = total_frame_size - cfun->machine->save_regs_offset;
652+ }
653+ else if (TOO_BIG_OFFSET (total_frame_size))
654+ {
655+ rtx tmp = gen_rtx_REG (Pmode, TEMP_REG_NUM);
656+
657+ emit_insn
658+ (gen_rtx_SET (Pmode, tmp,
659+ gen_int_mode (cfun->machine->save_regs_offset,
660+ Pmode)));
661+ emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, tmp));
662+ save_offset = 0;
663+ sp_adjust = total_frame_size - cfun->machine->save_regs_offset;
664+ }
665+ else
666+ {
667+ save_offset = cfun->machine->save_regs_offset;
668+ sp_adjust = total_frame_size;
669+ }
670+
671+ save_mask = cfun->machine->save_mask;
672+ save_offset += cfun->machine->save_reg_size;
673+
674+ for (ix = 32; ix--;)
675+ if (save_mask & ((unsigned HOST_WIDE_INT)1 << ix))
676+ {
677+ save_offset -= 4;
678+ restore_reg (ix, save_offset);
679+ }
680+
681+ if (sp_adjust)
682+ emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
683+ gen_int_mode (sp_adjust, Pmode)));
684+
685+ /* Add in the __builtin_eh_return stack adjustment. */
686+ if (crtl->calls_eh_return)
687+ emit_insn (gen_add3_insn (stack_pointer_rtx,
688+ stack_pointer_rtx,
689+ EH_RETURN_STACKADJ_RTX));
690+
691+ if (!sibcall_p)
692+ emit_jump_insn (gen_return_from_epilogue (gen_rtx_REG (Pmode, RA_REGNO)));
693+}
694+
695+/* Implement RETURN_ADDR_RTX. Note, we do not support moving
696+ back to a previous frame. */
697+rtx
698+nios2_get_return_address (int count)
699+{
700+ if (count != 0)
701+ return const0_rtx;
702+
703+ return get_hard_reg_initial_val (Pmode, RA_REGNO);
704+}
705+
706+/* Emit code to change the current function's return address to
707+ ADDRESS. SCRATCH is available as a scratch register, if needed.
708+ ADDRESS and SCRATCH are both word-mode GPRs. */
709+void
710+nios2_set_return_address (rtx address, rtx scratch)
711+{
712+ compute_frame_size ();
713+ if ((cfun->machine->save_mask >> RA_REGNO) & 1)
714+ {
715+ unsigned offset = cfun->machine->save_reg_size - 4;
716+ rtx base;
717+
718+ if (frame_pointer_needed)
719+ base = hard_frame_pointer_rtx;
720+ else
721+ {
722+ base = stack_pointer_rtx;
723+ offset += cfun->machine->save_regs_offset;
724+
725+ if (TOO_BIG_OFFSET (offset))
726+ {
727+ emit_insn (gen_rtx_SET (Pmode, scratch,
728+ gen_int_mode (offset, Pmode)));
729+ emit_insn (gen_add3_insn (scratch, scratch, base));
730+ base = scratch;
731+ offset = 0;
732+ }
733+ }
734+ if (offset)
735+ base = gen_rtx_PLUS (Pmode, base, gen_int_mode (offset, Pmode));
736+ emit_insn (gen_rtx_SET (Pmode, gen_rtx_MEM (Pmode, base), address));
737+ }
738+ else
739+ emit_insn (gen_rtx_SET (Pmode, gen_rtx_REG (Pmode, RA_REGNO), address));
740+}
741+
742+
743+/* Profiling. */
744+
745+void
746+nios2_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
747+{
748+ fprintf (file, "\tmov\tr8, ra\n");
749+ if (flag_pic)
750+ {
751+ fprintf (file, "\tnextpc\tr2\n");
752+ fprintf (file, "\t1: movhi\tr3, %%hiadj(_GLOBAL_OFFSET_TABLE_ - 1b)\n");
753+ fprintf (file, "\taddi\tr3, r3, %%lo(_GLOBAL_OFFSET_TABLE_ - 1b)\n");
754+ fprintf (file, "\tadd\tr2, r2, r3\n");
755+ fprintf (file, "\tldw\tr2, %%call(_mcount)(r2)\n");
756+ fprintf (file, "\tcallr\tr2\n");
757+ }
758+ else
759+ fprintf (file, "\tcall\t_mcount\n");
760+ fprintf (file, "\tmov\tra, r8\n");
761+}
762+
763+/* Stack Layout. */
764+static void
765+dump_frame_size (FILE *file)
766+{
767+ fprintf (file, "\t%s Current Frame Info\n", ASM_COMMENT_START);
768+
769+ fprintf (file, "\t%s total_size = %ld\n", ASM_COMMENT_START,
770+ cfun->machine->total_size);
771+ fprintf (file, "\t%s var_size = %ld\n", ASM_COMMENT_START,
772+ cfun->machine->var_size);
773+ fprintf (file, "\t%s args_size = %ld\n", ASM_COMMENT_START,
774+ cfun->machine->args_size);
775+ fprintf (file, "\t%s save_reg_size = %d\n", ASM_COMMENT_START,
776+ cfun->machine->save_reg_size);
777+ fprintf (file, "\t%s initialized = %d\n", ASM_COMMENT_START,
778+ cfun->machine->initialized);
779+ fprintf (file, "\t%s save_regs_offset = %ld\n", ASM_COMMENT_START,
780+ cfun->machine->save_regs_offset);
781+ fprintf (file, "\t%s current_function_is_leaf = %d\n", ASM_COMMENT_START,
782+ current_function_is_leaf);
783+ fprintf (file, "\t%s frame_pointer_needed = %d\n", ASM_COMMENT_START,
784+ frame_pointer_needed);
785+ fprintf (file, "\t%s pretend_args_size = %d\n", ASM_COMMENT_START,
786+ crtl->args.pretend_args_size);
787+
788+}
789+
790+/* Return true if REGNO should be saved in a prologue. */
791+static bool
792+save_reg_p (unsigned regno)
793+{
794+ gcc_assert (GP_REGNO_P (regno));
795+
796+ if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
797+ return true;
798+
799+ if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
800+ return true;
801+
802+ if (regno == PIC_OFFSET_TABLE_REGNUM && crtl->uses_pic_offset_table)
803+ return true;
804+
805+ if (regno == RA_REGNO && df_regs_ever_live_p (RA_REGNO))
806+ return true;
807+
808+ return false;
809+}
810+
811+/* Return the bytes needed to compute the frame pointer from the current
812+ stack pointer. */
813+static HOST_WIDE_INT
814+compute_frame_size (void)
815+{
816+ unsigned int regno;
817+ HOST_WIDE_INT var_size; /* # of var. bytes allocated. */
818+ HOST_WIDE_INT total_size; /* # bytes that the entire frame takes up. */
819+ HOST_WIDE_INT save_reg_size; /* # bytes needed to store callee save regs. */
820+ HOST_WIDE_INT out_args_size; /* # bytes needed for outgoing args. */
821+ unsigned HOST_WIDE_INT save_mask = 0;
822+
823+ if (cfun->machine->initialized)
824+ return cfun->machine->total_size;
825+
826+ save_reg_size = 0;
827+ var_size = STACK_ALIGN (get_frame_size ());
828+ out_args_size = STACK_ALIGN (crtl->outgoing_args_size);
829+
830+ total_size = var_size + out_args_size;
831+
832+ /* Calculate space needed for gp registers. */
833+ for (regno = 0; GP_REGNO_P (regno); regno++)
834+ if (save_reg_p (regno))
835+ {
836+ save_mask |= (unsigned HOST_WIDE_INT)1 << regno;
837+ save_reg_size += 4;
838+ }
839+
840+ /* If we call eh_return, we need to save the EH data registers. */
841+ if (crtl->calls_eh_return)
842+ {
843+ unsigned i;
844+ unsigned r;
845+
846+ for (i = 0; (r = EH_RETURN_DATA_REGNO (i)) != INVALID_REGNUM; i++)
847+ if (!(save_mask & (1 << r)))
848+ {
849+ save_mask |= 1 << r;
850+ save_reg_size += 4;
851+ }
852+ }
853+
854+ save_reg_size = STACK_ALIGN (save_reg_size);
855+ total_size += save_reg_size;
856+
857+ total_size += STACK_ALIGN (crtl->args.pretend_args_size);
858+
859+ /* Save other computed information. */
860+ cfun->machine->save_mask = save_mask;
861+ cfun->machine->total_size = total_size;
862+ cfun->machine->var_size = var_size;
863+ cfun->machine->args_size = out_args_size;
864+ cfun->machine->save_reg_size = save_reg_size;
865+ cfun->machine->initialized = reload_completed;
866+ cfun->machine->save_regs_offset = out_args_size + var_size;
867+
868+ return total_size;
869+}
870+
871+/* Implement TARGET_CAN_ELIMINATE. */
872+static bool
873+nios2_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
874+{
875+ if (to == STACK_POINTER_REGNUM)
876+ return !frame_pointer_needed;
877+ return true;
878+}
879+
880+int
881+nios2_initial_elimination_offset (int from, int to)
882+{
883+ int offset;
884+
885+ compute_frame_size ();
886+
887+ /* Set OFFSET to the offset from the stack pointer. */
888+ switch (from)
889+ {
890+ case FRAME_POINTER_REGNUM:
891+ offset = cfun->machine->args_size;
892+ break;
893+
894+ case ARG_POINTER_REGNUM:
895+ offset = cfun->machine->total_size;
896+ offset -= crtl->args.pretend_args_size;
897+ break;
898+
899+ default:
900+ gcc_unreachable ();
901+ }
902+
903+ /* If we are asked for the frame pointer offset, then adjust OFFSET
904+ by the offset from the frame pointer to the stack pointer. */
905+ if (to == HARD_FRAME_POINTER_REGNUM)
906+ offset -= cfun->machine->save_regs_offset;
907+
908+ return offset;
909+}
910+
911+/* Return nonzero if this function is known to have a null epilogue.
912+ This allows the optimizer to omit jumps to jumps if no stack
913+ was created. */
914+int
915+nios2_can_use_return_insn (void)
916+{
917+ if (!reload_completed)
918+ return 0;
919+
920+ if (df_regs_ever_live_p (RA_REGNO) || crtl->profile)
921+ return 0;
922+
923+ if (cfun->machine->initialized)
924+ return cfun->machine->total_size == 0;
925+
926+ return compute_frame_size () == 0;
927+}
928+
929+
930+
931+/* Check and signal some warnings/errors on FPU insn options. */
932+static void
933+nios2_custom_check_insns (void)
934+{
935+ unsigned int i, j;
936+ bool errors = false;
937+
938+ for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
939+ if (N2FPU_ENABLED_P (i) && N2FPU_DOUBLE_P (i))
940+ {
941+ for (j = 0; j < ARRAY_SIZE (nios2_fpu_insn); j++)
942+ if (N2FPU_DOUBLE_REQUIRED_P (j) && ! N2FPU_ENABLED_P (j))
943+ {
944+ error ("switch `-mcustom-%s' is required for double precision "
945+ "floating point", N2FPU_NAME (j));
946+ errors = true;
947+ }
948+ break;
949+ }
950+
951+ /* Warn if the user has certain exotic operations that won't get used
952+ without -funsafe-math-optimizations. See expand_builtin () in
953+ builtins.c. */
954+ if (!flag_unsafe_math_optimizations)
955+ for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
956+ if (N2FPU_ENABLED_P (i) && N2FPU_UNSAFE_P (i))
957+ warning (0, "switch `-mcustom-%s' has no effect unless "
958+ "-funsafe-math-optimizations is specified", N2FPU_NAME (i));
959+
960+ /* Warn if the user is trying to use -mcustom-fmins et. al, that won't
961+ get used without -ffinite-math-only. See fold_builtin_fmin_fmax ()
962+ in builtins.c. */
963+ if (!flag_finite_math_only)
964+ for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
965+ if (N2FPU_ENABLED_P (i) && N2FPU_FINITE_P (i))
966+ warning (0, "switch `-mcustom-%s' has no effect unless "
967+ "-ffinite-math-only is specified", N2FPU_NAME (i));
968+
969+ if (errors || custom_code_conflict)
970+ fatal_error ("conflicting use of -mcustom switches, target attributes, "
971+ "and/or __builtin_custom_ functions");
972+}
973+
974+static void
975+nios2_set_fpu_custom_code (enum n2fpu_code code, int N, bool override_p)
976+{
977+ if (override_p || N2FPU_N (code) == -1)
978+ N2FPU_N (code) = N;
979+ nios2_register_custom_code (N, CCS_FPU, (int) code);
980+}
981+
982+static void
983+nios2_handle_custom_fpu_cfg (const char *cfg, bool override_p)
984+{
985+ if (!strncasecmp (cfg, "60-1", 4))
986+ {
987+ nios2_set_fpu_custom_code (n2fpu_fmuls, 252, override_p);
988+ nios2_set_fpu_custom_code (n2fpu_fadds, 253, override_p);
989+ nios2_set_fpu_custom_code (n2fpu_fsubs, 254, override_p);
990+ flag_single_precision_constant = 1;
991+ }
992+ else if (!strncasecmp (cfg, "60-2", 4))
993+ {
994+ nios2_set_fpu_custom_code (n2fpu_fmuls, 252, override_p);
995+ nios2_set_fpu_custom_code (n2fpu_fadds, 253, override_p);
996+ nios2_set_fpu_custom_code (n2fpu_fsubs, 254, override_p);
997+ nios2_set_fpu_custom_code (n2fpu_fdivs, 255, override_p);
998+ flag_single_precision_constant = 1;
999+ }
1000+ else if (!strncasecmp (cfg, "72-3", 4))
1001+ {
1002+ nios2_set_fpu_custom_code (n2fpu_floatus, 243, override_p);
1003+ nios2_set_fpu_custom_code (n2fpu_fixsi, 244, override_p);
1004+ nios2_set_fpu_custom_code (n2fpu_floatis, 245, override_p);
1005+ nios2_set_fpu_custom_code (n2fpu_fcmpgts, 246, override_p);
1006+ nios2_set_fpu_custom_code (n2fpu_fcmples, 249, override_p);
1007+ nios2_set_fpu_custom_code (n2fpu_fcmpeqs, 250, override_p);
1008+ nios2_set_fpu_custom_code (n2fpu_fcmpnes, 251, override_p);
1009+ nios2_set_fpu_custom_code (n2fpu_fmuls, 252, override_p);
1010+ nios2_set_fpu_custom_code (n2fpu_fadds, 253, override_p);
1011+ nios2_set_fpu_custom_code (n2fpu_fsubs, 254, override_p);
1012+ nios2_set_fpu_custom_code (n2fpu_fdivs, 255, override_p);
1013+ flag_single_precision_constant = 1;
1014+ }
1015+ else
1016+ warning (0, "ignoring unrecognized switch `-mcustom-fpu-cfg' value `%s'",
1017+ cfg);
1018+
1019+ /* Guard against errors in the standard configurations. */
1020+ nios2_custom_check_insns ();
1021+}
1022+
1023+/* Check individual FPU insn options, and register custom code. */
1024+static void
1025+nios2_handle_custom_fpu_insn_option (int fpu_insn_index)
1026+{
1027+ int param = N2FPU_N (fpu_insn_index);
1028+
1029+ if (0 <= param && param <= 255)
1030+ nios2_register_custom_code (param, CCS_FPU, fpu_insn_index);
1031+
1032+ /* Valid values are 0-255, but also allow -1 so that the
1033+ -mno-custom-<opt> switches work. */
1034+ else if (param != -1)
1035+ error ("switch `-mcustom-%s' value %d must be between 0 and 255",
1036+ N2FPU_NAME (fpu_insn_index), param);
1037+}
1038+
1039+/* Implement TARGET_OPTION_OVERRIDE. */
1040+static void
1041+nios2_option_override (void)
1042+{
1043+ unsigned int i;
1044+
1045+#ifdef SUBTARGET_OVERRIDE_OPTIONS
1046+ SUBTARGET_OVERRIDE_OPTIONS;
1047+#endif
1048+
1049+ /* Check for unsupported options. */
1050+ if (flag_pic && !TARGET_LINUX_ABI)
1051+ error ("position-independent code requires the Linux ABI");
1052+
1053+ /* Function to allocate machine-dependent function status. */
1054+ init_machine_status = &nios2_init_machine_status;
1055+
1056+ nios2_section_threshold
1057+ = (global_options_set.x_g_switch_value
1058+ ? g_switch_value : NIOS2_DEFAULT_GVALUE);
1059+
1060+ /* If we don't have mul, we don't have mulx either! */
1061+ if (!TARGET_HAS_MUL && TARGET_HAS_MULX)
1062+ target_flags &= ~MASK_HAS_MULX;
1063+
1064+ /* Set up default handling for floating point custom instructions.
1065+
1066+ Putting things in this order means that the -mcustom-fpu-cfg=
1067+ switch will always be overridden by individual -mcustom-fadds=
1068+ switches, regardless of the order in which they were specified
1069+ on the command line.
1070+
1071+ This behavior of prioritization of individual -mcustom-<insn>=
1072+ options before the -mcustom-fpu-cfg= switch is maintained for
1073+ compatibility. */
1074+ if (nios2_custom_fpu_cfg_string && *nios2_custom_fpu_cfg_string)
1075+ nios2_handle_custom_fpu_cfg (nios2_custom_fpu_cfg_string, false);
1076+
1077+ /* Handle options for individual FPU insns. */
1078+ for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
1079+ nios2_handle_custom_fpu_insn_option (i);
1080+
1081+ nios2_custom_check_insns ();
1082+
1083+ /* Save the initial options in case the user does function specific options */
1084+ target_option_default_node = target_option_current_node
1085+ = build_target_option_node ();
1086+}
1087+
1088+/* Allocate a chunk of memory for per-function machine-dependent data. */
1089+static struct machine_function *
1090+nios2_init_machine_status (void)
1091+{
1092+ return ggc_alloc_cleared_machine_function ();
1093+}
1094+
1095+
1096+/* Return true if CST is a constant within range of movi/movui/movhi. */
1097+static bool
1098+nios2_simple_const_p (const_rtx cst)
1099+{
1100+ HOST_WIDE_INT val = INTVAL (cst);
1101+ return (SMALL_INT (val) || SMALL_INT_UNSIGNED (val) || UPPER16_INT (val));
1102+}
1103+
1104+/* Compute a (partial) cost for rtx X. Return true if the complete
1105+ cost has been computed, and false if subexpressions should be
1106+ scanned. In either case, *TOTAL contains the cost result. */
1107+static bool
1108+nios2_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
1109+ int opno ATTRIBUTE_UNUSED,
1110+ int *total, bool speed ATTRIBUTE_UNUSED)
1111+{
1112+ switch (code)
1113+ {
1114+ case CONST_INT:
1115+ if (INTVAL (x) == 0)
1116+ {
1117+ *total = COSTS_N_INSNS (0);
1118+ return true;
1119+ }
1120+ else if (nios2_simple_const_p (x))
1121+ {
1122+ *total = COSTS_N_INSNS (2);
1123+ return true;
1124+ }
1125+ else
1126+ {
1127+ *total = COSTS_N_INSNS (4);
1128+ return true;
1129+ }
1130+
1131+ case LABEL_REF:
1132+ case SYMBOL_REF:
1133+ /* ??? gp relative stuff will fit in here. */
1134+ /* fall through */
1135+ case CONST:
1136+ case CONST_DOUBLE:
1137+ {
1138+ *total = COSTS_N_INSNS (4);
1139+ return true;
1140+ }
1141+
1142+ case AND:
1143+ {
1144+ /* Recognize 'nor' insn pattern. */
1145+ if (GET_CODE (XEXP (x, 0)) == NOT
1146+ && GET_CODE (XEXP (x, 1)) == NOT)
1147+ {
1148+ *total = COSTS_N_INSNS (1);
1149+ return true;
1150+ }
1151+ return false;
1152+ }
1153+
1154+ case MULT:
1155+ {
1156+ *total = COSTS_N_INSNS (1);
1157+ return false;
1158+ }
1159+ case SIGN_EXTEND:
1160+ {
1161+ *total = COSTS_N_INSNS (3);
1162+ return false;
1163+ }
1164+ case ZERO_EXTEND:
1165+ {
1166+ *total = COSTS_N_INSNS (1);
1167+ return false;
1168+ }
1169+
1170+ default:
1171+ return false;
1172+ }
1173+}
1174+
1175+/* Implement TARGET_PREFERRED_RELOAD_CLASS. */
1176+
1177+static reg_class_t
1178+nios2_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, reg_class_t regclass)
1179+{
1180+ return (regclass == NO_REGS ? GENERAL_REGS : regclass);
1181+}
1182+
1183+/* Instruction support:
1184+ These functions are used within the machine description to
1185+ handle common or complicated output and expansions from
1186+ instructions. */
1187+
1188+/* Return TRUE if X references a SYMBOL_REF. */
1189+static int
1190+symbol_mentioned_p (rtx x)
1191+{
1192+ const char * fmt;
1193+ int i;
1194+
1195+ if (GET_CODE (x) == SYMBOL_REF)
1196+ return 1;
1197+
1198+ /* UNSPEC_TLS entries for a symbol include the SYMBOL_REF, but they
1199+ are constant offsets, not symbols. */
1200+ if (GET_CODE (x) == UNSPEC && IS_UNSPEC_TLS (XINT (x, 1)))
1201+ return 0;
1202+
1203+ fmt = GET_RTX_FORMAT (GET_CODE (x));
1204+
1205+ for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
1206+ if (fmt[i] == 'E')
1207+ {
1208+ int j;
1209+
1210+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
1211+ if (symbol_mentioned_p (XVECEXP (x, i, j)))
1212+ return 1;
1213+ }
1214+ else if (fmt[i] == 'e' && symbol_mentioned_p (XEXP (x, i)))
1215+ return 1;
1216+
1217+ return 0;
1218+}
1219+
1220+/* Return TRUE if X references a LABEL_REF. */
1221+static int
1222+label_mentioned_p (rtx x)
1223+{
1224+ const char * fmt;
1225+ int i;
1226+
1227+ if (GET_CODE (x) == LABEL_REF)
1228+ return 1;
1229+
1230+ /* UNSPEC_TLS entries for a symbol include a LABEL_REF for the referencing
1231+ instruction, but they are constant offsets, not symbols. */
1232+ if (GET_CODE (x) == UNSPEC && IS_UNSPEC_TLS (XINT (x, 1)))
1233+ return 0;
1234+
1235+ fmt = GET_RTX_FORMAT (GET_CODE (x));
1236+ for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
1237+ if (fmt[i] == 'E')
1238+ {
1239+ int j;
1240+
1241+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
1242+ if (label_mentioned_p (XVECEXP (x, i, j)))
1243+ return 1;
1244+ }
1245+ else if (fmt[i] == 'e' && label_mentioned_p (XEXP (x, i)))
1246+ return 1;
1247+
1248+ return 0;
1249+}
1250+
1251+static int
1252+tls_mentioned_p (rtx x)
1253+{
1254+ switch (GET_CODE (x))
1255+ {
1256+ case CONST:
1257+ return tls_mentioned_p (XEXP (x, 0));
1258+
1259+ case UNSPEC:
1260+ if (IS_UNSPEC_TLS (XINT (x, 1)))
1261+ return 1;
1262+
1263+ default:
1264+ return 0;
1265+ }
1266+}
1267+
1268+/* Helper for nios2_tls_referenced_p. */
1269+static int
1270+nios2_tls_operand_p_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
1271+{
1272+ if (GET_CODE (*x) == SYMBOL_REF)
1273+ return SYMBOL_REF_TLS_MODEL (*x) != 0;
1274+
1275+ /* Don't recurse into UNSPEC_TLS looking for TLS symbols; these are
1276+ TLS offsets, not real symbol references. */
1277+ if (GET_CODE (*x) == UNSPEC
1278+ && IS_UNSPEC_TLS (XINT (*x, 1)))
1279+ return -1;
1280+
1281+ return 0;
1282+}
1283+
1284+/* Return TRUE if X contains any TLS symbol references. */
1285+static bool
1286+nios2_tls_referenced_p (rtx x)
1287+{
1288+ if (! TARGET_HAVE_TLS)
1289+ return false;
1290+
1291+ return for_each_rtx (&x, nios2_tls_operand_p_1, NULL);
1292+}
1293+
1294+static bool
1295+nios2_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
1296+{
1297+ return nios2_tls_referenced_p (x);
1298+}
1299+
1300+/* Emit a call to __tls_get_addr. TI is the argument to this function. RET is
1301+ an RTX for the return value location. The entire insn sequence is
1302+ returned. */
1303+static GTY(()) rtx nios2_tls_symbol;
1304+
1305+static rtx
1306+nios2_call_tls_get_addr (rtx ti)
1307+{
1308+ rtx arg = gen_rtx_REG (Pmode, FIRST_ARG_REGNO);
1309+ rtx ret = gen_rtx_REG (Pmode, FIRST_RETVAL_REGNO);
1310+ rtx fn, insn;
1311+
1312+ if (!nios2_tls_symbol)
1313+ nios2_tls_symbol = init_one_libfunc ("__tls_get_addr");
1314+
1315+ emit_insn (gen_rtx_SET (Pmode, arg, ti));
1316+ fn = gen_rtx_MEM (QImode, nios2_tls_symbol);
1317+ insn = emit_call_insn (gen_call_value (ret, fn, const0_rtx));
1318+ RTL_CONST_CALL_P (insn) = 1;
1319+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), ret);
1320+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), arg);
1321+
1322+ return ret;
1323+}
1324+
1325+/* Generate the code to access LOC, a thread local SYMBOL_REF. The
1326+ return value will be a valid address and move_operand (either a REG
1327+ or a LO_SUM). */
1328+static rtx
1329+nios2_legitimize_tls_address (rtx loc)
1330+{
1331+ rtx dest = gen_reg_rtx (Pmode);
1332+ rtx ret, tmp1;
1333+ enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
1334+
1335+ switch (model)
1336+ {
1337+ case TLS_MODEL_GLOBAL_DYNAMIC:
1338+ tmp1 = gen_reg_rtx (Pmode);
1339+ emit_insn (gen_add_tls_gd (tmp1, pic_offset_table_rtx, loc));
1340+ crtl->uses_pic_offset_table = 1;
1341+ ret = nios2_call_tls_get_addr (tmp1);
1342+ emit_insn (gen_rtx_SET (Pmode, dest, ret));
1343+ break;
1344+
1345+ case TLS_MODEL_LOCAL_DYNAMIC:
1346+ tmp1 = gen_reg_rtx (Pmode);
1347+ emit_insn (gen_add_tls_ldm (tmp1, pic_offset_table_rtx, loc));
1348+ crtl->uses_pic_offset_table = 1;
1349+ ret = nios2_call_tls_get_addr (tmp1);
1350+
1351+ emit_insn (gen_add_tls_ldo (dest, ret, loc));
1352+
1353+ break;
1354+
1355+ case TLS_MODEL_INITIAL_EXEC:
1356+ tmp1 = gen_reg_rtx (Pmode);
1357+ emit_insn (gen_load_tls_ie (tmp1, pic_offset_table_rtx, loc));
1358+ crtl->uses_pic_offset_table = 1;
1359+ emit_insn (gen_add3_insn (dest,
1360+ gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM),
1361+ tmp1));
1362+ break;
1363+
1364+ case TLS_MODEL_LOCAL_EXEC:
1365+ emit_insn (gen_add_tls_le (dest,
1366+ gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM),
1367+ loc));
1368+ break;
1369+
1370+ default:
1371+ gcc_unreachable ();
1372+ }
1373+
1374+ return dest;
1375+}
1376+
1377+int
1378+nios2_emit_move_sequence (rtx *operands, enum machine_mode mode)
1379+{
1380+ rtx to = operands[0];
1381+ rtx from = operands[1];
1382+
1383+ if (!register_operand (to, mode) && !reg_or_0_operand (from, mode))
1384+ {
1385+ gcc_assert (can_create_pseudo_p ());
1386+ from = copy_to_mode_reg (mode, from);
1387+ }
1388+
1389+ /* Recognize the case where from is a reference to thread-local
1390+ data and load its address to a register. */
1391+ if (nios2_tls_referenced_p (from))
1392+ {
1393+ rtx tmp = from;
1394+ rtx addend = NULL;
1395+
1396+ if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
1397+ {
1398+ addend = XEXP (XEXP (tmp, 0), 1);
1399+ tmp = XEXP (XEXP (tmp, 0), 0);
1400+ }
1401+
1402+ gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
1403+ gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
1404+
1405+ tmp = nios2_legitimize_tls_address (tmp);
1406+ if (addend)
1407+ {
1408+ tmp = gen_rtx_PLUS (SImode, tmp, addend);
1409+ tmp = force_operand (tmp, to);
1410+ }
1411+ from = tmp;
1412+ }
1413+ else if (flag_pic && (CONSTANT_P (from) || symbol_mentioned_p (from) ||
1414+ label_mentioned_p (from)))
1415+ from = nios2_legitimize_pic_address (from, SImode,
1416+ (can_create_pseudo_p () ? 0 : to));
1417+
1418+ operands[0] = to;
1419+ operands[1] = from;
1420+ return 0;
1421+}
1422+
1423+/* Divide Support */
1424+
1425+/*
1426+ If -O3 is used, we want to output a table lookup for
1427+ divides between small numbers (both num and den >= 0
1428+ and < 0x10). The overhead of this method in the worse
1429+ case is 40 bytes in the text section (10 insns) and
1430+ 256 bytes in the data section. Additional divides do
1431+ not incur additional penalties in the data section.
1432+
1433+ Code speed is improved for small divides by about 5x
1434+ when using this method in the worse case (~9 cycles
1435+ vs ~45). And in the worse case divides not within the
1436+ table are penalized by about 10% (~5 cycles vs ~45).
1437+ However in the typical case the penalty is not as bad
1438+ because doing the long divide in only 45 cycles is
1439+ quite optimistic.
1440+
1441+ ??? It would be nice to have some benchmarks other
1442+ than Dhrystone to back this up.
1443+
1444+ This bit of expansion is to create this instruction
1445+ sequence as rtl.
1446+ or $8, $4, $5
1447+ slli $9, $4, 4
1448+ cmpgeui $3, $8, 16
1449+ beq $3, $0, .L3
1450+ or $10, $9, $5
1451+ add $12, $11, divide_table
1452+ ldbu $2, 0($12)
1453+ br .L1
1454+.L3:
1455+ call slow_div
1456+.L1:
1457+# continue here with result in $2
1458+
1459+ ??? Ideally I would like the emit libcall block to contain
1460+ all of this code, but I don't know how to do that. What it
1461+ means is that if the divide can be eliminated, it may not
1462+ completely disappear.
1463+
1464+ ??? The __divsi3_table label should ideally be moved out
1465+ of this block and into a global. If it is placed into the
1466+ sdata section we can save even more cycles by doing things
1467+ gp relative.
1468+*/
1469+int
1470+nios2_emit_expensive_div (rtx *operands, enum machine_mode mode)
1471+{
1472+ rtx or_result, shift_left_result;
1473+ rtx lookup_value;
1474+ rtx lab1, lab3;
1475+ rtx insns;
1476+ rtx libfunc;
1477+ rtx final_result;
1478+ rtx tmp;
1479+ rtx table;
1480+
1481+ /* It may look a little generic, but only SImode
1482+ is supported for now. */
1483+ gcc_assert (mode == SImode);
1484+ libfunc = optab_libfunc (sdiv_optab, SImode);
1485+
1486+ lab1 = gen_label_rtx ();
1487+ lab3 = gen_label_rtx ();
1488+
1489+ or_result = expand_simple_binop (SImode, IOR,
1490+ operands[1], operands[2],
1491+ 0, 0, OPTAB_LIB_WIDEN);
1492+
1493+ emit_cmp_and_jump_insns (or_result, GEN_INT (15), GTU, 0,
1494+ GET_MODE (or_result), 0, lab3);
1495+ JUMP_LABEL (get_last_insn ()) = lab3;
1496+
1497+ shift_left_result = expand_simple_binop (SImode, ASHIFT,
1498+ operands[1], GEN_INT (4),
1499+ 0, 0, OPTAB_LIB_WIDEN);
1500+
1501+ lookup_value = expand_simple_binop (SImode, IOR,
1502+ shift_left_result, operands[2],
1503+ 0, 0, OPTAB_LIB_WIDEN);
1504+ table = gen_rtx_PLUS (SImode, lookup_value,
1505+ gen_rtx_SYMBOL_REF (SImode, "__divsi3_table"));
1506+ convert_move (operands[0], gen_rtx_MEM (QImode, table), 1);
1507+
1508+ tmp = emit_jump_insn (gen_jump (lab1));
1509+ JUMP_LABEL (tmp) = lab1;
1510+ emit_barrier ();
1511+
1512+ emit_label (lab3);
1513+ LABEL_NUSES (lab3) = 1;
1514+
1515+ start_sequence ();
1516+ final_result = emit_library_call_value (libfunc, NULL_RTX,
1517+ LCT_CONST, SImode, 2,
1518+ operands[1], SImode,
1519+ operands[2], SImode);
1520+
1521+
1522+ insns = get_insns ();
1523+ end_sequence ();
1524+ emit_libcall_block (insns, operands[0], final_result,
1525+ gen_rtx_DIV (SImode, operands[1], operands[2]));
1526+
1527+ emit_label (lab1);
1528+ LABEL_NUSES (lab1) = 1;
1529+ return 1;
1530+}
1531+
1532+/* The function with address *ADDR is being called. If the address
1533+ needs to be loaded from the GOT, emit the instruction to do so and
1534+ update *ADDR to point to the rtx for the loaded value. */
1535+void
1536+nios2_adjust_call_address (rtx *addr)
1537+{
1538+ if (flag_pic
1539+ && (GET_CODE (*addr) == SYMBOL_REF || GET_CODE (*addr) == LABEL_REF))
1540+ {
1541+ rtx addr_orig;
1542+ crtl->uses_pic_offset_table = 1;
1543+ addr_orig = *addr;
1544+ *addr = gen_reg_rtx (GET_MODE (addr_orig));
1545+ emit_insn (gen_pic_load_call_addr (*addr,
1546+ pic_offset_table_rtx, addr_orig));
1547+ }
1548+}
1549+
1550+
1551+
1552+/* Branches/Compares. */
1553+
1554+/* Return in *ALT_CODE and *ALT_OP, an alternate equivalent constant
1555+ comparision, e.g. >= 1 into > 0. */
1556+static void
1557+nios2_alternate_compare_const (enum rtx_code code, rtx op,
1558+ enum rtx_code *alt_code, rtx *alt_op,
1559+ enum machine_mode mode)
1560+{
1561+ HOST_WIDE_INT opval = INTVAL (op);
1562+ enum rtx_code scode = signed_condition (code);
1563+ *alt_code = ((code == EQ || code == NE) ? code
1564+ /* The required conversion between [>,>=] and [<,<=] is captured
1565+ by a reverse + swap of condition codes. */
1566+ : reverse_condition (swap_condition (code)));
1567+ *alt_op = ((scode == LT || scode == GE) ? gen_int_mode (opval - 1, mode)
1568+ : (scode == LE || scode == GT) ? gen_int_mode (opval + 1, mode)
1569+ : gen_int_mode (opval, mode));
1570+}
1571+
1572+/* Return true if the constant comparison is supported by nios2. */
1573+static bool
1574+nios2_valid_compare_const_p (enum rtx_code code, rtx op)
1575+{
1576+ switch (code)
1577+ {
1578+ case EQ: case NE: case GE: case LT:
1579+ return SMALL_INT (INTVAL (op));
1580+ case GEU: case LTU:
1581+ return SMALL_INT_UNSIGNED (INTVAL (op));
1582+ default:
1583+ return false;
1584+ }
1585+}
1586+
1587+/* Return true if compares in MODE is supported, mainly for floating-point
1588+ modes. */
1589+bool
1590+nios2_supported_compare_p (enum machine_mode mode)
1591+{
1592+ switch (mode)
1593+ {
1594+ case SFmode:
1595+ return (N2FPU_OP_ENABLED_P (fcmpeqs) && N2FPU_OP_ENABLED_P (fcmpnes)
1596+ && (N2FPU_OP_ENABLED_P (fcmplts) || N2FPU_OP_ENABLED_P (fcmpgts))
1597+ && (N2FPU_OP_ENABLED_P (fcmpges) || N2FPU_OP_ENABLED_P (fcmples)));
1598+
1599+ case DFmode:
1600+ return (N2FPU_OP_ENABLED_P (fcmpeqd) && N2FPU_OP_ENABLED_P (fcmpned)
1601+ && (N2FPU_OP_ENABLED_P (fcmpltd) || N2FPU_OP_ENABLED_P (fcmpgtd))
1602+ && (N2FPU_OP_ENABLED_P (fcmpged) || N2FPU_OP_ENABLED_P (fcmpled)));
1603+ default:
1604+ return true;
1605+ }
1606+}
1607+
1608+/* Checks and modifies the comparison in *CMP, *OP1, and *OP2 into valid
1609+ nios2 supported form. Returns true if success. */
1610+bool
1611+nios2_validate_compare (enum machine_mode mode, rtx *cmp, rtx *op1, rtx *op2)
1612+{
1613+ enum rtx_code code = GET_CODE (*cmp);
1614+ enum rtx_code alt_code;
1615+ rtx alt_op2;
1616+
1617+ if (GET_MODE_CLASS (mode) == MODE_FLOAT)
1618+ {
1619+ if (nios2_fpu_compare_enabled (code, mode))
1620+ {
1621+ *op1 = force_reg (mode, *op1);
1622+ *op2 = force_reg (mode, *op2);
1623+ goto rebuild_cmp;
1624+ }
1625+ else
1626+ {
1627+ enum rtx_code rev_code = swap_condition (code);
1628+ if (nios2_fpu_compare_enabled (rev_code, mode))
1629+ {
1630+ rtx tmp = *op1;
1631+ *op1 = force_reg (mode, *op2);
1632+ *op2 = force_reg (mode, tmp);
1633+ code = rev_code;
1634+ goto rebuild_cmp;
1635+ }
1636+ else
1637+ return false;
1638+ }
1639+ }
1640+
1641+ if (!reg_or_0_operand (*op2, mode))
1642+ {
1643+ /* Create alternate constant compare. */
1644+ nios2_alternate_compare_const (code, *op2, &alt_code, &alt_op2, mode);
1645+
1646+ /* If alterate op2 is zero(0), we can use it directly, possibly
1647+ swapping the compare code. */
1648+ if (alt_op2 == const0_rtx)
1649+ {
1650+ code = alt_code;
1651+ *op2 = alt_op2;
1652+ goto check_rebuild_cmp;
1653+ }
1654+
1655+ /* Check if either constant compare can be used. */
1656+ if (nios2_valid_compare_const_p (code, *op2))
1657+ return true;
1658+ else if (nios2_valid_compare_const_p (alt_code, alt_op2))
1659+ {
1660+ code = alt_code;
1661+ *op2 = alt_op2;
1662+ goto rebuild_cmp;
1663+ }
1664+
1665+ /* We have to force op2 into a register now. Try to pick one
1666+ with a lower cost. */
1667+ if (! nios2_simple_const_p (*op2)
1668+ && nios2_simple_const_p (alt_op2))
1669+ {
1670+ code = alt_code;
1671+ *op2 = alt_op2;
1672+ }
1673+ *op2 = force_reg (SImode, *op2);
1674+ }
1675+ check_rebuild_cmp:
1676+ if (code == GT || code == GTU || code == LE || code == LEU)
1677+ {
1678+ rtx t = *op1; *op1 = *op2; *op2 = t;
1679+ code = swap_condition (code);
1680+ }
1681+ rebuild_cmp:
1682+ *cmp = gen_rtx_fmt_ee (code, mode, *op1, *op2);
1683+ return true;
1684+}
1685+
1686+
1687+/* Addressing Modes. */
1688+
1689+/* Implement TARGET_LEGITIMATE_CONSTANT_P. */
1690+static bool
1691+nios2_legitimate_constant_p (enum machine_mode mode, rtx x)
1692+{
1693+ switch (GET_CODE (x))
1694+ {
1695+ case SYMBOL_REF:
1696+ return !SYMBOL_REF_TLS_MODEL (x);
1697+ case CONST:
1698+ {
1699+ rtx op = XEXP (x, 0);
1700+ if (GET_CODE (op) != PLUS)
1701+ return false;
1702+ return (nios2_legitimate_constant_p (mode, XEXP (op, 0))
1703+ && nios2_legitimate_constant_p (mode, XEXP (op, 1)));
1704+ }
1705+ default:
1706+ return true;
1707+ }
1708+}
1709+
1710+/* Implement TARGET_LEGITIMATE_ADDRESS_P. */
1711+static bool
1712+nios2_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
1713+ rtx operand, bool strict)
1714+{
1715+ int ret_val = 0;
1716+
1717+ switch (GET_CODE (operand))
1718+ {
1719+ /* Direct. */
1720+ case SYMBOL_REF:
1721+ if (SYMBOL_REF_TLS_MODEL (operand))
1722+ break;
1723+
1724+ if (SYMBOL_REF_IN_NIOS2_SMALL_DATA_P (operand))
1725+ {
1726+ ret_val = 1;
1727+ break;
1728+ }
1729+ /* Else, fall through. */
1730+ case LABEL_REF:
1731+ case CONST_INT:
1732+ case CONST:
1733+ case CONST_DOUBLE:
1734+ /* ??? In here I need to add gp addressing. */
1735+ ret_val = 0;
1736+
1737+ break;
1738+
1739+ /* Register indirect. */
1740+ case REG:
1741+ ret_val = REG_OK_FOR_BASE_P2 (operand, strict);
1742+ break;
1743+
1744+ /* Register indirect with displacement. */
1745+ case PLUS:
1746+ {
1747+ rtx op0 = XEXP (operand, 0);
1748+ rtx op1 = XEXP (operand, 1);
1749+
1750+ if (REG_P (op0) && REG_P (op1))
1751+ ret_val = 0;
1752+ else if (REG_P (op0) && GET_CODE (op1) == CONST_INT)
1753+ ret_val = (REG_OK_FOR_BASE_P2 (op0, strict)
1754+ && SMALL_INT (INTVAL (op1)));
1755+ else if (REG_P (op1) && GET_CODE (op0) == CONST_INT)
1756+ ret_val = (REG_OK_FOR_BASE_P2 (op1, strict)
1757+ && SMALL_INT (INTVAL (op0)));
1758+ else
1759+ ret_val = 0;
1760+ }
1761+ break;
1762+
1763+ default:
1764+ ret_val = 0;
1765+ break;
1766+ }
1767+
1768+ return ret_val;
1769+}
1770+
1771+/* Return true if EXP should be placed in the small data section. */
1772+static bool
1773+nios2_in_small_data_p (const_tree exp)
1774+{
1775+ /* We want to merge strings, so we never consider them small data. */
1776+ if (TREE_CODE (exp) == STRING_CST)
1777+ return false;
1778+
1779+ if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
1780+ {
1781+ const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp));
1782+ /* ??? these string names need moving into
1783+ an array in some header file */
1784+ if (nios2_section_threshold > 0
1785+ && (strcmp (section, ".sbss") == 0
1786+ || strncmp (section, ".sbss.", 6) == 0
1787+ || strcmp (section, ".sdata") == 0
1788+ || strncmp (section, ".sdata.", 7) == 0))
1789+ return true;
1790+ }
1791+ else if (TREE_CODE (exp) == VAR_DECL)
1792+ {
1793+ HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
1794+
1795+ /* If this is an incomplete type with size 0, then we can't put it
1796+ in sdata because it might be too big when completed. */
1797+ if (size > 0 && (unsigned HOST_WIDE_INT)size <= nios2_section_threshold)
1798+ return true;
1799+ }
1800+
1801+ return false;
1802+}
1803+
1804+static void
1805+nios2_encode_section_info (tree decl, rtx rtl, int first)
1806+{
1807+ rtx symbol;
1808+ int flags;
1809+
1810+ default_encode_section_info (decl, rtl, first);
1811+
1812+ /* Careful not to prod global register variables. */
1813+ if (GET_CODE (rtl) != MEM)
1814+ return;
1815+ symbol = XEXP (rtl, 0);
1816+ if (GET_CODE (symbol) != SYMBOL_REF)
1817+ return;
1818+
1819+ flags = SYMBOL_REF_FLAGS (symbol);
1820+
1821+ /* We don't want weak variables to be addressed with gp in case they end up
1822+ with value 0 which is not within 2^15 of $gp. */
1823+ if (DECL_P (decl) && DECL_WEAK (decl))
1824+ flags |= SYMBOL_FLAG_WEAK_DECL;
1825+
1826+ SYMBOL_REF_FLAGS (symbol) = flags;
1827+}
1828+
1829+static unsigned int
1830+nios2_section_type_flags (tree decl, const char *name, int reloc)
1831+{
1832+ unsigned int flags;
1833+
1834+ flags = default_section_type_flags (decl, name, reloc);
1835+
1836+ if (strcmp (name, ".sbss") == 0
1837+ || strncmp (name, ".sbss.", 6) == 0
1838+ || strcmp (name, ".sdata") == 0
1839+ || strncmp (name, ".sdata.", 7) == 0)
1840+ flags |= SECTION_SMALL;
1841+
1842+ return flags;
1843+}
1844+
1845+
1846+/* Position Independent Code related. */
1847+
1848+/* Emit code to load the PIC register. */
1849+static void
1850+nios2_load_pic_register (void)
1851+{
1852+ rtx tmp = gen_rtx_REG (Pmode, TEMP_REG_NUM);
1853+
1854+ emit_insn (gen_load_got_register (pic_offset_table_rtx, tmp));
1855+ emit_insn (gen_add3_insn (pic_offset_table_rtx, pic_offset_table_rtx, tmp));
1856+}
1857+
1858+/* Nonzero if the constant value X is a legitimate general operand
1859+ when generating PIC code. It is given that flag_pic is on and
1860+ that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
1861+bool
1862+nios2_legitimate_pic_operand_p (rtx x)
1863+{
1864+ rtx inner;
1865+
1866+ /* UNSPEC_TLS is always PIC. */
1867+ if (tls_mentioned_p (x))
1868+ return true;
1869+
1870+ if (GET_CODE (x) == SYMBOL_REF)
1871+ return false;
1872+ if (GET_CODE (x) == LABEL_REF)
1873+ return false;
1874+ if (GET_CODE (x) == CONST)
1875+ {
1876+ inner = XEXP (x, 0);
1877+ if (GET_CODE (inner) == PLUS
1878+ && GET_CODE (XEXP (inner, 0)) == SYMBOL_REF)
1879+ return false;
1880+ }
1881+ return true;
1882+}
1883+
1884+rtx
1885+nios2_legitimize_pic_address (rtx orig,
1886+ enum machine_mode mode ATTRIBUTE_UNUSED, rtx reg)
1887+{
1888+ if (GET_CODE (orig) == SYMBOL_REF
1889+ || GET_CODE (orig) == LABEL_REF)
1890+ {
1891+ if (reg == 0)
1892+ {
1893+ gcc_assert (can_create_pseudo_p ());
1894+ reg = gen_reg_rtx (Pmode);
1895+ }
1896+
1897+ emit_insn (gen_pic_load_addr (reg, pic_offset_table_rtx, orig));
1898+
1899+ crtl->uses_pic_offset_table = 1;
1900+
1901+ return reg;
1902+ }
1903+ else if (GET_CODE (orig) == CONST)
1904+ {
1905+ rtx base, offset;
1906+
1907+ if (GET_CODE (XEXP (orig, 0)) == PLUS
1908+ && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
1909+ return orig;
1910+
1911+ if (GET_CODE (XEXP (orig, 0)) == UNSPEC
1912+ && IS_UNSPEC_TLS (XINT (XEXP (orig, 0), 1)))
1913+ return orig;
1914+
1915+ if (reg == 0)
1916+ {
1917+ gcc_assert (can_create_pseudo_p ());
1918+ reg = gen_reg_rtx (Pmode);
1919+ }
1920+
1921+ gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
1922+
1923+ base = nios2_legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode,
1924+ reg);
1925+ offset = nios2_legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
1926+ base == reg ? 0 : reg);
1927+
1928+ if (CONST_INT_P (offset))
1929+ {
1930+ if (SMALL_INT (INTVAL (offset)))
1931+ return plus_constant (base, INTVAL (offset));
1932+ else
1933+ offset = force_reg (Pmode, offset);
1934+ }
1935+
1936+ return gen_rtx_PLUS (Pmode, base, offset);
1937+ }
1938+
1939+ return orig;
1940+}
1941+
1942+/* Test for various thread-local symbols. */
1943+
1944+/* Return TRUE if X is a thread-local symbol. */
1945+static bool
1946+nios2_tls_symbol_p (rtx x)
1947+{
1948+ return (TARGET_HAVE_TLS && GET_CODE (x) == SYMBOL_REF
1949+ && SYMBOL_REF_TLS_MODEL (x) != 0);
1950+}
1951+
1952+/* Implement TARGET_LEGITIMIZE_ADDRESS. */
1953+static rtx
1954+nios2_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
1955+{
1956+ if (nios2_tls_symbol_p (x))
1957+ return nios2_legitimize_tls_address (x);
1958+
1959+ if (flag_pic)
1960+ {
1961+ /* We need to find and carefully transform any SYMBOL and LABEL
1962+ references; so go back to the original address expression. */
1963+ rtx new_x = nios2_legitimize_pic_address (orig_x, mode, NULL_RTX);
1964+
1965+ if (new_x != orig_x)
1966+ x = new_x;
1967+ }
1968+
1969+ return x;
1970+}
1971+
1972+
1973+/* Output assembly language related definitions. */
1974+
1975+/* Print the operand OP to file stream
1976+ FILE modified by LETTER. LETTER
1977+ can be one of:
1978+ i: print "i" if OP is an immediate, except 0
1979+ o: print "io" if OP is volatile
1980+
1981+ z: for const0_rtx print $0 instead of 0
1982+ H: for %hiadj
1983+ L: for %lo
1984+ U: for upper half of 32 bit value
1985+ D: for the upper 32-bits of a 64-bit double value
1986+ R: prints reverse condition. */
1987+static void
1988+nios2_print_operand (FILE *file, rtx op, int letter)
1989+{
1990+
1991+ switch (letter)
1992+ {
1993+ case 'i':
1994+ if (CONSTANT_P (op) && (op != const0_rtx))
1995+ fprintf (file, "i");
1996+ return;
1997+
1998+ case 'o':
1999+ if (GET_CODE (op) == MEM
2000+ && ((MEM_VOLATILE_P (op) && TARGET_BYPASS_CACHE_VOLATILE)
2001+ || TARGET_BYPASS_CACHE))
2002+ fprintf (file, "io");
2003+ return;
2004+
2005+ default:
2006+ break;
2007+ }
2008+
2009+ if (comparison_operator (op, VOIDmode))
2010+ {
2011+ enum rtx_code cond = GET_CODE (op);
2012+ if (letter == 0)
2013+ {
2014+ fprintf (file, "%s", GET_RTX_NAME (cond));
2015+ return;
2016+ }
2017+ if (letter == 'R')
2018+ {
2019+ fprintf (file, "%s", GET_RTX_NAME (reverse_condition (cond)));
2020+ return;
2021+ }
2022+ }
2023+
2024+ switch (GET_CODE (op))
2025+ {
2026+ case REG:
2027+ if (letter == 0 || letter == 'z')
2028+ {
2029+ fprintf (file, "%s", reg_names[REGNO (op)]);
2030+ return;
2031+ }
2032+ else if (letter == 'D')
2033+ {
2034+ fprintf (file, "%s", reg_names[REGNO (op)+1]);
2035+ return;
2036+ }
2037+ break;
2038+
2039+ case CONST_INT:
2040+ if (INTVAL (op) == 0 && letter == 'z')
2041+ {
2042+ fprintf (file, "zero");
2043+ return;
2044+ }
2045+ else if (letter == 'U')
2046+ {
2047+ HOST_WIDE_INT val = INTVAL (op);
2048+ rtx new_op;
2049+ val = (val / 65536) & 0xFFFF;
2050+ new_op = gen_int_mode (val, SImode);
2051+ output_addr_const (file, new_op);
2052+ return;
2053+ }
2054+ /* Else, fall through. */
2055+
2056+ case CONST:
2057+ case LABEL_REF:
2058+ case SYMBOL_REF:
2059+ case CONST_DOUBLE:
2060+ if (letter == 0 || letter == 'z')
2061+ {
2062+ output_addr_const (file, op);
2063+ return;
2064+ }
2065+ else if (letter == 'H')
2066+ {
2067+ fprintf (file, "%%hiadj(");
2068+ output_addr_const (file, op);
2069+ fprintf (file, ")");
2070+ return;
2071+ }
2072+ else if (letter == 'L')
2073+ {
2074+ fprintf (file, "%%lo(");
2075+ output_addr_const (file, op);
2076+ fprintf (file, ")");
2077+ return;
2078+ }
2079+ break;
2080+
2081+
2082+ case SUBREG:
2083+ case MEM:
2084+ if (letter == 0)
2085+ {
2086+ output_address (op);
2087+ return;
2088+ }
2089+ break;
2090+
2091+ case CODE_LABEL:
2092+ if (letter == 0)
2093+ {
2094+ output_addr_const (file, op);
2095+ return;
2096+ }
2097+ break;
2098+
2099+ default:
2100+ break;
2101+ }
2102+
2103+ fprintf (stderr, "Missing way to print (%c) ", letter);
2104+ debug_rtx (op);
2105+ gcc_unreachable ();
2106+}
2107+
2108+static int
2109+gprel_constant (rtx op)
2110+{
2111+ if (GET_CODE (op) == SYMBOL_REF
2112+ && SYMBOL_REF_IN_NIOS2_SMALL_DATA_P (op))
2113+ return 1;
2114+ else if (GET_CODE (op) == CONST
2115+ && GET_CODE (XEXP (op, 0)) == PLUS)
2116+ return gprel_constant (XEXP (XEXP (op, 0), 0));
2117+ else
2118+ return 0;
2119+}
2120+
2121+static void
2122+nios2_print_operand_address (FILE *file, rtx op)
2123+{
2124+ switch (GET_CODE (op))
2125+ {
2126+ case CONST:
2127+ case CONST_INT:
2128+ case LABEL_REF:
2129+ case CONST_DOUBLE:
2130+ case SYMBOL_REF:
2131+ if (gprel_constant (op))
2132+ {
2133+ fprintf (file, "%%gprel(");
2134+ output_addr_const (file, op);
2135+ fprintf (file, ")(%s)", reg_names[GP_REGNO]);
2136+ return;
2137+ }
2138+
2139+ break;
2140+
2141+ case PLUS:
2142+ {
2143+ rtx op0 = XEXP (op, 0);
2144+ rtx op1 = XEXP (op, 1);
2145+
2146+ if (REG_P (op0) && CONSTANT_P (op1))
2147+ {
2148+ output_addr_const (file, op1);
2149+ fprintf (file, "(%s)", reg_names[REGNO (op0)]);
2150+ return;
2151+ }
2152+ else if (REG_P (op1) && CONSTANT_P (op0))
2153+ {
2154+ output_addr_const (file, op0);
2155+ fprintf (file, "(%s)", reg_names[REGNO (op1)]);
2156+ return;
2157+ }
2158+ }
2159+ break;
2160+
2161+ case REG:
2162+ fprintf (file, "0(%s)", reg_names[REGNO (op)]);
2163+ return;
2164+
2165+ case MEM:
2166+ {
2167+ rtx base = XEXP (op, 0);
2168+ nios2_print_operand_address (file, base);
2169+ return;
2170+ }
2171+ default:
2172+ break;
2173+ }
2174+
2175+ fprintf (stderr, "Missing way to print address\n");
2176+ debug_rtx (op);
2177+ gcc_unreachable ();
2178+}
2179+
2180+static void
2181+nios2_output_dwarf_dtprel (FILE *file, int size, rtx x)
2182+{
2183+ gcc_assert (size == 4);
2184+ fprintf (file, "\t.4byte\t%%tls_ldo(");
2185+ output_addr_const (file, x);
2186+ fprintf (file, ")");
2187+}
2188+
2189+static void
2190+nios2_asm_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
2191+{
2192+ if (flag_verbose_asm || flag_debug_asm)
2193+ {
2194+ compute_frame_size ();
2195+ dump_frame_size (file);
2196+ }
2197+}
2198+
2199+/* Emit assembly of custom FPU instructions. */
2200+const char*
2201+nios2_fpu_insn_asm (enum n2fpu_code code)
2202+{
2203+ static char buf[256];
2204+ const char *op1, *op2, *op3;
2205+ int ln = 256, n = 0;
2206+
2207+ int N = N2FPU_N (code);
2208+ int num_operands = N2FPU (code).num_operands;
2209+ const char* insn_name = N2FPU_NAME (code);
2210+ tree ftype = nios2_ftype (N2FPU_FTCODE (code));
2211+ enum machine_mode dst_mode = TYPE_MODE (TREE_TYPE (ftype));
2212+ enum machine_mode src_mode = TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (ftype)));
2213+
2214+ /* Prepare X register for DF input operands. */
2215+ if (GET_MODE_SIZE (src_mode) == 8 && num_operands == 3)
2216+ n = snprintf (buf, ln, "custom\t%d, zero, %%1, %%D1 # fwrx %%1\n\t",
2217+ N2FPU_N (n2fpu_fwrx));
2218+
2219+ if (src_mode == SFmode)
2220+ {
2221+ if (dst_mode == VOIDmode)
2222+ {
2223+ /* The fwry case. */
2224+ op1 = op3 = "zero";
2225+ op2 = "%0";
2226+ num_operands -= 1;
2227+ }
2228+ else
2229+ {
2230+ op1 = "%0"; op2 = "%1";
2231+ op3 = (num_operands == 2 ? "zero" : "%2");
2232+ }
2233+ }
2234+ else if (src_mode == DFmode)
2235+ {
2236+ if (dst_mode == VOIDmode)
2237+ {
2238+ /* The fwrx case. */
2239+ op1 = "zero";
2240+ op2 = "%0";
2241+ op3 = "%D0";
2242+ num_operands -= 1;
2243+ }
2244+ else
2245+ {
2246+ op1 = (dst_mode == DFmode ? "%D0" : "%0");
2247+ op2 = (num_operands == 2 ? "%1" : "%2");
2248+ op3 = (num_operands == 2 ? "%D1" : "%D2");
2249+ }
2250+ }
2251+ else if (src_mode == VOIDmode)
2252+ {
2253+ /* frdxlo, frdxhi, frdy cases. */
2254+ gcc_assert (dst_mode == SFmode);
2255+ op1 = "%0";
2256+ op2 = op3 = "zero";
2257+ }
2258+ else if (src_mode == SImode)
2259+ {
2260+ /* Conversion operators. */
2261+ gcc_assert (num_operands == 2);
2262+ op1 = (dst_mode == DFmode ? "%D0" : "%0");
2263+ op2 = "%1";
2264+ op3 = "zero";
2265+ }
2266+ else
2267+ gcc_unreachable ();
2268+
2269+ /* Main instruction string. */
2270+ n += snprintf (buf + n, ln - n, "custom\t%d, %s, %s, %s # %s %%0%s%s",
2271+ N, op1, op2, op3, insn_name,
2272+ (num_operands >= 2 ? ", %1" : ""),
2273+ (num_operands == 3 ? ", %2" : ""));
2274+
2275+ /* Extraction of Y register for DF results. */
2276+ if (dst_mode == DFmode)
2277+ snprintf (buf + n, ln - n, "\n\tcustom\t%d, %%0, zero, zero # frdy %%0",
2278+ N2FPU_N (n2fpu_frdy));
2279+ return buf;
2280+}
2281+
2282+
2283+
2284+/* Instruction scheduler related. */
2285+
2286+static int
2287+nios2_issue_rate (void)
2288+{
2289+#ifdef MAX_DFA_ISSUE_RATE
2290+ return MAX_DFA_ISSUE_RATE;
2291+#else
2292+ return 1;
2293+#endif
2294+}
2295+
2296+
2297+
2298+/* Function argument related. */
2299+
2300+void
2301+nios2_init_cumulative_args (CUMULATIVE_ARGS *cum,
2302+ tree fntype ATTRIBUTE_UNUSED,
2303+ rtx libname ATTRIBUTE_UNUSED,
2304+ tree fndecl ATTRIBUTE_UNUSED,
2305+ int n_named_args ATTRIBUTE_UNUSED)
2306+{
2307+ cum->regs_used = 0;
2308+}
2309+
2310+/* Define where to put the arguments to a function. Value is zero to
2311+ push the argument on the stack, or a hard register in which to
2312+ store the argument.
2313+
2314+ MODE is the argument's machine mode.
2315+ TYPE is the data type of the argument (as a tree).
2316+ This is null for libcalls where that information may
2317+ not be available.
2318+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
2319+ the preceding args and about the function being called.
2320+ NAMED is nonzero if this argument is a named parameter
2321+ (otherwise it is an extra parameter matching an ellipsis). */
2322+
2323+static rtx
2324+nios2_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
2325+ const_tree type ATTRIBUTE_UNUSED,
2326+ bool named ATTRIBUTE_UNUSED)
2327+{
2328+ CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2329+ rtx return_rtx = NULL_RTX;
2330+
2331+ if (cum->regs_used < NUM_ARG_REGS)
2332+ return_rtx = gen_rtx_REG (mode, FIRST_ARG_REGNO + cum->regs_used);
2333+
2334+ return return_rtx;
2335+}
2336+
2337+/* Return number of bytes, at the beginning of the argument, that must be
2338+ put in registers. 0 is the argument is entirely in registers or entirely
2339+ in memory. */
2340+
2341+static int
2342+nios2_arg_partial_bytes (cumulative_args_t cum_v,
2343+ enum machine_mode mode, tree type,
2344+ bool named ATTRIBUTE_UNUSED)
2345+{
2346+ CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2347+ HOST_WIDE_INT param_size;
2348+
2349+ if (mode == BLKmode)
2350+ {
2351+ param_size = int_size_in_bytes (type);
2352+ if (param_size < 0)
2353+ internal_error
2354+ ("Do not know how to handle large structs or variable length types");
2355+ }
2356+ else
2357+ param_size = GET_MODE_SIZE (mode);
2358+
2359+ /* Convert to words (round up). */
2360+ param_size = (3 + param_size) / 4;
2361+
2362+ if (cum->regs_used < NUM_ARG_REGS
2363+ && cum->regs_used + param_size > NUM_ARG_REGS)
2364+ return (NUM_ARG_REGS - cum->regs_used) * UNITS_PER_WORD;
2365+ else
2366+ return 0;
2367+}
2368+
2369+/* Update the data in CUM to advance over an argument
2370+ of mode MODE and data type TYPE.
2371+ (TYPE is null for libcalls where that information may not be available.) */
2372+
2373+static void
2374+nios2_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
2375+ const_tree type ATTRIBUTE_UNUSED,
2376+ bool named ATTRIBUTE_UNUSED)
2377+{
2378+ CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2379+ HOST_WIDE_INT param_size;
2380+
2381+ if (mode == BLKmode)
2382+ {
2383+ param_size = int_size_in_bytes (type);
2384+ if (param_size < 0)
2385+ internal_error
2386+ ("Do not know how to handle large structs or variable length types");
2387+ }
2388+ else
2389+ param_size = GET_MODE_SIZE (mode);
2390+
2391+ /* Convert to words (round up). */
2392+ param_size = (3 + param_size) / 4;
2393+
2394+ if (cum->regs_used + param_size > NUM_ARG_REGS)
2395+ cum->regs_used = NUM_ARG_REGS;
2396+ else
2397+ cum->regs_used += param_size;
2398+
2399+ return;
2400+}
2401+
2402+enum direction
2403+nios2_function_arg_padding (enum machine_mode mode, const_tree type)
2404+{
2405+ /* On little-endian targets, the first byte of every stack argument
2406+ is passed in the first byte of the stack slot. */
2407+ if (!BYTES_BIG_ENDIAN)
2408+ return upward;
2409+
2410+ /* Otherwise, integral types are padded downward: the last byte of a
2411+ stack argument is passed in the last byte of the stack slot. */
2412+ if (type != 0
2413+ ? INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)
2414+ : GET_MODE_CLASS (mode) == MODE_INT)
2415+ return downward;
2416+
2417+ /* Arguments smaller than a stack slot are padded downward. */
2418+ if (mode != BLKmode)
2419+ return (GET_MODE_BITSIZE (mode) >= PARM_BOUNDARY) ? upward : downward;
2420+ else
2421+ return ((int_size_in_bytes (type) >= (PARM_BOUNDARY / BITS_PER_UNIT))
2422+ ? upward : downward);
2423+}
2424+
2425+enum direction
2426+nios2_block_reg_padding (enum machine_mode mode, tree type,
2427+ int first ATTRIBUTE_UNUSED)
2428+{
2429+ /* ??? Do we need to treat floating point specially, ala MIPS? */
2430+ return nios2_function_arg_padding (mode, type);
2431+}
2432+
2433+
2434+/* Emit RTL insns to initialize the variable parts of a trampoline.
2435+ FNADDR is an RTX for the address of the function's pure code.
2436+ CXT is an RTX for the static chain value for the function.
2437+ On Nios II, we handle this by a library call. */
2438+static void
2439+nios2_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt)
2440+{
2441+ rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
2442+ rtx ctx_reg = force_reg (Pmode, cxt);
2443+ rtx addr = force_reg (Pmode, XEXP (m_tramp, 0));
2444+
2445+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__trampoline_setup"),
2446+ LCT_NORMAL, VOIDmode, 3,
2447+ addr, Pmode,
2448+ fnaddr, Pmode,
2449+ ctx_reg, Pmode);
2450+}
2451+
2452+static rtx
2453+nios2_function_value (const_tree ret_type, const_tree fn ATTRIBUTE_UNUSED,
2454+ bool outgoing ATTRIBUTE_UNUSED)
2455+{
2456+ return gen_rtx_REG (TYPE_MODE (ret_type), FIRST_RETVAL_REGNO);
2457+}
2458+
2459+static rtx
2460+nios2_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
2461+{
2462+ return gen_rtx_REG (mode, FIRST_RETVAL_REGNO);
2463+}
2464+
2465+static bool
2466+nios2_function_value_regno_p (const unsigned int regno)
2467+{
2468+ return (regno == FIRST_RETVAL_REGNO);
2469+}
2470+
2471+static bool
2472+nios2_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
2473+{
2474+ return (int_size_in_bytes (type) > (2 * UNITS_PER_WORD)
2475+ || int_size_in_bytes (type) == -1);
2476+}
2477+
2478+/* ??? It may be possible to eliminate the copyback and implement
2479+ my own va_arg type, but that is more work for now. */
2480+static void
2481+nios2_setup_incoming_varargs (cumulative_args_t cum_v,
2482+ enum machine_mode mode, tree type,
2483+ int *pretend_size, int second_time)
2484+{
2485+ CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2486+ CUMULATIVE_ARGS local_cum;
2487+ cumulative_args_t local_cum_v = pack_cumulative_args (&local_cum);
2488+ int regs_to_push;
2489+ int pret_size;
2490+
2491+ local_cum = *cum;
2492+ nios2_function_arg_advance (local_cum_v, mode, type, 1);
2493+
2494+ regs_to_push = NUM_ARG_REGS - local_cum.regs_used;
2495+
2496+ if (!second_time && regs_to_push > 0)
2497+ {
2498+ rtx ptr = virtual_incoming_args_rtx;
2499+ rtx mem = gen_rtx_MEM (BLKmode, ptr);
2500+ emit_insn (gen_blockage ());
2501+ move_block_from_reg (local_cum.regs_used + FIRST_ARG_REGNO, mem,
2502+ regs_to_push);
2503+ emit_insn (gen_blockage ());
2504+ }
2505+
2506+ pret_size = regs_to_push * UNITS_PER_WORD;
2507+
2508+ if (pret_size)
2509+ *pretend_size = pret_size;
2510+}
2511+
2512+
2513+
2514+/* Init FPU builtins. */
2515+static void
2516+nios2_init_fpu_builtins (int start_code)
2517+{
2518+ char builtin_name[64] = "__builtin_custom_";
2519+ unsigned int i, n = strlen ("__builtin_custom_");
2520+
2521+ for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
2522+ {
2523+ snprintf (builtin_name + n, sizeof (builtin_name) - n,
2524+ "%s", N2FPU_NAME (i));
2525+ add_builtin_function (builtin_name, nios2_ftype (N2FPU_FTCODE (i)),
2526+ start_code + i, BUILT_IN_MD, NULL, NULL_TREE);
2527+ }
2528+}
2529+
2530+static rtx
2531+nios2_expand_fpu_builtin (tree exp, unsigned int code, rtx target)
2532+{
2533+ struct expand_operand ops[MAX_RECOG_OPERANDS];
2534+ enum insn_code icode = N2FPU_ICODE (code);
2535+ int nargs, argno, opno = 0;
2536+ int num_operands = N2FPU (code).num_operands;
2537+ enum machine_mode dst_mode = TYPE_MODE (TREE_TYPE (exp));
2538+ bool has_target_p = (dst_mode != VOIDmode);
2539+
2540+ if (N2FPU_N (code) < 0)
2541+ fatal_error ("Cannot call `__builtin_custom_%s' without specifying switch"
2542+ " `-mcustom-%s'", N2FPU_NAME (code), N2FPU_NAME (code));
2543+ if (has_target_p)
2544+ create_output_operand (&ops[opno++], target, dst_mode);
2545+ else
2546+ /* Subtract away the count of the VOID return, mainly for fwrx/fwry. */
2547+ num_operands -= 1;
2548+ nargs = call_expr_nargs (exp);
2549+ for (argno = 0; argno < nargs; argno++)
2550+ {
2551+ tree arg = CALL_EXPR_ARG (exp, argno);
2552+ create_input_operand (&ops[opno++], expand_normal (arg),
2553+ TYPE_MODE (TREE_TYPE (arg)));
2554+ }
2555+ if (!maybe_expand_insn (icode, num_operands, ops))
2556+ {
2557+ error ("invalid argument to built-in function");
2558+ return has_target_p ? gen_reg_rtx (ops[0].mode) : const0_rtx;
2559+ }
2560+ return has_target_p ? ops[0].value : const0_rtx;
2561+}
2562+
2563+
2564+/* Nios II has custom instruction built-in functions of the forms:
2565+ __builtin_custom_n
2566+ __builtin_custom_nX
2567+ __builtin_custom_nXX
2568+ __builtin_custom_Xn
2569+ __builtin_custom_XnX
2570+ __builtin_custom_XnXX
2571+
2572+ where each X could be either 'i' (int), 'f' (float), or 'p' (void*).
2573+ Therefore with 0-1 return values, and 0-2 arguments, we have a
2574+ total of (3 + 1) * (1 + 3 + 9) == 52 custom builtin functions.
2575+*/
2576+#define NUM_CUSTOM_BUILTINS ((3 + 1) * (1 + 3 + 9))
2577+static char custom_builtin_name[NUM_CUSTOM_BUILTINS][5];
2578+
2579+static void
2580+nios2_init_custom_builtins (int start_code)
2581+{
2582+ tree builtin_ftype, ret_type;
2583+ char builtin_name[32] = "__builtin_custom_";
2584+ int n = strlen ("__builtin_custom_");
2585+ int builtin_code = 0;
2586+ int lhs, rhs1, rhs2;
2587+
2588+ struct { tree type; const char* c; } op[4];
2589+ /* z */ op[0].c = ""; op[0].type = NULL_TREE;
2590+ /* f */ op[1].c = "f"; op[1].type = float_type_node;
2591+ /* i */ op[2].c = "i"; op[2].type = integer_type_node;
2592+ /* p */ op[3].c = "p"; op[3].type = ptr_type_node;
2593+
2594+ /* This way of constructing the function tree types will slightly
2595+ overlap with the N2_FTYPES list used by other builtins. */
2596+
2597+ for (lhs = 0; lhs < 4; lhs++)
2598+ for (rhs1 = 0; rhs1 < 4; rhs1++)
2599+ for (rhs2 = 0; rhs2 < 4; rhs2++)
2600+ {
2601+ if (rhs1 == 0 && rhs2 != 0)
2602+ continue;
2603+ ret_type = (op[lhs].type ? op[lhs].type : void_type_node);
2604+ builtin_ftype
2605+ = build_function_type_list (ret_type, integer_type_node,
2606+ op[rhs1].type, op[rhs2].type,
2607+ NULL_TREE);
2608+ snprintf (builtin_name + n, 32 - n, "%sn%s%s",
2609+ op[lhs].c, op[rhs1].c, op[rhs2].c);
2610+ /* Save copy of parameter string into custom_builtin_name[]. */
2611+ strncpy (custom_builtin_name[builtin_code], builtin_name + n, 5);
2612+ add_builtin_function (builtin_name, builtin_ftype,
2613+ start_code + builtin_code,
2614+ BUILT_IN_MD, NULL, NULL_TREE);
2615+ builtin_code += 1;
2616+ }
2617+}
2618+
2619+static rtx
2620+nios2_expand_custom_builtin (tree exp, unsigned int index, rtx target)
2621+{
2622+ bool has_target_p = (TREE_TYPE (exp) != void_type_node);
2623+ enum machine_mode tmode = VOIDmode;
2624+ int nargs, argno;
2625+ rtx value, insn, unspec_args[3];
2626+ tree arg;
2627+
2628+ /* XnXX form. */
2629+ if (has_target_p)
2630+ {
2631+ tmode = TYPE_MODE (TREE_TYPE (exp));
2632+ if (!target || GET_MODE (target) != tmode
2633+ || !REG_P (target))
2634+ target = gen_reg_rtx (tmode);
2635+ }
2636+
2637+ nargs = call_expr_nargs (exp);
2638+ for (argno = 0; argno < nargs; argno++)
2639+ {
2640+ arg = CALL_EXPR_ARG (exp, argno);
2641+ value = expand_normal (arg);
2642+ unspec_args[argno] = value;
2643+ if (argno == 0)
2644+ {
2645+ if (!custom_insn_opcode (value, VOIDmode))
2646+ error ("Custom instruction opcode must be compile time "
2647+ "constant in the range 0-255 for __builtin_custom_%s",
2648+ custom_builtin_name[index]);
2649+ }
2650+ else
2651+ /* For other arguments, force into a register. */
2652+ unspec_args[argno] = force_reg (TYPE_MODE (TREE_TYPE (arg)),
2653+ unspec_args[argno]);
2654+ }
2655+ /* Fill remaining unspec operands with zero. */
2656+ for (; argno < 3; argno++)
2657+ unspec_args[argno] = const0_rtx;
2658+
2659+ insn = (has_target_p
2660+ ? gen_rtx_SET (VOIDmode, target,
2661+ gen_rtx_UNSPEC_VOLATILE (tmode,
2662+ gen_rtvec_v (3, unspec_args),
2663+ UNSPECV_CUSTOM_XNXX))
2664+ : gen_rtx_UNSPEC_VOLATILE (VOIDmode, gen_rtvec_v (3, unspec_args),
2665+ UNSPECV_CUSTOM_NXX));
2666+ emit_insn (insn);
2667+ return has_target_p ? target : const0_rtx;
2668+}
2669+
2670+
2671+
2672+
2673+/* Main definition of built-in functions. Nios II has a small number of fixed
2674+ builtins, plus a large number of FPU insn builtins, and builtins for
2675+ generating custom instructions. */
2676+
2677+struct nios2_builtin_desc
2678+{
2679+ enum insn_code icode;
2680+ enum nios2_ftcode ftype;
2681+ const char* name;
2682+};
2683+
2684+#define N2_BUILTINS \
2685+ N2_BUILTIN_DEF (sync, N2_FTYPE_VOID_VOID) \
2686+ N2_BUILTIN_DEF (ldbio, N2_FTYPE_SI_CVPTR) \
2687+ N2_BUILTIN_DEF (ldbuio, N2_FTYPE_UI_CVPTR) \
2688+ N2_BUILTIN_DEF (ldhio, N2_FTYPE_SI_CVPTR) \
2689+ N2_BUILTIN_DEF (ldhuio, N2_FTYPE_UI_CVPTR) \
2690+ N2_BUILTIN_DEF (ldwio, N2_FTYPE_SI_CVPTR) \
2691+ N2_BUILTIN_DEF (stbio, N2_FTYPE_VOID_VPTR_SI) \
2692+ N2_BUILTIN_DEF (sthio, N2_FTYPE_VOID_VPTR_SI) \
2693+ N2_BUILTIN_DEF (stwio, N2_FTYPE_VOID_VPTR_SI) \
2694+ N2_BUILTIN_DEF (rdctl, N2_FTYPE_SI_SI) \
2695+ N2_BUILTIN_DEF (wrctl, N2_FTYPE_VOID_SI_SI)
2696+
2697+enum nios2_builtin_code {
2698+#define N2_BUILTIN_DEF(name, ftype) NIOS2_BUILTIN_ ## name,
2699+ N2_BUILTINS
2700+#undef N2_BUILTIN_DEF
2701+ NUM_FIXED_NIOS2_BUILTINS
2702+};
2703+
2704+static const struct nios2_builtin_desc nios2_builtins[] = {
2705+#define N2_BUILTIN_DEF(name, ftype) \
2706+ { CODE_FOR_ ## name, ftype, "__builtin_" #name },
2707+ N2_BUILTINS
2708+#undef N2_BUILTIN_DEF
2709+};
2710+
2711+/* Start/ends of FPU/custom insn builtin index ranges. */
2712+static unsigned int nios2_fpu_builtin_base;
2713+static unsigned int nios2_custom_builtin_base;
2714+static unsigned int nios2_custom_builtin_end;
2715+
2716+static void
2717+nios2_init_builtins (void)
2718+{
2719+ unsigned int i;
2720+
2721+ /* Initialize fixed builtins. */
2722+ for (i = 0; i < ARRAY_SIZE (nios2_builtins); i++)
2723+ {
2724+ const struct nios2_builtin_desc *d = &nios2_builtins[i];
2725+ add_builtin_function (d->name, nios2_ftype (d->ftype), i,
2726+ BUILT_IN_MD, NULL, NULL);
2727+ }
2728+
2729+ /* Initialize FPU builtins. */
2730+ nios2_fpu_builtin_base = ARRAY_SIZE (nios2_builtins);
2731+ nios2_init_fpu_builtins (nios2_fpu_builtin_base);
2732+
2733+ /* Initialize custom insn builtins. */
2734+ nios2_custom_builtin_base
2735+ = nios2_fpu_builtin_base + ARRAY_SIZE (nios2_fpu_insn);
2736+ nios2_custom_builtin_end
2737+ = nios2_custom_builtin_base + NUM_CUSTOM_BUILTINS;
2738+ nios2_init_custom_builtins (nios2_custom_builtin_base);
2739+}
2740+
2741+static rtx
2742+nios2_expand_builtin_insn (const struct nios2_builtin_desc *d, int n,
2743+ struct expand_operand* ops, bool has_target_p)
2744+{
2745+ if (maybe_expand_insn (d->icode, n, ops))
2746+ return has_target_p ? ops[0].value : const0_rtx;
2747+ else
2748+ {
2749+ error ("invalid argument to built-in function %s", d->name);
2750+ return has_target_p ? gen_reg_rtx (ops[0].mode) : const0_rtx;
2751+ }
2752+}
2753+
2754+static rtx
2755+nios2_expand_ldstio_builtin (tree exp, rtx target,
2756+ const struct nios2_builtin_desc *d)
2757+{
2758+ bool has_target_p;
2759+ rtx addr, mem, val;
2760+ struct expand_operand ops[MAX_RECOG_OPERANDS];
2761+ enum machine_mode mode = insn_data[d->icode].operand[0].mode;
2762+
2763+ addr = expand_normal (CALL_EXPR_ARG (exp, 0));
2764+ mem = gen_rtx_MEM (mode, addr);
2765+
2766+ if (insn_data[d->icode].operand[0].allows_mem)
2767+ {
2768+ /* stxio */
2769+ val = force_reg (mode, expand_normal (CALL_EXPR_ARG (exp, 1)));
2770+ val = simplify_gen_subreg (mode, val, GET_MODE (val), 0);
2771+ create_output_operand (&ops[0], mem, mode);
2772+ create_input_operand (&ops[1], val, mode);
2773+ has_target_p = false;
2774+ }
2775+ else
2776+ {
2777+ /* ldxio */
2778+ create_output_operand (&ops[0], target, mode);
2779+ create_input_operand (&ops[1], mem, mode);
2780+ has_target_p = true;
2781+ }
2782+ return nios2_expand_builtin_insn (d, 2, ops, has_target_p);
2783+}
2784+
2785+static rtx
2786+nios2_expand_rdwrctl_builtin (tree exp, rtx target,
2787+ const struct nios2_builtin_desc *d)
2788+{
2789+ bool has_target_p = (insn_data[d->icode].operand[0].predicate
2790+ == register_operand);
2791+ rtx ctlcode = expand_normal (CALL_EXPR_ARG (exp, 0));
2792+ struct expand_operand ops[MAX_RECOG_OPERANDS];
2793+ if (!rdwrctl_operand (ctlcode, VOIDmode))
2794+ {
2795+ error ("Control register number must be in range 0-31 for %s",
2796+ d->name);
2797+ return has_target_p ? gen_reg_rtx (SImode) : const0_rtx;
2798+ }
2799+ if (has_target_p)
2800+ {
2801+ create_output_operand (&ops[0], target, SImode);
2802+ create_integer_operand (&ops[1], INTVAL (ctlcode));
2803+ }
2804+ else
2805+ {
2806+ rtx val = expand_normal (CALL_EXPR_ARG (exp, 1));
2807+ create_integer_operand (&ops[0], INTVAL (ctlcode));
2808+ create_input_operand (&ops[1], val, SImode);
2809+ }
2810+ return nios2_expand_builtin_insn (d, 2, ops, has_target_p);
2811+}
2812+
2813+/* Expand an expression EXP that calls a built-in function,
2814+ with result going to TARGET if that's convenient
2815+ (and in mode MODE if that's convenient).
2816+ SUBTARGET may be used as the target for computing one of EXP's operands.
2817+ IGNORE is nonzero if the value is to be ignored. */
2818+
2819+static rtx
2820+nios2_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
2821+ enum machine_mode mode ATTRIBUTE_UNUSED,
2822+ int ignore ATTRIBUTE_UNUSED)
2823+{
2824+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
2825+ unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
2826+
2827+ if (fcode < nios2_fpu_builtin_base)
2828+ {
2829+ const struct nios2_builtin_desc *d = &nios2_builtins[fcode];
2830+
2831+ switch (fcode)
2832+ {
2833+ case NIOS2_BUILTIN_sync:
2834+ emit_insn (gen_sync ());
2835+ return const0_rtx;
2836+
2837+ case NIOS2_BUILTIN_ldbio:
2838+ case NIOS2_BUILTIN_ldbuio:
2839+ case NIOS2_BUILTIN_ldhio:
2840+ case NIOS2_BUILTIN_ldhuio:
2841+ case NIOS2_BUILTIN_ldwio:
2842+ case NIOS2_BUILTIN_stbio:
2843+ case NIOS2_BUILTIN_sthio:
2844+ case NIOS2_BUILTIN_stwio:
2845+ return nios2_expand_ldstio_builtin (exp, target, d);
2846+
2847+ case NIOS2_BUILTIN_rdctl:
2848+ case NIOS2_BUILTIN_wrctl:
2849+ return nios2_expand_rdwrctl_builtin (exp, target, d);
2850+
2851+ default:
2852+ gcc_unreachable ();
2853+ }
2854+ }
2855+ else if (fcode < nios2_custom_builtin_base)
2856+ /* FPU builtin range. */
2857+ return nios2_expand_fpu_builtin (exp, fcode - nios2_fpu_builtin_base,
2858+ target);
2859+ else if (fcode < nios2_custom_builtin_end)
2860+ /* Custom insn builtin range. */
2861+ return nios2_expand_custom_builtin (exp, fcode - nios2_custom_builtin_base,
2862+ target);
2863+ else
2864+ gcc_unreachable ();
2865+}
2866+
2867+static void
2868+nios2_init_libfuncs (void)
2869+{
2870+ /* For Linux, we have access to kernel support for atomic operations. */
2871+ if (TARGET_LINUX_ABI)
2872+ init_sync_libfuncs (UNITS_PER_WORD);
2873+}
2874+
2875+
2876+
2877+
2878+/* Register a custom code use, and signal error if a conflict was found. */
2879+static void
2880+nios2_register_custom_code (unsigned int N, enum nios2_ccs_code status,
2881+ int index)
2882+{
2883+ gcc_assert (N <= 255);
2884+
2885+ if (status == CCS_FPU)
2886+ {
2887+ if (custom_code_status[N] == CCS_FPU && index != custom_code_index[N])
2888+ {
2889+ custom_code_conflict = true;
2890+ error ("switch `-mcustom-%s' conflicts with switch `-mcustom-%s'",
2891+ N2FPU_NAME (custom_code_index[N]), N2FPU_NAME (index));
2892+ }
2893+ else if (custom_code_status[N] == CCS_BUILTIN_CALL)
2894+ {
2895+ custom_code_conflict = true;
2896+ error ("call to `__builtin_custom_%s' conflicts with switch "
2897+ "`-mcustom-%s'", custom_builtin_name[custom_code_index[N]],
2898+ N2FPU_NAME (index));
2899+ }
2900+ }
2901+ else if (status == CCS_BUILTIN_CALL)
2902+ {
2903+ if (custom_code_status[N] == CCS_FPU)
2904+ {
2905+ custom_code_conflict = true;
2906+ error ("call to `__builtin_custom_%s' conflicts with switch "
2907+ "`-mcustom-%s'", custom_builtin_name[index],
2908+ N2FPU_NAME (custom_code_index[N]));
2909+ }
2910+ /* Code conflicts between different __builtin_custom_xnxx calls
2911+ do not seem to be checked. ??? */
2912+ }
2913+ else
2914+ gcc_unreachable ();
2915+
2916+ custom_code_status[N] = status;
2917+ custom_code_index[N] = index;
2918+}
2919+
2920+/* Mark a custom code as not in use. */
2921+static void
2922+nios2_deregister_custom_code (unsigned int N)
2923+{
2924+ if (N <= 255)
2925+ {
2926+ custom_code_status[N] = CCS_UNUSED;
2927+ custom_code_index[N] = 0;
2928+ }
2929+}
2930+
2931+/* Target attributes can affect per-function option state, so we need to
2932+ save/restore the custom code tracking info using the
2933+ TARGET_OPTION_SAVE/TARGET_OPTION_RESTORE hooks. */
2934+
2935+static void
2936+nios2_option_save (struct cl_target_option *ptr)
2937+{
2938+ unsigned int i;
2939+ for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
2940+ ptr->saved_fpu_custom_code[i] = N2FPU_N (i);
2941+ memcpy (ptr->saved_custom_code_status, custom_code_status,
2942+ sizeof (custom_code_status));
2943+ memcpy (ptr->saved_custom_code_index, custom_code_index,
2944+ sizeof (custom_code_index));
2945+}
2946+
2947+static void
2948+nios2_option_restore (struct cl_target_option *ptr)
2949+{
2950+ unsigned int i;
2951+ for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
2952+ N2FPU_N (i) = ptr->saved_fpu_custom_code[i];
2953+ memcpy (custom_code_status, ptr->saved_custom_code_status,
2954+ sizeof (custom_code_status));
2955+ memcpy (custom_code_index, ptr->saved_custom_code_index,
2956+ sizeof (custom_code_index));
2957+}
2958+
2959+/* Inner function to process the attribute((target(...))), take an argument and
2960+ set the current options from the argument. If we have a list, recursively go
2961+ over the list. */
2962+
2963+static bool
2964+nios2_valid_target_attribute_rec (tree args)
2965+{
2966+ if (TREE_CODE (args) == TREE_LIST)
2967+ {
2968+ bool ret = true;
2969+ for (; args; args = TREE_CHAIN (args))
2970+ if (TREE_VALUE (args)
2971+ && !nios2_valid_target_attribute_rec (TREE_VALUE (args)))
2972+ ret = false;
2973+ return ret;
2974+ }
2975+ else if (TREE_CODE (args) == STRING_CST)
2976+ {
2977+ char *argstr = ASTRDUP (TREE_STRING_POINTER (args));
2978+ while (argstr && *argstr != '\0')
2979+ {
2980+ bool no_opt = false, end_p = false;
2981+ char *eq = NULL, *p;
2982+ while (ISSPACE (*argstr))
2983+ argstr++;
2984+ p = argstr;
2985+ while (*p != '\0' && *p != ',')
2986+ {
2987+ if (!eq && *p == '=')
2988+ eq = p;
2989+ ++p;
2990+ }
2991+ if (*p == '\0')
2992+ end_p = true;
2993+ else
2994+ *p = '\0';
2995+ if (eq) *eq = '\0';
2996+
2997+ if (!strncmp (argstr, "no-", 3))
2998+ {
2999+ no_opt = true;
3000+ argstr += 3;
3001+ }
3002+ if (!strncmp (argstr, "custom-fpu-cfg", 14))
3003+ {
3004+ if (no_opt)
3005+ {
3006+ error ("custom-fpu-cfg option does not support `no-'");
3007+ return false;
3008+ }
3009+ if (!eq)
3010+ {
3011+ error ("custom-fpu-cfg option requires configuration"
3012+ " argument");
3013+ return false;
3014+ }
3015+ /* Increment and skip whitespace. */
3016+ while (ISSPACE (*(++eq))) ;
3017+ nios2_handle_custom_fpu_cfg (eq, true);
3018+ }
3019+ else if (!strncmp (argstr, "custom-", 7))
3020+ {
3021+ int code = -1;
3022+ unsigned int i;
3023+ for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
3024+ if (!strncmp (argstr + 7, N2FPU_NAME (i),
3025+ strlen (N2FPU_NAME (i))))
3026+ {
3027+ /* Found insn. */
3028+ code = i;
3029+ break;
3030+ }
3031+ if (code >= 0)
3032+ {
3033+ if (no_opt)
3034+ {
3035+ if (eq)
3036+ {
3037+ error ("`no-custom-%s' does not accept arguments",
3038+ N2FPU_NAME (code));
3039+ return false;
3040+ }
3041+ /* Disable option by setting to -1. */
3042+ nios2_deregister_custom_code (N2FPU_N (code));
3043+ N2FPU_N (code) = -1;
3044+ }
3045+ else
3046+ {
3047+ char *t;
3048+ if (eq)
3049+ while (ISSPACE (*(++eq))) ;
3050+ if (!eq || eq == p)
3051+ {
3052+ error ("`custom-%s=' requires argument",
3053+ N2FPU_NAME (code));
3054+ return false;
3055+ }
3056+ for (t = eq; t != p; ++t)
3057+ {
3058+ if (ISSPACE (*t))
3059+ continue;
3060+ if (!ISDIGIT (*t))
3061+ {
3062+ error ("`custom-%s=' argument requires "
3063+ "numeric digits", N2FPU_NAME (code));
3064+ return false;
3065+ }
3066+ }
3067+ /* Set option to argument. */
3068+ N2FPU_N (code) = atoi (eq);
3069+ nios2_handle_custom_fpu_insn_option (code);
3070+ }
3071+ }
3072+ else
3073+ {
3074+ error ("`custom-%s=' is not recognised as FPU instruction",
3075+ argstr + 7);
3076+ return false;
3077+ }
3078+ }
3079+ else
3080+ {
3081+ error ("`%s' is unknown", argstr);
3082+ return false;
3083+ }
3084+
3085+ if (end_p)
3086+ break;
3087+ else
3088+ argstr = p + 1;
3089+ }
3090+ return true;
3091+ }
3092+ else
3093+ gcc_unreachable ();
3094+}
3095+
3096+/* Return a TARGET_OPTION_NODE tree of the target options listed or NULL. */
3097+
3098+static tree
3099+nios2_valid_target_attribute_tree (tree args)
3100+{
3101+ if (!nios2_valid_target_attribute_rec (args))
3102+ return NULL_TREE;
3103+ nios2_custom_check_insns ();
3104+ return build_target_option_node ();
3105+}
3106+
3107+/* Hook to validate attribute((target("string"))). */
3108+
3109+static bool
3110+nios2_valid_target_attribute_p (tree fndecl,
3111+ tree ARG_UNUSED (name),
3112+ tree args,
3113+ int ARG_UNUSED (flags))
3114+{
3115+ struct cl_target_option cur_target;
3116+ bool ret = true;
3117+ tree old_optimize = build_optimization_node ();
3118+ tree new_target, new_optimize;
3119+ tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
3120+
3121+ /* If the function changed the optimization levels as well as setting target
3122+ options, start with the optimizations specified. */
3123+ if (func_optimize && func_optimize != old_optimize)
3124+ cl_optimization_restore (&global_options,
3125+ TREE_OPTIMIZATION (func_optimize));
3126+
3127+ /* The target attributes may also change some optimization flags, so update
3128+ the optimization options if necessary. */
3129+ cl_target_option_save (&cur_target, &global_options);
3130+ new_target = nios2_valid_target_attribute_tree (args);
3131+ new_optimize = build_optimization_node ();
3132+
3133+ if (!new_target)
3134+ ret = false;
3135+
3136+ else if (fndecl)
3137+ {
3138+ DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_target;
3139+
3140+ if (old_optimize != new_optimize)
3141+ DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize;
3142+ }
3143+
3144+ cl_target_option_restore (&global_options, &cur_target);
3145+
3146+ if (old_optimize != new_optimize)
3147+ cl_optimization_restore (&global_options,
3148+ TREE_OPTIMIZATION (old_optimize));
3149+ return ret;
3150+}
3151+
3152+/* Remember the last target of nios2_set_current_function. */
3153+static GTY(()) tree nios2_previous_fndecl;
3154+
3155+/* Establish appropriate back-end context for processing the function
3156+ FNDECL. The argument might be NULL to indicate processing at top
3157+ level, outside of any function scope. */
3158+static void
3159+nios2_set_current_function (tree fndecl)
3160+{
3161+ tree old_tree = (nios2_previous_fndecl
3162+ ? DECL_FUNCTION_SPECIFIC_TARGET (nios2_previous_fndecl)
3163+ : NULL_TREE);
3164+
3165+ tree new_tree = (fndecl
3166+ ? DECL_FUNCTION_SPECIFIC_TARGET (fndecl)
3167+ : NULL_TREE);
3168+
3169+ if (fndecl && fndecl != nios2_previous_fndecl)
3170+ {
3171+ nios2_previous_fndecl = fndecl;
3172+ if (old_tree == new_tree)
3173+ ;
3174+
3175+ else if (new_tree)
3176+ {
3177+ cl_target_option_restore (&global_options,
3178+ TREE_TARGET_OPTION (new_tree));
3179+ target_reinit ();
3180+ }
3181+
3182+ else if (old_tree)
3183+ {
3184+ struct cl_target_option *def
3185+ = TREE_TARGET_OPTION (target_option_current_node);
3186+
3187+ cl_target_option_restore (&global_options, def);
3188+ target_reinit ();
3189+ }
3190+ }
3191+}
3192+
3193+/* Hook to validate the current #pragma GCC target and set the FPU custom
3194+ code option state. If ARGS is NULL, then POP_TARGET is used to reset
3195+ the options. */
3196+
3197+static bool
3198+nios2_pragma_target_parse (tree args, tree pop_target)
3199+{
3200+ tree cur_tree;
3201+ if (! args)
3202+ {
3203+ cur_tree = ((pop_target)
3204+ ? pop_target
3205+ : target_option_default_node);
3206+ cl_target_option_restore (&global_options,
3207+ TREE_TARGET_OPTION (cur_tree));
3208+ }
3209+ else
3210+ {
3211+ cur_tree = nios2_valid_target_attribute_tree (args);
3212+ if (!cur_tree)
3213+ return false;
3214+ }
3215+
3216+ target_option_current_node = cur_tree;
3217+ return true;
3218+}
3219+
3220+/* Implement TARGET_MERGE_DECL_ATTRIBUTES.
3221+ We are just using this hook to add some additional error checking to
3222+ the default behavior. GCC does not provide a target hook for merging
3223+ the target options, and only correctly handles merging empty vs non-empty
3224+ option data; see merge_decls() in c-decl.c.
3225+ So here we require either that at least one of the decls has empty
3226+ target options, or that the target options/data be identical. */
3227+static tree
3228+nios2_merge_decl_attributes (tree olddecl, tree newdecl)
3229+{
3230+ tree oldopts = lookup_attribute ("target", DECL_ATTRIBUTES (olddecl));
3231+ tree newopts = lookup_attribute ("target", DECL_ATTRIBUTES (newdecl));
3232+ if (newopts && oldopts && newopts != oldopts)
3233+ {
3234+ tree oldtree = DECL_FUNCTION_SPECIFIC_TARGET (olddecl);
3235+ tree newtree = DECL_FUNCTION_SPECIFIC_TARGET (newdecl);
3236+ if (oldtree && newtree && oldtree != newtree)
3237+ {
3238+ struct cl_target_option *olddata = TREE_TARGET_OPTION (oldtree);
3239+ struct cl_target_option *newdata = TREE_TARGET_OPTION (newtree);
3240+ if (olddata != newdata
3241+ && memcmp (olddata, newdata, sizeof (struct cl_target_option)))
3242+ error ("%qE redeclared with conflicting %qs attributes",
3243+ DECL_NAME (newdecl), "target");
3244+ }
3245+ }
3246+ return merge_attributes (DECL_ATTRIBUTES (olddecl),
3247+ DECL_ATTRIBUTES (newdecl));
3248+}
3249+
3250+#include "gt-nios2.h"
--- /dev/null
+++ b/gcc/config/nios2/nios2.h
@@ -0,0 +1,705 @@
1+/* Definitions of target machine for Altera Nios II.
2+ Copyright (C) 2012 Free Software Foundation, Inc.
3+ Contributed by Jonah Graham (jgraham@altera.com),
4+ Will Reece (wreece@altera.com), and Jeff DaSilva (jdasilva@altera.com).
5+ Contributed by Mentor Graphics, Inc.
6+
7+ This file is part of GCC.
8+
9+ GCC is free software; you can redistribute it and/or modify it
10+ under the terms of the GNU General Public License as published
11+ by the Free Software Foundation; either version 3, or (at your
12+ option) any later version.
13+
14+ GCC is distributed in the hope that it will be useful, but WITHOUT
15+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17+ License for more details.
18+
19+ You should have received a copy of the GNU General Public License
20+ along with GCC; see the file COPYING3. If not see
21+ <http://www.gnu.org/licenses/>. */
22+
23+#ifndef GCC_NIOS2_H
24+#define GCC_NIOS2_H
25+
26+/* FPU insn codes declared here. */
27+#include "config/nios2/nios2-opts.h"
28+
29+/* Define built-in preprocessor macros. */
30+#define TARGET_CPU_CPP_BUILTINS() \
31+ do \
32+ { \
33+ builtin_define_std ("NIOS2"); \
34+ builtin_define_std ("nios2"); \
35+ if (TARGET_BIG_ENDIAN) \
36+ builtin_define_std ("nios2_big_endian"); \
37+ else \
38+ builtin_define_std ("nios2_little_endian"); \
39+ } \
40+ while (0)
41+
42+/* We're little endian, unless otherwise specified by defining
43+ BIG_ENDIAN_FLAG. */
44+#ifndef TARGET_ENDIAN_DEFAULT
45+# define TARGET_ENDIAN_DEFAULT 0
46+#endif
47+
48+/* Default target_flags if no switches specified. */
49+#ifndef TARGET_DEFAULT
50+# define TARGET_DEFAULT (MASK_HAS_MUL | TARGET_ENDIAN_DEFAULT)
51+#endif
52+
53+#define CC1_SPEC "%{G*}"
54+
55+#if TARGET_ENDIAN_DEFAULT == 0
56+# define ASM_SPEC "%{!meb:-EL} %{meb:-EB}"
57+# define LINK_SPEC_ENDIAN "%{!meb:-EL} %{meb:-EB}"
58+# define MULTILIB_DEFAULTS { "EL" }
59+#else
60+# define ASM_SPEC "%{!mel:-EB} %{mel:-EL}"
61+# define LINK_SPEC_ENDIAN "%{!mel:-EB} %{mel:-EL}"
62+# define MULTILIB_DEFAULTS { "EB" }
63+#endif
64+
65+#define LINK_SPEC LINK_SPEC_ENDIAN \
66+ " %{shared:-shared} \
67+ %{static:-Bstatic}"
68+
69+
70+/* Storage Layout. */
71+
72+#define DEFAULT_SIGNED_CHAR 1
73+#define BITS_BIG_ENDIAN 0
74+#define BYTES_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0)
75+#define WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0)
76+#define BITS_PER_UNIT 8
77+#define BITS_PER_WORD 32
78+#define UNITS_PER_WORD 4
79+#define POINTER_SIZE 32
80+#define BIGGEST_ALIGNMENT 32
81+#define STRICT_ALIGNMENT 1
82+#define FUNCTION_BOUNDARY 32
83+#define PARM_BOUNDARY 32
84+#define STACK_BOUNDARY 32
85+#define PREFERRED_STACK_BOUNDARY 32
86+#define MAX_FIXED_MODE_SIZE 64
87+
88+#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
89+ ((TREE_CODE (EXP) == STRING_CST) \
90+ && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
91+
92+
93+/* Layout of Source Language Data Types. */
94+
95+#define INT_TYPE_SIZE 32
96+#define SHORT_TYPE_SIZE 16
97+#define LONG_TYPE_SIZE 32
98+#define LONG_LONG_TYPE_SIZE 64
99+#define FLOAT_TYPE_SIZE 32
100+#define DOUBLE_TYPE_SIZE 64
101+#define LONG_DOUBLE_TYPE_SIZE DOUBLE_TYPE_SIZE
102+
103+#undef SIZE_TYPE
104+#define SIZE_TYPE "unsigned int"
105+
106+#undef PTRDIFF_TYPE
107+#define PTRDIFF_TYPE "int"
108+
109+
110+/* Basic Characteristics of Registers:
111+Register Number
112+ Register Name
113+ Alternate Name
114+ Purpose
115+0 r0 zero always zero
116+1 r1 at Assembler Temporary
117+2-3 r2-r3 Return Location
118+4-7 r4-r7 Register Arguments
119+8-15 r8-r15 Caller Saved Registers
120+16-22 r16-r22 Callee Saved Registers
121+22 r22 Global Offset Table pointer (Linux ABI only)
122+23 r23 Thread pointer (Linux ABI only)
123+24 r24 et Exception Temporary
124+25 r25 bt Breakpoint Temporary
125+26 r26 gp Global Pointer
126+27 r27 sp Stack Pointer
127+28 r28 fp Frame Pointer
128+29 r29 ea Exception Return Address
129+30 r30 ba Breakpoint Return Address
130+31 r31 ra Return Address
131+
132+32 ctl0 status
133+33 ctl1 estatus STATUS saved by exception ?
134+34 ctl2 bstatus STATUS saved by break ?
135+35 ctl3 ipri Interrupt Priority Mask ?
136+36 ctl4 ecause Exception Cause ?
137+
138+37 pc Not an actual register
139+
140+38 fake_fp Fake Frame Pointer which will always be eliminated.
141+39 fake_ap Fake Argument Pointer which will always be eliminated.
142+
143+40 First Pseudo Register
144+
145+In addition, r12 is used as the static chain register and r13, r14, and r15
146+are clobbered by PLT code sequences.
147+
148+The definitions for all the hard register numbers
149+are located in nios2.md.
150+*/
151+
152+#define ET_REGNO (24)
153+#define GP_REGNO (26)
154+#define SP_REGNO (27)
155+#define FP_REGNO (28)
156+#define EA_REGNO (29)
157+#define RA_REGNO (31)
158+#define FIRST_RETVAL_REGNO (2)
159+#define LAST_RETVAL_REGNO (3)
160+#define FIRST_ARG_REGNO (4)
161+#define LAST_ARG_REGNO (7)
162+#define SC_REGNO (12)
163+#define PC_REGNO (37)
164+#define FAKE_FP_REGNO (38)
165+#define FAKE_AP_REGNO (39)
166+
167+#define FIRST_PSEUDO_REGISTER 40
168+#define NUM_ARG_REGS (LAST_ARG_REGNO - FIRST_ARG_REGNO + 1)
169+
170+
171+
172+#define FIXED_REGISTERS \
173+ { \
174+/* +0 1 2 3 4 5 6 7 8 9 */ \
175+/* 0 */ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, \
176+/* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
177+/* 20 */ 0, 0, TARGET_LINUX_ABI, TARGET_LINUX_ABI, 1, 1, 1, 1, 0, 1, \
178+/* 30 */ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, \
179+ }
180+
181+/* call used is the same as caller saved
182+ + fixed regs + args + ret vals */
183+#define CALL_USED_REGISTERS \
184+ { \
185+/* +0 1 2 3 4 5 6 7 8 9 */ \
186+/* 0 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
187+/* 10 */ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, \
188+/* 20 */ 0, 0, TARGET_LINUX_ABI, TARGET_LINUX_ABI, 1, 1, 1, 1, 0, 1, \
189+/* 30 */ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, \
190+ }
191+
192+#define THREAD_POINTER_REGNUM 23
193+
194+#define HARD_REGNO_NREGS(REGNO, MODE) \
195+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \
196+ / UNITS_PER_WORD)
197+
198+#define HARD_REGNO_MODE_OK(REGNO, MODE) 1
199+#define MODES_TIEABLE_P(MODE1, MODE2) 1
200+
201+/* Register Classes. */
202+
203+enum reg_class
204+{
205+ NO_REGS,
206+ D00_REG,
207+ D01_REG,
208+ D02_REG,
209+ D03_REG,
210+ D04_REG,
211+ D05_REG,
212+ D06_REG,
213+ D07_REG,
214+ D08_REG,
215+ D09_REG,
216+ D10_REG,
217+ D11_REG,
218+ D12_REG,
219+ D13_REG,
220+ D14_REG,
221+ D15_REG,
222+ D16_REG,
223+ D17_REG,
224+ D18_REG,
225+ D19_REG,
226+ D20_REG,
227+ D21_REG,
228+ D22_REG,
229+ D23_REG,
230+ D24_REG,
231+ D25_REG,
232+ D26_REG,
233+ D27_REG,
234+ D28_REG,
235+ D29_REG,
236+ D30_REG,
237+ D31_REG,
238+ SIB_REGS,
239+ GP_REGS,
240+ ALL_REGS,
241+ LIM_REG_CLASSES
242+};
243+
244+#define N_REG_CLASSES (int) LIM_REG_CLASSES
245+
246+#define REG_CLASS_NAMES \
247+ { "NO_REGS", \
248+ "D00_REG", \
249+ "D01_REG", \
250+ "D02_REG", \
251+ "D03_REG", \
252+ "D04_REG", \
253+ "D05_REG", \
254+ "D06_REG", \
255+ "D07_REG", \
256+ "D08_REG", \
257+ "D09_REG", \
258+ "D10_REG", \
259+ "D11_REG", \
260+ "D12_REG", \
261+ "D13_REG", \
262+ "D14_REG", \
263+ "D15_REG", \
264+ "D16_REG", \
265+ "D17_REG", \
266+ "D18_REG", \
267+ "D19_REG", \
268+ "D20_REG", \
269+ "D21_REG", \
270+ "D22_REG", \
271+ "D23_REG", \
272+ "D24_REG", \
273+ "D25_REG", \
274+ "D26_REG", \
275+ "D27_REG", \
276+ "D28_REG", \
277+ "D29_REG", \
278+ "D30_REG", \
279+ "D31_REG", \
280+ "SIB_REGS", \
281+ "GP_REGS", \
282+ "ALL_REGS" }
283+
284+#define GENERAL_REGS ALL_REGS
285+
286+#define REG_CLASS_CONTENTS \
287+/* NO_REGS */ {{ 0, 0}, \
288+/* D00_REG */ { 1 << 0, 0}, \
289+/* D01_REG */ { 1 << 1, 0}, \
290+/* D02_REG */ { 1 << 2, 0}, \
291+/* D03_REG */ { 1 << 3, 0}, \
292+/* D04_REG */ { 1 << 4, 0}, \
293+/* D05_REG */ { 1 << 5, 0}, \
294+/* D06_REG */ { 1 << 6, 0}, \
295+/* D07_REG */ { 1 << 7, 0}, \
296+/* D08_REG */ { 1 << 8, 0}, \
297+/* D09_REG */ { 1 << 9, 0}, \
298+/* D10_REG */ { 1 << 10, 0}, \
299+/* D11_REG */ { 1 << 11, 0}, \
300+/* D12_REG */ { 1 << 12, 0}, \
301+/* D13_REG */ { 1 << 13, 0}, \
302+/* D14_REG */ { 1 << 14, 0}, \
303+/* D15_REG */ { 1 << 15, 0}, \
304+/* D16_REG */ { 1 << 16, 0}, \
305+/* D17_REG */ { 1 << 17, 0}, \
306+/* D18_REG */ { 1 << 18, 0}, \
307+/* D19_REG */ { 1 << 19, 0}, \
308+/* D20_REG */ { 1 << 20, 0}, \
309+/* D21_REG */ { 1 << 21, 0}, \
310+/* D22_REG */ { 1 << 22, 0}, \
311+/* D23_REG */ { 1 << 23, 0}, \
312+/* D24_REG */ { 1 << 24, 0}, \
313+/* D25_REG */ { 1 << 25, 0}, \
314+/* D26_REG */ { 1 << 26, 0}, \
315+/* D27_REG */ { 1 << 27, 0}, \
316+/* D28_REG */ { 1 << 28, 0}, \
317+/* D29_REG */ { 1 << 29, 0}, \
318+/* D30_REG */ { 1 << 30, 0}, \
319+/* D31_REG */ { 1 << 31, 0}, \
320+/* SIB_REGS */ { 0xfe0c, 0}, \
321+/* GP_REGS */ {~0, 0}, \
322+/* ALL_REGS */ {~0,~0}} \
323+
324+#define GP_REGNO_P(REGNO) ((REGNO) < 32)
325+#define REGNO_REG_CLASS(REGNO) (GP_REGNO_P (REGNO) ? GP_REGS : ALL_REGS)
326+
327+#define BASE_REG_CLASS ALL_REGS
328+#define INDEX_REG_CLASS ALL_REGS
329+
330+#define REGNO_OK_FOR_BASE_P2(REGNO, STRICT) \
331+ ((STRICT) \
332+ ? (REGNO) < FIRST_PSEUDO_REGISTER \
333+ : ((REGNO) < FIRST_PSEUDO_REGISTER \
334+ || (reg_renumber && reg_renumber[REGNO] < FIRST_PSEUDO_REGISTER)))
335+
336+#define REGNO_OK_FOR_INDEX_P2(REGNO, STRICT) \
337+ (REGNO_OK_FOR_BASE_P2 (REGNO, STRICT))
338+
339+#define REGNO_OK_FOR_BASE_P(REGNO) \
340+ (REGNO_OK_FOR_BASE_P2 (REGNO, 1))
341+
342+#define REGNO_OK_FOR_INDEX_P(REGNO) \
343+ (REGNO_OK_FOR_INDEX_P2 (REGNO, 1))
344+
345+#define REG_OK_FOR_BASE_P2(X, STRICT) \
346+ (STRICT \
347+ ? REGNO_OK_FOR_BASE_P2 (REGNO (X), 1) \
348+ : (REGNO_OK_FOR_BASE_P2 (REGNO (X), 1) \
349+ || REGNO(X) >= FIRST_PSEUDO_REGISTER))
350+
351+#define REG_OK_FOR_INDEX_P2(X, STRICT) \
352+ (STRICT \
353+ ? REGNO_OK_FOR_INDEX_P2 (REGNO (X), 1) \
354+ : (REGNO_OK_FOR_INDEX_P2 (REGNO (X), 1) \
355+ || REGNO(X) >= FIRST_PSEUDO_REGISTER))
356+
357+#define CLASS_MAX_NREGS(CLASS, MODE) \
358+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \
359+ / UNITS_PER_WORD)
360+
361+#define SMALL_INT(X) ((X) >= -0x8000 && (X) < 0x8000)
362+#define SMALL_INT_UNSIGNED(X) ((X) >= 0 && (X) < 0x10000)
363+#define UPPER16_INT(X) (((X) & 0xffff) == 0)
364+#define SHIFT_INT(X) ((X) >= 0 && (X) <= 31)
365+#define RDWRCTL_INT(X) ((X) >= 0 && (X) <= 31)
366+#define CUSTOM_INSN_OPCODE(X) ((X) >= 0 && (X) <= 255)
367+
368+/* Say that the epilogue uses the return address register. Note that
369+ in the case of sibcalls, the values "used by the epilogue" are
370+ considered live at the start of the called function. */
371+#define EPILOGUE_USES(REGNO) ((REGNO) == RA_REGNO)
372+
373+/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
374+ the stack pointer does not matter. The value is tested only in
375+ functions that have frame pointers.
376+ No definition is equivalent to always zero. */
377+
378+#define EXIT_IGNORE_STACK 1
379+
380+/* Trampolines use a 5-instruction sequence. */
381+#define TRAMPOLINE_SIZE 20
382+
383+
384+/* Stack Layout and Calling Conventions. */
385+
386+/* The downward variants are used by the compiler,
387+ the upward ones serve as documentation. */
388+#define STACK_GROWS_DOWNWARD
389+#define FRAME_GROWS_UPWARD
390+#define ARGS_GROW_UPWARD
391+
392+#define STARTING_FRAME_OFFSET 0
393+#define FIRST_PARM_OFFSET(FUNDECL) 0
394+
395+/* Before the prologue, RA lives in r31. */
396+#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (VOIDmode, RA_REGNO)
397+#define RETURN_ADDR_RTX(C,F) nios2_get_return_address (C)
398+
399+/* Registers That Address the Stack Frame. */
400+#define STACK_POINTER_REGNUM SP_REGNO
401+#define STATIC_CHAIN_REGNUM SC_REGNO
402+#define PC_REGNUM PC_REGNO
403+#define DWARF_FRAME_RETURN_COLUMN RA_REGNO
404+
405+/* Base register for access to local variables of the function. We
406+ pretend that the frame pointer is a non-existent hard register, and
407+ then eliminate it to HARD_FRAME_POINTER_REGNUM. */
408+#define FRAME_POINTER_REGNUM FAKE_FP_REGNO
409+
410+#define HARD_FRAME_POINTER_REGNUM FP_REGNO
411+
412+/* The argument pointer needs to always be eliminated
413+ so it is set to a fake hard register. */
414+#define ARG_POINTER_REGNUM FAKE_AP_REGNO
415+
416+/* The CFA includes the pretend args. */
417+#define ARG_POINTER_CFA_OFFSET(FNDECL) \
418+ (gcc_assert ((FNDECL) == current_function_decl), \
419+ FIRST_PARM_OFFSET (FNDECL) + crtl->args.pretend_args_size)
420+
421+/* Frame/arg pointer elimination settings. */
422+#define ELIMINABLE_REGS \
423+{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
424+ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
425+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
426+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
427+
428+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
429+ (OFFSET) = nios2_initial_elimination_offset ((FROM), (TO))
430+
431+/* Treat LOC as a byte offset from the stack pointer and round it up
432+ to the next fully-aligned offset. */
433+#define STACK_ALIGN(LOC) \
434+ (((LOC) + ((PREFERRED_STACK_BOUNDARY / 8) - 1)) \
435+ & ~((PREFERRED_STACK_BOUNDARY / 8) - 1))
436+
437+/* Calling convention definitions. */
438+typedef struct nios2_args
439+{
440+ int regs_used;
441+} CUMULATIVE_ARGS;
442+
443+/* This is to initialize the above unused CUM data type. */
444+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
445+ (nios2_init_cumulative_args (&CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS))
446+
447+#define FUNCTION_ARG_PADDING(MODE, TYPE) \
448+ (nios2_function_arg_padding ((MODE), (TYPE)))
449+
450+#define PAD_VARARGS_DOWN \
451+ (FUNCTION_ARG_PADDING (TYPE_MODE (type), type) == downward)
452+
453+#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
454+ (nios2_block_reg_padding ((MODE), (TYPE), (FIRST)))
455+
456+#define FUNCTION_ARG_REGNO_P(REGNO) \
457+ ((REGNO) >= FIRST_ARG_REGNO && (REGNO) <= LAST_ARG_REGNO)
458+
459+/* Passing Function Arguments on the Stack. */
460+#define PUSH_ARGS 0
461+#define ACCUMULATE_OUTGOING_ARGS 1
462+
463+/* We define TARGET_RETURN_IN_MEMORY, so set to zero. */
464+#define DEFAULT_PCC_STRUCT_RETURN 0
465+
466+/* Profiling. */
467+#define PROFILE_BEFORE_PROLOGUE
468+#define NO_PROFILE_COUNTERS 1
469+#define FUNCTION_PROFILER(FILE, LABELNO) \
470+ nios2_function_profiler ((FILE), (LABELNO))
471+
472+/* Addressing Modes. */
473+
474+#define CONSTANT_ADDRESS_P(X) \
475+ (CONSTANT_P (X) && memory_address_p (SImode, X))
476+
477+#define MAX_REGS_PER_ADDRESS 1
478+
479+#ifndef REG_OK_STRICT
480+#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P2 (REGNO (X), 0)
481+#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P2 (REGNO (X), 0)
482+#else
483+#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P2 (REGNO (X), 1)
484+#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P2 (REGNO (X), 1)
485+#endif
486+
487+/* Set if this has a weak declaration. */
488+#define SYMBOL_FLAG_WEAK_DECL (1 << SYMBOL_FLAG_MACH_DEP_SHIFT)
489+#define SYMBOL_REF_WEAK_DECL_P(RTX) \
490+ ((SYMBOL_REF_FLAGS (RTX) & SYMBOL_FLAG_WEAK_DECL) != 0)
491+
492+
493+/* True if a symbol is both small and not weak. In this case, GP-relative
494+ access can be used. GP-relative access cannot be used in
495+ position-independent code. GP-relative access cannot be used for externally
496+ defined symbols, because the compilation unit that defines the symbol may
497+ place it in a section that cannot be reached from GP. */
498+#define SYMBOL_REF_IN_NIOS2_SMALL_DATA_P(RTX) \
499+ (!flag_pic && SYMBOL_REF_SMALL_P (RTX) \
500+ && !SYMBOL_REF_WEAK_DECL_P (RTX) \
501+ && !SYMBOL_REF_EXTERNAL_P (RTX) \
502+ && SYMBOL_REF_TLS_MODEL (RTX) == 0)
503+
504+/* Describing Relative Costs of Operations. */
505+#define MOVE_MAX 4
506+#define SLOW_BYTE_ACCESS 1
507+
508+/* It is as good to call a constant function address as to call an address
509+ kept in a register.
510+ ??? Not true anymore really. Now that call cannot address full range
511+ of memory callr may need to be used */
512+
513+#define NO_FUNCTION_CSE
514+
515+/* Position Independent Code. */
516+
517+#define PIC_OFFSET_TABLE_REGNUM 22
518+#define LEGITIMATE_PIC_OPERAND_P(X) nios2_legitimate_pic_operand_p (X)
519+
520+/* Define output assembler language. */
521+
522+#define ASM_APP_ON "#APP\n"
523+#define ASM_APP_OFF "#NO_APP\n"
524+
525+#define ASM_COMMENT_START "# "
526+
527+#define GLOBAL_ASM_OP "\t.global\t"
528+
529+#define REGISTER_NAMES \
530+ { \
531+ "zero", \
532+ "at", \
533+ "r2", \
534+ "r3", \
535+ "r4", \
536+ "r5", \
537+ "r6", \
538+ "r7", \
539+ "r8", \
540+ "r9", \
541+ "r10", \
542+ "r11", \
543+ "r12", \
544+ "r13", \
545+ "r14", \
546+ "r15", \
547+ "r16", \
548+ "r17", \
549+ "r18", \
550+ "r19", \
551+ "r20", \
552+ "r21", \
553+ "r22", \
554+ "r23", \
555+ "et", \
556+ "bt", \
557+ "gp", \
558+ "sp", \
559+ "fp", \
560+ "ta", \
561+ "ba", \
562+ "ra", \
563+ "status", \
564+ "estatus", \
565+ "bstatus", \
566+ "ipri", \
567+ "ecause", \
568+ "pc", \
569+ "fake_fp", \
570+ "fake_ap", \
571+}
572+
573+#define ADDITIONAL_REGISTER_NAMES \
574+{ \
575+ {"r0", 0}, \
576+ {"r1", 1}, \
577+ {"r24", 24}, \
578+ {"r25", 25}, \
579+ {"r26", 26}, \
580+ {"r27", 27}, \
581+ {"r28", 28}, \
582+ {"r29", 29}, \
583+ {"r30", 30}, \
584+ {"r31", 31} \
585+}
586+
587+
588+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
589+ do \
590+ { \
591+ fputs (integer_asm_op (POINTER_SIZE / BITS_PER_UNIT, TRUE), FILE); \
592+ fprintf (FILE, ".L%u\n", (unsigned) (VALUE)); \
593+ } \
594+ while (0)
595+
596+#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL)\
597+ do \
598+ { \
599+ fputs (integer_asm_op (POINTER_SIZE / BITS_PER_UNIT, TRUE), STREAM); \
600+ fprintf (STREAM, ".L%u-.L%u\n", (unsigned) (VALUE), (unsigned) (REL)); \
601+ } \
602+ while (0)
603+
604+
605+/* Section directives. */
606+
607+/* Output before read-only data. */
608+#define TEXT_SECTION_ASM_OP "\t.section\t.text"
609+
610+/* Output before writable data. */
611+#define DATA_SECTION_ASM_OP "\t.section\t.data"
612+
613+/* Output before uninitialized data. */
614+#define BSS_SECTION_ASM_OP "\t.section\t.bss"
615+
616+/* Output before 'small' uninitialized data. */
617+#define SBSS_SECTION_ASM_OP "\t.section\t.sbss"
618+
619+#ifndef IN_LIBGCC2
620+/* Default the definition of "small data" to 8 bytes. */
621+extern unsigned HOST_WIDE_INT nios2_section_threshold;
622+#endif
623+
624+#define NIOS2_DEFAULT_GVALUE 8
625+
626+/* This says how to output assembler code to declare an
627+ uninitialized external linkage data object. Under SVR4,
628+ the linker seems to want the alignment of data objects
629+ to depend on their types. We do exactly that here. */
630+#undef COMMON_ASM_OP
631+#define COMMON_ASM_OP "\t.comm\t"
632+
633+#define ASM_OUTPUT_ALIGN(FILE, LOG) \
634+ do { \
635+ fprintf ((FILE), "%s%d\n", ALIGN_ASM_OP, (LOG)); \
636+ } while (0)
637+
638+#undef ASM_OUTPUT_ALIGNED_COMMON
639+#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \
640+do \
641+ { \
642+ fprintf ((FILE), "%s", COMMON_ASM_OP); \
643+ assemble_name ((FILE), (NAME)); \
644+ fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED",%u\n", (SIZE), \
645+ (ALIGN) / BITS_PER_UNIT); \
646+ } \
647+while (0)
648+
649+
650+/* This says how to output assembler code to declare an
651+ uninitialized internal linkage data object. Under SVR4,
652+ the linker seems to want the alignment of data objects
653+ to depend on their types. We do exactly that here. */
654+
655+#undef ASM_OUTPUT_ALIGNED_LOCAL
656+#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
657+do { \
658+ if ((SIZE) <= nios2_section_threshold) \
659+ switch_to_section (sbss_section); \
660+ else \
661+ switch_to_section (bss_section); \
662+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
663+ if (!flag_inhibit_size_directive) \
664+ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, SIZE); \
665+ ASM_OUTPUT_ALIGN ((FILE), exact_log2((ALIGN) / BITS_PER_UNIT)); \
666+ ASM_OUTPUT_LABEL(FILE, NAME); \
667+ ASM_OUTPUT_SKIP((FILE), (SIZE) ? (SIZE) : 1); \
668+} while (0)
669+
670+/* Put the jump tables in .text because when using position-independent code,
671+ Nios II elf has no relocation that can represent arbitrary differences
672+ between symbols in different sections. */
673+#define JUMP_TABLES_IN_TEXT_SECTION 1
674+
675+/* Exception Handling */
676+
677+/* Describe __builtin_eh_return. */
678+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, LAST_RETVAL_REGNO)
679+#define EH_RETURN_DATA_REGNO(N) ((N) <= (LAST_ARG_REGNO - FIRST_ARG_REGNO) \
680+ ? (N) + FIRST_ARG_REGNO : INVALID_REGNUM)
681+
682+/* Nios II has no appropriate relocations for a 32-bit PC-relative or
683+ section-relative pointer encoding. This therefore always chooses an
684+ absolute representation for pointers. An unfortunate consequence of
685+ this is that ld complains about the absolute fde encoding when linking
686+ with -shared or -fpie, but the warning is harmless and there seems to
687+ be no good way to suppress it. */
688+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) \
689+ (flag_pic ? DW_EH_PE_aligned : DW_EH_PE_sdata4)
690+
691+/* Misc. Parameters. */
692+
693+#define STORE_FLAG_VALUE 1
694+#define Pmode SImode
695+#define FUNCTION_MODE QImode
696+
697+#define CASE_VECTOR_MODE Pmode
698+
699+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
700+
701+#define LOAD_EXTEND_OP(MODE) (ZERO_EXTEND)
702+
703+#define WORD_REGISTER_OPERATIONS
704+
705+#endif /* GCC_NIOS2_H */
--- /dev/null
+++ b/gcc/config/nios2/nios2.md
@@ -0,0 +1,1072 @@
1+;; Machine Description for Altera Nios II.
2+;; Copyright (C) 2012 Free Software Foundation, Inc.
3+;; Contributed by Jonah Graham (jgraham@altera.com) and
4+;; Will Reece (wreece@altera.com).
5+;; Contributed by Mentor Graphics, Inc.
6+;;
7+;; This file is part of GCC.
8+;;
9+;; GCC is free software; you can redistribute it and/or modify
10+;; it under the terms of the GNU General Public License as published by
11+;; the Free Software Foundation; either version 3, or (at your option)
12+;; any later version.
13+;;
14+;; GCC is distributed in the hope that it will be useful,
15+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+;; GNU General Public License for more details.
18+;;
19+;; You should have received a copy of the GNU General Public License
20+;; along with GCC; see the file COPYING3. If not see
21+;; <http://www.gnu.org/licenses/>.
22+
23+
24+;; Enumeration of UNSPECs
25+
26+(define_c_enum "unspecv" [
27+ UNSPECV_BLOCKAGE
28+ UNSPECV_WRCTL
29+ UNSPECV_RDCTL
30+ UNSPECV_TRAP
31+ UNSPECV_STACK_OVERFLOW_DETECT_AND_TRAP
32+ UNSPECV_FWRX
33+ UNSPECV_FWRY
34+ UNSPECV_FRDXLO
35+ UNSPECV_FRDXHI
36+ UNSPECV_FRDY
37+ UNSPECV_CUSTOM_NXX
38+ UNSPECV_CUSTOM_XNXX
39+ UNSPECV_LDXIO
40+ UNSPECV_STXIO
41+])
42+
43+(define_c_enum "unspec" [
44+ UNSPEC_FCOS
45+ UNSPEC_FSIN
46+ UNSPEC_FTAN
47+ UNSPEC_FATAN
48+ UNSPEC_FEXP
49+ UNSPEC_FLOG
50+ UNSPEC_LOAD_GOT_REGISTER
51+ UNSPEC_PIC_SYM
52+ UNSPEC_PIC_CALL_SYM
53+ UNSPEC_TLS
54+ UNSPEC_TLS_LDM
55+ UNSPEC_LOAD_TLS_IE
56+ UNSPEC_ADD_TLS_LE
57+ UNSPEC_ADD_TLS_GD
58+ UNSPEC_ADD_TLS_LDM
59+ UNSPEC_ADD_TLS_LDO
60+ UNSPEC_EH_RETURN
61+ UNSPEC_SYNC
62+])
63+
64+
65+;; Instruction scheduler
66+
67+; No schedule info is currently available, using an assumption that no
68+; instruction can use the results of the previous instruction without
69+; incuring a stall.
70+
71+; length of an instruction (in bytes)
72+(define_attr "length" "" (const_int 4))
73+(define_attr "type"
74+ "unknown,complex,control,alu,cond_alu,st,ld,shift,mul,div,custom"
75+ (const_string "complex"))
76+
77+(define_asm_attributes
78+ [(set_attr "length" "4")
79+ (set_attr "type" "complex")])
80+
81+(define_automaton "nios2")
82+(automata_option "v")
83+;(automata_option "no-minimization")
84+(automata_option "ndfa")
85+
86+; The nios2 pipeline is fairly straightforward for the fast model.
87+; Every alu operation is pipelined so that an instruction can
88+; be issued every cycle. However, there are still potential
89+; stalls which this description tries to deal with.
90+
91+(define_cpu_unit "cpu" "nios2")
92+
93+(define_insn_reservation "complex" 1
94+ (eq_attr "type" "complex")
95+ "cpu")
96+
97+(define_insn_reservation "control" 1
98+ (eq_attr "type" "control")
99+ "cpu")
100+
101+(define_insn_reservation "alu" 1
102+ (eq_attr "type" "alu")
103+ "cpu")
104+
105+(define_insn_reservation "cond_alu" 1
106+ (eq_attr "type" "cond_alu")
107+ "cpu")
108+
109+(define_insn_reservation "st" 1
110+ (eq_attr "type" "st")
111+ "cpu")
112+
113+(define_insn_reservation "custom" 1
114+ (eq_attr "type" "custom")
115+ "cpu")
116+
117+; shifts, muls and lds have three cycle latency
118+(define_insn_reservation "ld" 3
119+ (eq_attr "type" "ld")
120+ "cpu")
121+
122+(define_insn_reservation "shift" 3
123+ (eq_attr "type" "shift")
124+ "cpu")
125+
126+(define_insn_reservation "mul" 3
127+ (eq_attr "type" "mul")
128+ "cpu")
129+
130+(define_insn_reservation "div" 1
131+ (eq_attr "type" "div")
132+ "cpu")
133+
134+(include "predicates.md")
135+(include "constraints.md")
136+
137+
138+;; Move instructions
139+
140+(define_mode_iterator M [QI HI SI])
141+
142+(define_expand "mov<mode>"
143+ [(set (match_operand:M 0 "nonimmediate_operand" "")
144+ (match_operand:M 1 "general_operand" ""))]
145+ ""
146+{
147+ if (nios2_emit_move_sequence (operands, <MODE>mode))
148+ DONE;
149+})
150+
151+(define_insn "movqi_internal"
152+ [(set (match_operand:QI 0 "nonimmediate_operand" "=m, r,r, r")
153+ (match_operand:QI 1 "general_operand" "rM,m,rM,I"))]
154+ "(register_operand (operands[0], QImode)
155+ || reg_or_0_operand (operands[1], QImode))"
156+ "@
157+ stb%o0\\t%z1, %0
158+ ldbu%o1\\t%0, %1
159+ mov\\t%0, %z1
160+ movi\\t%0, %1"
161+ [(set_attr "type" "st,ld,alu,alu")])
162+
163+(define_insn "movhi_internal"
164+ [(set (match_operand:HI 0 "nonimmediate_operand" "=m, r,r, r,r")
165+ (match_operand:HI 1 "general_operand" "rM,m,rM,I,J"))]
166+ "(register_operand (operands[0], HImode)
167+ || reg_or_0_operand (operands[1], HImode))"
168+ "@
169+ sth%o0\\t%z1, %0
170+ ldhu%o1\\t%0, %1
171+ mov\\t%0, %z1
172+ movi\\t%0, %1
173+ movui\\t%0, %1"
174+ [(set_attr "type" "st,ld,alu,alu,alu")])
175+
176+(define_insn "movsi_internal"
177+ [(set (match_operand:SI 0 "nonimmediate_operand" "=m, r,r, r,r,r,r,r")
178+ (match_operand:SI 1 "general_operand" "rM,m,rM,I,J,K,S,i"))]
179+ "(register_operand (operands[0], SImode)
180+ || reg_or_0_operand (operands[1], SImode))"
181+ "@
182+ stw%o0\\t%z1, %0
183+ ldw%o1\\t%0, %1
184+ mov\\t%0, %z1
185+ movi\\t%0, %1
186+ movui\\t%0, %1
187+ movhi\\t%0, %H1
188+ addi\\t%0, gp, %%gprel(%1)
189+ movhi\\t%0, %H1\;addi\\t%0, %0, %L1"
190+ [(set_attr "type" "st,ld,alu,alu,alu,alu,alu,alu")
191+ (set_attr "length" "4,4,4,4,4,4,4,8")])
192+
193+
194+(define_mode_iterator BH [QI HI])
195+(define_mode_iterator BHW [QI HI SI])
196+(define_mode_attr bh [(QI "b") (HI "h")])
197+(define_mode_attr bhw [(QI "b") (HI "h") (SI "w")])
198+(define_mode_attr bhw_uns [(QI "bu") (HI "hu") (SI "w")])
199+
200+(define_insn "ld<bhw_uns>io"
201+ [(set (match_operand:BHW 0 "register_operand" "=r")
202+ (unspec_volatile:BHW
203+ [(match_operand:BHW 1 "memory_operand" "m")] UNSPECV_LDXIO))]
204+ ""
205+ "ld<bhw_uns>io\\t%0, %1"
206+ [(set_attr "type" "ld")])
207+
208+(define_expand "ld<bh>io"
209+ [(set (match_operand:BH 0 "register_operand" "=r")
210+ (match_operand:BH 1 "memory_operand" "m"))]
211+ ""
212+{
213+ rtx tmp = gen_reg_rtx (SImode);
214+ emit_insn (gen_ld<bh>io_signed (tmp, operands[1]));
215+ emit_insn (gen_mov<mode> (operands[0], gen_lowpart (<MODE>mode, tmp)));
216+ DONE;
217+})
218+
219+(define_insn "ld<bh>io_signed"
220+ [(set (match_operand:SI 0 "register_operand" "=r")
221+ (sign_extend:SI
222+ (unspec_volatile:BH
223+ [(match_operand:BH 1 "memory_operand" "m")] UNSPECV_LDXIO)))]
224+ ""
225+ "ld<bh>io\\t%0, %1"
226+ [(set_attr "type" "ld")])
227+
228+(define_insn "st<bhw>io"
229+ [(set (match_operand:BHW 0 "memory_operand" "=m")
230+ (unspec_volatile:BHW
231+ [(match_operand:BHW 1 "reg_or_0_operand" "rM")] UNSPECV_STXIO))]
232+ ""
233+ "st<bhw>io\\t%z1, %0"
234+ [(set_attr "type" "st")])
235+
236+
237+;; QI to [HI, SI] extension patterns are collected together
238+(define_mode_iterator QX [HI SI])
239+
240+;; Zero extension patterns
241+(define_insn "zero_extendhisi2"
242+ [(set (match_operand:SI 0 "register_operand" "=r,r")
243+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
244+ ""
245+ "@
246+ andi\\t%0, %1, 0xffff
247+ ldhu%o1\\t%0, %1"
248+ [(set_attr "type" "alu,ld")])
249+
250+(define_insn "zero_extendqi<mode>2"
251+ [(set (match_operand:QX 0 "register_operand" "=r,r")
252+ (zero_extend:QX (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
253+ ""
254+ "@
255+ andi\\t%0, %1, 0xff
256+ ldbu%o1\\t%0, %1"
257+ [(set_attr "type" "alu,ld")])
258+
259+;; Sign extension patterns
260+
261+(define_insn "extendhisi2"
262+ [(set (match_operand:SI 0 "register_operand" "=r,r")
263+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
264+ ""
265+ "@
266+ #
267+ ldh%o1\\t%0, %1"
268+ [(set_attr "type" "alu,ld")])
269+
270+(define_insn "extendqi<mode>2"
271+ [(set (match_operand:QX 0 "register_operand" "=r,r")
272+ (sign_extend:QX (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
273+ ""
274+ "@
275+ #
276+ ldb%o1\\t%0, %1"
277+ [(set_attr "type" "alu,ld")])
278+
279+;; Split patterns for register alternative cases.
280+(define_split
281+ [(set (match_operand:SI 0 "register_operand" "")
282+ (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
283+ "reload_completed"
284+ [(set (match_dup 0)
285+ (and:SI (match_dup 1) (const_int 65535)))
286+ (set (match_dup 0)
287+ (xor:SI (match_dup 0) (const_int 32768)))
288+ (set (match_dup 0)
289+ (plus:SI (match_dup 0) (const_int -32768)))]
290+ "operands[1] = gen_lowpart (SImode, operands[1]);")
291+
292+(define_split
293+ [(set (match_operand:QX 0 "register_operand" "")
294+ (sign_extend:QX (match_operand:QI 1 "register_operand" "")))]
295+ "reload_completed"
296+ [(set (match_dup 0)
297+ (and:SI (match_dup 1) (const_int 255)))
298+ (set (match_dup 0)
299+ (xor:SI (match_dup 0) (const_int 128)))
300+ (set (match_dup 0)
301+ (plus:SI (match_dup 0) (const_int -128)))]
302+ "operands[0] = gen_lowpart (SImode, operands[0]);
303+ operands[1] = gen_lowpart (SImode, operands[1]);")
304+
305+
306+;; Arithmetic Operations
307+
308+(define_insn "addsi3"
309+ [(set (match_operand:SI 0 "register_operand" "=r")
310+ (plus:SI (match_operand:SI 1 "register_operand" "%r")
311+ (match_operand:SI 2 "arith_operand" "rI")))]
312+ ""
313+ "add%i2\\t%0, %1, %z2"
314+ [(set_attr "type" "alu")])
315+
316+(define_insn "subsi3"
317+ [(set (match_operand:SI 0 "register_operand" "=r")
318+ (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
319+ (match_operand:SI 2 "register_operand" "r")))]
320+ ""
321+ "sub\\t%0, %z1, %2"
322+ [(set_attr "type" "alu")])
323+
324+(define_insn "mulsi3"
325+ [(set (match_operand:SI 0 "register_operand" "=r")
326+ (mult:SI (match_operand:SI 1 "register_operand" "%r")
327+ (match_operand:SI 2 "arith_operand" "rI")))]
328+ "TARGET_HAS_MUL"
329+ "mul%i2\\t%0, %1, %z2"
330+ [(set_attr "type" "mul")])
331+
332+(define_expand "divsi3"
333+ [(set (match_operand:SI 0 "register_operand" "=r")
334+ (div:SI (match_operand:SI 1 "register_operand" "r")
335+ (match_operand:SI 2 "register_operand" "r")))]
336+ ""
337+{
338+ if (!TARGET_HAS_DIV)
339+ {
340+ if (!TARGET_FAST_SW_DIV)
341+ FAIL;
342+ else
343+ {
344+ if (nios2_emit_expensive_div (operands, SImode))
345+ DONE;
346+ }
347+ }
348+})
349+
350+(define_insn "divsi3_insn"
351+ [(set (match_operand:SI 0 "register_operand" "=r")
352+ (div:SI (match_operand:SI 1 "register_operand" "r")
353+ (match_operand:SI 2 "register_operand" "r")))]
354+ "TARGET_HAS_DIV"
355+ "div\\t%0, %1, %2"
356+ [(set_attr "type" "div")])
357+
358+(define_insn "udivsi3"
359+ [(set (match_operand:SI 0 "register_operand" "=r")
360+ (udiv:SI (match_operand:SI 1 "register_operand" "r")
361+ (match_operand:SI 2 "register_operand" "r")))]
362+ "TARGET_HAS_DIV"
363+ "divu\\t%0, %1, %2"
364+ [(set_attr "type" "div")])
365+
366+(define_code_iterator EXTEND [sign_extend zero_extend])
367+(define_code_attr us [(sign_extend "s") (zero_extend "u")])
368+(define_code_attr mul [(sign_extend "mul") (zero_extend "umul")])
369+
370+(define_insn "<us>mulsi3_highpart"
371+ [(set (match_operand:SI 0 "register_operand" "=r")
372+ (truncate:SI
373+ (lshiftrt:DI
374+ (mult:DI (EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
375+ (EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
376+ (const_int 32))))]
377+ "TARGET_HAS_MULX"
378+ "mulx<us><us>\\t%0, %1, %2"
379+ [(set_attr "type" "mul")])
380+
381+(define_expand "<mul>sidi3"
382+ [(set (match_operand:DI 0 "register_operand" "")
383+ (mult:DI (EXTEND:DI (match_operand:SI 1 "register_operand" ""))
384+ (EXTEND:DI (match_operand:SI 2 "register_operand" ""))))]
385+ "TARGET_HAS_MULX"
386+{
387+ rtx hi = gen_reg_rtx (SImode);
388+ rtx lo = gen_reg_rtx (SImode);
389+
390+ emit_insn (gen_<us>mulsi3_highpart (hi, operands[1], operands[2]));
391+ emit_insn (gen_mulsi3 (lo, operands[1], operands[2]));
392+ emit_move_insn (gen_lowpart (SImode, operands[0]), lo);
393+ emit_move_insn (gen_highpart (SImode, operands[0]), hi);
394+ DONE;
395+})
396+
397+
398+;; Negate and ones complement
399+
400+(define_insn "negsi2"
401+ [(set (match_operand:SI 0 "register_operand" "=r")
402+ (neg:SI (match_operand:SI 1 "register_operand" "r")))]
403+ ""
404+ "sub\\t%0, zero, %1"
405+ [(set_attr "type" "alu")])
406+
407+(define_insn "one_cmplsi2"
408+ [(set (match_operand:SI 0 "register_operand" "=r")
409+ (not:SI (match_operand:SI 1 "register_operand" "r")))]
410+ ""
411+ "nor\\t%0, zero, %1"
412+ [(set_attr "type" "alu")])
413+
414+
415+;; Integer logical Operations
416+
417+(define_code_iterator LOGICAL [and ior xor])
418+(define_code_attr logical_asm [(and "and") (ior "or") (xor "xor")])
419+
420+(define_insn "<code>si3"
421+ [(set (match_operand:SI 0 "register_operand" "=r,r,r")
422+ (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r,r")
423+ (match_operand:SI 2 "logical_operand" "rM,J,K")))]
424+ ""
425+ "@
426+ <logical_asm>\\t%0, %1, %z2
427+ <logical_asm>%i2\\t%0, %1, %2
428+ <logical_asm>h%i2\\t%0, %1, %U2"
429+ [(set_attr "type" "alu")])
430+
431+(define_insn "*norsi3"
432+ [(set (match_operand:SI 0 "register_operand" "=r")
433+ (and:SI (not:SI (match_operand:SI 1 "register_operand" "%r"))
434+ (not:SI (match_operand:SI 2 "reg_or_0_operand" "rM"))))]
435+ ""
436+ "nor\\t%0, %1, %z2"
437+ [(set_attr "type" "alu")])
438+
439+
440+;; Shift instructions
441+
442+(define_code_iterator SHIFT [ashift ashiftrt lshiftrt rotate])
443+(define_code_attr shift_op [(ashift "ashl") (ashiftrt "ashr")
444+ (lshiftrt "lshr") (rotate "rotl")])
445+(define_code_attr shift_asm [(ashift "sll") (ashiftrt "sra")
446+ (lshiftrt "srl") (rotate "rol")])
447+
448+(define_insn "<shift_op>si3"
449+ [(set (match_operand:SI 0 "register_operand" "=r")
450+ (SHIFT:SI (match_operand:SI 1 "register_operand" "r")
451+ (match_operand:SI 2 "shift_operand" "rL")))]
452+ ""
453+ "<shift_asm>%i2\\t%0, %1, %z2"
454+ [(set_attr "type" "shift")])
455+
456+(define_insn "rotrsi3"
457+ [(set (match_operand:SI 0 "register_operand" "=r")
458+ (rotatert:SI (match_operand:SI 1 "register_operand" "r")
459+ (match_operand:SI 2 "register_operand" "r")))]
460+ ""
461+ "ror\\t%0, %1, %2"
462+ [(set_attr "type" "shift")])
463+
464+
465+
466+;; Floating point instructions
467+
468+;; Mode iterator for single/double float
469+(define_mode_iterator F [SF DF])
470+(define_mode_attr f [(SF "s") (DF "d")])
471+
472+;; Basic arithmetic instructions
473+(define_code_iterator FOP3 [plus minus mult div])
474+(define_code_attr fop3 [(plus "add") (minus "sub") (mult "mul") (div "div")])
475+
476+(define_insn "<fop3><mode>3"
477+ [(set (match_operand:F 0 "register_operand" "=r")
478+ (FOP3:F (match_operand:F 1 "register_operand" "r")
479+ (match_operand:F 2 "register_operand" "r")))]
480+ "nios2_fpu_insn_enabled (n2fpu_f<fop3><f>)"
481+ "* return nios2_fpu_insn_asm (n2fpu_f<fop3><f>);"
482+ [(set_attr "type" "custom")])
483+
484+;; Floating point min/max operations
485+(define_code_iterator SMINMAX [smin smax])
486+(define_code_attr minmax [(smin "min") (smax "max")])
487+(define_insn "<code><mode>3"
488+ [(set (match_operand:F 0 "register_operand" "=r")
489+ (SMINMAX:F (match_operand:F 1 "register_operand" "r")
490+ (match_operand:F 2 "register_operand" "r")))]
491+ "nios2_fpu_insn_enabled (n2fpu_f<minmax><f>)"
492+ "* return nios2_fpu_insn_asm (n2fpu_f<minmax><f>);"
493+ [(set_attr "type" "custom")])
494+
495+;; These 2-operand FP operations can be collected together
496+(define_code_iterator FOP2 [abs neg sqrt])
497+(define_insn "<code><mode>2"
498+ [(set (match_operand:F 0 "register_operand" "=r")
499+ (FOP2:F (match_operand:F 1 "register_operand" "r")))]
500+ "nios2_fpu_insn_enabled (n2fpu_f<code><f>)"
501+ "* return nios2_fpu_insn_asm (n2fpu_f<code><f>);"
502+ [(set_attr "type" "custom")])
503+
504+;; X, Y register access instructions
505+(define_insn "nios2_fwrx"
506+ [(unspec_volatile [(match_operand:DF 0 "register_operand" "r")] UNSPECV_FWRX)]
507+ "nios2_fpu_insn_enabled (n2fpu_fwrx)"
508+ "* return nios2_fpu_insn_asm (n2fpu_fwrx);"
509+ [(set_attr "type" "custom")])
510+
511+(define_insn "nios2_fwry"
512+ [(unspec_volatile [(match_operand:SF 0 "register_operand" "r")] UNSPECV_FWRY)]
513+ "nios2_fpu_insn_enabled (n2fpu_fwry)"
514+ "* return nios2_fpu_insn_asm (n2fpu_fwry);"
515+ [(set_attr "type" "custom")])
516+
517+;; The X, Y read insns uses an int iterator
518+(define_int_iterator UNSPEC_READ_XY [UNSPECV_FRDXLO UNSPECV_FRDXHI
519+ UNSPECV_FRDY])
520+(define_int_attr read_xy [(UNSPECV_FRDXLO "frdxlo") (UNSPECV_FRDXHI "frdxhi")
521+ (UNSPECV_FRDY "frdy")])
522+(define_insn "nios2_<read_xy>"
523+ [(set (match_operand:SF 0 "register_operand" "=r")
524+ (unspec_volatile:SF [(const_int 0)] UNSPEC_READ_XY))]
525+ "nios2_fpu_insn_enabled (n2fpu_<read_xy>)"
526+ "* return nios2_fpu_insn_asm (n2fpu_<read_xy>);"
527+ [(set_attr "type" "custom")])
528+
529+;; Various math functions
530+(define_int_iterator MATHFUNC
531+ [UNSPEC_FCOS UNSPEC_FSIN UNSPEC_FTAN UNSPEC_FATAN UNSPEC_FEXP UNSPEC_FLOG])
532+(define_int_attr mathfunc [(UNSPEC_FCOS "cos") (UNSPEC_FSIN "sin")
533+ (UNSPEC_FTAN "tan") (UNSPEC_FATAN "atan")
534+ (UNSPEC_FEXP "exp") (UNSPEC_FLOG "log")])
535+
536+(define_insn "<mathfunc><mode>2"
537+ [(set (match_operand:F 0 "register_operand" "=r")
538+ (unspec:F [(match_operand:F 1 "register_operand" "r")] MATHFUNC))]
539+ "nios2_fpu_insn_enabled (n2fpu_f<mathfunc><f>)"
540+ "* return nios2_fpu_insn_asm (n2fpu_f<mathfunc><f>);"
541+ [(set_attr "type" "custom")])
542+
543+;; Converting between floating point and fixed point
544+
545+(define_code_iterator FLOAT [float unsigned_float])
546+(define_code_iterator FIX [fix unsigned_fix])
547+
548+(define_code_attr conv_op [(float "float") (unsigned_float "floatuns")
549+ (fix "fix") (unsigned_fix "fixuns")])
550+(define_code_attr i [(float "i") (unsigned_float "u")
551+ (fix "i") (unsigned_fix "u")])
552+
553+;; Integer to float conversions
554+(define_insn "<conv_op>si<mode>2"
555+ [(set (match_operand:F 0 "register_operand" "=r")
556+ (FLOAT:F (match_operand:SI 1 "register_operand" "r")))]
557+ "nios2_fpu_insn_enabled (n2fpu_float<i><f>)"
558+ "* return nios2_fpu_insn_asm (n2fpu_float<i><f>);"
559+ [(set_attr "type" "custom")])
560+
561+;; Float to integer conversions
562+(define_insn "<conv_op>_trunc<mode>si2"
563+ [(set (match_operand:SI 0 "register_operand" "=r")
564+ (FIX:SI (match_operand:F 1 "general_operand" "r")))]
565+ "nios2_fpu_insn_enabled (n2fpu_fix<f><i>)"
566+ "* return nios2_fpu_insn_asm (n2fpu_fix<f><i>);"
567+ [(set_attr "type" "custom")])
568+
569+(define_insn "extendsfdf2"
570+ [(set (match_operand:DF 0 "register_operand" "=r")
571+ (float_extend:DF (match_operand:SF 1 "general_operand" "r")))]
572+ "nios2_fpu_insn_enabled (n2fpu_fextsd)"
573+ "* return nios2_fpu_insn_asm (n2fpu_fextsd);"
574+ [(set_attr "type" "custom")])
575+
576+(define_insn "truncdfsf2"
577+ [(set (match_operand:SF 0 "register_operand" "=r")
578+ (float_truncate:SF (match_operand:DF 1 "general_operand" "r")))]
579+ "nios2_fpu_insn_enabled (n2fpu_ftruncds)"
580+ "* return nios2_fpu_insn_asm (n2fpu_ftruncds);"
581+ [(set_attr "type" "custom")])
582+
583+
584+
585+;; Prologue, Epilogue and Return
586+
587+(define_expand "prologue"
588+ [(const_int 1)]
589+ ""
590+{
591+ expand_prologue ();
592+ DONE;
593+})
594+
595+(define_expand "epilogue"
596+ [(return)]
597+ ""
598+{
599+ expand_epilogue (false);
600+ DONE;
601+})
602+
603+(define_expand "sibcall_epilogue"
604+ [(return)]
605+ ""
606+{
607+ expand_epilogue (true);
608+ DONE;
609+})
610+
611+(define_insn "return"
612+ [(return)]
613+ "nios2_can_use_return_insn ()"
614+ "ret"
615+)
616+
617+(define_insn "return_from_epilogue"
618+ [(use (match_operand 0 "pmode_register_operand" ""))
619+ (return)]
620+ "reload_completed"
621+ "ret"
622+)
623+
624+;; Block any insns from being moved before this point, since the
625+;; profiling call to mcount can use various registers that aren't
626+;; saved or used to pass arguments.
627+
628+(define_insn "blockage"
629+ [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
630+ ""
631+ ""
632+ [(set_attr "type" "unknown")
633+ (set_attr "length" "0")])
634+
635+;; This is used in compiling the unwind routines.
636+(define_expand "eh_return"
637+ [(use (match_operand 0 "general_operand"))]
638+ ""
639+{
640+ if (GET_MODE (operands[0]) != Pmode)
641+ operands[0] = convert_to_mode (Pmode, operands[0], 0);
642+ emit_insn (gen_eh_set_ra (operands[0]));
643+
644+ DONE;
645+})
646+
647+;; Clobber the return address on the stack. We can't expand this
648+;; until we know where it will be put in the stack frame.
649+
650+(define_insn "eh_set_ra"
651+ [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
652+ (clobber (match_scratch:SI 1 "=&r"))]
653+ ""
654+ "#")
655+
656+(define_split
657+ [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN)
658+ (clobber (match_scratch 1))]
659+ "reload_completed"
660+ [(const_int 0)]
661+{
662+ nios2_set_return_address (operands[0], operands[1]);
663+ DONE;
664+})
665+
666+
667+;; Jumps and calls
668+
669+; Note that the assembler fixes up any out-of-range branch instructions not
670+; caught by the compiler branch shortening code. The sequence emitted by
671+; the assembler can be very inefficient, but it is correct for PIC code.
672+; For non-PIC we are better off converting to an absolute JMPI.
673+;
674+; Direct calls and sibcalls use the CALL and JMPI instructions, respectively.
675+; These instructions have an immediate operand that specifies the low 28 bits
676+; of the PC, effectively allowing direct calls within a 256MB memory segment.
677+; Per the Nios II Processor Reference Handbook, the linker is not required to
678+; check or adjust for overflow.
679+
680+(define_insn "indirect_jump"
681+ [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
682+ ""
683+ "jmp\\t%0"
684+ [(set_attr "type" "control")])
685+
686+(define_insn "jump"
687+ [(set (pc)
688+ (label_ref (match_operand 0 "" "")))]
689+ ""
690+ {
691+ if (flag_pic || get_attr_length (insn) == 4)
692+ return "br\\t%0";
693+ else
694+ return "jmpi\\t%0";
695+ }
696+ [(set_attr "type" "control")
697+ (set (attr "length")
698+ (if_then_else
699+ (and (ge (minus (match_dup 0) (pc)) (const_int -32768))
700+ (le (minus (match_dup 0) (pc)) (const_int 32764)))
701+ (const_int 4)
702+ (const_int 8)))])
703+
704+
705+(define_expand "call"
706+ [(parallel [(call (match_operand 0 "" "")
707+ (match_operand 1 "" ""))
708+ (clobber (reg:SI 31))])]
709+ ""
710+ "nios2_adjust_call_address (&XEXP (operands[0], 0));"
711+)
712+
713+(define_expand "call_value"
714+ [(parallel [(set (match_operand 0 "" "")
715+ (call (match_operand 1 "" "")
716+ (match_operand 2 "" "")))
717+ (clobber (reg:SI 31))])]
718+ ""
719+ "nios2_adjust_call_address (&XEXP (operands[1], 0));"
720+)
721+
722+(define_insn "*call"
723+ [(call (mem:QI (match_operand:SI 0 "call_operand" "i,r"))
724+ (match_operand 1 "" ""))
725+ (clobber (reg:SI 31))]
726+ ""
727+ "@
728+ call\\t%0
729+ callr\\t%0"
730+ [(set_attr "type" "control,control")])
731+
732+(define_insn "*call_value"
733+ [(set (match_operand 0 "" "")
734+ (call (mem:QI (match_operand:SI 1 "call_operand" "i,r"))
735+ (match_operand 2 "" "")))
736+ (clobber (reg:SI 31))]
737+ ""
738+ "@
739+ call\\t%1
740+ callr\\t%1"
741+ [(set_attr "type" "control,control")])
742+
743+(define_expand "sibcall"
744+ [(parallel [(call (match_operand 0 "" "")
745+ (match_operand 1 "" ""))
746+ (return)])]
747+ ""
748+ "nios2_adjust_call_address (&XEXP (operands[0], 0));"
749+)
750+
751+(define_expand "sibcall_value"
752+ [(parallel [(set (match_operand 0 "" "")
753+ (call (match_operand 1 "" "")
754+ (match_operand 2 "" "")))
755+ (return)])]
756+ ""
757+ "nios2_adjust_call_address (&XEXP (operands[1], 0));"
758+)
759+
760+(define_insn "*sibcall"
761+ [(call (mem:QI (match_operand:SI 0 "call_operand" "i,j"))
762+ (match_operand 1 "" ""))
763+ (return)]
764+ ""
765+ "@
766+ jmpi\\t%0
767+ jmp\\t%0"
768+)
769+
770+(define_insn "*sibcall_value"
771+ [(set (match_operand 0 "register_operand" "")
772+ (call (mem:QI (match_operand:SI 1 "call_operand" "i,j"))
773+ (match_operand 2 "" "")))
774+ (return)]
775+ ""
776+ "@
777+ jmpi\\t%1
778+ jmp\\t%1"
779+)
780+
781+(define_expand "tablejump"
782+ [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
783+ (use (label_ref (match_operand 1 "" "")))])]
784+ ""
785+ {
786+ if (flag_pic)
787+ {
788+ /* Hopefully, CSE will eliminate this copy. */
789+ rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
790+ rtx reg2 = gen_reg_rtx (SImode);
791+
792+ emit_insn (gen_addsi3 (reg2, operands[0], reg1));
793+ operands[0] = reg2;
794+ }
795+ }
796+)
797+
798+(define_insn "*tablejump"
799+ [(set (pc)
800+ (match_operand:SI 0 "register_operand" "r"))
801+ (use (label_ref (match_operand 1 "" "")))]
802+ ""
803+ "jmp\\t%0"
804+ [(set_attr "type" "control")])
805+
806+
807+
808+;; cstore, cbranch patterns
809+
810+(define_mode_iterator CM [SI SF DF])
811+
812+(define_expand "cstore<mode>4"
813+ [(set (match_operand:SI 0 "register_operand" "=r")
814+ (match_operator:SI 1 "ordered_comparison_operator"
815+ [(match_operand:CM 2 "register_operand")
816+ (match_operand:CM 3 "nonmemory_operand")]))]
817+ "nios2_supported_compare_p (<MODE>mode)"
818+ {
819+ if (!nios2_validate_compare (<MODE>mode, &operands[1], &operands[2],
820+ &operands[3]))
821+ FAIL;
822+ })
823+
824+(define_expand "cbranch<mode>4"
825+ [(set (pc)
826+ (if_then_else
827+ (match_operator 0 "ordered_comparison_operator"
828+ [(match_operand:CM 1 "register_operand")
829+ (match_operand:CM 2 "nonmemory_operand")])
830+ (label_ref (match_operand 3 ""))
831+ (pc)))]
832+ "nios2_supported_compare_p (<MODE>mode)"
833+ {
834+ if (!nios2_validate_compare (<MODE>mode, &operands[0], &operands[1],
835+ &operands[2]))
836+ FAIL;
837+ if (GET_MODE_CLASS (<MODE>mode) == MODE_FLOAT
838+ || !reg_or_0_operand (operands[2], <MODE>mode))
839+ {
840+ rtx condreg = gen_reg_rtx (SImode);
841+ emit_insn (gen_cstore<mode>4
842+ (condreg, operands[0], operands[1], operands[2]));
843+ operands[1] = condreg;
844+ operands[2] = const0_rtx;
845+ operands[0] = gen_rtx_fmt_ee (NE, VOIDmode, condreg, const0_rtx);
846+ }
847+ })
848+
849+(define_insn "nios2_cbranch"
850+ [(set (pc)
851+ (if_then_else
852+ (match_operator 0 "ordered_comparison_operator"
853+ [(match_operand:SI 1 "reg_or_0_operand" "rM")
854+ (match_operand:SI 2 "reg_or_0_operand" "rM")])
855+ (label_ref (match_operand 3 "" ""))
856+ (pc)))]
857+ ""
858+ {
859+ if (flag_pic || get_attr_length (insn) == 4)
860+ return "b%0\t%z1, %z2, %l3";
861+ else
862+ return "b%R0\t%z1, %z2, .+8;jmpi\t%l3";
863+ }
864+ [(set_attr "type" "control")
865+ (set (attr "length")
866+ (if_then_else
867+ (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
868+ (le (minus (match_dup 1) (pc)) (const_int 32764)))
869+ (const_int 4) (const_int 8)))])
870+
871+;; Floating point comparisons
872+(define_code_iterator FCMP [eq ne gt ge le lt])
873+(define_insn "nios2_s<code><mode>"
874+ [(set (match_operand:SI 0 "register_operand" "=r")
875+ (FCMP:SI (match_operand:F 1 "register_operand" "r")
876+ (match_operand:F 2 "register_operand" "r")))]
877+ "nios2_fpu_insn_enabled (n2fpu_fcmp<code><f>)"
878+ "* return nios2_fpu_insn_asm (n2fpu_fcmp<code><f>);"
879+ [(set_attr "type" "custom")])
880+
881+;; Integer comparisons
882+
883+(define_code_iterator EQNE [eq ne])
884+(define_insn "nios2_cmp<code>"
885+ [(set (match_operand:SI 0 "register_operand" "=r")
886+ (EQNE:SI (match_operand:SI 1 "reg_or_0_operand" "%rM")
887+ (match_operand:SI 2 "arith_operand" "rI")))]
888+ ""
889+ "cmp<code>%i2\\t%0, %z1, %z2"
890+ [(set_attr "type" "alu")])
891+
892+(define_code_iterator SCMP [ge lt])
893+(define_insn "nios2_cmp<code>"
894+ [(set (match_operand:SI 0 "register_operand" "=r")
895+ (SCMP:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
896+ (match_operand:SI 2 "arith_operand" "rI")))]
897+ ""
898+ "cmp<code>%i2\\t%0, %z1, %z2"
899+ [(set_attr "type" "alu")])
900+
901+(define_code_iterator UCMP [geu ltu])
902+(define_insn "nios2_cmp<code>"
903+ [(set (match_operand:SI 0 "register_operand" "=r")
904+ (UCMP:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
905+ (match_operand:SI 2 "uns_arith_operand" "rJ")))]
906+ ""
907+ "cmp<code>%i2\\t%0, %z1, %z2"
908+ [(set_attr "type" "alu")])
909+
910+
911+
912+;; Custom instruction patterns. The operands are intentionally
913+;; mode-less, to serve as generic carriers of all Altera defined
914+;; built-in instruction/function types.
915+
916+(define_insn "custom_nxx"
917+ [(unspec_volatile [(match_operand 0 "custom_insn_opcode" "N")
918+ (match_operand 1 "reg_or_0_operand" "rM")
919+ (match_operand 2 "reg_or_0_operand" "rM")]
920+ UNSPECV_CUSTOM_NXX)]
921+ ""
922+ "custom\\t%0, zero, %z1, %z2"
923+ [(set_attr "type" "custom")])
924+
925+(define_insn "custom_xnxx"
926+ [(set (match_operand 0 "register_operand" "=r")
927+ (unspec_volatile [(match_operand 1 "custom_insn_opcode" "N")
928+ (match_operand 2 "reg_or_0_operand" "rM")
929+ (match_operand 3 "reg_or_0_operand" "rM")]
930+ UNSPECV_CUSTOM_XNXX))]
931+ ""
932+ "custom\\t%1, %0, %z2, %z3"
933+ [(set_attr "type" "custom")])
934+
935+
936+;; Misc. patterns
937+
938+(define_insn "nop"
939+ [(const_int 0)]
940+ ""
941+ "nop"
942+ [(set_attr "type" "alu")])
943+
944+;; Connect 'sync' to 'memory_barrier' standard expand name
945+(define_expand "memory_barrier"
946+ [(const_int 0)]
947+ ""
948+{
949+ emit_insn (gen_sync ());
950+ DONE;
951+})
952+
953+;; For the nios2 __builtin_sync built-in function
954+(define_expand "sync"
955+ [(set (match_dup 0)
956+ (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
957+ ""
958+{
959+ operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
960+ MEM_VOLATILE_P (operands[0]) = 1;
961+})
962+
963+(define_insn "*sync_insn"
964+ [(set (match_operand:BLK 0 "" "")
965+ (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
966+ ""
967+ "sync"
968+ [(set_attr "type" "control")])
969+
970+(define_insn "rdctl"
971+ [(set (match_operand:SI 0 "register_operand" "=r")
972+ (unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O")]
973+ UNSPECV_RDCTL))]
974+ ""
975+ "rdctl\\t%0, ctl%1"
976+ [(set_attr "type" "control")])
977+
978+(define_insn "wrctl"
979+ [(unspec_volatile:SI [(match_operand:SI 0 "rdwrctl_operand" "O")
980+ (match_operand:SI 1 "reg_or_0_operand" "rM")]
981+ UNSPECV_WRCTL)]
982+ ""
983+ "wrctl\\tctl%0, %z1"
984+ [(set_attr "type" "control")])
985+
986+;; Used to signal a stack overflow
987+(define_insn "trap"
988+ [(unspec_volatile [(const_int 0)] UNSPECV_TRAP)]
989+ ""
990+ "break\\t3"
991+ [(set_attr "type" "control")])
992+
993+(define_insn "stack_overflow_detect_and_trap"
994+ [(unspec_volatile [(const_int 0)] UNSPECV_STACK_OVERFLOW_DETECT_AND_TRAP)]
995+ ""
996+ "bgeu\\tsp, et, 1f\;break\\t3\;1:"
997+ [(set_attr "type" "control")
998+ (set_attr "length" "8")])
999+
1000+;; Load the GOT register.
1001+(define_insn "load_got_register"
1002+ [(set (match_operand:SI 0 "register_operand" "=&r")
1003+ (unspec:SI [(const_int 0)] UNSPEC_LOAD_GOT_REGISTER))
1004+ (set (match_operand:SI 1 "register_operand" "=r")
1005+ (unspec:SI [(const_int 0)] UNSPEC_LOAD_GOT_REGISTER))]
1006+ ""
1007+ "nextpc\\t%0
1008+\\t1:
1009+\\tmovhi\\t%1, %%hiadj(_GLOBAL_OFFSET_TABLE_ - 1b)
1010+\\taddi\\t%1, %1, %%lo(_GLOBAL_OFFSET_TABLE_ - 1b)"
1011+ [(set_attr "length" "12")])
1012+
1013+;; When generating pic, we need to load the symbol offset into a register.
1014+;; So that the optimizer does not confuse this with a normal symbol load
1015+;; we use an unspec. The offset will be loaded from a constant pool entry,
1016+;; since that is the only type of relocation we can use.
1017+
1018+;; The rather odd constraints on the following are to force reload to leave
1019+;; the insn alone, and to force the minipool generation pass to then move
1020+;; the GOT symbol to memory.
1021+
1022+(define_insn "pic_load_addr"
1023+ [(set (match_operand:SI 0 "register_operand" "=r")
1024+ (unspec:SI [(match_operand:SI 1 "register_operand" "r")
1025+ (match_operand:SI 2 "" "mX")] UNSPEC_PIC_SYM))]
1026+ "flag_pic && TARGET_LINUX_ABI"
1027+ "ldw\\t%0, %%got(%2)(%1)")
1028+
1029+(define_insn "pic_load_call_addr"
1030+ [(set (match_operand:SI 0 "register_operand" "=r")
1031+ (unspec:SI [(match_operand:SI 1 "register_operand" "r")
1032+ (match_operand:SI 2 "" "mX")] UNSPEC_PIC_CALL_SYM))]
1033+ "flag_pic && TARGET_LINUX_ABI"
1034+ "ldw\\t%0, %%call(%2)(%1)")
1035+
1036+;; TLS support
1037+
1038+(define_insn "add_tls_gd"
1039+ [(set (match_operand:SI 0 "register_operand" "=r")
1040+ (unspec:SI [(match_operand:SI 1 "register_operand" "r")
1041+ (match_operand:SI 2 "" "mX")] UNSPEC_ADD_TLS_GD))]
1042+ "TARGET_LINUX_ABI"
1043+ "addi\t%0, %1, %%tls_gd(%2)")
1044+
1045+(define_insn "load_tls_ie"
1046+ [(set (match_operand:SI 0 "register_operand" "=r")
1047+ (unspec:SI [(match_operand:SI 1 "register_operand" "r")
1048+ (match_operand:SI 2 "" "mX")] UNSPEC_LOAD_TLS_IE))]
1049+ "TARGET_LINUX_ABI"
1050+ "ldw\t%0, %%tls_ie(%2)(%1)")
1051+
1052+(define_insn "add_tls_ldm"
1053+ [(set (match_operand:SI 0 "register_operand" "=r")
1054+ (unspec:SI [(match_operand:SI 1 "register_operand" "r")
1055+ (match_operand:SI 2 "" "mX")] UNSPEC_ADD_TLS_LDM))]
1056+ "TARGET_LINUX_ABI"
1057+ "addi\t%0, %1, %%tls_ldm(%2)")
1058+
1059+(define_insn "add_tls_ldo"
1060+ [(set (match_operand:SI 0 "register_operand" "=r")
1061+ (unspec:SI [(match_operand:SI 1 "register_operand" "r")
1062+ (match_operand:SI 2 "" "mX")] UNSPEC_ADD_TLS_LDO))]
1063+ "TARGET_LINUX_ABI"
1064+ "addi\t%0, %1, %%tls_ldo(%2)")
1065+
1066+(define_insn "add_tls_le"
1067+ [(set (match_operand:SI 0 "register_operand" "=r")
1068+ (unspec:SI [(match_operand:SI 1 "register_operand" "r")
1069+ (match_operand:SI 2 "" "mX")] UNSPEC_ADD_TLS_LE))]
1070+ "TARGET_LINUX_ABI"
1071+ "addi\t%0, %1, %%tls_le(%2)")
1072+
--- /dev/null
+++ b/gcc/config/nios2/nios2.opt
@@ -0,0 +1,527 @@
1+; Options for the Altera Nios II port of the compiler.
2+; Copyright (C) 2012 Free Software Foundation, Inc.
3+; Contributed by Altera and Mentor Graphics, Inc.
4+;
5+; This file is part of GCC.
6+;
7+; GCC is free software; you can redistribute it and/or modify
8+; it under the terms of the GNU General Public License as published by
9+; the Free Software Foundation; either version 3, or (at your option)
10+; any later version.
11+;
12+; GCC is distributed in the hope that it will be useful,
13+; but WITHOUT ANY WARRANTY; without even the implied warranty of
14+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+; GNU General Public License for more details.
16+;
17+; You should have received a copy of the GNU General Public License
18+; along with GCC; see the file COPYING3. If not see
19+; <http://www.gnu.org/licenses/>.
20+
21+HeaderInclude
22+config/nios2/nios2-opts.h
23+
24+TargetSave
25+int saved_fpu_custom_code[n2fpu_code_num]
26+
27+TargetSave
28+enum nios2_ccs_code saved_custom_code_status[256]
29+
30+TargetSave
31+int saved_custom_code_index[256]
32+
33+mhw-div
34+Target Report Mask(HAS_DIV)
35+Enable DIV, DIVU
36+
37+mhw-mul
38+Target Report Mask(HAS_MUL)
39+Enable MUL instructions
40+
41+mhw-mulx
42+Target Report Mask(HAS_MULX)
43+Enable MULX instructions, assume fast shifter
44+
45+mfast-sw-div
46+Target Report Mask(FAST_SW_DIV)
47+Use table based fast divide (default at -O3)
48+
49+mbypass-cache
50+Target Report Mask(BYPASS_CACHE)
51+All memory accesses use I/O load/store instructions
52+
53+mno-cache-volatile
54+Target Report RejectNegative Mask(BYPASS_CACHE_VOLATILE)
55+Volatile memory accesses use I/O load/store instructions
56+
57+mcache-volatile
58+Target Report RejectNegative Undocumented InverseMask(BYPASS_CACHE_VOLATILE)
59+Volatile memory accesses do not use I/O load/store instructions
60+
61+meb
62+Target Report RejectNegative Mask(BIG_ENDIAN)
63+Use big-endian byte order
64+
65+mel
66+Target Report RejectNegative InverseMask(BIG_ENDIAN)
67+Use little-endian byte order
68+
69+mcustom-fpu-cfg=
70+Target RejectNegative Joined Var(nios2_custom_fpu_cfg_string)
71+Floating point custom instruction configuration name
72+
73+mno-custom-ftruncds
74+Target Report RejectNegative Var(nios2_custom_ftruncds, -1)
75+Do not use the ftruncds custom instruction
76+
77+mcustom-ftruncds=
78+Target Report RejectNegative Joined UInteger Var(nios2_custom_ftruncds) Init(-1)
79+Integer id (N) of ftruncds custom instruction
80+
81+mno-custom-fextsd
82+Target Report RejectNegative Var(nios2_custom_fextsd, -1)
83+Do not use the fextsd custom instruction
84+
85+mcustom-fextsd=
86+Target Report RejectNegative Joined UInteger Var(nios2_custom_fextsd) Init(-1)
87+Integer id (N) of fextsd custom instruction
88+
89+mno-custom-fixdu
90+Target Report RejectNegative Var(nios2_custom_fixdu, -1)
91+Do not use the fixdu custom instruction
92+
93+mcustom-fixdu=
94+Target Report RejectNegative Joined UInteger Var(nios2_custom_fixdu) Init(-1)
95+Integer id (N) of fixdu custom instruction
96+
97+mno-custom-fixdi
98+Target Report RejectNegative Var(nios2_custom_fixdi, -1)
99+Do not use the fixdi custom instruction
100+
101+mcustom-fixdi=
102+Target Report RejectNegative Joined UInteger Var(nios2_custom_fixdi) Init(-1)
103+Integer id (N) of fixdi custom instruction
104+
105+mno-custom-fixsu
106+Target Report RejectNegative Var(nios2_custom_fixsu, -1)
107+Do not use the fixsu custom instruction
108+
109+mcustom-fixsu=
110+Target Report RejectNegative Joined UInteger Var(nios2_custom_fixsu) Init(-1)
111+Integer id (N) of fixsu custom instruction
112+
113+mno-custom-fixsi
114+Target Report RejectNegative Var(nios2_custom_fixsi, -1)
115+Do not use the fixsi custom instruction
116+
117+mcustom-fixsi=
118+Target Report RejectNegative Joined UInteger Var(nios2_custom_fixsi) Init(-1)
119+Integer id (N) of fixsi custom instruction
120+
121+mno-custom-floatud
122+Target Report RejectNegative Var(nios2_custom_floatud, -1)
123+Do not use the floatud custom instruction
124+
125+mcustom-floatud=
126+Target Report RejectNegative Joined UInteger Var(nios2_custom_floatud) Init(-1)
127+Integer id (N) of floatud custom instruction
128+
129+mno-custom-floatid
130+Target Report RejectNegative Var(nios2_custom_floatid, -1)
131+Do not use the floatid custom instruction
132+
133+mcustom-floatid=
134+Target Report RejectNegative Joined UInteger Var(nios2_custom_floatid) Init(-1)
135+Integer id (N) of floatid custom instruction
136+
137+mno-custom-floatus
138+Target Report RejectNegative Var(nios2_custom_floatus, -1)
139+Do not use the floatus custom instruction
140+
141+mcustom-floatus=
142+Target Report RejectNegative Joined UInteger Var(nios2_custom_floatus) Init(-1)
143+Integer id (N) of floatus custom instruction
144+
145+mno-custom-floatis
146+Target Report RejectNegative Var(nios2_custom_floatis, -1)
147+Do not use the floatis custom instruction
148+
149+mcustom-floatis=
150+Target Report RejectNegative Joined UInteger Var(nios2_custom_floatis) Init(-1)
151+Integer id (N) of floatis custom instruction
152+
153+mno-custom-fcmpned
154+Target Report RejectNegative Var(nios2_custom_fcmpned, -1)
155+Do not use the fcmpned custom instruction
156+
157+mcustom-fcmpned=
158+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpned) Init(-1)
159+Integer id (N) of fcmpned custom instruction
160+
161+mno-custom-fcmpeqd
162+Target Report RejectNegative Var(nios2_custom_fcmpeqd, -1)
163+Do not use the fcmpeqd custom instruction
164+
165+mcustom-fcmpeqd=
166+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpeqd) Init(-1)
167+Integer id (N) of fcmpeqd custom instruction
168+
169+mno-custom-fcmpged
170+Target Report RejectNegative Var(nios2_custom_fcmpged, -1)
171+Do not use the fcmpged custom instruction
172+
173+mcustom-fcmpged=
174+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpged) Init(-1)
175+Integer id (N) of fcmpged custom instruction
176+
177+mno-custom-fcmpgtd
178+Target Report RejectNegative Var(nios2_custom_fcmpgtd, -1)
179+Do not use the fcmpgtd custom instruction
180+
181+mcustom-fcmpgtd=
182+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpgtd) Init(-1)
183+Integer id (N) of fcmpgtd custom instruction
184+
185+mno-custom-fcmpled
186+Target Report RejectNegative Var(nios2_custom_fcmpled, -1)
187+Do not use the fcmpled custom instruction
188+
189+mcustom-fcmpled=
190+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpled) Init(-1)
191+Integer id (N) of fcmpled custom instruction
192+
193+mno-custom-fcmpltd
194+Target Report RejectNegative Var(nios2_custom_fcmpltd, -1)
195+Do not use the fcmpltd custom instruction
196+
197+mcustom-fcmpltd=
198+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpltd) Init(-1)
199+Integer id (N) of fcmpltd custom instruction
200+
201+mno-custom-flogd
202+Target Report RejectNegative Var(nios2_custom_flogd, -1)
203+Do not use the flogd custom instruction
204+
205+mcustom-flogd=
206+Target Report RejectNegative Joined UInteger Var(nios2_custom_flogd) Init(-1)
207+Integer id (N) of flogd custom instruction
208+
209+mno-custom-fexpd
210+Target Report RejectNegative Var(nios2_custom_fexpd, -1)
211+Do not use the fexpd custom instruction
212+
213+mcustom-fexpd=
214+Target Report RejectNegative Joined UInteger Var(nios2_custom_fexpd) Init(-1)
215+Integer id (N) of fexpd custom instruction
216+
217+mno-custom-fatand
218+Target Report RejectNegative Var(nios2_custom_fatand, -1)
219+Do not use the fatand custom instruction
220+
221+mcustom-fatand=
222+Target Report RejectNegative Joined UInteger Var(nios2_custom_fatand) Init(-1)
223+Integer id (N) of fatand custom instruction
224+
225+mno-custom-ftand
226+Target Report RejectNegative Var(nios2_custom_ftand, -1)
227+Do not use the ftand custom instruction
228+
229+mcustom-ftand=
230+Target Report RejectNegative Joined UInteger Var(nios2_custom_ftand) Init(-1)
231+Integer id (N) of ftand custom instruction
232+
233+mno-custom-fsind
234+Target Report RejectNegative Var(nios2_custom_fsind, -1)
235+Do not use the fsind custom instruction
236+
237+mcustom-fsind=
238+Target Report RejectNegative Joined UInteger Var(nios2_custom_fsind) Init(-1)
239+Integer id (N) of fsind custom instruction
240+
241+mno-custom-fcosd
242+Target Report RejectNegative Var(nios2_custom_fcosd, -1)
243+Do not use the fcosd custom instruction
244+
245+mcustom-fcosd=
246+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcosd) Init(-1)
247+Integer id (N) of fcosd custom instruction
248+
249+mno-custom-fsqrtd
250+Target Report RejectNegative Var(nios2_custom_fsqrtd, -1)
251+Do not use the fsqrtd custom instruction
252+
253+mcustom-fsqrtd=
254+Target Report RejectNegative Joined UInteger Var(nios2_custom_fsqrtd) Init(-1)
255+Integer id (N) of fsqrtd custom instruction
256+
257+mno-custom-fabsd
258+Target Report RejectNegative Var(nios2_custom_fabsd, -1)
259+Do not use the fabsd custom instruction
260+
261+mcustom-fabsd=
262+Target Report RejectNegative Joined UInteger Var(nios2_custom_fabsd) Init(-1)
263+Integer id (N) of fabsd custom instruction
264+
265+mno-custom-fnegd
266+Target Report RejectNegative Var(nios2_custom_fnegd, -1)
267+Do not use the fnegd custom instruction
268+
269+mcustom-fnegd=
270+Target Report RejectNegative Joined UInteger Var(nios2_custom_fnegd) Init(-1)
271+Integer id (N) of fnegd custom instruction
272+
273+mno-custom-fmaxd
274+Target Report RejectNegative Var(nios2_custom_fmaxd, -1)
275+Do not use the fmaxd custom instruction
276+
277+mcustom-fmaxd=
278+Target Report RejectNegative Joined UInteger Var(nios2_custom_fmaxd) Init(-1)
279+Integer id (N) of fmaxd custom instruction
280+
281+mno-custom-fmind
282+Target Report RejectNegative Var(nios2_custom_fmind, -1)
283+Do not use the fmind custom instruction
284+
285+mcustom-fmind=
286+Target Report RejectNegative Joined UInteger Var(nios2_custom_fmind) Init(-1)
287+Integer id (N) of fmind custom instruction
288+
289+mno-custom-fdivd
290+Target Report RejectNegative Var(nios2_custom_fdivd, -1)
291+Do not use the fdivd custom instruction
292+
293+mcustom-fdivd=
294+Target Report RejectNegative Joined UInteger Var(nios2_custom_fdivd) Init(-1)
295+Integer id (N) of fdivd custom instruction
296+
297+mno-custom-fmuld
298+Target Report RejectNegative Var(nios2_custom_fmuld, -1)
299+Do not use the fmuld custom instruction
300+
301+mcustom-fmuld=
302+Target Report RejectNegative Joined UInteger Var(nios2_custom_fmuld) Init(-1)
303+Integer id (N) of fmuld custom instruction
304+
305+mno-custom-fsubd
306+Target Report RejectNegative Var(nios2_custom_fsubd, -1)
307+Do not use the fsubd custom instruction
308+
309+mcustom-fsubd=
310+Target Report RejectNegative Joined UInteger Var(nios2_custom_fsubd) Init(-1)
311+Integer id (N) of fsubd custom instruction
312+
313+mno-custom-faddd
314+Target Report RejectNegative Var(nios2_custom_faddd, -1)
315+Do not use the faddd custom instruction
316+
317+mcustom-faddd=
318+Target Report RejectNegative Joined UInteger Var(nios2_custom_faddd) Init(-1)
319+Integer id (N) of faddd custom instruction
320+
321+mno-custom-fcmpnes
322+Target Report RejectNegative Var(nios2_custom_fcmpnes, -1)
323+Do not use the fcmpnes custom instruction
324+
325+mcustom-fcmpnes=
326+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpnes) Init(-1)
327+Integer id (N) of fcmpnes custom instruction
328+
329+mno-custom-fcmpeqs
330+Target Report RejectNegative Var(nios2_custom_fcmpeqs, -1)
331+Do not use the fcmpeqs custom instruction
332+
333+mcustom-fcmpeqs=
334+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpeqs) Init(-1)
335+Integer id (N) of fcmpeqs custom instruction
336+
337+mno-custom-fcmpges
338+Target Report RejectNegative Var(nios2_custom_fcmpges, -1)
339+Do not use the fcmpges custom instruction
340+
341+mcustom-fcmpges=
342+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpges) Init(-1)
343+Integer id (N) of fcmpges custom instruction
344+
345+mno-custom-fcmpgts
346+Target Report RejectNegative Var(nios2_custom_fcmpgts, -1)
347+Do not use the fcmpgts custom instruction
348+
349+mcustom-fcmpgts=
350+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpgts) Init(-1)
351+Integer id (N) of fcmpgts custom instruction
352+
353+mno-custom-fcmples
354+Target Report RejectNegative Var(nios2_custom_fcmples, -1)
355+Do not use the fcmples custom instruction
356+
357+mcustom-fcmples=
358+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmples) Init(-1)
359+Integer id (N) of fcmples custom instruction
360+
361+mno-custom-fcmplts
362+Target Report RejectNegative Var(nios2_custom_fcmplts, -1)
363+Do not use the fcmplts custom instruction
364+
365+mcustom-fcmplts=
366+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmplts) Init(-1)
367+Integer id (N) of fcmplts custom instruction
368+
369+mno-custom-flogs
370+Target Report RejectNegative Var(nios2_custom_flogs, -1)
371+Do not use the flogs custom instruction
372+
373+mcustom-flogs=
374+Target Report RejectNegative Joined UInteger Var(nios2_custom_flogs) Init(-1)
375+Integer id (N) of flogs custom instruction
376+
377+mno-custom-fexps
378+Target Report RejectNegative Var(nios2_custom_fexps, -1)
379+Do not use the fexps custom instruction
380+
381+mcustom-fexps=
382+Target Report RejectNegative Joined UInteger Var(nios2_custom_fexps) Init(-1)
383+Integer id (N) of fexps custom instruction
384+
385+mno-custom-fatans
386+Target Report RejectNegative Var(nios2_custom_fatans, -1)
387+Do not use the fatans custom instruction
388+
389+mcustom-fatans=
390+Target Report RejectNegative Joined UInteger Var(nios2_custom_fatans) Init(-1)
391+Integer id (N) of fatans custom instruction
392+
393+mno-custom-ftans
394+Target Report RejectNegative Var(nios2_custom_ftans, -1)
395+Do not use the ftans custom instruction
396+
397+mcustom-ftans=
398+Target Report RejectNegative Joined UInteger Var(nios2_custom_ftans) Init(-1)
399+Integer id (N) of ftans custom instruction
400+
401+mno-custom-fsins
402+Target Report RejectNegative Var(nios2_custom_fsins, -1)
403+Do not use the fsins custom instruction
404+
405+mcustom-fsins=
406+Target Report RejectNegative Joined UInteger Var(nios2_custom_fsins) Init(-1)
407+Integer id (N) of fsins custom instruction
408+
409+mno-custom-fcoss
410+Target Report RejectNegative Var(nios2_custom_fcoss, -1)
411+Do not use the fcoss custom instruction
412+
413+mcustom-fcoss=
414+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcoss) Init(-1)
415+Integer id (N) of fcoss custom instruction
416+
417+mno-custom-fsqrts
418+Target Report RejectNegative Var(nios2_custom_fsqrts, -1)
419+Do not use the fsqrts custom instruction
420+
421+mcustom-fsqrts=
422+Target Report RejectNegative Joined UInteger Var(nios2_custom_fsqrts) Init(-1)
423+Integer id (N) of fsqrts custom instruction
424+
425+mno-custom-fabss
426+Target Report RejectNegative Var(nios2_custom_fabss, -1)
427+Do not use the fabss custom instr
428+
429+mcustom-fabss=
430+Target Report RejectNegative Joined UInteger Var(nios2_custom_fabss) Init(-1)
431+Integer id (N) of fabss custom instruction
432+
433+mno-custom-fnegs
434+Target Report RejectNegative Var(nios2_custom_fnegs, -1)
435+Do not use the fnegs custom instruction
436+
437+mcustom-fnegs=
438+Target Report RejectNegative Joined UInteger Var(nios2_custom_fnegs) Init(-1)
439+Integer id (N) of fnegs custom instruction
440+
441+mno-custom-fmaxs
442+Target Report RejectNegative Var(nios2_custom_fmaxs, -1)
443+Do not use the fmaxs custom instruction
444+
445+mcustom-fmaxs=
446+Target Report RejectNegative Joined UInteger Var(nios2_custom_fmaxs) Init(-1)
447+Integer id (N) of fmaxs custom instruction
448+
449+mno-custom-fmins
450+Target Report RejectNegative Var(nios2_custom_fmins, -1)
451+Do not use the fmins custom instruction
452+
453+mcustom-fmins=
454+Target Report RejectNegative Joined UInteger Var(nios2_custom_fmins) Init(-1)
455+Integer id (N) of fmins custom instruction
456+
457+mno-custom-fdivs
458+Target Report RejectNegative Var(nios2_custom_fdivs, -1)
459+Do not use the fdivs custom instruction
460+
461+mcustom-fdivs=
462+Target Report RejectNegative Joined UInteger Var(nios2_custom_fdivs) Init(-1)
463+Integer id (N) of fdivs custom instruction
464+
465+mno-custom-fmuls
466+Target Report RejectNegative Var(nios2_custom_fmuls, -1)
467+Do not use the fmuls custom instruction
468+
469+mcustom-fmuls=
470+Target Report RejectNegative Joined UInteger Var(nios2_custom_fmuls) Init(-1)
471+Integer id (N) of fmuls custom instruction
472+
473+mno-custom-fsubs
474+Target Report RejectNegative Var(nios2_custom_fsubs, -1)
475+Do not use the fsubs custom instruction
476+
477+mcustom-fsubs=
478+Target Report RejectNegative Joined UInteger Var(nios2_custom_fsubs) Init(-1)
479+Integer id (N) of fsubs custom instruction
480+
481+mno-custom-fadds
482+Target Report RejectNegative Var(nios2_custom_fadds, -1)
483+Do not use the fadds custom instruction
484+
485+mcustom-fadds=
486+Target Report RejectNegative Joined UInteger Var(nios2_custom_fadds) Init(-1)
487+Integer id (N) of fadds custom instruction
488+
489+mno-custom-frdy
490+Target Report RejectNegative Var(nios2_custom_frdy, -1)
491+Do not use the frdy custom instruction
492+
493+mcustom-frdy=
494+Target Report RejectNegative Joined UInteger Var(nios2_custom_frdy) Init(-1)
495+Integer id (N) of frdy custom instruction
496+
497+mno-custom-frdxhi
498+Target Report RejectNegative Var(nios2_custom_frdxhi, -1)
499+Do not use the frdxhi custom instruction
500+
501+mcustom-frdxhi=
502+Target Report RejectNegative Joined UInteger Var(nios2_custom_frdxhi) Init(-1)
503+Integer id (N) of frdxhi custom instruction
504+
505+mno-custom-frdxlo
506+Target Report RejectNegative Var(nios2_custom_frdxlo, -1)
507+Do not use the frdxlo custom instruction
508+
509+mcustom-frdxlo=
510+Target Report RejectNegative Joined UInteger Var(nios2_custom_frdxlo) Init(-1)
511+Integer id (N) of frdxlo custom instruction
512+
513+mno-custom-fwry
514+Target Report RejectNegative Var(nios2_custom_fwry, -1)
515+Do not use the fwry custom instruction
516+
517+mcustom-fwry=
518+Target Report RejectNegative Joined UInteger Var(nios2_custom_fwry) Init(-1)
519+Integer id (N) of fwry custom instruction
520+
521+mno-custom-fwrx
522+Target Report RejectNegative Var(nios2_custom_fwrx, -1)
523+Do not use the fwrx custom instruction
524+
525+mcustom-fwrx=
526+Target Report RejectNegative Joined UInteger Var(nios2_custom_fwrx) Init(-1)
527+Integer id (N) of fwrx custom instruction
--- /dev/null
+++ b/gcc/config/nios2/predicates.md
@@ -0,0 +1,72 @@
1+;; Predicate definitions for Altera Nios II.
2+;; Copyright (C) 2012 Free Software Foundation, Inc.
3+;; Contributed by Chung-Lin Tang <cltang@codesourcery.com>
4+;;
5+;; This file is part of GCC.
6+;;
7+;; GCC is free software; you can redistribute it and/or modify
8+;; it under the terms of the GNU General Public License as published by
9+;; the Free Software Foundation; either version 3, or (at your option)
10+;; any later version.
11+;;
12+;; GCC is distributed in the hope that it will be useful,
13+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+;; GNU General Public License for more details.
16+;;
17+;; You should have received a copy of the GNU General Public License
18+;; along with GCC; see the file COPYING3. If not see
19+;; <http://www.gnu.org/licenses/>.
20+
21+(define_predicate "const_0_operand"
22+ (and (match_code "const_int,const_double,const_vector")
23+ (match_test "op == CONST0_RTX (GET_MODE (op))")))
24+
25+(define_predicate "reg_or_0_operand"
26+ (ior (match_operand 0 "const_0_operand")
27+ (match_operand 0 "register_operand")))
28+
29+(define_predicate "const_uns_arith_operand"
30+ (and (match_code "const_int")
31+ (match_test "SMALL_INT_UNSIGNED (INTVAL (op))")))
32+
33+(define_predicate "uns_arith_operand"
34+ (ior (match_operand 0 "const_uns_arith_operand")
35+ (match_operand 0 "register_operand")))
36+
37+(define_predicate "const_arith_operand"
38+ (and (match_code "const_int")
39+ (match_test "SMALL_INT (INTVAL (op))")))
40+
41+(define_predicate "arith_operand"
42+ (ior (match_operand 0 "const_arith_operand")
43+ (match_operand 0 "register_operand")))
44+
45+(define_predicate "const_logical_operand"
46+ (and (match_code "const_int")
47+ (match_test "(INTVAL (op) & 0xffff) == 0
48+ || (INTVAL (op) & 0xffff0000) == 0")))
49+
50+(define_predicate "logical_operand"
51+ (ior (match_operand 0 "const_logical_operand")
52+ (match_operand 0 "register_operand")))
53+
54+(define_predicate "const_shift_operand"
55+ (and (match_code "const_int")
56+ (match_test "SHIFT_INT (INTVAL (op))")))
57+
58+(define_predicate "shift_operand"
59+ (ior (match_operand 0 "const_shift_operand")
60+ (match_operand 0 "register_operand")))
61+
62+(define_predicate "call_operand"
63+ (ior (match_operand 0 "immediate_operand")
64+ (match_operand 0 "register_operand")))
65+
66+(define_predicate "rdwrctl_operand"
67+ (and (match_code "const_int")
68+ (match_test "RDWRCTL_INT (INTVAL (op))")))
69+
70+(define_predicate "custom_insn_opcode"
71+ (and (match_code "const_int")
72+ (match_test "CUSTOM_INSN_OPCODE (INTVAL (op))")))
--- /dev/null
+++ b/gcc/config/nios2/t-nios2
@@ -0,0 +1,131 @@
1+# Target Makefile Fragment for Altera Nios II.
2+# Copyright (C) 2012 Free Software Foundation, Inc.
3+# Contributed by Altera and Mentor Graphics, Inc.
4+#
5+# This file is part of GCC.
6+#
7+# GCC is free software; you can redistribute it and/or modify it
8+# under the terms of the GNU General Public License as published
9+# by the Free Software Foundation; either version 3, or (at your
10+# option) any later version.
11+#
12+# GCC is distributed in the hope that it will be useful, but WITHOUT
13+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15+# License for more details.
16+#
17+# You should have received a copy of the GNU General Public License
18+# along with GCC; see the file COPYING3. If not see
19+# <http://www.gnu.org/licenses/>.
20+
21+
22+## MULTILIB_OPTIONS
23+## For some targets, invoking GCC in different ways produces objects that
24+## can not be linked together. For example, for some targets GCC produces
25+## both big and little endian code. For these targets, you must arrange
26+## for multiple versions of libgcc.a to be compiled, one for each set of
27+## incompatible options. When GCC invokes the linker, it arranges to link
28+## in the right version of libgcc.a, based on the command line options
29+## used.
30+## The MULTILIB_OPTIONS macro lists the set of options for which special
31+## versions of libgcc.a must be built. Write options that are mutually
32+## incompatible side by side, separated by a slash. Write options that may
33+## be used together separated by a space. The build procedure will build
34+## all combinations of compatible options.
35+##
36+## For example, if you set MULTILIB_OPTIONS to m68000/m68020 msoft-float,
37+## Makefile will build special versions of libgcc.a using the following
38+## sets of options: -m68000, -m68020, -msoft-float, -m68000 -msoft-float,
39+## and -m68020 -msoft-float.
40+
41+
42+## The BUILD_BE_MULTILIB and BUILD_PG_MULTILIB variables allow the
43+## makefile user to enable/disable the generation of the precompiled
44+## big endian and profiling libraries. By default, the big endian
45+## libraries are not created on a windows build and the profiling
46+## libraries are not created on a Solaris build. All other library
47+## combinations are created by default.
48+
49+# Uncomment to temporarily avoid building big endian and profiling libraries during a Windows build.
50+#ifeq ($(DEV_HOST_OS), win32)
51+#BUILD_BE_MULTILIB ?= 0
52+#BUILD_PG_MULTILIB ?= 0
53+#endif
54+
55+#By default, avoid building the profiling libraries during a Solaris build.
56+ifeq ($(DEV_HOST_OS), solaris)
57+BUILD_PG_MULTILIB ?= 0
58+endif
59+
60+BUILD_BE_MULTILIB ?= 0
61+BUILD_PG_MULTILIB ?= 1
62+BUILD_MULTILIB ?= 0
63+
64+ifeq ($(BUILD_MULTILIB), 1)
65+
66+MULTILIB_OPTIONS = mno-hw-mul mhw-mulx mstack-check mcustom-fpu-cfg=60-1 mcustom-fpu-cfg=60-2
67+
68+#Add the profiling flag to the multilib variable if required
69+ifeq ($(BUILD_PG_MULTILIB), 1)
70+MULTILIB_OPTIONS += pg
71+endif
72+
73+#Add the big endian flag to the multilib variable if required
74+ifeq ($(BUILD_BE_MULTILIB), 1)
75+MULTILIB_OPTIONS += EB/EL
76+endif
77+
78+endif
79+
80+## MULTILIB_DIRNAMES
81+## If MULTILIB_OPTIONS is used, this variable specifies the directory names
82+## that should be used to hold the various libraries. Write one element in
83+## MULTILIB_DIRNAMES for each element in MULTILIB_OPTIONS. If
84+## MULTILIB_DIRNAMES is not used, the default value will be
85+## MULTILIB_OPTIONS, with all slashes treated as spaces.
86+## For example, if MULTILIB_OPTIONS is set to m68000/m68020 msoft-float,
87+## then the default value of MULTILIB_DIRNAMES is m68000 m68020
88+## msoft-float. You may specify a different value if you desire a
89+## different set of directory names.
90+
91+# MULTILIB_DIRNAMES =
92+
93+## MULTILIB_MATCHES
94+## Sometimes the same option may be written in two different ways. If an
95+## option is listed in MULTILIB_OPTIONS, GCC needs to know about any
96+## synonyms. In that case, set MULTILIB_MATCHES to a list of items of the
97+## form option=option to describe all relevant synonyms. For example,
98+## m68000=mc68000 m68020=mc68020.
99+
100+ifeq ($(BUILD_MULTILIB), 1)
101+ifeq ($(BUILD_BE_MULTILIB), 1)
102+MULTILIB_MATCHES = EL=mel EB=meb
103+endif
104+endif
105+
106+##
107+## MULTILIB_EXCEPTIONS
108+## Sometimes when there are multiple sets of MULTILIB_OPTIONS being
109+## specified, there are combinations that should not be built. In that
110+## case, set MULTILIB_EXCEPTIONS to be all of the switch exceptions in
111+## shell case syntax that should not be built.
112+## For example, in the PowerPC embedded ABI support, it is not desirable to
113+## build libraries compiled with the -mcall-aix option and either of the
114+## -fleading-underscore or -mlittle options at the same time. Therefore
115+## MULTILIB_EXCEPTIONS is set to
116+##
117+## *mcall-aix/*fleading-underscore* *mlittle/*mcall-aix*
118+##
119+
120+ifeq ($(BUILD_MULTILIB), 1)
121+MULTILIB_EXCEPTIONS = *mno-hw-mul/*mhw-mulx* *mcustom-fpu-cfg=60-1/*mcustom-fpu-cfg=60-2*
122+endif
123+
124+##
125+## MULTILIB_EXTRA_OPTS Sometimes it is desirable that when building
126+## multiple versions of libgcc.a certain options should always be passed on
127+## to the compiler. In that case, set MULTILIB_EXTRA_OPTS to be the list
128+## of options to be used for all builds.
129+##
130+
131+
Show on old repository browser