summaryrefslogtreecommitdiff
path: root/toolchain/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'toolchain/gcc')
-rw-r--r--toolchain/gcc/3.4.6/900-nios2.patch4950
-rw-r--r--toolchain/gcc/3.4.6/901-nios2-ctor_dtor.patch52
-rw-r--r--toolchain/gcc/3.4.6/nios2-config-fix.patch.conditional19
-rw-r--r--toolchain/gcc/gcc-uclibc-3.x.mk3
4 files changed, 4558 insertions, 466 deletions
diff --git a/toolchain/gcc/3.4.6/900-nios2.patch b/toolchain/gcc/3.4.6/900-nios2.patch
index bfa06a21c..3a84d01ab 100644
--- a/toolchain/gcc/3.4.6/900-nios2.patch
+++ b/toolchain/gcc/3.4.6/900-nios2.patch
@@ -1,17 +1,28 @@
---- gcc-3.4.3/gcc/Makefile.in
-+++ gcc-3.4.3-nios2/gcc/Makefile.in
-@@ -3085,7 +3085,7 @@ install-mkheaders: stmp-int-hdrs $(STMP_
- $(INSTALL_DATA) $(srcdir)/README-fixinc \
- $(DESTDIR)$(itoolsdatadir)/include/README ; \
- $(INSTALL_SCRIPT) fixinc.sh $(DESTDIR)$(itoolsdir)/fixinc.sh ; \
-- $(INSTALL_PROGRAM) fixinc/fixincl $(DESTDIR)$(itoolsdir)/fixincl ; \
-+ $(INSTALL_PROGRAM) fixinc/fixincl$(build_exeext) $(DESTDIR)$(itoolsdir)/fixincl$(build_exeext) ; \
- $(INSTALL_DATA) $(srcdir)/gsyslimits.h \
- $(DESTDIR)$(itoolsdatadir)/gsyslimits.h ; \
- else :; fi
---- gcc-3.4.3/gcc/combine.c
-+++ gcc-3.4.3-nios2/gcc/combine.c
-@@ -4380,6 +4380,14 @@ combine_simplify_rtx (rtx x, enum machin
+diff --git a/config.sub b/config.sub
+index d2e3557..2297c30 100755
+--- a/config.sub
++++ b/config.sub
+@@ -276,6 +276,15 @@ case $basic_machine in
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
++ # JBG
++ nios2 | nios2-* | nios2el | nios2el-*)
++ basic_machine=nios2-altera
++ os=-none_el
++ ;;
++ nios2eb | nios2eb-*)
++ basic_machine=nios2-altera
++ os=-none_eb
++ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+
+diff --git a/gcc/combine.c b/gcc/combine.c
+index 8f43c23..02648b1 100644
+--- a/gcc/combine.c
++++ b/gcc/combine.c
+@@ -4381,6 +4381,14 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int last,
mode);
}
@@ -26,7 +37,7 @@
else if (STORE_FLAG_VALUE == 1
&& new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
&& op1 == const0_rtx
-@@ -4391,6 +4399,7 @@ combine_simplify_rtx (rtx x, enum machin
+@@ -4392,6 +4400,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int last,
gen_lowpart_for_combine (mode, op0),
const1_rtx);
}
@@ -34,8 +45,62 @@
else if (STORE_FLAG_VALUE == 1
&& new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
---- gcc-3.4.3/gcc/config/nios2/crti.asm
-+++ gcc-3.4.3-nios2/gcc/config/nios2/crti.asm
+diff --git a/gcc/config.gcc b/gcc/config.gcc
+index d22f34b..4ecb6e9 100644
+--- a/gcc/config.gcc
++++ b/gcc/config.gcc
+@@ -1337,6 +1337,17 @@ m32rle-*-linux*)
+ thread_file='posix'
+ fi
+ ;;
++# JBG
++nios2-*-elf*_eb)
++ tm_file="elfos.h nios2/big.h ${tm_file}"
++ ;;
++nios2-*-elf*)
++ tm_file="elfos.h ${tm_file}"
++ ;;
++nios2-*-uclibc*) # Altera Nios2 running uClinux with uClibc
++ tm_file="elfos.h ${tm_file} nios2/nios2-uclibc.h"
++ tmake_file=nios2/t-nios2-uclibc
++ ;;
+ # m68hc11 and m68hc12 share the same machine description.
+ m68hc11-*-*|m6811-*-*)
+ tm_file="dbxelf.h elfos.h m68hc11/m68hc11.h"
+diff --git a/gcc/config/nios2/big.h b/gcc/config/nios2/big.h
+new file mode 100644
+index 0000000..b7b1731
+--- /dev/null
++++ b/gcc/config/nios2/big.h
+@@ -0,0 +1,23 @@
++/*
++ big.h - Additional definitions for nios2 targets that default to big-endian
++
++ Copyright (C) 2006 Altera
++
++This file is part of GNU CC.
++
++GNU CC is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 2, or (at your option)
++any later version.
++
++GNU CC is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with GNU CC; see the file COPYING. If not, write to
++the Free Software Foundation, 59 Temple Place - Suite 330,
++Boston, MA 02111-1307, USA. */
++
++#define TARGET_ENDIAN_DEFAULT BIG_ENDIAN_FLAG
+diff --git a/gcc/config/nios2/crti.asm b/gcc/config/nios2/crti.asm
+new file mode 100644
+index 0000000..1fcfeb2
+--- /dev/null
++++ b/gcc/config/nios2/crti.asm
@@ -0,0 +1,88 @@
+/*
+ Copyright (C) 2003
@@ -125,8 +190,11 @@
+ mov fp, sp
+
+
---- gcc-3.4.3/gcc/config/nios2/crtn.asm
-+++ gcc-3.4.3-nios2/gcc/config/nios2/crtn.asm
+diff --git a/gcc/config/nios2/crtn.asm b/gcc/config/nios2/crtn.asm
+new file mode 100644
+index 0000000..e337480
+--- /dev/null
++++ b/gcc/config/nios2/crtn.asm
@@ -0,0 +1,70 @@
+/*
+ Copyright (C) 2003
@@ -198,8 +266,11 @@
+ addi sp, sp, -48
+ ret
+
---- gcc-3.4.3/gcc/config/nios2/lib2-divmod-hi.c
-+++ gcc-3.4.3-nios2/gcc/config/nios2/lib2-divmod-hi.c
+diff --git a/gcc/config/nios2/lib2-divmod-hi.c b/gcc/config/nios2/lib2-divmod-hi.c
+new file mode 100644
+index 0000000..10bd6e4
+--- /dev/null
++++ b/gcc/config/nios2/lib2-divmod-hi.c
@@ -0,0 +1,123 @@
+
+/* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is
@@ -324,8 +395,11 @@
+ return udivmodhi4 (a, b, 1);
+}
+
---- gcc-3.4.3/gcc/config/nios2/lib2-divmod.c
-+++ gcc-3.4.3-nios2/gcc/config/nios2/lib2-divmod.c
+diff --git a/gcc/config/nios2/lib2-divmod.c b/gcc/config/nios2/lib2-divmod.c
+new file mode 100644
+index 0000000..00e730d
+--- /dev/null
++++ b/gcc/config/nios2/lib2-divmod.c
@@ -0,0 +1,126 @@
+
+/* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is
@@ -453,8 +527,11 @@
+ return udivmodsi4 (a, b, 1);
+}
+
---- gcc-3.4.3/gcc/config/nios2/lib2-divtable.c
-+++ gcc-3.4.3-nios2/gcc/config/nios2/lib2-divtable.c
+diff --git a/gcc/config/nios2/lib2-divtable.c b/gcc/config/nios2/lib2-divtable.c
+new file mode 100644
+index 0000000..48a7bd7
+--- /dev/null
++++ b/gcc/config/nios2/lib2-divtable.c
@@ -0,0 +1,46 @@
+
+/* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is
@@ -502,8 +579,11 @@
+ 0, 15/1, 15/2, 15/3, 15/4, 15/5, 15/6, 15/7, 15/8, 15/9, 15/10, 15/11, 15/12, 15/13, 15/14, 15/15,
+};
+
---- gcc-3.4.3/gcc/config/nios2/lib2-mul.c
-+++ gcc-3.4.3-nios2/gcc/config/nios2/lib2-mul.c
+diff --git a/gcc/config/nios2/lib2-mul.c b/gcc/config/nios2/lib2-mul.c
+new file mode 100644
+index 0000000..8511b33
+--- /dev/null
++++ b/gcc/config/nios2/lib2-mul.c
@@ -0,0 +1,103 @@
+/* while we are debugging (ie compile outside of gcc build)
+ disable gcc specific headers */
@@ -608,10 +688,16 @@
+ return error;
+}
+#endif
---- gcc-3.4.3/gcc/config/nios2/nios2-dp-bit.c
-+++ gcc-3.4.3-nios2/gcc/config/nios2/nios2-dp-bit.c
-@@ -0,0 +1,1652 @@
-+
+diff --git a/gcc/config/nios2/nios2-dp-bit.c b/gcc/config/nios2/nios2-dp-bit.c
+new file mode 100644
+index 0000000..4d63748
+--- /dev/null
++++ b/gcc/config/nios2/nios2-dp-bit.c
+@@ -0,0 +1,1655 @@
++
++#ifndef __nios2_big_endian__
++#define FLOAT_BIT_ORDER_MISMATCH
++#endif
+/* This is a software floating point library which can be used
+ for targets without hardware floating point.
+ Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004
@@ -2263,10 +2349,16 @@
+
+#endif /* ! FLOAT */
+#endif /* !EXTENDED_FLOAT_STUBS */
---- gcc-3.4.3/gcc/config/nios2/nios2-fp-bit.c
-+++ gcc-3.4.3-nios2/gcc/config/nios2/nios2-fp-bit.c
-@@ -0,0 +1,1652 @@
+diff --git a/gcc/config/nios2/nios2-fp-bit.c b/gcc/config/nios2/nios2-fp-bit.c
+new file mode 100644
+index 0000000..839ffcc
+--- /dev/null
++++ b/gcc/config/nios2/nios2-fp-bit.c
+@@ -0,0 +1,1655 @@
+#define FLOAT
++#ifndef __nios2_big_endian__
++#define FLOAT_BIT_ORDER_MISMATCH
++#endif
+/* This is a software floating point library which can be used
+ for targets without hardware floating point.
+ Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004
@@ -3918,9 +4010,12 @@
+
+#endif /* ! FLOAT */
+#endif /* !EXTENDED_FLOAT_STUBS */
---- gcc-3.4.3/gcc/config/nios2/nios2-protos.h
-+++ gcc-3.4.3-nios2/gcc/config/nios2/nios2-protos.h
-@@ -0,0 +1,70 @@
+diff --git a/gcc/config/nios2/nios2-protos.h b/gcc/config/nios2/nios2-protos.h
+new file mode 100644
+index 0000000..dc75c4f
+--- /dev/null
++++ b/gcc/config/nios2/nios2-protos.h
+@@ -0,0 +1,78 @@
+/* Subroutines for assembler code output for Altera NIOS 2G NIOS2 version.
+ Copyright (C) 2003 Altera
+ Contributed by Jonah Graham (jgraham@altera.com).
@@ -3951,7 +4046,8 @@
+extern void expand_prologue (void);
+extern void expand_epilogue (bool);
+extern void function_profiler (FILE *, int);
-+
++extern enum reg_class reg_class_from_constraint (char, const char *);
++extern void nios2_register_target_pragmas (void);
+
+#ifdef RTX_CODE
+extern int nios2_legitimate_address (rtx, enum machine_mode, int);
@@ -3975,11 +4071,18 @@
+extern int custom_insn_opcode (rtx, enum machine_mode);
+extern int rdwrctl_operand (rtx, enum machine_mode);
+
++/* custom fpu instruction output */
++extern const char *nios2_output_fpu_insn_cmps (rtx, enum rtx_code);
++extern const char *nios2_output_fpu_insn_cmpd (rtx, enum rtx_code);
++
+# ifdef HAVE_MACHINE_MODES
+# if defined TREE_CODE
-+extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
+extern rtx function_arg (const CUMULATIVE_ARGS *, enum machine_mode, tree, int);
++extern int nios2_must_pass_in_stack (enum machine_mode, tree);
+extern int function_arg_partial_nregs (const CUMULATIVE_ARGS *, enum machine_mode, tree, int);
++extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
++extern int nios2_function_arg_padding (enum machine_mode, tree);
++extern int nios2_block_reg_padding (enum machine_mode, tree, int);
+extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
+extern int nios2_setup_incoming_varargs (const CUMULATIVE_ARGS *, enum machine_mode, tree, int);
+
@@ -3991,12 +4094,96 @@
+extern int nios2_return_in_memory (tree);
+
+#endif /* TREE_CODE */
---- gcc-3.4.3/gcc/config/nios2/nios2.c
-+++ gcc-3.4.3-nios2/gcc/config/nios2/nios2.c
-@@ -0,0 +1,2853 @@
+diff --git a/gcc/config/nios2/nios2-uclibc.h b/gcc/config/nios2/nios2-uclibc.h
+new file mode 100644
+index 0000000..af98cdd
+--- /dev/null
++++ b/gcc/config/nios2/nios2-uclibc.h
+@@ -0,0 +1,75 @@
++#ifdef USE_UCLIBC
++
++#undef TARGET_SWITCHES
++#define TARGET_SWITCHES \
++{ \
++ { "hw-div", HAS_DIV_FLAG, \
++ N_("Enable DIV, DIVU") }, \
++ { "no-hw-div", -HAS_DIV_FLAG, \
++ N_("Disable DIV, DIVU (default)") }, \
++ { "hw-mul", HAS_MUL_FLAG, \
++ N_("Enable MUL instructions (default)") }, \
++ { "hw-mulx", HAS_MULX_FLAG, \
++ N_("Enable MULX instructions, assume fast shifter") }, \
++ { "no-hw-mul", -HAS_MUL_FLAG, \
++ N_("Disable MUL instructions") }, \
++ { "no-hw-mulx", -HAS_MULX_FLAG, \
++ N_("Disable MULX instructions, assume slow shifter (default and implied by -mno-hw-mul)") }, \
++ { "fast-sw-div", FAST_SW_DIV_FLAG, \
++ N_("Use table based fast divide (default at -O3)") }, \
++ { "no-fast-sw-div", -FAST_SW_DIV_FLAG, \
++ N_("Don't use table based fast divide ever") }, \
++ { "inline-memcpy", INLINE_MEMCPY_FLAG, \
++ N_("Inline small memcpy (default when optimizing)") }, \
++ { "no-inline-memcpy", -INLINE_MEMCPY_FLAG, \
++ N_("Don't Inline small memcpy") }, \
++ { "cache-volatile", CACHE_VOLATILE_FLAG, \
++ N_("Volatile accesses use non-io variants of instructions (default)") }, \
++ { "no-cache-volatile", -CACHE_VOLATILE_FLAG, \
++ N_("Volatile accesses use io variants of instructions") }, \
++ { "bypass-cache", BYPASS_CACHE_FLAG, \
++ N_("All ld/st instructins use io variants") }, \
++ { "no-bypass-cache", -BYPASS_CACHE_FLAG, \
++ N_("All ld/st instructins do not use io variants (default)") }, \
++ { "smallc", 0, \
++ N_("Link with a limited version of the C library") }, \
++ { "stack-check", STACK_CHECK_FLAG, \
++ N_("Enable stack limit checking.") }, \
++ { "no-stack-check", -STACK_CHECK_FLAG, \
++ N_("Disable stack limit checking (default).") }, \
++ { "reverse-bitfields", REVERSE_BITFIELDS_FLAG, \
++ N_("Reverse the order of bitfields in a struct.") }, \
++ { "no-reverse-bitfields", -REVERSE_BITFIELDS_FLAG, \
++ N_("Use the normal order of bitfields in a struct (default).") }, \
++ { "eb", BIG_ENDIAN_FLAG, \
++ N_("Use big-endian byte order") }, \
++ { "el", -BIG_ENDIAN_FLAG, \
++ N_("Use little-endian byte order") }, \
++ { "", TARGET_DEFAULT, 0 } \
++}
++
++/* The GNU C++ standard library requires that these macros be defined. */
++#undef CPLUSPLUS_CPP_SPEC
++#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
++
++#undef LIB_SPEC
++#define LIB_SPEC \
++"--start-group %{msmallc: -lsmallc} %{!msmallc: -lc} -lgcc \
++ %{msys-lib=*: -l%*} \
++ %{!msys-lib=*: -lc} \
++ --end-group \
++ %{msys-lib=: %eYou need a library name for -msys-lib=} \
++"
++
++#undef STARTFILE_SPEC
++#define STARTFILE_SPEC \
++"%{msys-crt0=*: %*} %{!msys-crt0=*: crt1%O%s} \
++ %{msys-crt0=: %eYou need a C startup file for -msys-crt0=} \
++ crti%O%s crtbegin%O%s \
++"
++
++#undef ENDFILE_SPEC
++#define ENDFILE_SPEC \
++ " crtend%O%s crtn%O%s"
++
++#endif /* USE_UCLIBC */
+diff --git a/gcc/config/nios2/nios2.c b/gcc/config/nios2/nios2.c
+new file mode 100644
+index 0000000..8723a86
+--- /dev/null
++++ b/gcc/config/nios2/nios2.c
+@@ -0,0 +1,4694 @@
+/* Subroutines for assembler code output for Altera NIOS 2G NIOS2 version.
-+ Copyright (C) 2003 Altera
-+ Contributed by Jonah Graham (jgraham@altera.com).
++ Copyright (C) 2005 Altera
++ Contributed by Jonah Graham (jgraham@altera.com) and Will Reece (wreece@altera.com).
+
+This file is part of GNU CC.
+
@@ -4043,6 +4230,8 @@
+#include "optabs.h"
+#include "target.h"
+#include "target-def.h"
++#include "c-pragma.h" /* for c_register_pragma */
++#include "cpplib.h" /* for CPP_NUMBER */
+
+/* local prototypes */
+static bool nios2_rtx_costs (rtx, int, int, int *);
@@ -4055,6 +4244,16 @@
+static rtx save_reg (int, HOST_WIDE_INT, rtx);
+static rtx restore_reg (int, HOST_WIDE_INT);
+static unsigned int nios2_section_type_flags (tree, const char *, int);
++
++/* 0 --> no #pragma seen
++ 1 --> in scope of #pragma reverse_bitfields
++ -1 --> in scope of #pragma no_reverse_bitfields */
++static int nios2_pragma_reverse_bitfields_flag = 0;
++static void nios2_pragma_reverse_bitfields (struct cpp_reader *);
++static void nios2_pragma_no_reverse_bitfields (struct cpp_reader *);
++static tree nios2_handle_struct_attribute (tree *, tree, tree, int, bool *);
++static void nios2_insert_attributes (tree, tree *);
++static bool nios2_reverse_bitfield_layout_p (tree record_type);
+static void nios2_init_builtins (void);
+static rtx nios2_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
+static bool nios2_function_ok_for_sibcall (tree, tree);
@@ -4076,6 +4275,9 @@
+#undef TARGET_SECTION_TYPE_FLAGS
+#define TARGET_SECTION_TYPE_FLAGS nios2_section_type_flags
+
++#undef TARGET_REVERSE_BITFIELD_LAYOUT_P
++#define TARGET_REVERSE_BITFIELD_LAYOUT_P nios2_reverse_bitfield_layout_p
++
+#undef TARGET_INIT_BUILTINS
+#define TARGET_INIT_BUILTINS nios2_init_builtins
+#undef TARGET_EXPAND_BUILTIN
@@ -4087,6 +4289,24 @@
+#undef TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS nios2_rtx_costs
+
++const struct attribute_spec nios2_attribute_table[] =
++{
++ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
++ { "reverse_bitfields", 0, 0, false, false, false, nios2_handle_struct_attribute },
++ { "no_reverse_bitfields", 0, 0, false, false, false, nios2_handle_struct_attribute },
++ { "pragma_reverse_bitfields", 0, 0, false, false, false, NULL },
++ { "pragma_no_reverse_bitfields", 0, 0, false, false, false, NULL },
++ { NULL, 0, 0, false, false, false, NULL }
++};
++
++#undef TARGET_ATTRIBUTE_TABLE
++#define TARGET_ATTRIBUTE_TABLE nios2_attribute_table
++
++#undef TARGET_INSERT_ATTRIBUTES
++#define TARGET_INSERT_ATTRIBUTES nios2_insert_attributes
++
++/* ??? Might want to redefine TARGET_RETURN_IN_MSB here to handle
++ big-endian case; depends on what ABI we choose. */
+
+struct gcc_target targetm = TARGET_INITIALIZER;
+
@@ -4125,11 +4345,27 @@
+
+
+/***************************************
-+ * Section encodings
++ * Register Classes
+ ***************************************/
+
++enum reg_class
++reg_class_from_constraint (char chr, const char *str)
++{
++ if (chr == 'D' && ISDIGIT (str[1]) && ISDIGIT (str[2]))
++ {
++ int regno;
++ int ones = str[2] - '0';
++ int tens = str[1] - '0';
++
++ regno = ones + (10 * tens);
++ if (regno < 0 || regno > 31)
++ return NO_REGS;
+
++ return D00_REG + regno;
++ }
+
++ return NO_REGS;
++}
+
+
+/***************************************
@@ -4239,7 +4475,7 @@
+{
+ int i;
+ HOST_WIDE_INT total_frame_size;
-+ int cfa_store_offset;
++ int cfa_store_offset = 0;
+ rtx insn;
+ rtx cfa_store_reg = 0;
+
@@ -4304,6 +4540,11 @@
+ = cfun->machine->frame.save_regs_offset
+ + cfun->machine->frame.save_reg_rounded;
+ }
++
++ if (current_function_limit_stack)
++ {
++ emit_insn (gen_stack_overflow_detect_and_trap ());
++ }
+ }
+
+ if (MUST_SAVE_REGISTER (RA_REGNO))
@@ -4433,17 +4674,11 @@
+ * ----------------------- */
+
+void
-+function_profiler (FILE *file, int labelno)
-+{
-+ fprintf (file, "\t%s mcount begin, label: .LP%d\n",
-+ ASM_COMMENT_START, labelno);
-+ fprintf (file, "\tnextpc\tr8\n");
-+ fprintf (file, "\tmov\tr9, ra\n");
-+ fprintf (file, "\tmovhi\tr10, %%hiadj(.LP%d)\n", labelno);
-+ fprintf (file, "\taddi\tr10, r10, %%lo(.LP%d)\n", labelno);
++function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
++{
++ fprintf (file, "\tmov\tr8, ra\n");
+ fprintf (file, "\tcall\tmcount\n");
-+ fprintf (file, "\tmov\tra, r9\n");
-+ fprintf (file, "\t%s mcount end\n", ASM_COMMENT_START);
++ fprintf (file, "\tmov\tra, r8\n");
+}
+
+
@@ -4593,13 +4828,490 @@
+ *
+ ***************************************/
+
++/*
++ * Try to take a bit of tedium out of the __builtin_custom_<blah>
++ * builtin functions, too.
++ */
++
++#define NIOS2_FOR_ALL_CUSTOM_BUILTINS \
++ NIOS2_DO_BUILTIN (N, n, n ) \
++ NIOS2_DO_BUILTIN (NI, ni, nX ) \
++ NIOS2_DO_BUILTIN (NF, nf, nX ) \
++ NIOS2_DO_BUILTIN (NP, np, nX ) \
++ NIOS2_DO_BUILTIN (NII, nii, nXX ) \
++ NIOS2_DO_BUILTIN (NIF, nif, nXX ) \
++ NIOS2_DO_BUILTIN (NIP, nip, nXX ) \
++ NIOS2_DO_BUILTIN (NFI, nfi, nXX ) \
++ NIOS2_DO_BUILTIN (NFF, nff, nXX ) \
++ NIOS2_DO_BUILTIN (NFP, nfp, nXX ) \
++ NIOS2_DO_BUILTIN (NPI, npi, nXX ) \
++ NIOS2_DO_BUILTIN (NPF, npf, nXX ) \
++ NIOS2_DO_BUILTIN (NPP, npp, nXX ) \
++ NIOS2_DO_BUILTIN (IN, in, Xn ) \
++ NIOS2_DO_BUILTIN (INI, ini, XnX ) \
++ NIOS2_DO_BUILTIN (INF, inf, XnX ) \
++ NIOS2_DO_BUILTIN (INP, inp, XnX ) \
++ NIOS2_DO_BUILTIN (INII, inii, XnXX ) \
++ NIOS2_DO_BUILTIN (INIF, inif, XnXX ) \
++ NIOS2_DO_BUILTIN (INIP, inip, XnXX ) \
++ NIOS2_DO_BUILTIN (INFI, infi, XnXX ) \
++ NIOS2_DO_BUILTIN (INFF, inff, XnXX ) \
++ NIOS2_DO_BUILTIN (INFP, infp, XnXX ) \
++ NIOS2_DO_BUILTIN (INPI, inpi, XnXX ) \
++ NIOS2_DO_BUILTIN (INPF, inpf, XnXX ) \
++ NIOS2_DO_BUILTIN (INPP, inpp, XnXX ) \
++ NIOS2_DO_BUILTIN (FN, fn, Xn ) \
++ NIOS2_DO_BUILTIN (FNI, fni, XnX ) \
++ NIOS2_DO_BUILTIN (FNF, fnf, XnX ) \
++ NIOS2_DO_BUILTIN (FNP, fnp, XnX ) \
++ NIOS2_DO_BUILTIN (FNII, fnii, XnXX ) \
++ NIOS2_DO_BUILTIN (FNIF, fnif, XnXX ) \
++ NIOS2_DO_BUILTIN (FNIP, fnip, XnXX ) \
++ NIOS2_DO_BUILTIN (FNFI, fnfi, XnXX ) \
++ NIOS2_DO_BUILTIN (FNFF, fnff, XnXX ) \
++ NIOS2_DO_BUILTIN (FNFP, fnfp, XnXX ) \
++ NIOS2_DO_BUILTIN (FNPI, fnpi, XnXX ) \
++ NIOS2_DO_BUILTIN (FNPF, fnpf, XnXX ) \
++ NIOS2_DO_BUILTIN (FNPP, fnpp, XnXX ) \
++ NIOS2_DO_BUILTIN (PN, pn, Xn ) \
++ NIOS2_DO_BUILTIN (PNI, pni, XnX ) \
++ NIOS2_DO_BUILTIN (PNF, pnf, XnX ) \
++ NIOS2_DO_BUILTIN (PNP, pnp, XnX ) \
++ NIOS2_DO_BUILTIN (PNII, pnii, XnXX ) \
++ NIOS2_DO_BUILTIN (PNIF, pnif, XnXX ) \
++ NIOS2_DO_BUILTIN (PNIP, pnip, XnXX ) \
++ NIOS2_DO_BUILTIN (PNFI, pnfi, XnXX ) \
++ NIOS2_DO_BUILTIN (PNFF, pnff, XnXX ) \
++ NIOS2_DO_BUILTIN (PNFP, pnfp, XnXX ) \
++ NIOS2_DO_BUILTIN (PNPI, pnpi, XnXX ) \
++ NIOS2_DO_BUILTIN (PNPF, pnpf, XnXX ) \
++ NIOS2_DO_BUILTIN (PNPP, pnpp, XnXX )
++
+const char *nios2_sys_nosys_string; /* for -msys=nosys */
+const char *nios2_sys_lib_string; /* for -msys-lib= */
+const char *nios2_sys_crt0_string; /* for -msys-crt0= */
+
++#undef NIOS2_FPU_INSN
++#define NIOS2_FPU_INSN(opt, insn, args) \
++static const char *NIOS2_CONCAT (nios2_output_fpu_insn_, insn) (rtx); \
++static void NIOS2_CONCAT (nios2_pragma_, insn) (struct cpp_reader *); \
++static void NIOS2_CONCAT (nios2_pragma_no_, insn) (struct cpp_reader *);
++NIOS2_FOR_ALL_FPU_INSNS
++
++nios2_fpu_info nios2_fpu_insns[nios2_fpu_max_insn] = {
++#undef NIOS2_FPU_INSN
++#define NIOS2_FPU_INSN(opt, insn, args) \
++ { NIOS2_STRINGIFY (opt), \
++ NIOS2_STRINGIFY (insn), \
++ NIOS2_STRINGIFY (args), \
++ 0, \
++ -1, \
++ NIOS2_CONCAT (nios2_output_fpu_insn_, insn), \
++ "custom_" NIOS2_STRINGIFY (opt), \
++ NIOS2_CONCAT (nios2_pragma_, insn), \
++ "no_custom_" NIOS2_STRINGIFY (opt), \
++ NIOS2_CONCAT (nios2_pragma_no_, insn), \
++ 0, \
++ 0, \
++ 0, \
++ 0, \
++ 0 },
++ NIOS2_FOR_ALL_FPU_INSNS
++};
++
++const char *nios2_custom_fpu_cfg_string;
++
++static const char *builtin_custom_seen[256];
++
++static void
++nios2_custom_switch (const char *parameter, int *value, const char *opt)
++{
++ /*
++ * We only document values from 0-255, but we secretly allow -1 so
++ * that the -mno-custom-<opt> switches work.
++ */
++ if (parameter && *parameter)
++ {
++ char *endptr;
++ long v = strtol (parameter, &endptr, 0);
++ if (*endptr)
++ {
++ error ("switch `-mcustom-%s' value `%s' must be a number between 0 and 255",
++ opt, parameter);
++ }
++ if (v < -1 || v > 255)
++ {
++ error ("switch `-mcustom-%s' value %ld must be between 0 and 255",
++ opt, v);
++ }
++ *value = (int)v;
++ }
++}
++
++static void
++nios2_custom_check_insns (int is_pragma)
++{
++ int i;
++ int has_double = 0;
++ int errors = 0;
++ const char *ns[256];
++ int ps[256];
++
++ for (i = 0; i < nios2_fpu_max_insn; i++)
++ {
++ if (nios2_fpu_insns[i].is_double && nios2_fpu_insns[i].N >= 0)
++ {
++ has_double = 1;
++ }
++ }
++
++ if (has_double)
++ {
++ for (i = 0; i < nios2_fpu_max_insn; i++)
++ {
++ if (nios2_fpu_insns[i].needed_by_double
++ && nios2_fpu_insns[i].N < 0)
++ {
++ if (is_pragma)
++ {
++ error ("either switch `-mcustom-%s' or `#pragma custom_%s' is required for double precision floating point",
++ nios2_fpu_insns[i].option,
++ nios2_fpu_insns[i].option);
++ }
++ else
++ {
++ error ("switch `-mcustom-%s' is required for double precision floating point",
++ nios2_fpu_insns[i].option);
++ }
++ errors = 1;
++ }
++ }
++ }
++
++ /*
++ * Warn if the user has certain exotic operations that won't get used
++ * without -funsafe-math-optimizations, See expand_builtin () in
++ * bulitins.c.
++ */
++ if (!flag_unsafe_math_optimizations)
++ {
++ for (i = 0; i < nios2_fpu_max_insn; i++)
++ {
++ if (nios2_fpu_insns[i].needs_unsafe && nios2_fpu_insns[i].N >= 0)
++ {
++ warning ("%s%s' has no effect unless -funsafe-math-optimizations is specified",
++ is_pragma ? "`#pragma custom_" : "switch `-mcustom-",
++ nios2_fpu_insns[i].option);
++ /* Just one warning per function per compilation unit, please. */
++ nios2_fpu_insns[i].needs_unsafe = 0;
++ }
++ }
++ }
++
++ /*
++ * Warn if the user is trying to use -mcustom-fmins et. al, that won't
++ * get used without -ffinite-math-only. See fold in fold () in
++ * fold-const.c
++ */
++ if (!flag_finite_math_only)
++ {
++ for (i = 0; i < nios2_fpu_max_insn; i++)
++ {
++ if (nios2_fpu_insns[i].needs_finite && nios2_fpu_insns[i].N >= 0)
++ {
++ warning ("%s%s' has no effect unless -ffinite-math-only is specified",
++ is_pragma ? "`#pragma custom_" : "switch `-mcustom-",
++ nios2_fpu_insns[i].option);
++ /* Just one warning per function per compilation unit, please. */
++ nios2_fpu_insns[i].needs_finite = 0;
++ }
++ }
++ }
++
++ /*
++ * Warn the user about double precision divide braindamage until we
++ * can fix it properly. See the RDIV_EXPR case of expand_expr_real in
++ * expr.c.
++ */
++ {
++ static int warned = 0;
++ if (flag_unsafe_math_optimizations
++ && !optimize_size
++ && nios2_fpu_insns[nios2_fpu_divdf3].N >= 0
++ && !warned)
++ {
++ warning ("%s%s' behaves poorly without -Os",
++ is_pragma ? "`#pragma custom_" : "switch `-mcustom-",
++ nios2_fpu_insns[nios2_fpu_divdf3].option);
++ warned = 1;
++ }
++ }
++
++ /*
++ * The following bit of voodoo is lifted from the generated file
++ * insn-opinit.c: to allow #pragmas to work properly, we have to tweak
++ * the optab_table manually -- it only gets initialized once after the
++ * switches are handled and before any #pragmas are seen.
++ */
++ if (is_pragma)
++ {
++ /* Only do this if the optabs have already been defined, not
++ when we're handling command line switches. */
++ addv_optab->handlers[SFmode].insn_code =
++ add_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++ addv_optab->handlers[DFmode].insn_code =
++ add_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++ subv_optab->handlers[SFmode].insn_code =
++ sub_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++ subv_optab->handlers[DFmode].insn_code =
++ sub_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++ smulv_optab->handlers[SFmode].insn_code =
++ smul_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++ smulv_optab->handlers[DFmode].insn_code =
++ smul_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++ sdiv_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++ sdiv_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++ negv_optab->handlers[SFmode].insn_code =
++ neg_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++ negv_optab->handlers[DFmode].insn_code =
++ neg_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++ smin_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++ smin_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++ smax_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++ smax_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++ absv_optab->handlers[SFmode].insn_code =
++ abs_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++ absv_optab->handlers[DFmode].insn_code =
++ abs_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++ sqrt_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++ sqrt_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++ cos_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++ cos_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++ sin_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++ sin_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++ tan_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++ tan_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++ atan_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++ atan_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++ exp_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++ exp_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++ log_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++ log_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++ sfloat_optab->handlers[SFmode][SImode].insn_code = CODE_FOR_nothing;
++ sfloat_optab->handlers[DFmode][SImode].insn_code = CODE_FOR_nothing;
++ ufloat_optab->handlers[SFmode][SImode].insn_code = CODE_FOR_nothing;
++ ufloat_optab->handlers[DFmode][SImode].insn_code = CODE_FOR_nothing;
++ sfix_optab->handlers[SImode][SFmode].insn_code = CODE_FOR_nothing;
++ sfix_optab->handlers[SImode][DFmode].insn_code = CODE_FOR_nothing;
++ ufix_optab->handlers[SImode][SFmode].insn_code = CODE_FOR_nothing;
++ ufix_optab->handlers[SImode][DFmode].insn_code = CODE_FOR_nothing;
++ sext_optab->handlers[DFmode][SFmode].insn_code = CODE_FOR_nothing;
++ trunc_optab->handlers[SFmode][DFmode].insn_code = CODE_FOR_nothing;
++ cmp_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++ cmp_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++
++ if (HAVE_addsf3)
++ addv_optab->handlers[SFmode].insn_code =
++ add_optab->handlers[SFmode].insn_code = CODE_FOR_addsf3;
++ if (HAVE_adddf3)
++ addv_optab->handlers[DFmode].insn_code =
++ add_optab->handlers[DFmode].insn_code = CODE_FOR_adddf3;
++ if (HAVE_subsf3)
++ subv_optab->handlers[SFmode].insn_code =
++ sub_optab->handlers[SFmode].insn_code = CODE_FOR_subsf3;
++ if (HAVE_subdf3)
++ subv_optab->handlers[DFmode].insn_code =
++ sub_optab->handlers[DFmode].insn_code = CODE_FOR_subdf3;
++ if (HAVE_mulsf3)
++ smulv_optab->handlers[SFmode].insn_code =
++ smul_optab->handlers[SFmode].insn_code = CODE_FOR_mulsf3;
++ if (HAVE_muldf3)
++ smulv_optab->handlers[DFmode].insn_code =
++ smul_optab->handlers[DFmode].insn_code = CODE_FOR_muldf3;
++ if (HAVE_divsf3)
++ sdiv_optab->handlers[SFmode].insn_code = CODE_FOR_divsf3;
++ if (HAVE_divdf3)
++ sdiv_optab->handlers[DFmode].insn_code = CODE_FOR_divdf3;
++ if (HAVE_negsf2)
++ negv_optab->handlers[SFmode].insn_code =
++ neg_optab->handlers[SFmode].insn_code = CODE_FOR_negsf2;
++ if (HAVE_negdf2)
++ negv_optab->handlers[DFmode].insn_code =
++ neg_optab->handlers[DFmode].insn_code = CODE_FOR_negdf2;
++ if (HAVE_minsf3)
++ smin_optab->handlers[SFmode].insn_code = CODE_FOR_minsf3;
++ if (HAVE_mindf3)
++ smin_optab->handlers[DFmode].insn_code = CODE_FOR_mindf3;
++ if (HAVE_maxsf3)
++ smax_optab->handlers[SFmode].insn_code = CODE_FOR_maxsf3;
++ if (HAVE_maxdf3)
++ smax_optab->handlers[DFmode].insn_code = CODE_FOR_maxdf3;
++ if (HAVE_abssf2)
++ absv_optab->handlers[SFmode].insn_code =
++ abs_optab->handlers[SFmode].insn_code = CODE_FOR_abssf2;
++ if (HAVE_absdf2)
++ absv_optab->handlers[DFmode].insn_code =
++ abs_optab->handlers[DFmode].insn_code = CODE_FOR_absdf2;
++ if (HAVE_sqrtsf2)
++ sqrt_optab->handlers[SFmode].insn_code = CODE_FOR_sqrtsf2;
++ if (HAVE_sqrtdf2)
++ sqrt_optab->handlers[DFmode].insn_code = CODE_FOR_sqrtdf2;
++ if (HAVE_cossf2)
++ cos_optab->handlers[SFmode].insn_code = CODE_FOR_cossf2;
++ if (HAVE_cosdf2)
++ cos_optab->handlers[DFmode].insn_code = CODE_FOR_cosdf2;
++ if (HAVE_sinsf2)
++ sin_optab->handlers[SFmode].insn_code = CODE_FOR_sinsf2;
++ if (HAVE_sindf2)
++ sin_optab->handlers[DFmode].insn_code = CODE_FOR_sindf2;
++ if (HAVE_tansf2)
++ tan_optab->handlers[SFmode].insn_code = CODE_FOR_tansf2;
++ if (HAVE_tandf2)
++ tan_optab->handlers[DFmode].insn_code = CODE_FOR_tandf2;
++ if (HAVE_atansf2)
++ atan_optab->handlers[SFmode].insn_code = CODE_FOR_atansf2;
++ if (HAVE_atandf2)
++ atan_optab->handlers[DFmode].insn_code = CODE_FOR_atandf2;
++ if (HAVE_expsf2)
++ exp_optab->handlers[SFmode].insn_code = CODE_FOR_expsf2;
++ if (HAVE_expdf2)
++ exp_optab->handlers[DFmode].insn_code = CODE_FOR_expdf2;
++ if (HAVE_logsf2)
++ log_optab->handlers[SFmode].insn_code = CODE_FOR_logsf2;
++ if (HAVE_logdf2)
++ log_optab->handlers[DFmode].insn_code = CODE_FOR_logdf2;
++ if (HAVE_floatsisf2)
++ sfloat_optab->handlers[SFmode][SImode].insn_code = CODE_FOR_floatsisf2;
++ if (HAVE_floatsidf2)
++ sfloat_optab->handlers[DFmode][SImode].insn_code = CODE_FOR_floatsidf2;
++ if (HAVE_floatunssisf2)
++ ufloat_optab->handlers[SFmode][SImode].insn_code = CODE_FOR_floatunssisf2;
++ if (HAVE_floatunssidf2)
++ ufloat_optab->handlers[DFmode][SImode].insn_code = CODE_FOR_floatunssidf2;
++ if (HAVE_fixsfsi2)
++ sfix_optab->handlers[SImode][SFmode].insn_code = CODE_FOR_fixsfsi2;
++ if (HAVE_fixdfsi2)
++ sfix_optab->handlers[SImode][DFmode].insn_code = CODE_FOR_fixdfsi2;
++ if (HAVE_fixunssfsi2)
++ ufix_optab->handlers[SImode][SFmode].insn_code = CODE_FOR_fixunssfsi2;
++ if (HAVE_fixunsdfsi2)
++ ufix_optab->handlers[SImode][DFmode].insn_code = CODE_FOR_fixunsdfsi2;
++ if (HAVE_extendsfdf2)
++ sext_optab->handlers[DFmode][SFmode].insn_code = CODE_FOR_extendsfdf2;
++ if (HAVE_truncdfsf2)
++ trunc_optab->handlers[SFmode][DFmode].insn_code = CODE_FOR_truncdfsf2;
++ if (HAVE_cmpsf)
++ cmp_optab->handlers[SFmode].insn_code = CODE_FOR_cmpsf;
++ if (HAVE_cmpdf)
++ cmp_optab->handlers[DFmode].insn_code = CODE_FOR_cmpdf;
++ }
++
++ /* Check for duplicate values of N */
++ for (i = 0; i < 256; i++)
++ {
++ ns[i] = 0;
++ ps[i] = 0;
++ }
++
++ for (i = 0; i < nios2_fpu_max_insn; i++)
++ {
++ int N = nios2_fpu_insns[i].N;
++ if (N >= 0)
++ {
++ if (ns[N])
++ {
++ error ("%s%s' conflicts with %s%s'",
++ is_pragma ? "`#pragma custom_" : "switch `-mcustom-",
++ nios2_fpu_insns[i].option,
++ ps[N] ? "`#pragma custom_" : "switch `-mcustom-",
++ ns[N]);
++ errors = 1;
++ }
++ else if (builtin_custom_seen[N])
++ {
++ error ("call to `%s' conflicts with %s%s'",
++ builtin_custom_seen[N],
++ (nios2_fpu_insns[i].pragma_seen
++ ? "`#pragma custom_" : "switch `-mcustom-"),
++ nios2_fpu_insns[i].option);
++ errors = 1;
++ }
++ else
++ {
++ ns[N] = nios2_fpu_insns[i].option;
++ ps[N] = nios2_fpu_insns[i].pragma_seen;
++ }
++ }
++ }
++
++ if (errors)
++ {
++ fatal_error ("conflicting use of -mcustom switches, #pragmas, and/or __builtin_custom_ functions");
++ }
++}
++
++static void
++nios2_handle_custom_fpu_cfg (const char *cfg, int is_pragma)
++{
++#undef NIOS2_FPU_INSN
++#define NIOS2_FPU_INSN(opt, insn, args) \
++ int opt = nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)].N;
++NIOS2_FOR_ALL_FPU_INSNS
++
++ /*
++ * ??? These are just some sample possibilities. We'll change these
++ * at the last minute to match the capabilities of the actual fpu.
++ */
++ if (!strcasecmp (cfg, "60-1"))
++ {
++ fmuls = 252;
++ fadds = 253;
++ fsubs = 254;
++ flag_single_precision_constant = 1;
++ }
++ else if (!strcasecmp (cfg, "60-2"))
++ {
++ fmuls = 252;
++ fadds = 253;
++ fsubs = 254;
++ fdivs = 255;
++ flag_single_precision_constant = 1;
++ }
++ else if (!strcasecmp (cfg, "72-3"))
++ {
++ floatus = 243;
++ fixsi = 244;
++ floatis = 245;
++ fcmpgts = 246;
++ fcmples = 249;
++ fcmpeqs = 250;
++ fcmpnes = 251;
++ fmuls = 252;
++ fadds = 253;
++ fsubs = 254;
++ fdivs = 255;
++ flag_single_precision_constant = 1;
++ }
++ else
++ {
++ warning ("ignoring unrecognized %sfpu-cfg' value `%s'",
++ is_pragma ? "`#pragma custom_" : "switch -mcustom-", cfg);
++ }
++
++#undef NIOS2_FPU_INSN
++#define NIOS2_FPU_INSN(opt, insn, args) \
++ nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)].N = opt;
++NIOS2_FOR_ALL_FPU_INSNS
++
++ /* Guard against errors in the standard configurations. */
++ nios2_custom_check_insns (is_pragma);
++}
++
+void
+override_options ()
+{
++ int i;
++
+ /* Function to allocate machine-dependent function status. */
+ init_machine_status = &nios2_init_machine_status;
+
@@ -4617,6 +5329,69 @@
+ target_flags &= ~HAS_MULX_FLAG;
+ }
+
++ /* Set up for stack limit checking */
++ if (TARGET_STACK_CHECK)
++ {
++ stack_limit_rtx = gen_rtx_REG(SImode, ET_REGNO);
++ }
++
++ for (i = 0; i < nios2_fpu_max_insn; i++)
++ {
++ nios2_fpu_insns[i].is_double = (nios2_fpu_insns[i].args[0] == 'd'
++ || nios2_fpu_insns[i].args[0] == 'd'
++ || nios2_fpu_insns[i].args[0] == 'd');
++ nios2_fpu_insns[i].needed_by_double = (i == nios2_fpu_nios2_fwrx
++ || i == nios2_fpu_nios2_fwry
++ || i == nios2_fpu_nios2_frdxlo
++ || i == nios2_fpu_nios2_frdxhi
++ || i == nios2_fpu_nios2_frdy);
++ nios2_fpu_insns[i].needs_unsafe = (i == nios2_fpu_cossf2
++ || i == nios2_fpu_cosdf2
++ || i == nios2_fpu_sinsf2
++ || i == nios2_fpu_sindf2
++ || i == nios2_fpu_tansf2
++ || i == nios2_fpu_tandf2
++ || i == nios2_fpu_atansf2
++ || i == nios2_fpu_atandf2
++ || i == nios2_fpu_expsf2
++ || i == nios2_fpu_expdf2
++ || i == nios2_fpu_logsf2
++ || i == nios2_fpu_logdf2);
++ nios2_fpu_insns[i].needs_finite = (i == nios2_fpu_minsf3
++ || i == nios2_fpu_maxsf3
++ || i == nios2_fpu_mindf3
++ || i == nios2_fpu_maxdf3);
++ }
++
++ /*
++ * We haven't seen any __builtin_custom functions yet.
++ */
++ for (i = 0; i < 256; i++)
++ {
++ builtin_custom_seen[i] = 0;
++ }
++
++ /*
++ * Set up default handling for floating point custom instructions.
++ *
++ * Putting things in this order means that the -mcustom-fpu-cfg=
++ * switch will always be overridden by individual -mcustom-fadds=
++ * switches, regardless of the order in which they were specified
++ * on the command line. ??? Remember to document this.
++ */
++ if (nios2_custom_fpu_cfg_string && *nios2_custom_fpu_cfg_string)
++ {
++ nios2_handle_custom_fpu_cfg (nios2_custom_fpu_cfg_string, 0);
++ }
++
++ for (i = 0; i < nios2_fpu_max_insn; i++)
++ {
++ nios2_custom_switch (nios2_fpu_insns[i].value,
++ &nios2_fpu_insns[i].N,
++ nios2_fpu_insns[i].option);
++ }
++
++ nios2_custom_check_insns (0);
+}
+
+void
@@ -4926,6 +5701,78 @@
+ return test;
+}
+
++bool have_nios2_fpu_cmp_insn( enum rtx_code cond_t, enum cmp_type cmp_t );
++enum rtx_code get_reverse_cond(enum rtx_code cond_t);
++
++bool
++have_nios2_fpu_cmp_insn( enum rtx_code cond_t, enum cmp_type cmp_t )
++{
++ if (cmp_t == CMP_SF)
++ {
++ switch (cond_t) {
++ case EQ:
++ return (nios2_fpu_insns[nios2_fpu_nios2_seqsf].N >= 0);
++ case NE:
++ return (nios2_fpu_insns[nios2_fpu_nios2_snesf].N >= 0);
++ case GT:
++ return (nios2_fpu_insns[nios2_fpu_nios2_sgtsf].N >= 0);
++ case GE:
++ return (nios2_fpu_insns[nios2_fpu_nios2_sgesf].N >= 0);
++ case LT:
++ return (nios2_fpu_insns[nios2_fpu_nios2_sltsf].N >= 0);
++ case LE:
++ return (nios2_fpu_insns[nios2_fpu_nios2_slesf].N >= 0);
++ default:
++ break;
++ }
++ }
++ else if (cmp_t == CMP_DF)
++ {
++ switch (cond_t) {
++ case EQ:
++ return (nios2_fpu_insns[nios2_fpu_nios2_seqdf].N >= 0);
++ case NE:
++ return (nios2_fpu_insns[nios2_fpu_nios2_snedf].N >= 0);
++ case GT:
++ return (nios2_fpu_insns[nios2_fpu_nios2_sgtdf].N >= 0);
++ case GE:
++ return (nios2_fpu_insns[nios2_fpu_nios2_sgedf].N >= 0);
++ case LT:
++ return (nios2_fpu_insns[nios2_fpu_nios2_sltdf].N >= 0);
++ case LE:
++ return (nios2_fpu_insns[nios2_fpu_nios2_sledf].N >= 0);
++ default:
++ break;
++ }
++ }
++
++ return false;
++}
++
++/* Note that get_reverse_cond() is not the same as get_inverse_cond()
++ get_reverse_cond() means that if the operand order is reversed,
++ what is the operand that is needed to generate the same condition?
++*/
++enum rtx_code
++get_reverse_cond(enum rtx_code cond_t)
++{
++ switch (cond_t)
++ {
++ case GT: return LT;
++ case GE: return LE;
++ case LT: return GT;
++ case LE: return GE;
++ case GTU: return LTU;
++ case GEU: return LEU;
++ case LTU: return GTU;
++ case LEU: return GEU;
++ default: break;
++ }
++
++ return cond_t;
++}
++
++
+/* Generate the code to compare (and possibly branch) two integer values
+ TEST_CODE is the comparison code we are trying to emulate
+ (or implement directly)
@@ -4981,8 +5828,6 @@
+ int branch_p;
+
+
-+
-+
+ test = map_test_to_internal_test (test_code);
+ if (test == ITEST_MAX)
+ abort ();
@@ -4995,6 +5840,56 @@
+
+ branch_p = (destination != 0);
+
++ /* Handle floating point comparison directly. */
++ if (branch_type == CMP_SF || branch_type == CMP_DF)
++ {
++
++ bool reverse_operands = false;
++
++ enum machine_mode float_mode = (branch_type == CMP_SF) ? SFmode : DFmode;
++
++ if (!register_operand (cmp0, float_mode)
++ || !register_operand (cmp1, float_mode))
++ {
++ abort ();
++ }
++
++ if (branch_p)
++ {
++ test_code = p_info->test_code_reg;
++ reverse_operands = (p_info->reverse_regs);
++ }
++
++ if ( !have_nios2_fpu_cmp_insn(test_code, branch_type) &&
++ have_nios2_fpu_cmp_insn(get_reverse_cond(test_code), branch_type) )
++ {
++ test_code = get_reverse_cond(test_code);
++ reverse_operands = !reverse_operands;
++ }
++
++ if (reverse_operands)
++ {
++ rtx temp = cmp0;
++ cmp0 = cmp1;
++ cmp1 = temp;
++ }
++
++ if (branch_p)
++ {
++ rtx cond = gen_rtx (test_code, SImode, cmp0, cmp1);
++ rtx label = gen_rtx_LABEL_REF (VOIDmode, destination);
++ rtx insn = gen_rtx_SET (VOIDmode, pc_rtx,
++ gen_rtx_IF_THEN_ELSE (VOIDmode,
++ cond, label, pc_rtx));
++ emit_jump_insn (insn);
++ }
++ else
++ {
++ emit_move_insn (result, gen_rtx (test_code, SImode, cmp0, cmp1));
++ }
++ return;
++ }
++
+ /* We can't, under any circumstances, have const_ints in cmp0
+ ??? Actually we could have const0 */
+ if (GET_CODE (cmp0) == CONST_INT)
@@ -5172,10 +6067,10 @@
+
+ if (REG_P (op0) && REG_P (op1))
+ ret_val = 0;
-+ else if (REG_P (op0) && CONSTANT_P (op1))
++ else if (REG_P (op0) && GET_CODE (op1) == CONST_INT)
+ ret_val = REG_OK_FOR_BASE_P2 (op0, strict)
+ && SMALL_INT (INTVAL (op1));
-+ else if (REG_P (op1) && CONSTANT_P (op0))
++ else if (REG_P (op1) && GET_CODE (op0) == CONST_INT)
+ ret_val = REG_OK_FOR_BASE_P2 (op1, strict)
+ && SMALL_INT (INTVAL (op0));
+ else
@@ -5218,7 +6113,7 @@
+
+ /* If this is an incomplete type with size 0, then we can't put it
+ in sdata because it might be too big when completed. */
-+ if (size > 0 && size <= nios2_section_threshold)
++ if (size > 0 && (unsigned HOST_WIDE_INT)size <= nios2_section_threshold)
+ return true;
+ }
+
@@ -5269,7 +6164,221 @@
+ return flags;
+}
+
++/* Handle a #pragma reverse_bitfields */
++static void
++nios2_pragma_reverse_bitfields (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
++{
++ nios2_pragma_reverse_bitfields_flag = 1; /* Reverse */
++}
++
++/* Handle a #pragma no_reverse_bitfields */
++static void
++nios2_pragma_no_reverse_bitfields (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
++{
++ nios2_pragma_reverse_bitfields_flag = -1; /* Forward */
++}
++
++/* Handle the various #pragma custom_<switch>s */
++static void
++nios2_pragma_fpu (int *value, const char *opt, int *seen)
++{
++ tree t;
++ if (c_lex (&t) != CPP_NUMBER)
++ {
++ error ("`#pragma custom_%s' value must be a number between 0 and 255",
++ opt);
++ return;
++ }
++
++ if (TREE_INT_CST_HIGH (t) == 0
++ && TREE_INT_CST_LOW (t) <= 255)
++ {
++ *value = (int)TREE_INT_CST_LOW (t);
++ *seen = 1;
++ }
++ else
++ {
++ error ("`#pragma custom_%s' value must be between 0 and 255", opt);
++ }
++ nios2_custom_check_insns (1);
++}
++
++/* Handle the various #pragma no_custom_<switch>s */
++static void
++nios2_pragma_no_fpu (int *value, const char *opt ATTRIBUTE_UNUSED)
++{
++ *value = -1;
++ nios2_custom_check_insns (1);
++}
++
++#undef NIOS2_FPU_INSN
++#define NIOS2_FPU_INSN(opt, insn, args) \
++static void \
++NIOS2_CONCAT (nios2_pragma_, insn) \
++ (struct cpp_reader *pfile ATTRIBUTE_UNUSED) \
++{ \
++ nios2_fpu_info *inf = &(nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)]); \
++ nios2_pragma_fpu (&(inf->N), inf->option, &(inf->pragma_seen)); \
++} \
++static void \
++NIOS2_CONCAT (nios2_pragma_no_, insn) \
++ (struct cpp_reader *pfile ATTRIBUTE_UNUSED) \
++{ \
++ nios2_fpu_info *inf = &(nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)]); \
++ nios2_pragma_no_fpu (&(inf->N), inf->option); \
++}
++NIOS2_FOR_ALL_FPU_INSNS
++
++static void
++nios2_pragma_handle_custom_fpu_cfg (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
++{
++ tree t;
++ if (c_lex (&t) != CPP_STRING)
++ {
++ error ("`#pragma custom_fpu_cfg' value must be a string");
++ return;
++ }
++
++ if (TREE_STRING_LENGTH (t) > 0)
++ {
++ nios2_handle_custom_fpu_cfg (TREE_STRING_POINTER (t), 1);
++ }
++}
++
++void
++nios2_register_target_pragmas ()
++{
++ int i;
++
++ c_register_pragma (0, "reverse_bitfields",
++ nios2_pragma_reverse_bitfields);
++ c_register_pragma (0, "no_reverse_bitfields",
++ nios2_pragma_no_reverse_bitfields);
++
++ for (i = 0; i < nios2_fpu_max_insn; i++)
++ {
++ nios2_fpu_info *inf = &(nios2_fpu_insns[i]);
++ c_register_pragma (0, inf->pname, inf->pragma);
++ c_register_pragma (0, inf->nopname, inf->nopragma);
++ }
++
++ c_register_pragma (0, "custom_fpu_cfg",
++ nios2_pragma_handle_custom_fpu_cfg);
++}
++
++/* Handle a "reverse_bitfields" or "no_reverse_bitfields" attribute.
++ ??? What do these attributes mean on a union? */
++static tree
++nios2_handle_struct_attribute (tree *node, tree name,
++ tree args ATTRIBUTE_UNUSED,
++ int flags ATTRIBUTE_UNUSED,
++ bool *no_add_attrs)
++{
++ tree *type = NULL;
++ if (DECL_P (*node))
++ {
++ if (TREE_CODE (*node) == TYPE_DECL)
++ {
++ type = &TREE_TYPE (*node);
++ }
++ }
++ else
++ {
++ type = node;
++ }
++
++ if (!(type && (TREE_CODE (*type) == RECORD_TYPE
++ || TREE_CODE (*type) == UNION_TYPE)))
++ {
++ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
++ *no_add_attrs = true;
++ }
++
++ else if ((is_attribute_p ("reverse_bitfields", name)
++ && lookup_attribute ("no_reverse_bitfields",
++ TYPE_ATTRIBUTES (*type)))
++ || ((is_attribute_p ("no_reverse_bitfields", name)
++ && lookup_attribute ("reverse_bitfields",
++ TYPE_ATTRIBUTES (*type)))))
++ {
++ warning ("`%s' incompatible attribute ignored",
++ IDENTIFIER_POINTER (name));
++ *no_add_attrs = true;
++ }
++
++ return NULL_TREE;
++}
++
++/*
++ Add __attribute__ ((pragma_reverse_bitfields)) when in the scope of a
++ #pragma reverse_bitfields, or __attribute__
++ ((pragma_no_reverse_bitfields)) when in the scope of a #pragma
++ no_reverse_bitfields. This gets called before
++ nios2_handle_struct_attribute above, so we can't just reuse the same
++ attributes.
++*/
++static void
++nios2_insert_attributes (tree node, tree *attr_ptr)
++{
++ tree type = NULL;
++ if (DECL_P (node))
++ {
++ if (TREE_CODE (node) == TYPE_DECL)
++ {
++ type = TREE_TYPE (node);
++ }
++ }
++ else
++ {
++ type = node;
++ }
++
++ if (!type
++ || (TREE_CODE (type) != RECORD_TYPE
++ && TREE_CODE (type) != UNION_TYPE))
++ {
++ /* We can ignore things other than structs & unions */
++ return;
++ }
++
++ if (lookup_attribute ("reverse_bitfields", TYPE_ATTRIBUTES (type))
++ || lookup_attribute ("no_reverse_bitfields", TYPE_ATTRIBUTES (type)))
++ {
++ /* If an attribute is already set, it silently overrides the
++ current #pragma, if any */
++ return;
++ }
+
++ if (nios2_pragma_reverse_bitfields_flag)
++ {
++ const char *id = (nios2_pragma_reverse_bitfields_flag == 1 ?
++ "pragma_reverse_bitfields" :
++ "pragma_no_reverse_bitfields");
++ /* No attribute set, and we are in the scope of a #pragma */
++ *attr_ptr = tree_cons (get_identifier (id), NULL, *attr_ptr);
++ }
++}
++
++
++/*
++ * The attributes take precedence over the pragmas, which in turn take
++ * precedence over the compile-time switches.
++ */
++static bool
++nios2_reverse_bitfield_layout_p (tree record_type)
++{
++ return ((TARGET_REVERSE_BITFIELDS
++ && !lookup_attribute ("pragma_no_reverse_bitfields",
++ TYPE_ATTRIBUTES (record_type))
++ && !lookup_attribute ("no_reverse_bitfields",
++ TYPE_ATTRIBUTES (record_type)))
++ || (lookup_attribute ("pragma_reverse_bitfields",
++ TYPE_ATTRIBUTES (record_type))
++ && !lookup_attribute ("no_reverse_bitfields",
++ TYPE_ATTRIBUTES (record_type)))
++ || lookup_attribute ("reverse_bitfields",
++ TYPE_ATTRIBUTES (record_type)));
++}
+
+
+/*****************************************
@@ -5296,6 +6405,7 @@
+ H: for %hiadj
+ L: for %lo
+ U: for upper half of 32 bit value
++ D: for the upper 32-bits of a 64-bit double value
+ */
+
+void
@@ -5338,6 +6448,12 @@
+ fprintf (file, "%s", reg_names[REGNO (op)]);
+ return;
+ }
++ else if (letter == 'D')
++ {
++ fprintf (file, "%s", reg_names[REGNO (op)+1]);
++ return;
++ }
++ break;
+
+ case CONST_INT:
+ if (INTVAL (op) == 0 && letter == 'z')
@@ -5379,6 +6495,7 @@
+ fprintf (file, ")");
+ return;
+ }
++ break;
+
+
+ case SUBREG:
@@ -5388,6 +6505,7 @@
+ output_address (op);
+ return;
+ }
++ break;
+
+ case CODE_LABEL:
+ if (letter == 0)
@@ -5395,6 +6513,7 @@
+ output_addr_const (file, op);
+ return;
+ }
++ break;
+
+ default:
+ break;
@@ -5575,6 +6694,431 @@
+
+
+
++/*****************************************************************************
++**
++** custom fpu instruction output
++**
++*****************************************************************************/
++
++static const char *nios2_custom_fpu_insn_zdz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_zsz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_szz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_sss (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_ssz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_iss (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_ddd (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_ddz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_idd (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_siz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_suz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_diz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_duz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_isz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_usz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_idz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_udz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_dsz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_sdz (rtx, int, const char *);
++
++static const char *
++nios2_custom_fpu_insn_zdz (rtx insn, int N, const char *opt)
++{
++ static char buf[1024];
++
++ if (N < 0)
++ {
++ fatal_insn ("attempt to use disabled fpu instruction", insn);
++ }
++ if (snprintf (buf, sizeof (buf),
++ "custom\t%d, zero, %%0, %%D0 # %s %%0",
++ N, opt) >= (int)sizeof (buf))
++ {
++ fatal_insn ("buffer overflow", insn);
++ }
++ return buf;
++}
++
++static const char *
++nios2_custom_fpu_insn_zsz (rtx insn, int N, const char *opt)
++{
++ static char buf[1024];
++
++ if (N < 0)
++ {
++ fatal_insn ("attempt to use disabled fpu instruction", insn);
++ }
++ if (snprintf (buf, sizeof (buf),
++ "custom\t%d, zero, %%0, zero # %s %%0",
++ N, opt) >= (int)sizeof (buf))
++ {
++ fatal_insn ("buffer overflow", insn);
++ }
++ return buf;
++}
++
++static const char *
++nios2_custom_fpu_insn_szz (rtx insn, int N, const char *opt)
++{
++ static char buf[1024];
++
++ if (N < 0)
++ {
++ fatal_insn ("attempt to use disabled fpu instruction", insn);
++ }
++ if (snprintf (buf, sizeof (buf),
++ "custom\t%d, %%0, zero, zero # %s %%0",
++ N, opt) >= (int)sizeof (buf))
++ {
++ fatal_insn ("buffer overflow", insn);
++ }
++ return buf;
++}
++
++static const char *
++nios2_custom_fpu_insn_sss (rtx insn, int N, const char *opt)
++{
++ static char buf[1024];
++
++ if (N < 0)
++ {
++ fatal_insn ("attempt to use disabled fpu instruction", insn);
++ }
++ if (snprintf (buf, sizeof (buf),
++ "custom\t%d, %%0, %%1, %%2 # %s %%0, %%1, %%2",
++ N, opt) >= (int)sizeof (buf))
++ {
++ fatal_insn ("buffer overflow", insn);
++ }
++ return buf;
++}
++
++static const char *
++nios2_custom_fpu_insn_ssz (rtx insn, int N, const char *opt)
++{
++ static char buf[1024];
++
++ if (N < 0)
++ {
++ fatal_insn ("attempt to use disabled fpu instruction", insn);
++ }
++ if (snprintf (buf, sizeof (buf),
++ "custom\t%d, %%0, %%1, zero # %s %%0, %%1",
++ N, opt) >= (int)sizeof (buf))
++ {
++ fatal_insn ("buffer overflow", insn);
++ }
++ return buf;
++}
++
++static const char *
++nios2_custom_fpu_insn_iss (rtx insn, int N, const char *opt)
++{
++ return nios2_custom_fpu_insn_sss (insn, N, opt);
++}
++
++static const char *
++nios2_custom_fpu_insn_ddd (rtx insn, int N, const char *opt)
++{
++ static char buf[1024];
++
++ if (N < 0
++ || nios2_fpu_insns[nios2_fpu_nios2_frdy].N < 0
++ || nios2_fpu_insns[nios2_fpu_nios2_fwrx].N < 0)
++ {
++ fatal_insn ("attempt to use disabled fpu instruction", insn);
++ }
++ if (snprintf (buf, sizeof (buf),
++ "custom\t%d, zero, %%1, %%D1 # fwrx %%1\n\t"
++ "custom\t%d, %%D0, %%2, %%D2 # %s %%0, %%1, %%2\n\t"
++ "custom\t%d, %%0, zero, zero # frdy %%0",
++ nios2_fpu_insns[nios2_fpu_nios2_fwrx].N,
++ N, opt,
++ nios2_fpu_insns[nios2_fpu_nios2_frdy].N) >= (int)sizeof (buf))
++ {
++ fatal_insn ("buffer overflow", insn);
++ }
++ return buf;
++}
++
++static const char *
++nios2_custom_fpu_insn_ddz (rtx insn, int N, const char *opt)
++{
++ static char buf[1024];
++
++ if (N < 0 || nios2_fpu_insns[nios2_fpu_nios2_frdy].N < 0)
++ {
++ fatal_insn ("attempt to use disabled fpu instruction", insn);
++ }
++ if (snprintf (buf, sizeof (buf),
++ "custom\t%d, %%D0, %%1, %%D1 # %s %%0, %%1\n\t"
++ "custom\t%d, %%0, zero, zero # frdy %%0",
++ N, opt,
++ nios2_fpu_insns[nios2_fpu_nios2_frdy].N) >= (int)sizeof (buf))
++ {
++ fatal_insn ("buffer overflow", insn);
++ }
++ return buf;
++}
++
++static const char *
++nios2_custom_fpu_insn_idd (rtx insn, int N, const char *opt)
++{
++ static char buf[1024];
++
++ if (N < 0 || nios2_fpu_insns[nios2_fpu_nios2_fwrx].N < 0)
++ {
++ fatal_insn ("attempt to use disabled fpu instruction", insn);
++ }
++ if (snprintf (buf, sizeof (buf),
++ "custom\t%d, zero, %%1, %%D1 # fwrx %%1\n\t"
++ "custom\t%d, %%0, %%2, %%D2 # %s %%0, %%1, %%2",
++ nios2_fpu_insns[nios2_fpu_nios2_fwrx].N,
++ N, opt) >= (int)sizeof (buf))
++ {
++ fatal_insn ("buffer overflow", insn);
++ }
++ return buf;
++}
++
++static const char *
++nios2_custom_fpu_insn_siz (rtx insn, int N, const char *opt)
++{
++ return nios2_custom_fpu_insn_ssz (insn, N, opt);
++}
++
++static const char *
++nios2_custom_fpu_insn_suz (rtx insn, int N, const char *opt)
++{
++ return nios2_custom_fpu_insn_ssz (insn, N, opt);
++}
++
++static const char *
++nios2_custom_fpu_insn_diz (rtx insn, int N, const char *opt)
++{
++ return nios2_custom_fpu_insn_dsz (insn, N, opt);
++}
++
++static const char *
++nios2_custom_fpu_insn_duz (rtx insn, int N, const char *opt)
++{
++ return nios2_custom_fpu_insn_dsz (insn, N, opt);
++}
++
++static const char *
++nios2_custom_fpu_insn_isz (rtx insn, int N, const char *opt)
++{
++ return nios2_custom_fpu_insn_ssz (insn, N, opt);
++}
++
++static const char *
++nios2_custom_fpu_insn_usz (rtx insn, int N, const char *opt)
++{
++ return nios2_custom_fpu_insn_ssz (insn, N, opt);
++}
++
++static const char *
++nios2_custom_fpu_insn_idz (rtx insn, int N, const char *opt)
++{
++ return nios2_custom_fpu_insn_sdz (insn, N, opt);
++}
++
++static const char *
++nios2_custom_fpu_insn_udz (rtx insn, int N, const char *opt)
++{
++ return nios2_custom_fpu_insn_sdz (insn, N, opt);
++}
++
++static const char *
++nios2_custom_fpu_insn_dsz (rtx insn, int N, const char *opt)
++{
++ static char buf[1024];
++
++ if (N < 0 || nios2_fpu_insns[nios2_fpu_nios2_frdy].N < 0)
++ {
++ fatal_insn ("attempt to use disabled fpu instruction", insn);
++ }
++ if (snprintf (buf, sizeof (buf),
++ "custom\t%d, %%D0, %%1, zero # %s %%0, %%1\n\t"
++ "custom\t%d, %%0, zero, zero # frdy %%0",
++ N, opt,
++ nios2_fpu_insns[nios2_fpu_nios2_frdy].N) >= (int)sizeof (buf))
++ {
++ fatal_insn ("buffer overflow", insn);
++ }
++ return buf;
++}
++
++static const char *
++nios2_custom_fpu_insn_sdz (rtx insn, int N, const char *opt)
++{
++ static char buf[1024];
++
++ if (N < 0)
++ {
++ fatal_insn ("attempt to use disabled fpu instruction", insn);
++ }
++ if (snprintf (buf, sizeof (buf),
++ "custom\t%d, %%0, %%1, %%D1 # %s %%0, %%1",
++ N, opt) >= (int)sizeof (buf))
++ {
++ fatal_insn ("buffer overflow", insn);
++ }
++ return buf;
++}
++
++#undef NIOS2_FPU_INSN
++#define NIOS2_FPU_INSN(opt, insn, args) \
++static const char * \
++NIOS2_CONCAT (nios2_output_fpu_insn_, insn) (rtx i) \
++{ \
++ return NIOS2_CONCAT (nios2_custom_fpu_insn_, args) \
++ (i, \
++ nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)].N, \
++ nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)].option); \
++}
++NIOS2_FOR_ALL_FPU_INSNS
++
++
++
++const char *
++nios2_output_fpu_insn_cmps (rtx insn, enum rtx_code cond)
++{
++ static char buf[1024];
++ int N;
++ const char *opt;
++
++ int operandL = 2;
++ int operandR = 3;
++
++ if ( !have_nios2_fpu_cmp_insn(cond, CMP_SF) &&
++ have_nios2_fpu_cmp_insn(get_reverse_cond(cond), CMP_SF) ) {
++
++ int temp = operandL;
++ operandL = operandR;
++ operandR = temp;
++
++ cond = get_reverse_cond(cond);
++ }
++
++ switch (cond)
++ {
++ case EQ:
++ N = nios2_fpu_insns[nios2_fpu_nios2_seqsf].N;
++ opt = "fcmpeqs";
++ break;
++ case NE:
++ N = nios2_fpu_insns[nios2_fpu_nios2_snesf].N;
++ opt = "fcmpnes";
++ break;
++ case GT:
++ N = nios2_fpu_insns[nios2_fpu_nios2_sgtsf].N;
++ opt = "fcmpgts";
++ break;
++ case GE:
++ N = nios2_fpu_insns[nios2_fpu_nios2_sgesf].N;
++ opt = "fcmpges";
++ break;
++ case LT:
++ N = nios2_fpu_insns[nios2_fpu_nios2_sltsf].N;
++ opt = "fcmplts";
++ break;
++ case LE:
++ N = nios2_fpu_insns[nios2_fpu_nios2_slesf].N;
++ opt = "fcmples"; break;
++ default:
++ fatal_insn ("bad single compare", insn);
++ }
++
++ if (N < 0)
++ {
++ fatal_insn ("attempt to use disabled fpu instruction", insn);
++ }
++
++ /*
++ * ??? This raises the whole vexing issue of how to handle
++ * out-of-range branches. Punt for now, seeing as how nios2-elf-as
++ * doesn't even _try_ to handle out-of-range branches yet!
++ */
++ if (snprintf (buf, sizeof (buf),
++ ".set\tnoat\n\t"
++ "custom\t%d, at, %%%d, %%%d # %s at, %%%d, %%%d\n\t"
++ "bne\tat, zero, %%l1\n\t"
++ ".set\tat",
++ N, operandL, operandR, opt, operandL, operandR) >= (int)sizeof (buf))
++ {
++ fatal_insn ("buffer overflow", insn);
++ }
++ return buf;
++}
++
++const char *
++nios2_output_fpu_insn_cmpd (rtx insn, enum rtx_code cond)
++{
++ static char buf[1024];
++ int N;
++ const char *opt;
++
++ int operandL = 2;
++ int operandR = 3;
++
++ if ( !have_nios2_fpu_cmp_insn(cond, CMP_DF) &&
++ have_nios2_fpu_cmp_insn(get_reverse_cond(cond), CMP_DF) ) {
++
++ int temp = operandL;
++ operandL = operandR;
++ operandR = temp;
++
++ cond = get_reverse_cond(cond);
++ }
++
++ switch (cond)
++ {
++ case EQ:
++ N = nios2_fpu_insns[nios2_fpu_nios2_seqdf].N;
++ opt = "fcmpeqd";
++ break;
++ case NE:
++ N = nios2_fpu_insns[nios2_fpu_nios2_snedf].N;
++ opt = "fcmpned";
++ break;
++ case GT:
++ N = nios2_fpu_insns[nios2_fpu_nios2_sgtdf].N;
++ opt = "fcmpgtd";
++ break;
++ case GE:
++ N = nios2_fpu_insns[nios2_fpu_nios2_sgedf].N;
++ opt = "fcmpged";
++ break;
++ case LT:
++ N = nios2_fpu_insns[nios2_fpu_nios2_sltdf].N;
++ opt = "fcmpltd";
++ break;
++ case LE:
++ N = nios2_fpu_insns[nios2_fpu_nios2_sledf].N;
++ opt = "fcmpled";
++ break;
++ default:
++ fatal_insn ("bad double compare", insn);
++ }
++
++ if (N < 0 || nios2_fpu_insns[nios2_fpu_nios2_fwrx].N < 0)
++ {
++ fatal_insn ("attempt to use disabled fpu instruction", insn);
++ }
++ if (snprintf (buf, sizeof (buf),
++ ".set\tnoat\n\t"
++ "custom\t%d, zero, %%%d, %%D%d # fwrx %%%d\n\t"
++ "custom\t%d, at, %%%d, %%D%d # %s at, %%%d, %%%d\n\t"
++ "bne\tat, zero, %%l1\n\t"
++ ".set\tat",
++ nios2_fpu_insns[nios2_fpu_nios2_fwrx].N, operandL, operandL, operandL,
++ N, operandR, operandR, operandL, operandR, opt) >= (int)sizeof (buf))
++ {
++ fatal_insn ("buffer overflow", insn);
++ }
++ return buf;
++}
++
+
+
+
@@ -5630,43 +7174,6 @@
+}
+
+
-+/* Update the data in CUM to advance over an argument
-+ of mode MODE and data type TYPE.
-+ (TYPE is null for libcalls where that information may not be available.) */
-+
-+void
-+function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
-+ tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED)
-+{
-+ HOST_WIDE_INT param_size;
-+
-+ if (mode == BLKmode)
-+ {
-+ param_size = int_size_in_bytes (type);
-+ if (param_size < 0)
-+ internal_error
-+ ("Do not know how to handle large structs or variable length types");
-+ }
-+ else
-+ {
-+ param_size = GET_MODE_SIZE (mode);
-+ }
-+
-+ /* convert to words (round up) */
-+ param_size = (3 + param_size) / 4;
-+
-+ if (cum->regs_used + param_size > NUM_ARG_REGS)
-+ {
-+ cum->regs_used = NUM_ARG_REGS;
-+ }
-+ else
-+ {
-+ cum->regs_used += param_size;
-+ }
-+
-+ return;
-+}
-+
+/* Define where to put the arguments to a function. Value is zero to
+ push the argument on the stack, or a hard register in which to
+ store the argument.
@@ -5693,6 +7200,29 @@
+ return return_rtx;
+}
+
++/*
++ * This is just default_must_pass_in_stack from calls.c sans the final
++ * test for padding which isn't needed: we define BLOCK_REG_PADDING
++ * instead.
++ */
++int
++nios2_must_pass_in_stack (enum machine_mode mode, tree type)
++{
++ if (!type)
++ return false;
++
++ /* If the type has variable size... */
++ if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
++ return true;
++
++ /* If the type is marked as addressable (it is required
++ to be constructed into the stack)... */
++ if (TREE_ADDRESSABLE (type))
++ return true;
++
++ return false;
++}
++
+int
+function_arg_partial_nregs (const CUMULATIVE_ARGS *cum,
+ enum machine_mode mode, tree type,
@@ -5727,6 +7257,74 @@
+}
+
+
++/* Update the data in CUM to advance over an argument
++ of mode MODE and data type TYPE.
++ (TYPE is null for libcalls where that information may not be available.) */
++
++void
++function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
++ tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED)
++{
++ HOST_WIDE_INT param_size;
++
++ if (mode == BLKmode)
++ {
++ param_size = int_size_in_bytes (type);
++ if (param_size < 0)
++ internal_error
++ ("Do not know how to handle large structs or variable length types");
++ }
++ else
++ {
++ param_size = GET_MODE_SIZE (mode);
++ }
++
++ /* convert to words (round up) */
++ param_size = (3 + param_size) / 4;
++
++ if (cum->regs_used + param_size > NUM_ARG_REGS)
++ {
++ cum->regs_used = NUM_ARG_REGS;
++ }
++ else
++ {
++ cum->regs_used += param_size;
++ }
++
++ return;
++}
++
++int
++nios2_function_arg_padding_upward (enum machine_mode mode, tree type)
++{
++ /* On little-endian targets, the first byte of every stack argument
++ is passed in the first byte of the stack slot. */
++ if (!BYTES_BIG_ENDIAN)
++ return 1;
++
++ /* Otherwise, integral types are padded downward: the last byte of a
++ stack argument is passed in the last byte of the stack slot. */
++ if (type != 0
++ ? INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)
++ : GET_MODE_CLASS (mode) == MODE_INT)
++ return 0;
++
++ /* Arguments smaller than a stack slot are padded downward. */
++ if (mode != BLKmode)
++ return (GET_MODE_BITSIZE (mode) >= PARM_BOUNDARY) ? 1 : 0;
++ else
++ return ((int_size_in_bytes (type) >= (PARM_BOUNDARY / BITS_PER_UNIT))
++ ? 1 : 0);
++}
++
++int
++nios2_block_reg_padding_upward (enum machine_mode mode, tree type,
++ int first ATTRIBUTE_UNUSED)
++{
++ /* ??? Do we need to treat floating point specially, ala MIPS? */
++ return nios2_function_arg_padding_upward (mode, type);
++}
++
+int
+nios2_return_in_memory (tree type)
+{
@@ -5803,59 +7401,19 @@
+ NIOS2_BUILTIN_RDCTL,
+ NIOS2_BUILTIN_WRCTL,
+
-+ NIOS2_BUILTIN_CUSTOM_N,
-+ NIOS2_BUILTIN_CUSTOM_NI,
-+ NIOS2_BUILTIN_CUSTOM_NF,
-+ NIOS2_BUILTIN_CUSTOM_NP,
-+ NIOS2_BUILTIN_CUSTOM_NII,
-+ NIOS2_BUILTIN_CUSTOM_NIF,
-+ NIOS2_BUILTIN_CUSTOM_NIP,
-+ NIOS2_BUILTIN_CUSTOM_NFI,
-+ NIOS2_BUILTIN_CUSTOM_NFF,
-+ NIOS2_BUILTIN_CUSTOM_NFP,
-+ NIOS2_BUILTIN_CUSTOM_NPI,
-+ NIOS2_BUILTIN_CUSTOM_NPF,
-+ NIOS2_BUILTIN_CUSTOM_NPP,
-+ NIOS2_BUILTIN_CUSTOM_IN,
-+ NIOS2_BUILTIN_CUSTOM_INI,
-+ NIOS2_BUILTIN_CUSTOM_INF,
-+ NIOS2_BUILTIN_CUSTOM_INP,
-+ NIOS2_BUILTIN_CUSTOM_INII,
-+ NIOS2_BUILTIN_CUSTOM_INIF,
-+ NIOS2_BUILTIN_CUSTOM_INIP,
-+ NIOS2_BUILTIN_CUSTOM_INFI,
-+ NIOS2_BUILTIN_CUSTOM_INFF,
-+ NIOS2_BUILTIN_CUSTOM_INFP,
-+ NIOS2_BUILTIN_CUSTOM_INPI,
-+ NIOS2_BUILTIN_CUSTOM_INPF,
-+ NIOS2_BUILTIN_CUSTOM_INPP,
-+ NIOS2_BUILTIN_CUSTOM_FN,
-+ NIOS2_BUILTIN_CUSTOM_FNI,
-+ NIOS2_BUILTIN_CUSTOM_FNF,
-+ NIOS2_BUILTIN_CUSTOM_FNP,
-+ NIOS2_BUILTIN_CUSTOM_FNII,
-+ NIOS2_BUILTIN_CUSTOM_FNIF,
-+ NIOS2_BUILTIN_CUSTOM_FNIP,
-+ NIOS2_BUILTIN_CUSTOM_FNFI,
-+ NIOS2_BUILTIN_CUSTOM_FNFF,
-+ NIOS2_BUILTIN_CUSTOM_FNFP,
-+ NIOS2_BUILTIN_CUSTOM_FNPI,
-+ NIOS2_BUILTIN_CUSTOM_FNPF,
-+ NIOS2_BUILTIN_CUSTOM_FNPP,
-+ NIOS2_BUILTIN_CUSTOM_PN,
-+ NIOS2_BUILTIN_CUSTOM_PNI,
-+ NIOS2_BUILTIN_CUSTOM_PNF,
-+ NIOS2_BUILTIN_CUSTOM_PNP,
-+ NIOS2_BUILTIN_CUSTOM_PNII,
-+ NIOS2_BUILTIN_CUSTOM_PNIF,
-+ NIOS2_BUILTIN_CUSTOM_PNIP,
-+ NIOS2_BUILTIN_CUSTOM_PNFI,
-+ NIOS2_BUILTIN_CUSTOM_PNFF,
-+ NIOS2_BUILTIN_CUSTOM_PNFP,
-+ NIOS2_BUILTIN_CUSTOM_PNPI,
-+ NIOS2_BUILTIN_CUSTOM_PNPF,
-+ NIOS2_BUILTIN_CUSTOM_PNPP,
++#undef NIOS2_DO_BUILTIN
++#define NIOS2_DO_BUILTIN(upper, lower, handler) \
++ NIOS2_CONCAT (NIOS2_BUILTIN_CUSTOM_, upper),
++NIOS2_FOR_ALL_CUSTOM_BUILTINS
++
++ NIOS2_FIRST_FPU_INSN,
+
++#undef NIOS2_FPU_INSN
++#define NIOS2_FPU_INSN(opt, insn, args) \
++ NIOS2_CONCAT (NIOS2_BUILTIN_FPU_, opt),
++NIOS2_FOR_ALL_FPU_INSNS
++
++ NIOS2_LAST_FPU_INSN,
+
+ LIM_NIOS2_BUILTINS
+};
@@ -5866,8 +7424,8 @@
+ const char *const name;
+ const enum nios2_builtins code;
+ const tree *type;
-+ rtx (* expander) PARAMS ((const struct builtin_description *,
-+ tree, rtx, rtx, enum machine_mode, int));
++ rtx (* expander) (const struct builtin_description *,
++ tree, rtx, rtx, enum machine_mode, int);
+};
+
+static rtx nios2_expand_STXIO (const struct builtin_description *,
@@ -5894,6 +7452,45 @@
+static rtx nios2_expand_custom_XnXX (const struct builtin_description *,
+ tree, rtx, rtx, enum machine_mode, int);
+
++static rtx nios2_expand_custom_zdz (const struct builtin_description *,
++ tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_zsz (const struct builtin_description *,
++ tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_szz (const struct builtin_description *,
++ tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_sss (const struct builtin_description *,
++ tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_ssz (const struct builtin_description *,
++ tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_iss (const struct builtin_description *,
++ tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_ddd (const struct builtin_description *,
++ tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_ddz (const struct builtin_description *,
++ tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_idd (const struct builtin_description *,
++ tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_siz (const struct builtin_description *,
++ tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_suz (const struct builtin_description *,
++ tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_diz (const struct builtin_description *,
++ tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_duz (const struct builtin_description *,
++ tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_isz (const struct builtin_description *,
++ tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_usz (const struct builtin_description *,
++ tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_idz (const struct builtin_description *,
++ tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_udz (const struct builtin_description *,
++ tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_dsz (const struct builtin_description *,
++ tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_sdz (const struct builtin_description *,
++ tree, rtx, rtx, enum machine_mode, int);
++
+static tree endlink;
+
+/* int fn (volatile const void *)
@@ -5916,59 +7513,30 @@
+ */
+static tree void_ftype_void;
+
-+static tree custom_n;
-+static tree custom_ni;
-+static tree custom_nf;
-+static tree custom_np;
-+static tree custom_nii;
-+static tree custom_nif;
-+static tree custom_nip;
-+static tree custom_nfi;
-+static tree custom_nff;
-+static tree custom_nfp;
-+static tree custom_npi;
-+static tree custom_npf;
-+static tree custom_npp;
-+static tree custom_in;
-+static tree custom_ini;
-+static tree custom_inf;
-+static tree custom_inp;
-+static tree custom_inii;
-+static tree custom_inif;
-+static tree custom_inip;
-+static tree custom_infi;
-+static tree custom_inff;
-+static tree custom_infp;
-+static tree custom_inpi;
-+static tree custom_inpf;
-+static tree custom_inpp;
-+static tree custom_fn;
-+static tree custom_fni;
-+static tree custom_fnf;
-+static tree custom_fnp;
-+static tree custom_fnii;
-+static tree custom_fnif;
-+static tree custom_fnip;
-+static tree custom_fnfi;
-+static tree custom_fnff;
-+static tree custom_fnfp;
-+static tree custom_fnpi;
-+static tree custom_fnpf;
-+static tree custom_fnpp;
-+static tree custom_pn;
-+static tree custom_pni;
-+static tree custom_pnf;
-+static tree custom_pnp;
-+static tree custom_pnii;
-+static tree custom_pnif;
-+static tree custom_pnip;
-+static tree custom_pnfi;
-+static tree custom_pnff;
-+static tree custom_pnfp;
-+static tree custom_pnpi;
-+static tree custom_pnpf;
-+static tree custom_pnpp;
-+
++#undef NIOS2_DO_BUILTIN
++#define NIOS2_DO_BUILTIN(upper, lower, handler) \
++ static tree NIOS2_CONCAT (custom_, lower);
++NIOS2_FOR_ALL_CUSTOM_BUILTINS
++
++static tree custom_zdz;
++static tree custom_zsz;
++static tree custom_szz;
++static tree custom_sss;
++static tree custom_ssz;
++static tree custom_iss;
++static tree custom_ddd;
++static tree custom_ddz;
++static tree custom_idd;
++static tree custom_siz;
++static tree custom_suz;
++static tree custom_diz;
++static tree custom_duz;
++static tree custom_isz;
++static tree custom_usz;
++static tree custom_idz;
++static tree custom_udz;
++static tree custom_dsz;
++static tree custom_sdz;
+
+static const struct builtin_description bdesc[] = {
+ {CODE_FOR_ldbio, "__builtin_ldbio", NIOS2_BUILTIN_LDBIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
@@ -5985,59 +7553,23 @@
+ {CODE_FOR_rdctl, "__builtin_rdctl", NIOS2_BUILTIN_RDCTL, &int_ftype_int, nios2_expand_rdctl},
+ {CODE_FOR_wrctl, "__builtin_wrctl", NIOS2_BUILTIN_WRCTL, &void_ftype_int_int, nios2_expand_wrctl},
+
-+ {CODE_FOR_custom_n, "__builtin_custom_n", NIOS2_BUILTIN_CUSTOM_N, &custom_n, nios2_expand_custom_n},
-+ {CODE_FOR_custom_ni, "__builtin_custom_ni", NIOS2_BUILTIN_CUSTOM_NI, &custom_ni, nios2_expand_custom_nX},
-+ {CODE_FOR_custom_nf, "__builtin_custom_nf", NIOS2_BUILTIN_CUSTOM_NF, &custom_nf, nios2_expand_custom_nX},
-+ {CODE_FOR_custom_np, "__builtin_custom_np", NIOS2_BUILTIN_CUSTOM_NP, &custom_np, nios2_expand_custom_nX},
-+ {CODE_FOR_custom_nii, "__builtin_custom_nii", NIOS2_BUILTIN_CUSTOM_NII, &custom_nii, nios2_expand_custom_nXX},
-+ {CODE_FOR_custom_nif, "__builtin_custom_nif", NIOS2_BUILTIN_CUSTOM_NIF, &custom_nif, nios2_expand_custom_nXX},
-+ {CODE_FOR_custom_nip, "__builtin_custom_nip", NIOS2_BUILTIN_CUSTOM_NIP, &custom_nip, nios2_expand_custom_nXX},
-+ {CODE_FOR_custom_nfi, "__builtin_custom_nfi", NIOS2_BUILTIN_CUSTOM_NFI, &custom_nfi, nios2_expand_custom_nXX},
-+ {CODE_FOR_custom_nff, "__builtin_custom_nff", NIOS2_BUILTIN_CUSTOM_NFF, &custom_nff, nios2_expand_custom_nXX},
-+ {CODE_FOR_custom_nfp, "__builtin_custom_nfp", NIOS2_BUILTIN_CUSTOM_NFP, &custom_nfp, nios2_expand_custom_nXX},
-+ {CODE_FOR_custom_npi, "__builtin_custom_npi", NIOS2_BUILTIN_CUSTOM_NPI, &custom_npi, nios2_expand_custom_nXX},
-+ {CODE_FOR_custom_npf, "__builtin_custom_npf", NIOS2_BUILTIN_CUSTOM_NPF, &custom_npf, nios2_expand_custom_nXX},
-+ {CODE_FOR_custom_npp, "__builtin_custom_npp", NIOS2_BUILTIN_CUSTOM_NPP, &custom_npp, nios2_expand_custom_nXX},
-+ {CODE_FOR_custom_in, "__builtin_custom_in", NIOS2_BUILTIN_CUSTOM_IN, &custom_in, nios2_expand_custom_Xn},
-+ {CODE_FOR_custom_ini, "__builtin_custom_ini", NIOS2_BUILTIN_CUSTOM_INI, &custom_ini, nios2_expand_custom_XnX},
-+ {CODE_FOR_custom_inf, "__builtin_custom_inf", NIOS2_BUILTIN_CUSTOM_INF, &custom_inf, nios2_expand_custom_XnX},
-+ {CODE_FOR_custom_inp, "__builtin_custom_inp", NIOS2_BUILTIN_CUSTOM_INP, &custom_inp, nios2_expand_custom_XnX},
-+ {CODE_FOR_custom_inii, "__builtin_custom_inii", NIOS2_BUILTIN_CUSTOM_INII, &custom_inii, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_inif, "__builtin_custom_inif", NIOS2_BUILTIN_CUSTOM_INIF, &custom_inif, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_inip, "__builtin_custom_inip", NIOS2_BUILTIN_CUSTOM_INIP, &custom_inip, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_infi, "__builtin_custom_infi", NIOS2_BUILTIN_CUSTOM_INFI, &custom_infi, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_inff, "__builtin_custom_inff", NIOS2_BUILTIN_CUSTOM_INFF, &custom_inff, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_infp, "__builtin_custom_infp", NIOS2_BUILTIN_CUSTOM_INFP, &custom_infp, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_inpi, "__builtin_custom_inpi", NIOS2_BUILTIN_CUSTOM_INPI, &custom_inpi, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_inpf, "__builtin_custom_inpf", NIOS2_BUILTIN_CUSTOM_INPF, &custom_inpf, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_inpp, "__builtin_custom_inpp", NIOS2_BUILTIN_CUSTOM_INPP, &custom_inpp, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_fn, "__builtin_custom_fn", NIOS2_BUILTIN_CUSTOM_FN, &custom_fn, nios2_expand_custom_Xn},
-+ {CODE_FOR_custom_fni, "__builtin_custom_fni", NIOS2_BUILTIN_CUSTOM_FNI, &custom_fni, nios2_expand_custom_XnX},
-+ {CODE_FOR_custom_fnf, "__builtin_custom_fnf", NIOS2_BUILTIN_CUSTOM_FNF, &custom_fnf, nios2_expand_custom_XnX},
-+ {CODE_FOR_custom_fnp, "__builtin_custom_fnp", NIOS2_BUILTIN_CUSTOM_FNP, &custom_fnp, nios2_expand_custom_XnX},
-+ {CODE_FOR_custom_fnii, "__builtin_custom_fnii", NIOS2_BUILTIN_CUSTOM_FNII, &custom_fnii, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_fnif, "__builtin_custom_fnif", NIOS2_BUILTIN_CUSTOM_FNIF, &custom_fnif, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_fnip, "__builtin_custom_fnip", NIOS2_BUILTIN_CUSTOM_FNIP, &custom_fnip, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_fnfi, "__builtin_custom_fnfi", NIOS2_BUILTIN_CUSTOM_FNFI, &custom_fnfi, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_fnff, "__builtin_custom_fnff", NIOS2_BUILTIN_CUSTOM_FNFF, &custom_fnff, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_fnfp, "__builtin_custom_fnfp", NIOS2_BUILTIN_CUSTOM_FNFP, &custom_fnfp, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_fnpi, "__builtin_custom_fnpi", NIOS2_BUILTIN_CUSTOM_FNPI, &custom_fnpi, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_fnpf, "__builtin_custom_fnpf", NIOS2_BUILTIN_CUSTOM_FNPF, &custom_fnpf, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_fnpp, "__builtin_custom_fnpp", NIOS2_BUILTIN_CUSTOM_FNPP, &custom_fnpp, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_pn, "__builtin_custom_pn", NIOS2_BUILTIN_CUSTOM_PN, &custom_pn, nios2_expand_custom_Xn},
-+ {CODE_FOR_custom_pni, "__builtin_custom_pni", NIOS2_BUILTIN_CUSTOM_PNI, &custom_pni, nios2_expand_custom_XnX},
-+ {CODE_FOR_custom_pnf, "__builtin_custom_pnf", NIOS2_BUILTIN_CUSTOM_PNF, &custom_pnf, nios2_expand_custom_XnX},
-+ {CODE_FOR_custom_pnp, "__builtin_custom_pnp", NIOS2_BUILTIN_CUSTOM_PNP, &custom_pnp, nios2_expand_custom_XnX},
-+ {CODE_FOR_custom_pnii, "__builtin_custom_pnii", NIOS2_BUILTIN_CUSTOM_PNII, &custom_pnii, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_pnif, "__builtin_custom_pnif", NIOS2_BUILTIN_CUSTOM_PNIF, &custom_pnif, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_pnip, "__builtin_custom_pnip", NIOS2_BUILTIN_CUSTOM_PNIP, &custom_pnip, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_pnfi, "__builtin_custom_pnfi", NIOS2_BUILTIN_CUSTOM_PNFI, &custom_pnfi, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_pnff, "__builtin_custom_pnff", NIOS2_BUILTIN_CUSTOM_PNFF, &custom_pnff, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_pnfp, "__builtin_custom_pnfp", NIOS2_BUILTIN_CUSTOM_PNFP, &custom_pnfp, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_pnpi, "__builtin_custom_pnpi", NIOS2_BUILTIN_CUSTOM_PNPI, &custom_pnpi, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_pnpf, "__builtin_custom_pnpf", NIOS2_BUILTIN_CUSTOM_PNPF, &custom_pnpf, nios2_expand_custom_XnXX},
-+ {CODE_FOR_custom_pnpp, "__builtin_custom_pnpp", NIOS2_BUILTIN_CUSTOM_PNPP, &custom_pnpp, nios2_expand_custom_XnXX},
-+
++#undef NIOS2_DO_BUILTIN
++#define NIOS2_DO_BUILTIN(upper, lower, handler) \
++ {NIOS2_CONCAT (CODE_FOR_custom_, lower), \
++ "__builtin_custom_" NIOS2_STRINGIFY (lower), \
++ NIOS2_CONCAT (NIOS2_BUILTIN_CUSTOM_, upper), \
++ &NIOS2_CONCAT (custom_, lower), \
++ NIOS2_CONCAT (nios2_expand_custom_, handler)},
++NIOS2_FOR_ALL_CUSTOM_BUILTINS
++
++#undef NIOS2_FPU_INSN
++#define NIOS2_FPU_INSN(opt, insn, args) \
++ {NIOS2_CONCAT (CODE_FOR_, insn), \
++ "__builtin_custom_" NIOS2_STRINGIFY (opt), \
++ NIOS2_CONCAT (NIOS2_BUILTIN_FPU_, opt), \
++ &NIOS2_CONCAT (custom_, args), \
++ NIOS2_CONCAT (nios2_expand_custom_, args)},
++NIOS2_FOR_ALL_FPU_INSNS
+
+ {0, 0, 0, 0, 0},
+};
@@ -6396,7 +7928,104 @@
+ def_param (ptr_type_node)
+ endlink))));
+
++ custom_zdz
++ = build_function_type (void_type_node,
++ def_param (double_type_node)
++ endlink));
++
++ custom_zsz
++ = build_function_type (void_type_node,
++ def_param (float_type_node)
++ endlink));
++
++ custom_szz
++ = build_function_type (float_type_node,
++ def_param (void_type_node)
++ endlink));
+
++ custom_sss
++ = build_function_type (float_type_node,
++ def_param (float_type_node)
++ def_param (float_type_node)
++ endlink)));
++
++ custom_ssz
++ = build_function_type (float_type_node,
++ def_param (float_type_node)
++ endlink));
++
++ custom_iss
++ = build_function_type (integer_type_node,
++ def_param (float_type_node)
++ def_param (float_type_node)
++ endlink)));
++
++ custom_ddd
++ = build_function_type (double_type_node,
++ def_param (double_type_node)
++ def_param (double_type_node)
++ endlink)));
++
++ custom_ddz
++ = build_function_type (double_type_node,
++ def_param (double_type_node)
++ endlink));
++
++ custom_idd
++ = build_function_type (integer_type_node,
++ def_param (double_type_node)
++ def_param (double_type_node)
++ endlink)));
++
++ custom_siz
++ = build_function_type (float_type_node,
++ def_param (integer_type_node)
++ endlink));
++
++ custom_suz
++ = build_function_type (float_type_node,
++ def_param (unsigned_type_node)
++ endlink));
++
++ custom_diz
++ = build_function_type (double_type_node,
++ def_param (integer_type_node)
++ endlink));
++
++ custom_duz
++ = build_function_type (double_type_node,
++ def_param (unsigned_type_node)
++ endlink));
++
++ custom_isz
++ = build_function_type (integer_type_node,
++ def_param (float_type_node)
++ endlink));
++
++ custom_usz
++ = build_function_type (unsigned_type_node,
++ def_param (float_type_node)
++ endlink));
++
++ custom_idz
++ = build_function_type (integer_type_node,
++ def_param (double_type_node)
++ endlink));
++
++ custom_udz
++ = build_function_type (unsigned_type_node,
++ def_param (double_type_node)
++ endlink));
++
++ custom_dsz
++ = build_function_type (double_type_node,
++ def_param (float_type_node)
++ endlink));
++
++ custom_sdz
++ = build_function_type (float_type_node,
++ def_param (double_type_node)
++ endlink));
+
+ /* *INDENT-ON* */
+
@@ -6424,7 +8053,25 @@
+
+ for (d = bdesc; d->name; d++)
+ if (d->code == fcode)
++ {
++ if (d->code > NIOS2_FIRST_FPU_INSN && d->code < NIOS2_LAST_FPU_INSN)
++ {
++ nios2_fpu_info *inf = &nios2_fpu_insns[d->code - (NIOS2_FIRST_FPU_INSN + 1)];
++ const struct insn_data *idata = &insn_data[d->icode];
++ if (inf->N < 0)
++ {
++ fatal_error ("Cannot call `%s' without specifying switch `-mcustom-%s'",
++ d->name,
++ inf->option);
++ }
++ if (inf->args[0] != 'z'
++ && (!target
++ || !(idata->operand[0].predicate) (target,
++ idata->operand[0].mode)))
++ target = gen_reg_rtx (idata->operand[0].mode);
++ }
+ return (d->expander) (d, exp, target, subtarget, mode, ignore);
++ }
+
+ /* we should have seen one of the functins we registered */
+ abort ();
@@ -6461,6 +8108,8 @@
+ if (!(*insn_data[d->icode].operand[op].predicate) (opcode, mode))
+ error ("Custom instruction opcode must be compile time constant in the range 0-255 for %s", d->name);
+
++ builtin_custom_seen[INTVAL (opcode)] = d->name;
++ nios2_custom_check_insns (0);
+ return opcode;
+}
+
@@ -6844,15 +8493,397 @@
+ return 0;
+}
+
++static rtx
++nios2_extract_double (const struct insn_data *idata, tree arglist, int index)
++{
++ rtx arg;
++
++ while (index--)
++ {
++ arglist = TREE_CHAIN (arglist);
++ }
++ arg = expand_expr (TREE_VALUE (arglist), NULL_RTX, DFmode, 0);
++ arg = protect_from_queue (arg, 0);
++ if (!(*(idata->operand[index+1].predicate)) (arg, DFmode))
++ {
++ arg = copy_to_mode_reg (DFmode, arg);
++ }
++ return arg;
++}
++
++static rtx
++nios2_extract_float (const struct insn_data *idata, tree arglist, int index)
++{
++ rtx arg;
++
++ while (index--)
++ {
++ arglist = TREE_CHAIN (arglist);
++ }
++ arg = expand_expr (TREE_VALUE (arglist), NULL_RTX, SFmode, 0);
++ arg = protect_from_queue (arg, 0);
++ if (!(*(idata->operand[index+1].predicate)) (arg, SFmode))
++ {
++ arg = copy_to_mode_reg (SFmode, arg);
++ }
++ return arg;
++}
++
++static rtx
++nios2_extract_integer (const struct insn_data *idata, tree arglist, int index)
++{
++ rtx arg;
++
++ while (index--)
++ {
++ arglist = TREE_CHAIN (arglist);
++ }
++ arg = expand_expr (TREE_VALUE (arglist), NULL_RTX, SImode, 0);
++ arg = protect_from_queue (arg, 0);
++ if (!(*(idata->operand[index+1].predicate)) (arg, SImode))
++ {
++ arg = copy_to_mode_reg (SImode, arg);
++ }
++ return protect_from_queue (arg, 0);
++}
++
++static rtx
++nios2_expand_custom_zdz (const struct builtin_description *d,
++ tree exp,
++ rtx target ATTRIBUTE_UNUSED,
++ rtx subtarget ATTRIBUTE_UNUSED,
++ enum machine_mode mode ATTRIBUTE_UNUSED,
++ int ignore ATTRIBUTE_UNUSED)
++{
++ tree arglist = TREE_OPERAND (exp, 1);
++ rtx pat = GEN_FCN (d->icode) (nios2_extract_double (&insn_data[d->icode],
++ arglist, 0));
++ if (pat)
++ emit_insn (pat);
++ return 0;
++}
++
++static rtx
++nios2_expand_custom_zsz (const struct builtin_description *d,
++ tree exp,
++ rtx target ATTRIBUTE_UNUSED,
++ rtx subtarget ATTRIBUTE_UNUSED,
++ enum machine_mode mode ATTRIBUTE_UNUSED,
++ int ignore ATTRIBUTE_UNUSED)
++{
++ tree arglist = TREE_OPERAND (exp, 1);
++ rtx pat = GEN_FCN (d->icode) (nios2_extract_float (&insn_data[d->icode],
++ arglist, 0));
++ if (pat)
++ emit_insn (pat);
++ return 0;
++}
++
++static rtx
++nios2_expand_custom_szz (const struct builtin_description *d,
++ tree exp ATTRIBUTE_UNUSED,
++ rtx target,
++ rtx subtarget ATTRIBUTE_UNUSED,
++ enum machine_mode mode ATTRIBUTE_UNUSED,
++ int ignore ATTRIBUTE_UNUSED)
++{
++ rtx pat = GEN_FCN (d->icode) (target);
++ if (pat)
++ emit_insn (pat);
++ return target;
++}
++
++static rtx
++nios2_expand_custom_sss (const struct builtin_description *d,
++ tree exp,
++ rtx target,
++ rtx subtarget ATTRIBUTE_UNUSED,
++ enum machine_mode mode ATTRIBUTE_UNUSED,
++ int ignore ATTRIBUTE_UNUSED)
++{
++ tree arglist = TREE_OPERAND (exp, 1);
++ rtx pat = GEN_FCN (d->icode) (target,
++ nios2_extract_float (&insn_data[d->icode],
++ arglist, 0),
++ nios2_extract_float (&insn_data[d->icode],
++ arglist, 1));
++ if (pat)
++ emit_insn (pat);
++ return target;
++}
++
++static rtx
++nios2_expand_custom_ssz (const struct builtin_description *d,
++ tree exp,
++ rtx target,
++ rtx subtarget ATTRIBUTE_UNUSED,
++ enum machine_mode mode ATTRIBUTE_UNUSED,
++ int ignore ATTRIBUTE_UNUSED)
++{
++ tree arglist = TREE_OPERAND (exp, 1);
++ rtx pat = GEN_FCN (d->icode) (target,
++ nios2_extract_float (&insn_data[d->icode],
++ arglist, 0));
++ if (pat)
++ emit_insn (pat);
++ return target;
++}
++
++static rtx
++nios2_expand_custom_iss (const struct builtin_description *d,
++ tree exp,
++ rtx target,
++ rtx subtarget ATTRIBUTE_UNUSED,
++ enum machine_mode mode ATTRIBUTE_UNUSED,
++ int ignore ATTRIBUTE_UNUSED)
++{
++ tree arglist = TREE_OPERAND (exp, 1);
++ rtx pat = GEN_FCN (d->icode) (target,
++ nios2_extract_float (&insn_data[d->icode],
++ arglist, 0),
++ nios2_extract_float (&insn_data[d->icode],
++ arglist, 1));
++ if (pat)
++ emit_insn (pat);
++ return target;
++}
++
++static rtx
++nios2_expand_custom_ddd (const struct builtin_description *d,
++ tree exp,
++ rtx target,
++ rtx subtarget ATTRIBUTE_UNUSED,
++ enum machine_mode mode ATTRIBUTE_UNUSED,
++ int ignore ATTRIBUTE_UNUSED)
++{
++ tree arglist = TREE_OPERAND (exp, 1);
++ rtx pat = GEN_FCN (d->icode) (target,
++ nios2_extract_double (&insn_data[d->icode],
++ arglist, 0),
++ nios2_extract_double (&insn_data[d->icode],
++ arglist, 1));
++ if (pat)
++ emit_insn (pat);
++ return target;
++}
++
++static rtx
++nios2_expand_custom_ddz (const struct builtin_description *d,
++ tree exp,
++ rtx target,
++ rtx subtarget ATTRIBUTE_UNUSED,
++ enum machine_mode mode ATTRIBUTE_UNUSED,
++ int ignore ATTRIBUTE_UNUSED)
++{
++ tree arglist = TREE_OPERAND (exp, 1);
++ rtx pat = GEN_FCN (d->icode) (target,
++ nios2_extract_double (&insn_data[d->icode],
++ arglist, 0));
++ if (pat)
++ emit_insn (pat);
++ return target;
++}
++
++static rtx
++nios2_expand_custom_idd (const struct builtin_description *d,
++ tree exp,
++ rtx target,
++ rtx subtarget ATTRIBUTE_UNUSED,
++ enum machine_mode mode ATTRIBUTE_UNUSED,
++ int ignore ATTRIBUTE_UNUSED)
++{
++ tree arglist = TREE_OPERAND (exp, 1);
++ rtx pat = GEN_FCN (d->icode) (target,
++ nios2_extract_double (&insn_data[d->icode],
++ arglist, 0),
++ nios2_extract_double (&insn_data[d->icode],
++ arglist, 1));
++ if (pat)
++ emit_insn (pat);
++ return target;
++}
++
++static rtx
++nios2_expand_custom_siz (const struct builtin_description *d,
++ tree exp,
++ rtx target,
++ rtx subtarget ATTRIBUTE_UNUSED,
++ enum machine_mode mode ATTRIBUTE_UNUSED,
++ int ignore ATTRIBUTE_UNUSED)
++{
++ tree arglist = TREE_OPERAND (exp, 1);
++ rtx pat = GEN_FCN (d->icode) (target,
++ nios2_extract_integer (&insn_data[d->icode],
++ arglist, 0));
++ if (pat)
++ emit_insn (pat);
++ return target;
++}
++
++static rtx
++nios2_expand_custom_suz (const struct builtin_description *d,
++ tree exp,
++ rtx target,
++ rtx subtarget ATTRIBUTE_UNUSED,
++ enum machine_mode mode ATTRIBUTE_UNUSED,
++ int ignore ATTRIBUTE_UNUSED)
++{
++ tree arglist = TREE_OPERAND (exp, 1);
++ rtx pat = GEN_FCN (d->icode) (target,
++ nios2_extract_integer (&insn_data[d->icode],
++ arglist, 0));
++ if (pat)
++ emit_insn (pat);
++ return target;
++}
++
++static rtx
++nios2_expand_custom_diz (const struct builtin_description *d,
++ tree exp,
++ rtx target,
++ rtx subtarget ATTRIBUTE_UNUSED,
++ enum machine_mode mode ATTRIBUTE_UNUSED,
++ int ignore ATTRIBUTE_UNUSED)
++{
++ tree arglist = TREE_OPERAND (exp, 1);
++ rtx pat = GEN_FCN (d->icode) (target,
++ nios2_extract_integer (&insn_data[d->icode],
++ arglist, 0));
++ if (pat)
++ emit_insn (pat);
++ return target;
++}
++
++static rtx
++nios2_expand_custom_duz (const struct builtin_description *d,
++ tree exp,
++ rtx target,
++ rtx subtarget ATTRIBUTE_UNUSED,
++ enum machine_mode mode ATTRIBUTE_UNUSED,
++ int ignore ATTRIBUTE_UNUSED)
++{
++ tree arglist = TREE_OPERAND (exp, 1);
++ rtx pat = GEN_FCN (d->icode) (target,
++ nios2_extract_integer (&insn_data[d->icode],
++ arglist, 0));
++ if (pat)
++ emit_insn (pat);
++ return target;
++}
++
++static rtx
++nios2_expand_custom_isz (const struct builtin_description *d,
++ tree exp,
++ rtx target,
++ rtx subtarget ATTRIBUTE_UNUSED,
++ enum machine_mode mode ATTRIBUTE_UNUSED,
++ int ignore ATTRIBUTE_UNUSED)
++{
++ tree arglist = TREE_OPERAND (exp, 1);
++ rtx pat = GEN_FCN (d->icode) (target,
++ nios2_extract_float (&insn_data[d->icode],
++ arglist, 0));
++ if (pat)
++ emit_insn (pat);
++ return target;
++}
++
++static rtx
++nios2_expand_custom_usz (const struct builtin_description *d,
++ tree exp,
++ rtx target,
++ rtx subtarget ATTRIBUTE_UNUSED,
++ enum machine_mode mode ATTRIBUTE_UNUSED,
++ int ignore ATTRIBUTE_UNUSED)
++{
++ tree arglist = TREE_OPERAND (exp, 1);
++ rtx pat = GEN_FCN (d->icode) (target,
++ nios2_extract_float (&insn_data[d->icode],
++ arglist, 0));
++ if (pat)
++ emit_insn (pat);
++ return target;
++}
++
++static rtx
++nios2_expand_custom_idz (const struct builtin_description *d,
++ tree exp,
++ rtx target,
++ rtx subtarget ATTRIBUTE_UNUSED,
++ enum machine_mode mode ATTRIBUTE_UNUSED,
++ int ignore ATTRIBUTE_UNUSED)
++{
++ tree arglist = TREE_OPERAND (exp, 1);
++ rtx pat = GEN_FCN (d->icode) (target,
++ nios2_extract_double (&insn_data[d->icode],
++ arglist, 0));
++ if (pat)
++ emit_insn (pat);
++ return target;
++}
++
++static rtx
++nios2_expand_custom_udz (const struct builtin_description *d,
++ tree exp,
++ rtx target,
++ rtx subtarget ATTRIBUTE_UNUSED,
++ enum machine_mode mode ATTRIBUTE_UNUSED,
++ int ignore ATTRIBUTE_UNUSED)
++{
++ tree arglist = TREE_OPERAND (exp, 1);
++ rtx pat = GEN_FCN (d->icode) (target,
++ nios2_extract_double (&insn_data[d->icode],
++ arglist, 0));
++ if (pat)
++ emit_insn (pat);
++ return target;
++}
++
++static rtx
++nios2_expand_custom_dsz (const struct builtin_description *d,
++ tree exp,
++ rtx target,
++ rtx subtarget ATTRIBUTE_UNUSED,
++ enum machine_mode mode ATTRIBUTE_UNUSED,
++ int ignore ATTRIBUTE_UNUSED)
++{
++ tree arglist = TREE_OPERAND (exp, 1);
++ rtx pat = GEN_FCN (d->icode) (target,
++ nios2_extract_float (&insn_data[d->icode],
++ arglist, 0));
++ if (pat)
++ emit_insn (pat);
++ return target;
++}
++
++static rtx
++nios2_expand_custom_sdz (const struct builtin_description *d,
++ tree exp,
++ rtx target,
++ rtx subtarget ATTRIBUTE_UNUSED,
++ enum machine_mode mode ATTRIBUTE_UNUSED,
++ int ignore ATTRIBUTE_UNUSED)
++{
++ tree arglist = TREE_OPERAND (exp, 1);
++ rtx pat = GEN_FCN (d->icode) (target,
++ nios2_extract_double (&insn_data[d->icode],
++ arglist, 0));
++ if (pat)
++ emit_insn (pat);
++ return target;
++}
+
+#include "gt-nios2.h"
+
---- gcc-3.4.3/gcc/config/nios2/nios2.h
-+++ gcc-3.4.3-nios2/gcc/config/nios2/nios2.h
-@@ -0,0 +1,824 @@
+diff --git a/gcc/config/nios2/nios2.h b/gcc/config/nios2/nios2.h
+new file mode 100644
+index 0000000..500ccf0
+--- /dev/null
++++ b/gcc/config/nios2/nios2.h
+@@ -0,0 +1,1130 @@
+/* Definitions of target machine for Altera NIOS 2G NIOS2 version.
-+ Copyright (C) 2003 Altera
-+ Contributed by Jonah Graham (jgraham@altera.com).
++ Copyright (C) 2005 Altera
++ Contributed by Jonah Graham (jgraham@altera.com) and Will Reece (wreece@altera.com).
+
+This file is part of GNU CC.
+
@@ -6878,7 +8909,10 @@
+ { \
+ builtin_define_std ("NIOS2"); \
+ builtin_define_std ("nios2"); \
-+ builtin_define ("_GNU_SOURCE"); \
++ if (TARGET_BIG_ENDIAN) \
++ builtin_define_std ("nios2_big_endian"); \
++ else \
++ builtin_define_std ("nios2_little_endian"); \
+ } \
+ while (0)
+#define TARGET_VERSION fprintf (stderr, " (Altera Nios II)")
@@ -6898,6 +8932,10 @@
+#define INLINE_MEMCPY_FLAG 0x00010
+#define CACHE_VOLATILE_FLAG 0x0020
+#define BYPASS_CACHE_FLAG 0x0040
++#define STACK_CHECK_FLAG 0x0080
++#define REVERSE_BITFIELDS_FLAG 0x0100
++/* Reserve 0x0200 for REVERSE_ENDIAN_FLAG */
++#define BIG_ENDIAN_FLAG 0x0400
+
+extern int target_flags;
+#define TARGET_HAS_DIV (target_flags & HAS_DIV_FLAG)
@@ -6907,6 +8945,9 @@
+#define TARGET_INLINE_MEMCPY (target_flags & INLINE_MEMCPY_FLAG)
+#define TARGET_CACHE_VOLATILE (target_flags & CACHE_VOLATILE_FLAG)
+#define TARGET_BYPASS_CACHE (target_flags & BYPASS_CACHE_FLAG)
++#define TARGET_STACK_CHECK (target_flags & STACK_CHECK_FLAG)
++#define TARGET_REVERSE_BITFIELDS (target_flags & REVERSE_BITFIELDS_FLAG)
++#define TARGET_BIG_ENDIAN (target_flags & BIG_ENDIAN_FLAG)
+
+#define TARGET_SWITCHES \
+{ \
@@ -6942,14 +8983,148 @@
+ N_("Link with a limited version of the C library") }, \
+ { "ctors-in-init", 0, \
+ "" /* undocumented: N_("Link with static constructors and destructors in init") */ }, \
++ { "stack-check", STACK_CHECK_FLAG, \
++ N_("Enable stack limit checking.") }, \
++ { "no-stack-check", -STACK_CHECK_FLAG, \
++ N_("Disable stack limit checking (default).") }, \
++ { "reverse-bitfields", REVERSE_BITFIELDS_FLAG, \
++ N_("Reverse the order of bitfields in a struct.") }, \
++ { "no-reverse-bitfields", -REVERSE_BITFIELDS_FLAG, \
++ N_("Use the normal order of bitfields in a struct (default).") }, \
++ { "eb", BIG_ENDIAN_FLAG, \
++ N_("Use big-endian byte order") }, \
++ { "el", -BIG_ENDIAN_FLAG, \
++ N_("Use little-endian byte order") }, \
+ { "", TARGET_DEFAULT, 0 } \
+}
+
-+
+extern const char *nios2_sys_nosys_string; /* for -msys=nosys */
+extern const char *nios2_sys_lib_string; /* for -msys-lib= */
+extern const char *nios2_sys_crt0_string; /* for -msys-crt0= */
+
++/*
++ * There's a lot of error-prone tedium with all the different
++ * custom floating point instructions. Try to automate it a bit
++ * to make it easier to deal with.
++ */
++#define NIOS2_STRINGIFY_INNER(x) #x
++#define NIOS2_STRINGIFY(x) NIOS2_STRINGIFY_INNER(x)
++#define NIOS2_CONCAT_INNER(x, y) x ## y
++#define NIOS2_CONCAT(x, y) NIOS2_CONCAT_INNER (x, y)
++
++#define NIOS2_FOR_ALL_FPU_INSNS \
++ NIOS2_FPU_INSN (fwrx, nios2_fwrx, zdz) \
++ NIOS2_FPU_INSN (fwry, nios2_fwry, zsz) \
++ NIOS2_FPU_INSN (frdxlo, nios2_frdxlo, szz) \
++ NIOS2_FPU_INSN (frdxhi, nios2_frdxhi, szz) \
++ NIOS2_FPU_INSN (frdy, nios2_frdy, szz) \
++\
++ NIOS2_FPU_INSN (fadds, addsf3, sss) \
++ NIOS2_FPU_INSN (fsubs, subsf3, sss) \
++ NIOS2_FPU_INSN (fmuls, mulsf3, sss) \
++ NIOS2_FPU_INSN (fdivs, divsf3, sss) \
++ NIOS2_FPU_INSN (fmins, minsf3, sss) \
++ NIOS2_FPU_INSN (fmaxs, maxsf3, sss) \
++ NIOS2_FPU_INSN (fnegs, negsf2, ssz) \
++ NIOS2_FPU_INSN (fabss, abssf2, ssz) \
++ NIOS2_FPU_INSN (fsqrts, sqrtsf2, ssz) \
++ NIOS2_FPU_INSN (fcoss, cossf2, ssz) \
++ NIOS2_FPU_INSN (fsins, sinsf2, ssz) \
++ NIOS2_FPU_INSN (ftans, tansf2, ssz) \
++ NIOS2_FPU_INSN (fatans, atansf2, ssz) \
++ NIOS2_FPU_INSN (fexps, expsf2, ssz) \
++ NIOS2_FPU_INSN (flogs, logsf2, ssz) \
++ NIOS2_FPU_INSN (fcmplts, nios2_sltsf, iss) \
++ NIOS2_FPU_INSN (fcmples, nios2_slesf, iss) \
++ NIOS2_FPU_INSN (fcmpgts, nios2_sgtsf, iss) \
++ NIOS2_FPU_INSN (fcmpges, nios2_sgesf, iss) \
++ NIOS2_FPU_INSN (fcmpeqs, nios2_seqsf, iss) \
++ NIOS2_FPU_INSN (fcmpnes, nios2_snesf, iss) \
++\
++ NIOS2_FPU_INSN (faddd, adddf3, ddd) \
++ NIOS2_FPU_INSN (fsubd, subdf3, ddd) \
++ NIOS2_FPU_INSN (fmuld, muldf3, ddd) \
++ NIOS2_FPU_INSN (fdivd, divdf3, ddd) \
++ NIOS2_FPU_INSN (fmind, mindf3, ddd) \
++ NIOS2_FPU_INSN (fmaxd, maxdf3, ddd) \
++ NIOS2_FPU_INSN (fnegd, negdf2, ddz) \
++ NIOS2_FPU_INSN (fabsd, absdf2, ddz) \
++ NIOS2_FPU_INSN (fsqrtd, sqrtdf2, ddz) \
++ NIOS2_FPU_INSN (fcosd, cosdf2, ddz) \
++ NIOS2_FPU_INSN (fsind, sindf2, ddz) \
++ NIOS2_FPU_INSN (ftand, tandf2, ddz) \
++ NIOS2_FPU_INSN (fatand, atandf2, ddz) \
++ NIOS2_FPU_INSN (fexpd, expdf2, ddz) \
++ NIOS2_FPU_INSN (flogd, logdf2, ddz) \
++ NIOS2_FPU_INSN (fcmpltd, nios2_sltdf, idd) \
++ NIOS2_FPU_INSN (fcmpled, nios2_sledf, idd) \
++ NIOS2_FPU_INSN (fcmpgtd, nios2_sgtdf, idd) \
++ NIOS2_FPU_INSN (fcmpged, nios2_sgedf, idd) \
++ NIOS2_FPU_INSN (fcmpeqd, nios2_seqdf, idd) \
++ NIOS2_FPU_INSN (fcmpned, nios2_snedf, idd) \
++\
++ NIOS2_FPU_INSN (floatis, floatsisf2, siz) \
++ NIOS2_FPU_INSN (floatus, floatunssisf2, suz) \
++ NIOS2_FPU_INSN (floatid, floatsidf2, diz) \
++ NIOS2_FPU_INSN (floatud, floatunssidf2, duz) \
++ NIOS2_FPU_INSN (fixsi, fixsfsi2, isz) \
++ NIOS2_FPU_INSN (fixsu, fixunssfsi2, usz) \
++ NIOS2_FPU_INSN (fixdi, fixdfsi2, idz) \
++ NIOS2_FPU_INSN (fixdu, fixunsdfsi2, udz) \
++ NIOS2_FPU_INSN (fextsd, extendsfdf2, dsz) \
++ NIOS2_FPU_INSN (ftruncds, truncdfsf2, sdz)
++
++enum
++{
++#define NIOS2_FPU_INSN(opt, insn, args) \
++ NIOS2_CONCAT (nios2_fpu_, insn),
++NIOS2_FOR_ALL_FPU_INSNS
++ nios2_fpu_max_insn
++};
++
++struct cpp_reader;
++typedef const char * (*nios2_outputfn) (rtx);
++typedef void (*nios2_pragmafn) (struct cpp_reader *);
++
++typedef struct
++{
++ const char *option; /* name of switch, e.g. fadds */
++ const char *insnnm; /* name of gcc insn, e.g. addsf3 */
++ const char *args; /* args to gcc insn, e.g. sss */
++ const char *value; /* value of switch as a string */
++ int N; /* value of switch as an integer, -1 = not used */
++ nios2_outputfn output; /* output function for use in .md file */
++ const char *pname; /* name of corresponding #pragma custom- */
++ nios2_pragmafn pragma; /* pragma function for register_target_pragmas */
++ const char *nopname; /* name of corresponding #pragma no-custom- */
++ nios2_pragmafn nopragma; /* pragma function for register_target_pragmas */
++ int is_double; /* does this insn have any double operands */
++ int needed_by_double; /* is this insn needed if doubles are used? */
++ int needs_unsafe; /* does this insn require
++ -funsafe-math-optimizations to work? */
++ int needs_finite; /* does this insn require
++ -ffinite-math-only to work? */
++ int pragma_seen; /* have we seen the corresponding #pragma? */
++} nios2_fpu_info;
++
++extern nios2_fpu_info nios2_fpu_insns[nios2_fpu_max_insn];
++extern const char *nios2_custom_fpu_cfg_string;
++
++#undef NIOS2_FPU_INSN
++#define NIOS2_FPU_INSN(opt, insn, args) \
++ { \
++ "custom-" NIOS2_STRINGIFY (opt) "=", \
++ &(nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)].value), \
++ N_("Integer id (N) of " NIOS2_STRINGIFY (opt) " custom instruction"), \
++ 0 \
++ }, \
++ { \
++ "no-custom-" NIOS2_STRINGIFY (opt), \
++ &(nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)].value), \
++ N_("Do not use the " NIOS2_STRINGIFY (opt) " custom instruction"), \
++ "-1" \
++ },
++
+#define TARGET_OPTIONS \
+{ \
+ { "sys=nosys", &nios2_sys_nosys_string, \
@@ -6958,12 +9133,19 @@
+ N_("Name of System Library to link against. (Converted to a -l option)"), 0}, \
+ { "sys-crt0=", &nios2_sys_crt0_string, \
+ N_("Name of the startfile. (default is a crt0 for the ISS only)"), 0}, \
++ NIOS2_FOR_ALL_FPU_INSNS \
++ { "custom-fpu-cfg=", &nios2_custom_fpu_cfg_string, \
++ N_("Floating point custom instruction configuration name"), 0 }, \
+}
+
++/* We're little endian, unless otherwise specified by including big.h */
++#ifndef TARGET_ENDIAN_DEFAULT
++# define TARGET_ENDIAN_DEFAULT 0
++#endif
+
+/* Default target_flags if no switches specified. */
+#ifndef TARGET_DEFAULT
-+# define TARGET_DEFAULT (HAS_MUL_FLAG | CACHE_VOLATILE_FLAG)
++# define TARGET_DEFAULT (HAS_MUL_FLAG | CACHE_VOLATILE_FLAG | TARGET_ENDIAN_DEFAULT)
+#endif
+
+/* Switch Recognition by gcc.c. Add -G xx support */
@@ -6976,13 +9158,27 @@
+#define CAN_DEBUG_WITHOUT_FP
+
+#define CC1_SPEC "\
-+%{G*}"
++%{G*} %{EB:-meb} %{EL:-mel} %{EB:%{EL:%emay not use both -EB and -EL}}"
++
++#if TARGET_ENDIAN_DEFAULT == 0
++# define ASM_SPEC "\
++%{!EB:%{!meb:-EL}} %{EB|meb:-EB}"
++# define LINK_SPEC "\
++%{!EB:%{!meb:-EL}} %{EB|meb:-EB}"
++# define MULTILIB_DEFAULTS { "EL" }
++#else
++# define ASM_SPEC "\
++%{!EL:%{!mel:-EB}} %{EL|mel:-EL}"
++# define LINK_SPEC "\
++%{!EL:%{!mel:-EB}} %{EL|mel:-EL}"
++# define MULTILIB_DEFAULTS { "EB" }
++#endif
+
+#undef LIB_SPEC
+#define LIB_SPEC \
+"--start-group %{msmallc: -lsmallc} %{!msmallc: -lc} -lgcc \
+ %{msys-lib=*: -l%*} \
-+ %{!msys-lib=*: -lc } \
++ %{!msys-lib=*: -lnosys -lstack} \
+ --end-group \
+ %{msys-lib=: %eYou need a library name for -msys-lib=} \
+"
@@ -6990,7 +9186,7 @@
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
-+"%{msys-crt0=*: %*} %{!msys-crt0=*: crt1%O%s} \
++"%{msys-crt0=*: %*} %{!msys-crt0=*: crt0%O%s} \
+ %{msys-crt0=: %eYou need a C startup file for -msys-crt0=} \
+ %{mctors-in-init: crti%O%s crtbegin%O%s} \
+"
@@ -7006,8 +9202,13 @@
+
+#define DEFAULT_SIGNED_CHAR 1
+#define BITS_BIG_ENDIAN 0
-+#define BYTES_BIG_ENDIAN 0
-+#define WORDS_BIG_ENDIAN 0
++#define BYTES_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0)
++#define WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0)
++#if defined(__nios2_big_endian__)
++#define LIBGCC2_WORDS_BIG_ENDIAN 1
++#else
++#define LIBGCC2_WORDS_BIG_ENDIAN 0
++#endif
+#define BITS_PER_UNIT 8
+#define BITS_PER_WORD 32
+#define UNITS_PER_WORD 4
@@ -7043,7 +9244,8 @@
+ ************************/
+
+/* comparison type */
-+/* ??? currently only CMP_SI is used */
++/* ??? Currently CMP_DI is unused. CMP_SF and CMP_DF are only used if
++ the corresponding -mcustom-<opcode> switches are present. */
+enum cmp_type {
+ CMP_SI, /* compare four byte integers */
+ CMP_DI, /* compare eight byte integers */
@@ -7077,8 +9279,8 @@
+23 r23 sc Static Chain (Callee Saved)
+ ??? Does $sc want to be caller or callee
+ saved. If caller, 15, else 23.
-+24 r24 Exception Temporary
-+25 r25 Breakpoint Temporary
++24 r24 et Exception Temporary
++25 r25 bt Breakpoint Temporary
+26 r26 gp Global Pointer
+27 r27 sp Stack Pointer
+28 r28 fp Frame Pointer
@@ -7120,7 +9322,7 @@
+/* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+/* 20 */ 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, \
+/* 30 */ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, \
-+/* 40 */ 1, \
++/* 40 */ 1 \
+ }
+
+/* call used is the same as caller saved
@@ -7132,7 +9334,7 @@
+/* 10 */ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, \
+/* 20 */ 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, \
+/* 30 */ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, \
-+/* 40 */ 1, \
++/* 40 */ 1 \
+ }
+
+#define HARD_REGNO_NREGS(REGNO, MODE) \
@@ -7155,6 +9357,39 @@
+enum reg_class
+{
+ NO_REGS,
++ D00_REG,
++ D01_REG,
++ D02_REG,
++ D03_REG,
++ D04_REG,
++ D05_REG,
++ D06_REG,
++ D07_REG,
++ D08_REG,
++ D09_REG,
++ D10_REG,
++ D11_REG,
++ D12_REG,
++ D13_REG,
++ D14_REG,
++ D15_REG,
++ D16_REG,
++ D17_REG,
++ D18_REG,
++ D19_REG,
++ D20_REG,
++ D21_REG,
++ D22_REG,
++ D23_REG,
++ D24_REG,
++ D25_REG,
++ D26_REG,
++ D27_REG,
++ D28_REG,
++ D29_REG,
++ D30_REG,
++ D31_REG,
++ GP_REGS,
+ ALL_REGS,
+ LIM_REG_CLASSES
+};
@@ -7163,21 +9398,89 @@
+
+#define REG_CLASS_NAMES \
+ {"NO_REGS", \
++ "D00_REG", \
++ "D01_REG", \
++ "D02_REG", \
++ "D03_REG", \
++ "D04_REG", \
++ "D05_REG", \
++ "D06_REG", \
++ "D07_REG", \
++ "D08_REG", \
++ "D09_REG", \
++ "D10_REG", \
++ "D11_REG", \
++ "D12_REG", \
++ "D13_REG", \
++ "D14_REG", \
++ "D15_REG", \
++ "D16_REG", \
++ "D17_REG", \
++ "D18_REG", \
++ "D19_REG", \
++ "D20_REG", \
++ "D21_REG", \
++ "D22_REG", \
++ "D23_REG", \
++ "D24_REG", \
++ "D25_REG", \
++ "D26_REG", \
++ "D27_REG", \
++ "D28_REG", \
++ "D29_REG", \
++ "D30_REG", \
++ "D31_REG", \
++ "GP_REGS", \
+ "ALL_REGS"}
+
+#define GENERAL_REGS ALL_REGS
+
+#define REG_CLASS_CONTENTS \
+/* NO_REGS */ {{ 0, 0}, \
++/* D00_REG */ { 1 << 0, 0}, \
++/* D01_REG */ { 1 << 1, 0}, \
++/* D02_REG */ { 1 << 2, 0}, \
++/* D03_REG */ { 1 << 3, 0}, \
++/* D04_REG */ { 1 << 4, 0}, \
++/* D05_REG */ { 1 << 5, 0}, \
++/* D06_REG */ { 1 << 6, 0}, \
++/* D07_REG */ { 1 << 7, 0}, \
++/* D08_REG */ { 1 << 8, 0}, \
++/* D09_REG */ { 1 << 9, 0}, \
++/* D10_REG */ { 1 << 10, 0}, \
++/* D11_REG */ { 1 << 11, 0}, \
++/* D12_REG */ { 1 << 12, 0}, \
++/* D13_REG */ { 1 << 13, 0}, \
++/* D14_REG */ { 1 << 14, 0}, \
++/* D15_REG */ { 1 << 15, 0}, \
++/* D16_REG */ { 1 << 16, 0}, \
++/* D17_REG */ { 1 << 17, 0}, \
++/* D18_REG */ { 1 << 18, 0}, \
++/* D19_REG */ { 1 << 19, 0}, \
++/* D20_REG */ { 1 << 20, 0}, \
++/* D21_REG */ { 1 << 21, 0}, \
++/* D22_REG */ { 1 << 22, 0}, \
++/* D23_REG */ { 1 << 23, 0}, \
++/* D24_REG */ { 1 << 24, 0}, \
++/* D25_REG */ { 1 << 25, 0}, \
++/* D26_REG */ { 1 << 26, 0}, \
++/* D27_REG */ { 1 << 27, 0}, \
++/* D28_REG */ { 1 << 28, 0}, \
++/* D29_REG */ { 1 << 29, 0}, \
++/* D30_REG */ { 1 << 30, 0}, \
++/* D31_REG */ { 1 << 31, 0}, \
++/* GP_REGS */ {~0, 0}, \
+/* ALL_REGS */ {~0,~0}} \
+
-+#define REGNO_REG_CLASS(REGNO) ALL_REGS
++#define REGNO_REG_CLASS(REGNO) ((REGNO) <= 31 ? GP_REGS : ALL_REGS)
+
+#define BASE_REG_CLASS ALL_REGS
+#define INDEX_REG_CLASS ALL_REGS
+
-+/* only one reg class, 'r', is handled automatically */
-+#define REG_CLASS_FROM_LETTER(CHAR) NO_REGS
++/* 'r', is handled automatically */
++#define REG_CLASS_FROM_CONSTRAINT(CHAR, STR) \
++ reg_class_from_constraint ((CHAR), (STR))
++
+
+#define REGNO_OK_FOR_BASE_P2(REGNO, STRICT) \
+ ((STRICT) \
@@ -7231,6 +9534,9 @@
+#define PREFERRED_RELOAD_CLASS(X, CLASS) \
+ ((CLASS) == NO_REGS ? GENERAL_REGS : (CLASS))
+
++#define CONSTRAINT_LEN(C, STR) \
++ ((C) == 'D' ? 3 : DEFAULT_CONSTRAINT_LEN ((C), (STR)))
++
+/* 'S' matches immediates which are in small data
+ and therefore can be added to gp to create a
+ 32-bit value. */
@@ -7338,6 +9644,9 @@
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+ (function_arg (&CUM, MODE, TYPE, NAMED))
+
++#define MUST_PASS_IN_STACK(MODE, TYPE) \
++ nios2_must_pass_in_stack ((MODE), (TYPE))
++
+#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
+ (function_arg_partial_nregs (&CUM, MODE, TYPE, NAMED))
+
@@ -7357,6 +9666,15 @@
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
+ (function_arg_advance (&CUM, MODE, TYPE, NAMED))
+
++#define FUNCTION_ARG_PADDING(MODE, TYPE) \
++ (nios2_function_arg_padding_upward ((MODE), (TYPE)) ? upward : downward)
++
++#define PAD_VARARGS_DOWN \
++ (FUNCTION_ARG_PADDING (TYPE_MODE (type), type) == downward)
++
++#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
++ (nios2_block_reg_padding_upward ((MODE), (TYPE), (FIRST)) ? upward : downward)
++
+#define FUNCTION_ARG_REGNO_P(REGNO) \
+ ((REGNO) >= FIRST_ARG_REGNO && (REGNO) <= LAST_ARG_REGNO)
+
@@ -7372,8 +9690,9 @@
+ * Generating Code for Profiling
+ * ----------------------------- */
+
-+#define PROFILE_BEFORE_PROLOGUE
+
++#define PROFILE_BEFORE_PROLOGUE
++#define NO_PROFILE_COUNTERS 1
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ function_profiler ((FILE), (LABELNO))
+
@@ -7546,8 +9865,8 @@
+ "r21", \
+ "r22", \
+ "r23", \
-+ "r24", \
-+ "r25", \
++ "et", \
++ "bt", \
+ "gp", \
+ "sp", \
+ "fp", \
@@ -7565,6 +9884,21 @@
+ "fake_ap", \
+}
+
++#define ADDITIONAL_REGISTER_NAMES \
++{ \
++ {"r0", 0}, \
++ {"r1", 1}, \
++ {"r24", 24}, \
++ {"r25", 25}, \
++ {"r26", 26}, \
++ {"r27", 27}, \
++ {"r28", 28}, \
++ {"r29", 29}, \
++ {"r30", 30}, \
++ {"r31", 31} \
++}
++
++
+#define ASM_OUTPUT_OPCODE(STREAM, PTR)\
+ (PTR) = asm_output_opcode (STREAM, PTR)
+
@@ -7664,9 +9998,12 @@
+
+#define MOVE_MAX 4
+
++#define STORE_FLAG_VALUE 1
+#define Pmode SImode
+#define FUNCTION_MODE QImode
+
++#define REGISTER_TARGET_PRAGMAS() nios2_register_target_pragmas ();
++
+#define CASE_VECTOR_MODE Pmode
+
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
@@ -7674,12 +10011,15 @@
+#define LOAD_EXTEND_OP(MODE) (ZERO_EXTEND)
+
+#define WORD_REGISTER_OPERATIONS
---- gcc-3.4.3/gcc/config/nios2/nios2.md
-+++ gcc-3.4.3-nios2/gcc/config/nios2/nios2.md
-@@ -0,0 +1,2078 @@
+diff --git a/gcc/config/nios2/nios2.md b/gcc/config/nios2/nios2.md
+new file mode 100644
+index 0000000..6183247
+--- /dev/null
++++ b/gcc/config/nios2/nios2.md
+@@ -0,0 +1,2867 @@
+;; Machine Description for Altera NIOS 2G NIOS2 version.
-+;; Copyright (C) 2003 Altera
-+;; Contributed by Jonah Graham (jgraham@altera.com).
++;; Copyright (C) 2005 Altera
++;; Contributed by Jonah Graham (jgraham@altera.com) and Will Reece (wreece@altera.com).
+;;
+;; This file is part of GNU CC.
+;;
@@ -7700,12 +10040,43 @@
+
+
+
++
++;*****************************************************************************
++;*
++;* constraint strings
++;*
++;*****************************************************************************
++;
++; We use the following constraint letters for constants
++;
++; I: -32768 to -32767
++; J: 0 to 65535
++; K: $nnnn0000 for some nnnn
++; L: 0 to 31 (for shift counts)
++; M: 0
++; N: 0 to 255 (for custom instruction numbers)
++; O: 0 to 31 (for control register numbers)
++;
++; We use the following built-in register classes:
++;
++; r: general purpose register (r0..r31)
++; m: memory operand
++;
++; Plus, we define the following constraint strings:
++;
++; S: symbol that is in the "small data" area
++; Dnn: Dnn_REG (just rnn)
++;
++
++
++
+;*****************************************************************************
+;*
+;* constants
+;*
+;*****************************************************************************
+(define_constants [
++ (ET_REGNO 24)
+ (GP_REGNO 26)
+ (SP_REGNO 27)
+ (FP_REGNO 28)
@@ -7733,7 +10104,26 @@
+ (UNSPEC_SYNC 9)
+ (UNSPEC_WRCTL 10)
+ (UNSPEC_RDCTL 11)
-+
++ (UNSPEC_TRAP 12)
++ (UNSPEC_STACK_OVERFLOW_DETECT_AND_TRAP 13)
++ (UNSPEC_FCOSS 14)
++ (UNSPEC_FCOSD 15)
++ (UNSPEC_FSINS 16)
++ (UNSPEC_FSIND 17)
++ (UNSPEC_FTANS 18)
++ (UNSPEC_FTAND 19)
++ (UNSPEC_FATANS 20)
++ (UNSPEC_FATAND 21)
++ (UNSPEC_FEXPS 22)
++ (UNSPEC_FEXPD 23)
++ (UNSPEC_FLOGS 24)
++ (UNSPEC_FLOGD 25)
++ (UNSPEC_FWRX 26)
++ (UNSPEC_FWRY 27)
++ (UNSPEC_FRDXLO 28)
++ (UNSPEC_FRDXHI 29)
++ (UNSPEC_FRDY 30)
++ ;; Note that values 100..151 are used by custom instructions, see below.
+])
+
+
@@ -7829,8 +10219,7 @@
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=m, r,r, r")
+ (match_operand:QI 1 "general_operand" "rM,m,rM,I"))]
+ "(register_operand (operands[0], QImode)
-+ || register_operand (operands[1], QImode)
-+ || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))"
++ || reg_or_0_operand (operands[1], QImode))"
+ "@
+ stb%o0\\t%z1, %0
+ ldbu%o1\\t%0, %1
@@ -7856,7 +10245,7 @@
+
+(define_insn "stbio"
+ [(set (match_operand:SI 0 "memory_operand" "=m")
-+ (match_operand:SI 1 "register_operand" "r"))
++ (match_operand:SI 1 "reg_or_0_operand" "rM"))
+ (unspec_volatile:SI [(const_int 0)] UNSPEC_STBIO)]
+ ""
+ "stbio\\t%z1, %0"
@@ -7876,8 +10265,7 @@
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=m, r,r, r,r")
+ (match_operand:HI 1 "general_operand" "rM,m,rM,I,J"))]
+ "(register_operand (operands[0], HImode)
-+ || register_operand (operands[1], HImode)
-+ || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))"
++ || reg_or_0_operand (operands[1], HImode))"
+ "@
+ sth%o0\\t%z1, %0
+ ldhu%o1\\t%0, %1
@@ -7904,7 +10292,7 @@
+
+(define_insn "sthio"
+ [(set (match_operand:SI 0 "memory_operand" "=m")
-+ (match_operand:SI 1 "register_operand" "r"))
++ (match_operand:SI 1 "reg_or_0_operand" "rM"))
+ (unspec_volatile:SI [(const_int 0)] UNSPEC_STHIO)]
+ ""
+ "sthio\\t%z1, %0"
@@ -7923,8 +10311,7 @@
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=m, r,r, r,r,r,r")
+ (match_operand:SI 1 "general_operand" "rM,m,rM,I,J,S,i"))]
+ "(register_operand (operands[0], SImode)
-+ || register_operand (operands[1], SImode)
-+ || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))"
++ || reg_or_0_operand (operands[1], SImode))"
+ "@
+ stw%o0\\t%z1, %0
+ ldw%o1\\t%0, %1
@@ -7945,7 +10332,7 @@
+
+(define_insn "stwio"
+ [(set (match_operand:SI 0 "memory_operand" "=m")
-+ (match_operand:SI 1 "register_operand" "r"))
++ (match_operand:SI 1 "reg_or_0_operand" "rM"))
+ (unspec_volatile:SI [(const_int 0)] UNSPEC_STWIO)]
+ ""
+ "stwio\\t%z1, %0"
@@ -7994,26 +10381,30 @@
+;* sign extension
+;*
+;*****************************************************************************
-+
+(define_expand "extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
+ ""
+{
-+ if (optimize && GET_CODE (operands[1]) == MEM)
-+ operands[1] = force_not_mem (operands[1]);
++})
+
-+ if (GET_CODE (operands[1]) != MEM)
-+ {
-+ rtx op1 = gen_lowpart (SImode, operands[1]);
-+ rtx temp = gen_reg_rtx (SImode);
-+ rtx shift = GEN_INT (16);
++(define_insn "*extendhisi2"
++ [(set (match_operand:SI 0 "register_operand" "=r")
++ (sign_extend:SI (match_operand:HI 1 "register_operand" "r")))]
++ ""
++ "#")
+
-+ emit_insn (gen_ashlsi3 (temp, op1, shift));
-+ emit_insn (gen_ashrsi3 (operands[0], temp, shift));
-+ DONE;
-+ }
-+})
++(define_split
++ [(set (match_operand:SI 0 "register_operand" "")
++ (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
++ "reload_completed"
++ [(set (match_dup 0)
++ (and:SI (match_dup 1) (const_int 65535)))
++ (set (match_dup 0)
++ (xor:SI (match_dup 0) (const_int 32768)))
++ (set (match_dup 0)
++ (plus:SI (match_dup 0) (const_int -32768)))]
++ "operands[1] = gen_lowpart (SImode, operands[1]);")
+
+(define_insn "extendhisi2_internal"
+ [(set (match_operand:SI 0 "register_operand" "=r")
@@ -8022,26 +10413,34 @@
+ "ldh%o1\\t%0, %1"
+ [(set_attr "type" "ld")])
+
++
+(define_expand "extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "")
+ (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))]
+ ""
+{
-+ if (optimize && GET_CODE (operands[1]) == MEM)
-+ operands[1] = force_not_mem (operands[1]);
++})
++
++(define_insn "*extendqihi2"
++ [(set (match_operand:HI 0 "register_operand" "=r")
++ (sign_extend:HI (match_operand:QI 1 "register_operand" "r")))]
++ ""
++ "#")
++
++(define_split
++ [(set (match_operand:HI 0 "register_operand" "")
++ (sign_extend:HI (match_operand:QI 1 "register_operand" "")))]
++ "reload_completed"
++ [(set (match_dup 0)
++ (and:SI (match_dup 1) (const_int 255)))
++ (set (match_dup 0)
++ (xor:SI (match_dup 0) (const_int 128)))
++ (set (match_dup 0)
++ (plus:SI (match_dup 0) (const_int -128)))]
++ "operands[0] = gen_lowpart (SImode, operands[0]);
++ operands[1] = gen_lowpart (SImode, operands[1]);")
+
-+ if (GET_CODE (operands[1]) != MEM)
-+ {
-+ rtx op0 = gen_lowpart (SImode, operands[0]);
-+ rtx op1 = gen_lowpart (SImode, operands[1]);
-+ rtx temp = gen_reg_rtx (SImode);
-+ rtx shift = GEN_INT (24);
+
-+ emit_insn (gen_ashlsi3 (temp, op1, shift));
-+ emit_insn (gen_ashrsi3 (op0, temp, shift));
-+ DONE;
-+ }
-+})
+
+(define_insn "extendqihi2_internal"
+ [(set (match_operand:HI 0 "register_operand" "=r")
@@ -8056,20 +10455,25 @@
+ (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
+ ""
+{
-+ if (optimize && GET_CODE (operands[1]) == MEM)
-+ operands[1] = force_not_mem (operands[1]);
++})
+
-+ if (GET_CODE (operands[1]) != MEM)
-+ {
-+ rtx op1 = gen_lowpart (SImode, operands[1]);
-+ rtx temp = gen_reg_rtx (SImode);
-+ rtx shift = GEN_INT (24);
++(define_insn "*extendqisi2"
++ [(set (match_operand:SI 0 "register_operand" "=r")
++ (sign_extend:SI (match_operand:QI 1 "register_operand" "r")))]
++ ""
++ "#")
+
-+ emit_insn (gen_ashlsi3 (temp, op1, shift));
-+ emit_insn (gen_ashrsi3 (operands[0], temp, shift));
-+ DONE;
-+ }
-+})
++(define_split
++ [(set (match_operand:SI 0 "register_operand" "")
++ (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
++ "reload_completed"
++ [(set (match_dup 0)
++ (and:SI (match_dup 1) (const_int 255)))
++ (set (match_dup 0)
++ (xor:SI (match_dup 0) (const_int 128)))
++ (set (match_dup 0)
++ (plus:SI (match_dup 0) (const_int -128)))]
++ "operands[1] = gen_lowpart (SImode, operands[1]);")
+
+(define_insn "extendqisi2_insn"
+ [(set (match_operand:SI 0 "register_operand" "=r")
@@ -8080,6 +10484,7 @@
+
+
+
++
+;*****************************************************************************
+;*
+;* Arithmetic Operations
@@ -8094,6 +10499,26 @@
+ "add%i2\\t%0, %1, %z2"
+ [(set_attr "type" "alu")])
+
++(define_insn "addsf3"
++ [(set (match_operand:SF 0 "register_operand" "=r")
++ (plus:SF (match_operand:SF 1 "register_operand" "%r")
++ (match_operand:SF 2 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_addsf3].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_addsf3].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "adddf3"
++ [(set (match_operand:DF 0 "register_operand" "=r")
++ (plus:DF (match_operand:DF 1 "register_operand" "%r")
++ (match_operand:DF 2 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_adddf3].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_adddf3].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
+(define_insn "subsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
@@ -8102,6 +10527,26 @@
+ "sub\\t%0, %z1, %2"
+ [(set_attr "type" "alu")])
+
++(define_insn "subsf3"
++ [(set (match_operand:SF 0 "register_operand" "=r")
++ (minus:SF (match_operand:SF 1 "register_operand" "r")
++ (match_operand:SF 2 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_subsf3].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_subsf3].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "subdf3"
++ [(set (match_operand:DF 0 "register_operand" "=r")
++ (minus:DF (match_operand:DF 1 "register_operand" "r")
++ (match_operand:DF 2 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_subdf3].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_subdf3].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
+(define_insn "mulsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (mult:SI (match_operand:SI 1 "register_operand" "r,r")
@@ -8110,6 +10555,26 @@
+ "mul%i2\\t%0, %1, %z2"
+ [(set_attr "type" "mul")])
+
++(define_insn "mulsf3"
++ [(set (match_operand:SF 0 "register_operand" "=r")
++ (mult:SF (match_operand:SF 1 "register_operand" "%r")
++ (match_operand:SF 2 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_mulsf3].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_mulsf3].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "muldf3"
++ [(set (match_operand:DF 0 "register_operand" "=r")
++ (mult:DF (match_operand:DF 1 "register_operand" "%r")
++ (match_operand:DF 2 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_muldf3].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_muldf3].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
+(define_expand "divsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (div:SI (match_operand:SI 1 "register_operand" "r")
@@ -8136,6 +10601,26 @@
+ "div\\t%0, %1, %2"
+ [(set_attr "type" "div")])
+
++(define_insn "divsf3"
++ [(set (match_operand:SF 0 "register_operand" "=r")
++ (div:SF (match_operand:SF 1 "register_operand" "r")
++ (match_operand:SF 2 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_divsf3].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_divsf3].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "divdf3"
++ [(set (match_operand:DF 0 "register_operand" "=r")
++ (div:DF (match_operand:DF 1 "register_operand" "r")
++ (match_operand:DF 2 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_divdf3].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_divdf3].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
+(define_insn "udivsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (udiv:SI (match_operand:SI 1 "register_operand" "r")
@@ -8167,7 +10652,7 @@
+ [(set_attr "type" "mul")])
+
+
-+(define_expand "mulsidi3"
++(define_expand "mulsidi3_little_endian"
+ [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 0)
+ (mult:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "register_operand" "")))
@@ -8175,10 +10660,42 @@
+ (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1))
+ (sign_extend:DI (match_dup 2)))
+ (const_int 32))))]
-+ "TARGET_HAS_MULX"
++ "TARGET_HAS_MULX && !WORDS_BIG_ENDIAN"
+ "")
+
-+(define_expand "umulsidi3"
++(define_expand "mulsidi3_big_endian"
++ [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 4)
++ (mult:SI (match_operand:SI 1 "register_operand" "")
++ (match_operand:SI 2 "register_operand" "")))
++ (set (subreg:SI (match_dup 0) 0)
++ (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1))
++ (sign_extend:DI (match_dup 2)))
++ (const_int 32))))]
++ "TARGET_HAS_MULX && WORDS_BIG_ENDIAN"
++ "")
++
++(define_expand "mulsidi3"
++ [(match_operand:DI 0 "register_operand" "")
++ (match_operand:SI 1 "register_operand" "")
++ (match_operand:SI 2 "register_operand" "")]
++ "TARGET_HAS_MULX"
++ {
++ if (WORDS_BIG_ENDIAN)
++ {
++ emit_insn (gen_mulsidi3_big_endian (operands[0],
++ operands[1],
++ operands[2]));
++ }
++ else
++ {
++ emit_insn (gen_mulsidi3_little_endian (operands[0],
++ operands[1],
++ operands[2]));
++ }
++ DONE;
++ })
++
++(define_expand "umulsidi3_little_endian"
+ [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 0)
+ (mult:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "register_operand" "")))
@@ -8186,9 +10703,40 @@
+ (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1))
+ (zero_extend:DI (match_dup 2)))
+ (const_int 32))))]
-+ "TARGET_HAS_MULX"
++ "TARGET_HAS_MULX && !WORDS_BIG_ENDIAN"
++ "")
++
++(define_expand "umulsidi3_big_endian"
++ [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 4)
++ (mult:SI (match_operand:SI 1 "register_operand" "")
++ (match_operand:SI 2 "register_operand" "")))
++ (set (subreg:SI (match_dup 0) 0)
++ (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1))
++ (zero_extend:DI (match_dup 2)))
++ (const_int 32))))]
++ "TARGET_HAS_MULX && WORDS_BIG_ENDIAN"
+ "")
+
++(define_expand "umulsidi3"
++ [(match_operand:DI 0 "register_operand" "")
++ (match_operand:SI 1 "register_operand" "")
++ (match_operand:SI 2 "register_operand" "")]
++ "TARGET_HAS_MULX"
++ {
++ if (WORDS_BIG_ENDIAN)
++ {
++ emit_insn (gen_umulsidi3_big_endian (operands[0],
++ operands[1],
++ operands[2]));
++ }
++ else
++ {
++ emit_insn (gen_umulsidi3_little_endian (operands[0],
++ operands[1],
++ operands[2]));
++ }
++ DONE;
++ })
+
+
+;*****************************************************************************
@@ -8207,6 +10755,24 @@
+}
+ [(set_attr "type" "alu")])
+
++(define_insn "negsf2"
++ [(set (match_operand:SF 0 "register_operand" "=r")
++ (neg:SF (match_operand:SF 1 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_negsf2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_negsf2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "negdf2"
++ [(set (match_operand:DF 0 "register_operand" "=r")
++ (neg:DF (match_operand:DF 1 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_negdf2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_negdf2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
+(define_insn "one_cmplsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (not:SI (match_operand:SI 1 "register_operand" "r")))]
@@ -8218,8 +10784,252 @@
+ [(set_attr "type" "alu")])
+
+
++;*****************************************************************************
++;*
++;* Miscellaneous floating point
++;*
++;*****************************************************************************
++(define_insn "nios2_fwrx"
++ [(unspec_volatile [(match_operand:DF 0 "register_operand" "r")] UNSPEC_FWRX)]
++ "nios2_fpu_insns[nios2_fpu_nios2_fwrx].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_nios2_fwrx].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "nios2_fwry"
++ [(unspec_volatile [(match_operand:SF 0 "register_operand" "r")] UNSPEC_FWRY)]
++ "nios2_fpu_insns[nios2_fpu_nios2_fwry].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_nios2_fwry].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "nios2_frdxlo"
++ [(set (match_operand:SF 0 "register_operand" "=r")
++ (unspec_volatile:SF [(const_int 0)] UNSPEC_FRDXLO))]
++ "nios2_fpu_insns[nios2_fpu_nios2_frdxlo].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_nios2_frdxlo].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "nios2_frdxhi"
++ [(set (match_operand:SF 0 "register_operand" "=r")
++ (unspec_volatile:SF [(const_int 0)] UNSPEC_FRDXHI))]
++ "nios2_fpu_insns[nios2_fpu_nios2_frdxhi].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_nios2_frdxhi].output) (insn);
++ }
++ [(set_attr "type" "custom")])
+
-+; Logical Operantions
++(define_insn "nios2_frdy"
++ [(set (match_operand:SF 0 "register_operand" "=r")
++ (unspec_volatile:SF [(const_int 0)] UNSPEC_FRDY))]
++ "nios2_fpu_insns[nios2_fpu_nios2_frdy].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_nios2_frdy].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "minsf3"
++ [(set (match_operand:SF 0 "register_operand" "=r")
++ (if_then_else:SF (lt:SF (match_operand:SF 1 "register_operand" "%r")
++ (match_operand:SF 2 "register_operand" "r"))
++ (match_dup 1)
++ (match_dup 2)))]
++ "nios2_fpu_insns[nios2_fpu_minsf3].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_minsf3].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "mindf3"
++ [(set (match_operand:DF 0 "register_operand" "=r")
++ (if_then_else:DF (lt:DF (match_operand:DF 1 "register_operand" "%r")
++ (match_operand:DF 2 "register_operand" "r"))
++ (match_dup 1)
++ (match_dup 2)))]
++ "nios2_fpu_insns[nios2_fpu_mindf3].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_mindf3].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "maxsf3"
++ [(set (match_operand:SF 0 "register_operand" "=r")
++ (if_then_else:SF (lt:SF (match_operand:SF 1 "register_operand" "%r")
++ (match_operand:SF 2 "register_operand" "r"))
++ (match_dup 2)
++ (match_dup 1)))]
++ "nios2_fpu_insns[nios2_fpu_maxsf3].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_maxsf3].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "maxdf3"
++ [(set (match_operand:DF 0 "register_operand" "=r")
++ (if_then_else:DF (lt:DF (match_operand:DF 1 "register_operand" "%r")
++ (match_operand:DF 2 "register_operand" "r"))
++ (match_dup 2)
++ (match_dup 1)))]
++ "nios2_fpu_insns[nios2_fpu_maxdf3].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_maxdf3].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "abssf2"
++ [(set (match_operand:SF 0 "register_operand" "=r")
++ (abs:SF (match_operand:SF 1 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_abssf2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_abssf2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "absdf2"
++ [(set (match_operand:DF 0 "register_operand" "=r")
++ (abs:DF (match_operand:DF 1 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_absdf2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_absdf2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "sqrtsf2"
++ [(set (match_operand:SF 0 "register_operand" "=r")
++ (sqrt:SF (match_operand:SF 1 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_sqrtsf2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_sqrtsf2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "sqrtdf2"
++ [(set (match_operand:DF 0 "register_operand" "=r")
++ (sqrt:DF (match_operand:DF 1 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_sqrtdf2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_sqrtdf2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "cossf2"
++ [(set (match_operand:SF 0 "register_operand" "=r")
++ (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_FCOSS))]
++ "nios2_fpu_insns[nios2_fpu_cossf2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_cossf2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "cosdf2"
++ [(set (match_operand:DF 0 "register_operand" "=r")
++ (unspec:DF [(match_operand:DF 1 "register_operand" "r")] UNSPEC_FCOSD))]
++ "nios2_fpu_insns[nios2_fpu_cosdf2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_cosdf2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "sinsf2"
++ [(set (match_operand:SF 0 "register_operand" "=r")
++ (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_FSINS))]
++ "nios2_fpu_insns[nios2_fpu_sinsf2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_sinsf2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "sindf2"
++ [(set (match_operand:DF 0 "register_operand" "=r")
++ (unspec:DF [(match_operand:DF 1 "register_operand" "r")] UNSPEC_FSIND))]
++ "nios2_fpu_insns[nios2_fpu_sindf2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_sindf2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "tansf2"
++ [(set (match_operand:SF 0 "register_operand" "=r")
++ (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_FTANS))]
++ "nios2_fpu_insns[nios2_fpu_tansf2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_tansf2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "tandf2"
++ [(set (match_operand:DF 0 "register_operand" "=r")
++ (unspec:DF [(match_operand:DF 1 "register_operand" "r")] UNSPEC_FTAND))]
++ "nios2_fpu_insns[nios2_fpu_tandf2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_tandf2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "atansf2"
++ [(set (match_operand:SF 0 "register_operand" "=r")
++ (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_FATANS))]
++ "nios2_fpu_insns[nios2_fpu_atansf2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_atansf2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "atandf2"
++ [(set (match_operand:DF 0 "register_operand" "=r")
++ (unspec:DF [(match_operand:DF 1 "register_operand" "r")] UNSPEC_FATAND))]
++ "nios2_fpu_insns[nios2_fpu_atandf2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_atandf2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "expsf2"
++ [(set (match_operand:SF 0 "register_operand" "=r")
++ (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_FEXPS))]
++ "nios2_fpu_insns[nios2_fpu_expsf2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_expsf2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "expdf2"
++ [(set (match_operand:DF 0 "register_operand" "=r")
++ (unspec:DF [(match_operand:DF 1 "register_operand" "r")] UNSPEC_FEXPD))]
++ "nios2_fpu_insns[nios2_fpu_expdf2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_expdf2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "logsf2"
++ [(set (match_operand:SF 0 "register_operand" "=r")
++ (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_FLOGS))]
++ "nios2_fpu_insns[nios2_fpu_logsf2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_logsf2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "logdf2"
++ [(set (match_operand:DF 0 "register_operand" "=r")
++ (unspec:DF [(match_operand:DF 1 "register_operand" "r")] UNSPEC_FLOGD))]
++ "nios2_fpu_insns[nios2_fpu_logdf2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_logdf2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++
++;*****************************************************************************
++;*
++;* Logical Operantions
++;*
++;*****************************************************************************
+
+(define_insn "andsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r, r,r")
@@ -8275,7 +11085,12 @@
+ (ashift:SI (match_operand:SI 1 "register_operand" "r,r")
+ (match_operand:SI 2 "shift_operand" "r,L")))]
+ ""
-+ "sll%i2\\t%0, %1, %z2"
++
++{
++ if( GET_CODE ( operands[2] ) == CONST_INT && INTVAL( operands[2] ) == 1 )
++ return "add\t%0,%1,%1";
++ return "sll%i2\t%0,%1,%z2";
++}
+ [(set_attr "type" "shift")])
+
+(define_insn "ashrsi3"
@@ -8334,6 +11149,108 @@
+
+;*****************************************************************************
+;*
++;* Converting between floating point and fixed point
++;*
++;*****************************************************************************
++(define_insn "floatsisf2"
++ [(set (match_operand:SF 0 "register_operand" "=r")
++ (float:SF (match_operand:SI 1 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_floatsisf2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_floatsisf2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "floatsidf2"
++ [(set (match_operand:DF 0 "register_operand" "=r")
++ (float:DF (match_operand:SI 1 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_floatsidf2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_floatsidf2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "floatunssisf2"
++ [(set (match_operand:SF 0 "register_operand" "=r")
++ (unsigned_float:SF (match_operand:SI 1 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_floatunssisf2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_floatunssisf2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "floatunssidf2"
++ [(set (match_operand:DF 0 "register_operand" "=r")
++ (unsigned_float:DF (match_operand:SI 1 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_floatunssidf2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_floatunssidf2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "fixsfsi2"
++ [(set (match_operand:SI 0 "register_operand" "=r")
++ (fix:SI (match_operand:SF 1 "general_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_fixsfsi2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_fixsfsi2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "fixdfsi2"
++ [(set (match_operand:SI 0 "register_operand" "=r")
++ (fix:SI (match_operand:DF 1 "general_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_fixdfsi2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_fixdfsi2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "fixunssfsi2"
++ [(set (match_operand:SI 0 "register_operand" "=r")
++ (unsigned_fix:SI (match_operand:SF 1 "general_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_fixunssfsi2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_fixunssfsi2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "fixunsdfsi2"
++ [(set (match_operand:SI 0 "register_operand" "=r")
++ (unsigned_fix:SI (match_operand:DF 1 "general_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_fixunsdfsi2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_fixunsdfsi2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "extendsfdf2"
++ [(set (match_operand:DF 0 "register_operand" "=r")
++ (float_extend:DF (match_operand:SF 1 "general_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_extendsfdf2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_extendsfdf2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++(define_insn "truncdfsf2"
++ [(set (match_operand:SF 0 "register_operand" "=r")
++ (float_truncate:SF (match_operand:DF 1 "general_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_truncdfsf2].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_truncdfsf2].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++
++
++
++
++
++
++
++;*****************************************************************************
++;*
+;* Prologue, Epilogue and Return
+;*
+;*****************************************************************************
@@ -8487,7 +11404,7 @@
+)
+
+(define_insn "sibcall_insn"
-+ [(call (mem:QI (match_operand:SI 0 "register_operand" "r"))
++ [(call (mem:QI (match_operand:SI 0 "register_operand" "D08"))
+ (match_operand 1 "" ""))
+ (return)
+ (use (match_operand 2 "" ""))]
@@ -8497,7 +11414,7 @@
+
+(define_insn "sibcall_value_insn"
+ [(set (match_operand 0 "register_operand" "")
-+ (call (mem:QI (match_operand:SI 1 "register_operand" "r"))
++ (call (mem:QI (match_operand:SI 1 "register_operand" "D08"))
+ (match_operand 2 "" "")))
+ (return)
+ (use (match_operand 3 "" ""))]
@@ -8569,6 +11486,40 @@
+ DONE;
+})
+
++(define_expand "cmpsf"
++ [(set (cc0)
++ (compare:CC (match_operand:SF 0 "register_operand" "")
++ (match_operand:SF 1 "register_operand" "")))]
++ "(nios2_fpu_insns[nios2_fpu_nios2_sltsf].N >= 0
++ || nios2_fpu_insns[nios2_fpu_nios2_sgtsf].N >= 0)
++ && (nios2_fpu_insns[nios2_fpu_nios2_sgesf].N >= 0
++ || nios2_fpu_insns[nios2_fpu_nios2_slesf].N >= 0)
++ && nios2_fpu_insns[nios2_fpu_nios2_seqsf].N >= 0
++ && nios2_fpu_insns[nios2_fpu_nios2_snesf].N >= 0"
++{
++ branch_cmp[0] = operands[0];
++ branch_cmp[1] = operands[1];
++ branch_type = CMP_SF;
++ DONE;
++})
++
++(define_expand "cmpdf"
++ [(set (cc0)
++ (compare:CC (match_operand:DF 0 "register_operand" "")
++ (match_operand:DF 1 "register_operand" "")))]
++ "(nios2_fpu_insns[nios2_fpu_nios2_sltdf].N >= 0
++ || nios2_fpu_insns[nios2_fpu_nios2_sgtdf].N >= 0)
++ && (nios2_fpu_insns[nios2_fpu_nios2_sgedf].N >= 0
++ || nios2_fpu_insns[nios2_fpu_nios2_sledf].N >= 0)
++ && nios2_fpu_insns[nios2_fpu_nios2_seqdf].N >= 0
++ && nios2_fpu_insns[nios2_fpu_nios2_snedf].N >= 0"
++{
++ branch_cmp[0] = operands[0];
++ branch_cmp[1] = operands[1];
++ branch_type = CMP_DF;
++ DONE;
++})
++
+
+;*****************************************************************************
+;*
@@ -8582,7 +11533,7 @@
+ (match_dup 2)))]
+ ""
+{
-+ if (branch_type != CMP_SI)
++ if (branch_type != CMP_SI && branch_type != CMP_SF && branch_type != CMP_DF)
+ FAIL;
+
+ /* set up operands from compare. */
@@ -8603,13 +11554,35 @@
+ [(set_attr "type" "alu")])
+
+
++(define_insn "nios2_seqsf"
++ [(set (match_operand:SI 0 "register_operand" "=r")
++ (eq:SI (match_operand:SF 1 "register_operand" "%r")
++ (match_operand:SF 2 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_nios2_seqsf].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_nios2_seqsf].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++
++(define_insn "nios2_seqdf"
++ [(set (match_operand:SI 0 "register_operand" "=r")
++ (eq:SI (match_operand:DF 1 "register_operand" "%r")
++ (match_operand:DF 2 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_nios2_seqdf].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_nios2_seqdf].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++
+(define_expand "sne"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ne:SI (match_dup 1)
+ (match_dup 2)))]
+ ""
+{
-+ if (branch_type != CMP_SI)
++ if (branch_type != CMP_SI && branch_type != CMP_SF && branch_type != CMP_DF)
+ FAIL;
+
+ /* set up operands from compare. */
@@ -8630,13 +11603,35 @@
+ [(set_attr "type" "alu")])
+
+
++(define_insn "nios2_snesf"
++ [(set (match_operand:SI 0 "register_operand" "=r")
++ (ne:SI (match_operand:SF 1 "register_operand" "%r")
++ (match_operand:SF 2 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_nios2_snesf].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_nios2_snesf].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++
++(define_insn "nios2_snedf"
++ [(set (match_operand:SI 0 "register_operand" "=r")
++ (ne:SI (match_operand:DF 1 "register_operand" "%r")
++ (match_operand:DF 2 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_nios2_snedf].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_nios2_snedf].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++
+(define_expand "sgt"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (gt:SI (match_dup 1)
+ (match_dup 2)))]
+ ""
+{
-+ if (branch_type != CMP_SI)
++ if (branch_type != CMP_SI && branch_type != CMP_SF && branch_type != CMP_DF)
+ FAIL;
+
+ /* set up operands from compare. */
@@ -8657,13 +11652,35 @@
+ [(set_attr "type" "alu")])
+
+
++(define_insn "nios2_sgtsf"
++ [(set (match_operand:SI 0 "register_operand" "=r")
++ (gt:SI (match_operand:SF 1 "register_operand" "r")
++ (match_operand:SF 2 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_nios2_sgtsf].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_nios2_sgtsf].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++
++(define_insn "nios2_sgtdf"
++ [(set (match_operand:SI 0 "register_operand" "=r")
++ (gt:SI (match_operand:DF 1 "register_operand" "r")
++ (match_operand:DF 2 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_nios2_sgtdf].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_nios2_sgtdf].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++
+(define_expand "sge"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ge:SI (match_dup 1)
+ (match_dup 2)))]
+ ""
+{
-+ if (branch_type != CMP_SI)
++ if (branch_type != CMP_SI && branch_type != CMP_SF && branch_type != CMP_DF)
+ FAIL;
+
+ /* set up operands from compare. */
@@ -8683,13 +11700,36 @@
+ "cmpge%i2\\t%0, %z1, %z2"
+ [(set_attr "type" "alu")])
+
++
++(define_insn "nios2_sgesf"
++ [(set (match_operand:SI 0 "register_operand" "=r")
++ (ge:SI (match_operand:SF 1 "register_operand" "r")
++ (match_operand:SF 2 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_nios2_sgesf].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_nios2_sgesf].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++
++(define_insn "nios2_sgedf"
++ [(set (match_operand:SI 0 "register_operand" "=r")
++ (ge:SI (match_operand:DF 1 "register_operand" "r")
++ (match_operand:DF 2 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_nios2_sgedf].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_nios2_sgedf].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++
+(define_expand "sle"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (le:SI (match_dup 1)
+ (match_dup 2)))]
+ ""
+{
-+ if (branch_type != CMP_SI)
++ if (branch_type != CMP_SI && branch_type != CMP_SF && branch_type != CMP_DF)
+ FAIL;
+
+ /* set up operands from compare. */
@@ -8710,13 +11750,35 @@
+ [(set_attr "type" "alu")])
+
+
++(define_insn "nios2_slesf"
++ [(set (match_operand:SI 0 "register_operand" "=r")
++ (le:SI (match_operand:SF 1 "register_operand" "r")
++ (match_operand:SF 2 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_nios2_slesf].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_nios2_slesf].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++
++(define_insn "nios2_sledf"
++ [(set (match_operand:SI 0 "register_operand" "=r")
++ (le:SI (match_operand:DF 1 "register_operand" "r")
++ (match_operand:DF 2 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_nios2_sledf].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_nios2_sledf].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++
+(define_expand "slt"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lt:SI (match_dup 1)
+ (match_dup 2)))]
+ ""
+{
-+ if (branch_type != CMP_SI)
++ if (branch_type != CMP_SI && branch_type != CMP_SF && branch_type != CMP_DF)
+ FAIL;
+
+ /* set up operands from compare. */
@@ -8737,6 +11799,28 @@
+ [(set_attr "type" "alu")])
+
+
++(define_insn "nios2_sltsf"
++ [(set (match_operand:SI 0 "register_operand" "=r")
++ (lt:SI (match_operand:SF 1 "register_operand" "r")
++ (match_operand:SF 2 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_nios2_sltsf].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_nios2_sltsf].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++
++(define_insn "nios2_sltdf"
++ [(set (match_operand:SI 0 "register_operand" "=r")
++ (lt:SI (match_operand:DF 1 "register_operand" "r")
++ (match_operand:DF 2 "register_operand" "r")))]
++ "nios2_fpu_insns[nios2_fpu_nios2_sltdf].N >= 0"
++ {
++ return (*nios2_fpu_insns[nios2_fpu_nios2_sltdf].output) (insn);
++ }
++ [(set_attr "type" "custom")])
++
++
+(define_expand "sgtu"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (gtu:SI (match_dup 1)
@@ -8865,6 +11949,36 @@
+ [(set_attr "type" "control")])
+
+
++(define_insn "nios2_cbranch_sf"
++ [(set (pc)
++ (if_then_else
++ (match_operator:SI 0 "comparison_operator"
++ [(match_operand:SF 2 "register_operand" "r")
++ (match_operand:SF 3 "register_operand" "r")])
++ (label_ref (match_operand 1 "" ""))
++ (pc)))]
++ ""
++ {
++ return nios2_output_fpu_insn_cmps (insn, GET_CODE (operands[0]));
++ }
++ [(set_attr "type" "custom")])
++
++
++(define_insn "nios2_cbranch_df"
++ [(set (pc)
++ (if_then_else
++ (match_operator:SI 0 "comparison_operator"
++ [(match_operand:DF 2 "register_operand" "r")
++ (match_operand:DF 3 "register_operand" "r")])
++ (label_ref (match_operand 1 "" ""))
++ (pc)))]
++ ""
++ {
++ return nios2_output_fpu_insn_cmpd (insn, GET_CODE (operands[0]));
++ }
++ [(set_attr "type" "custom")])
++
++
+(define_expand "beq"
+ [(set (pc)
+ (if_then_else (eq:CC (cc0)
@@ -9741,11 +12855,23 @@
+
+(define_insn "wrctl"
+ [(unspec_volatile:SI [(match_operand:SI 0 "rdwrctl_operand" "O")
-+ (match_operand:SI 1 "register_operand" "r")] UNSPEC_WRCTL)]
++ (match_operand:SI 1 "reg_or_0_operand" "rM")] UNSPEC_WRCTL)]
+ ""
-+ "wrctl\\tctl%0, %1"
++ "wrctl\\tctl%0, %z1"
+ [(set_attr "type" "control")])
+
++;Used to signal a stack overflow
++(define_insn "trap"
++ [(unspec_volatile [(const_int 0)] UNSPEC_TRAP)]
++ ""
++ "break\\t3"
++ [(set_attr "type" "control")])
++
++(define_insn "stack_overflow_detect_and_trap"
++ [(unspec_volatile [(const_int 0)] UNSPEC_STACK_OVERFLOW_DETECT_AND_TRAP)]
++ ""
++ "bgeu\\tsp, et, 1f\;break\\t3\;1:"
++ [(set_attr "type" "control")])
+
+
+;*****************************************************************************
@@ -9755,9 +12881,15 @@
+;*****************************************************************************
+
+
---- gcc-3.4.3/gcc/config/nios2/t-nios2
-+++ gcc-3.4.3-nios2/gcc/config/nios2/t-nios2
-@@ -0,0 +1,123 @@
++;; Local Variables:
++;; mode: lisp
++;; End:
+diff --git a/gcc/config/nios2/t-nios2 b/gcc/config/nios2/t-nios2
+new file mode 100644
+index 0000000..b92f80a
+--- /dev/null
++++ b/gcc/config/nios2/t-nios2
+@@ -0,0 +1,175 @@
+##
+## Compiler flags to use when compiling libgcc2.c.
+##
@@ -9790,10 +12922,16 @@
+
+$(FPBIT): $(srcdir)/config/fp-bit.c Makefile
+ echo '#define FLOAT' > ${FPBIT}
++ echo '#ifndef __nios2_big_endian__' >> ${FPBIT}
++ echo '#define FLOAT_BIT_ORDER_MISMATCH' >> ${FPBIT}
++ echo '#endif' >> ${FPBIT}
+ cat $(srcdir)/config/fp-bit.c >> ${FPBIT}
+
+$(DPBIT): $(srcdir)/config/fp-bit.c Makefile
+ echo '' > ${DPBIT}
++ echo '#ifndef __nios2_big_endian__' >> ${DPBIT}
++ echo '#define FLOAT_BIT_ORDER_MISMATCH' >> ${DPBIT}
++ echo '#endif' >> ${DPBIT}
+ cat $(srcdir)/config/fp-bit.c >> ${DPBIT}
+
+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
@@ -9837,7 +12975,44 @@
+## sets of options: -m68000, -m68020, -msoft-float, -m68000 -msoft-float,
+## and -m68020 -msoft-float.
+
-+MULTILIB_OPTIONS = mno-hw-mul mhw-mulx
++
++## The BUILD_BE_MULTILIB and BUILD_PG_MULTILIB variables allow the
++## makefile user to enable/disable the generation of the precompiled
++## big endian and profiling libraries. By default, the big endian
++## libraries are not created on a windows build and the profiling
++## libraries are not created on a Solaris build. All other library
++## combinations are created by default.
++
++# Uncomment to temporarily avoid building big endian and profiling libraries during a Windows build.
++#ifeq ($(DEV_HOST_OS), win32)
++#BUILD_BE_MULTILIB ?= 0
++#BUILD_PG_MULTILIB ?= 0
++#endif
++
++#By default, avoid building the profiling libraries during a Solaris build.
++ifeq ($(DEV_HOST_OS), solaris)
++BUILD_PG_MULTILIB ?= 0
++endif
++
++BUILD_BE_MULTILIB ?= 1
++BUILD_PG_MULTILIB ?= 1
++BUILD_MULTILIB ?= 1
++
++ifeq ($(BUILD_MULTILIB), 1)
++
++MULTILIB_OPTIONS = mno-hw-mul mhw-mulx mstack-check mcustom-fpu-cfg=60-1 mcustom-fpu-cfg=60-2
++
++#Add the profiling flag to the multilib variable if required
++ifeq ($(BUILD_PG_MULTILIB), 1)
++MULTILIB_OPTIONS += pg
++endif
++
++#Add the big endian flag to the multilib variable if required
++ifeq ($(BUILD_BE_MULTILIB), 1)
++MULTILIB_OPTIONS += EB/EL
++endif
++
++endif
+
+## MULTILIB_DIRNAMES
+## If MULTILIB_OPTIONS is used, this variable specifies the directory names
@@ -9858,6 +13033,13 @@
+## synonyms. In that case, set MULTILIB_MATCHES to a list of items of the
+## form option=option to describe all relevant synonyms. For example,
+## m68000=mc68000 m68020=mc68020.
++
++ifeq ($(BUILD_MULTILIB), 1)
++ifeq ($(BUILD_BE_MULTILIB), 1)
++MULTILIB_MATCHES = EL=mel EB=meb
++endif
++endif
++
+##
+## MULTILIB_EXCEPTIONS
+## Sometimes when there are multiple sets of MULTILIB_OPTIONS being
@@ -9872,7 +13054,9 @@
+## *mcall-aix/*fleading-underscore* *mlittle/*mcall-aix*
+##
+
-+MULTILIB_EXCEPTIONS = *mno-hw-mul/*mhw-mulx*
++ifeq ($(BUILD_MULTILIB), 1)
++MULTILIB_EXCEPTIONS = *mno-hw-mul/*mhw-mulx* *mcustom-fpu-cfg=60-1/*mcustom-fpu-cfg=60-2*
++endif
+
+##
+## MULTILIB_EXTRA_OPTS Sometimes it is desirable that when building
@@ -9881,22 +13065,169 @@
+## of options to be used for all builds.
+##
+
---- gcc-3.4.3/gcc/config.gcc
-+++ gcc-3.4.3-nios2/gcc/config.gcc
-@@ -1321,6 +1321,10 @@ m32rle-*-linux*)
- thread_file='posix'
- fi
- ;;
-+# JBG
-+nios2-*-* | nios2-*-*)
-+ tm_file="elfos.h ${tm_file}"
-+ ;;
- # m68hc11 and m68hc12 share the same machine description.
- m68hc11-*-*|m6811-*-*)
- tm_file="dbxelf.h elfos.h m68hc11/m68hc11.h"
---- gcc-3.4.3/gcc/cse.c
-+++ gcc-3.4.3-nios2/gcc/cse.c
-@@ -3134,6 +3134,10 @@ find_comparison_args (enum rtx_code code
+diff --git a/gcc/config/nios2/t-nios2-uclibc b/gcc/config/nios2/t-nios2-uclibc
+new file mode 100644
+index 0000000..9a303db
+--- /dev/null
++++ b/gcc/config/nios2/t-nios2-uclibc
+@@ -0,0 +1,152 @@
++##
++## Compiler flags to use when compiling libgcc2.c.
++##
++## LIB2FUNCS_EXTRA
++## A list of source file names to be compiled or assembled and inserted into libgcc.a.
++
++LIB2FUNCS_EXTRA=$(srcdir)/config/nios2/lib2-divmod.c \
++ $(srcdir)/config/nios2/lib2-divmod-hi.c \
++ $(srcdir)/config/nios2/lib2-divtable.c \
++ $(srcdir)/config/nios2/lib2-mul.c
++
++##
++## Floating Point Emulation
++## To have GCC include software floating point libraries in libgcc.a define FPBIT
++## and DPBIT along with a few rules as follows:
++##
++## # We want fine grained libraries, so use the new code
++## # to build the floating point emulation libraries.
++FPBIT=$(srcdir)/config/nios2/nios2-fp-bit.c
++DPBIT=$(srcdir)/config/nios2/nios2-dp-bit.c
++
++TARGET_LIBGCC2_CFLAGS = -O2
++
++# FLOAT_ONLY - no doubles
++# SMALL_MACHINE - QI/HI is faster than SI
++# Actually SMALL_MACHINE uses chars and shorts instead of ints
++# since ints (16-bit ones as they are today) are at least as fast
++# as chars and shorts, don't define SMALL_MACHINE
++# CMPtype - type returned by FP compare, i.e. INT (hard coded in fp-bit - see code )
++
++$(FPBIT): $(srcdir)/config/fp-bit.c Makefile
++ echo '#define FLOAT' > ${FPBIT}
++ echo '#ifndef __nios2_big_endian__' >> ${FPBIT}
++ echo '#define FLOAT_BIT_ORDER_MISMATCH' >> ${FPBIT}
++ echo '#endif' >> ${FPBIT}
++ cat $(srcdir)/config/fp-bit.c >> ${FPBIT}
++
++$(DPBIT): $(srcdir)/config/fp-bit.c Makefile
++ echo '' > ${DPBIT}
++ echo '#ifndef __nios2_big_endian__' >> ${DPBIT}
++ echo '#define FLOAT_BIT_ORDER_MISMATCH' >> ${DPBIT}
++ echo '#endif' >> ${DPBIT}
++ cat $(srcdir)/config/fp-bit.c >> ${DPBIT}
++
++EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o
++
++## You may need to provide additional #defines at the beginning of
++## fp-bit.c and dp-bit.c to control target endianness and other options
++##
++## CRTSTUFF_T_CFLAGS
++## Special flags used when compiling crtstuff.c. See Initialization.
++##
++## CRTSTUFF_T_CFLAGS_S
++## Special flags used when compiling crtstuff.c for shared linking. Used
++## if you use crtbeginS.o and crtendS.o in EXTRA-PARTS. See Initialization.
++##
++## MULTILIB_OPTIONS
++## For some targets, invoking GCC in different ways produces objects that
++## can not be linked together. For example, for some targets GCC produces
++## both big and little endian code. For these targets, you must arrange
++## for multiple versions of libgcc.a to be compiled, one for each set of
++## incompatible options. When GCC invokes the linker, it arranges to link
++## in the right version of libgcc.a, based on the command line options
++## used.
++## The MULTILIB_OPTIONS macro lists the set of options for which special
++## versions of libgcc.a must be built. Write options that are mutually
++## incompatible side by side, separated by a slash. Write options that may
++## be used together separated by a space. The build procedure will build
++## all combinations of compatible options.
++##
++## For example, if you set MULTILIB_OPTIONS to m68000/m68020 msoft-float,
++## Makefile will build special versions of libgcc.a using the following
++## sets of options: -m68000, -m68020, -msoft-float, -m68000 -msoft-float,
++## and -m68020 -msoft-float.
++
++
++## The BUILD_BE_MULTILIB and BUILD_PG_MULTILIB variables allow the
++## makefile user to enable/disable the generation of the precompiled
++## big endian and profiling libraries.
++
++# By default, avoid building big endian and profiling libraries
++BUILD_BE_MULTILIB ?= 0
++BUILD_PG_MULTILIB ?= 0
++BUILD_MULTILIB ?= 1
++
++ifeq ($(BUILD_MULTILIB), 1)
++
++MULTILIB_OPTIONS = mno-hw-mul mhw-mulx mstack-check mcustom-fpu-cfg=60-1 mcustom-fpu-cfg=60-2
++
++#Add the profiling flag to the multilib variable if required
++ifeq ($(BUILD_PG_MULTILIB), 1)
++MULTILIB_OPTIONS += pg
++endif
++
++#Add the big endian flag to the multilib variable if required
++ifeq ($(BUILD_BE_MULTILIB), 1)
++MULTILIB_OPTIONS += EB/EL
++endif
++
++endif
++
++## MULTILIB_DIRNAMES
++## If MULTILIB_OPTIONS is used, this variable specifies the directory names
++## that should be used to hold the various libraries. Write one element in
++## MULTILIB_DIRNAMES for each element in MULTILIB_OPTIONS. If
++## MULTILIB_DIRNAMES is not used, the default value will be
++## MULTILIB_OPTIONS, with all slashes treated as spaces.
++## For example, if MULTILIB_OPTIONS is set to m68000/m68020 msoft-float,
++## then the default value of MULTILIB_DIRNAMES is m68000 m68020
++## msoft-float. You may specify a different value if you desire a
++## different set of directory names.
++
++# MULTILIB_DIRNAMES =
++
++## MULTILIB_MATCHES
++## Sometimes the same option may be written in two different ways. If an
++## option is listed in MULTILIB_OPTIONS, GCC needs to know about any
++## synonyms. In that case, set MULTILIB_MATCHES to a list of items of the
++## form option=option to describe all relevant synonyms. For example,
++## m68000=mc68000 m68020=mc68020.
++
++ifeq ($(BUILD_MULTILIB), 1)
++ifeq ($(BUILD_BE_MULTILIB), 1)
++MULTILIB_MATCHES = EL=mel EB=meb
++endif
++endif
++
++##
++## MULTILIB_EXCEPTIONS
++## Sometimes when there are multiple sets of MULTILIB_OPTIONS being
++## specified, there are combinations that should not be built. In that
++## case, set MULTILIB_EXCEPTIONS to be all of the switch exceptions in
++## shell case syntax that should not be built.
++## For example, in the PowerPC embedded ABI support, it is not desirable to
++## build libraries compiled with the -mcall-aix option and either of the
++## -fleading-underscore or -mlittle options at the same time. Therefore
++## MULTILIB_EXCEPTIONS is set to
++##
++## *mcall-aix/*fleading-underscore* *mlittle/*mcall-aix*
++##
++
++ifeq ($(BUILD_MULTILIB), 1)
++MULTILIB_EXCEPTIONS = *mno-hw-mul/*mhw-mulx* *mcustom-fpu-cfg=60-1/*mcustom-fpu-cfg=60-2*
++endif
++
++##
++## MULTILIB_EXTRA_OPTS Sometimes it is desirable that when building
++## multiple versions of libgcc.a certain options should always be passed on
++## to the compiler. In that case, set MULTILIB_EXTRA_OPTS to be the list
++## of options to be used for all builds.
++##
++
+diff --git a/gcc/cse.c b/gcc/cse.c
+index 72af39a..b36310c 100644
+--- a/gcc/cse.c
++++ b/gcc/cse.c
+@@ -3134,6 +3134,10 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
#ifdef FLOAT_STORE_FLAG_VALUE
REAL_VALUE_TYPE fsfv;
#endif
@@ -9907,9 +13238,45 @@
/* If the entry isn't valid, skip it. */
if (! exp_equiv_p (p->exp, p->exp, 1, 0))
---- gcc-3.4.3/gcc/doc/extend.texi
-+++ gcc-3.4.3-nios2/gcc/doc/extend.texi
-@@ -5636,12 +5636,118 @@ to those machines. Generally these gene
+diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
+index 4638645..cdb248d 100644
+--- a/gcc/doc/extend.texi
++++ b/gcc/doc/extend.texi
+@@ -2488,6 +2488,33 @@ contents of that register. The @code{short_call} attribute always places
+ the offset to the function from the call site into the @samp{BL}
+ instruction directly.
+
++@item reverse_bitfields/no_reverse_bitfields
++@cindex reverse_bitfields on Altera Nios II
++This attribute specifies the order of bitfield allocation within a
++particular struct on Altera's Nios II processor. This overrides both
++the @option{-mno-reverse-bitfields} and @option{-mreverse-bitfields}
++switches, as well as any @code{#pragma} that might be present. It is
++ignored except when present on a struct.
++
++@smallexample
++struct inner
++@{
++ unsigned int a:1;
++ unsigned int b:31;
++@} __attribute__ ((reverse_bitfields));
++
++union outer
++@{
++ struct inner inner;
++ unsigned int val;
++@};
++
++@end smallexample
++
++will cause a to be allocated overlapping the most significant bit of
++val, regardless of any @code{#pragma} or compiler switch. See the
++@option{-mreverse-bitfields} switch for more examples.
++
+ @item function_vector
+ @cindex calling functions through the function vector on the H8/300 processors
+ Use this attribute on the H8/300, H8/300H, and H8S to indicate that the specified
+@@ -5638,12 +5665,118 @@ to those machines. Generally these generate calls to specific machine
instructions, but allow the compiler to schedule those calls.
@menu
@@ -10028,9 +13395,49 @@
@node Alpha Built-in Functions
@subsection Alpha Built-in Functions
---- gcc-3.4.3/gcc/doc/invoke.texi
-+++ gcc-3.4.3-nios2/gcc/doc/invoke.texi
-@@ -337,6 +337,14 @@ in the following sections.
+@@ -8022,6 +8155,7 @@ we do not recommend the use of pragmas; @xref{Function Attributes},
+ for further explanation.
+
+ @menu
++* Altera Nios II Pragmas::
+ * ARM Pragmas::
+ * RS/6000 and PowerPC Pragmas::
+ * Darwin Pragmas::
+@@ -8029,6 +8163,29 @@ for further explanation.
+ * Tru64 Pragmas::
+ @end menu
+
++@node Altera Nios II Pragmas
++@subsection Altera Nios II Pragmas
++
++The Altera Nios II target defines two pragmas to control the placement
++of bitfields within a struct.
++
++@table @code
++@item reverse_bitfields
++@cindex pragma, reverse_bitfields
++Cause all subsequent structs to behave as though the -mreverse-bitfields
++compiler switch had been given. Can be overridden by the
++@code{no_reverse_bitfields} attribute or a subsequent
++@code{#pragma no_reverse_bitfields}.
++
++@item no_reverse_bitfields
++@cindex pragma, no_reverse_bitfields
++Cause all subsequent structs to behave as though the -mno-reverse-bitfields
++compiler switch had been given. Can be overridden by the
++@code{reverse_bitfields} attribute or a subsequent
++@code{#pragma reverse_bitfields}.
++
++@end table
++
+ @node ARM Pragmas
+ @subsection ARM Pragmas
+
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index e683d0c..b34200f 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -337,6 +337,16 @@ in the following sections.
@item Machine Dependent Options
@xref{Submodel Options,,Hardware Models and Configurations}.
@@ -10040,12 +13447,14 @@
+-minline-memcpy -mno-fast-sw-div -mfast-sw-div @gol
+-mhw-mul -mno-hw-mul -mhw-mulx -mno-hw-mulx @gol
+-mno-hw-div -mhw-div @gol
-+-msys-crt0= -msys-lib= -msys=nosys }
++-mno-stack-check -mstack-check @gol
++-msys-crt0= -msys-lib= -msys=nosys @gol
++-mreverse-bitfields -mno-reverse-bitfields}
+
@emph{M680x0 Options}
@gccoptlist{-m68000 -m68020 -m68020-40 -m68020-60 -m68030 -m68040 @gol
-m68060 -mcpu32 -m5200 -m68881 -mbitfield -mc68000 -mc68020 @gol
-@@ -5836,6 +5844,7 @@ machine description. The default for th
+@@ -5839,6 +5849,7 @@ machine description. The default for the options is also defined by
that macro, which enables you to change the defaults.
@menu
@@ -10053,7 +13462,7 @@
* M680x0 Options::
* M68hc1x Options::
* VAX Options::
-@@ -5871,6 +5880,103 @@ that macro, which enables you to change
+@@ -5874,6 +5885,290 @@ that macro, which enables you to change the defaults.
* FRV Options::
@end menu
@@ -10069,7 +13478,6 @@
+
+@item -msmallc
+@opindex msmallc
-+
+Link with a limited version of the C library, -lsmallc. For more
+information see the C Library Documentation.
+
@@ -10078,7 +13486,6 @@
+@itemx -mno-bypass-cache
+@opindex mno-bypass-cache
+@opindex mbypass-cache
-+
+Force all load and store instructions to always bypass cache by
+using io variants of the instructions. The default is to not
+bypass the cache.
@@ -10087,7 +13494,6 @@
+@itemx -mcache-volatile
+@opindex mcache-volatile
+@opindex mno-cache-volatile
-+
+Volatile memory access bypass the cache using the io variants of
+the ld and st instructions. The default is to cache volatile
+accesses.
@@ -10100,7 +13506,6 @@
+@itemx -minline-memcpy
+@opindex mno-inline-memcpy
+@opindex minline-memcpy
-+
+Do not inline memcpy. The default is to inline when -O is on.
+
+
@@ -10108,7 +13513,6 @@
+@itemx -mfast-sw-div
+@opindex mno-fast-sw-div
+@opindex mfast-sw-div
-+
+Do no use table based fast divide for small numbers. The default
+is to use the fast divide at -O3 and above.
+
@@ -10125,7 +13529,6 @@
+@opindex mhw-mulx
+@opindex mno-hw-div
+@opindex mhw-div
-+
+Enable or disable emitting @code{mul}, @code{mulx} and @code{div} family of
+instructions by the compiler. The default is to emit @code{mul}
+and not emit @code{div} and @code{mulx}.
@@ -10133,10 +13536,16 @@
+The different combinations of @code{mul} and @code{mulx} instructions
+generate a different multilib options.
+
++@item -mno-stack-check
++@itemx -mstack-check
++@opindex no-stack-check
++@opindex stack-check
++Enables or disables the checking for sufficient memory when
++items are pushed onto the stack. A checked and non-checked
++version of each of the multilibs is provided.
+
+@item -msys-crt0=@var{startfile}
+@opindex msys-crt0
-+
+@var{startfile} is the file name of the startfile (crt0) to use
+when linking. The default is crt0.o that comes with libgloss
+and is only suitable for use with the instruction set
@@ -10145,21 +13554,210 @@
+@item -msys-lib=@var{systemlib}
+@itemx -msys-lib=nosys
+@opindex msys-lib
-+
+@var{systemlib} is the library name of the library which provides
+the system calls required by the C library, e.g. @code{read}, @code{write}
+etc. The default is to use nosys, this library provides
+stub implementations of the calls and is part of libgloss.
+
++@item -mno-reverse-bitfields
++@itemx -mreverse-bitfields
++@opindex mno-reverse-bitfields
++@opindex mreverse-bitfields
++When enabled, bitfields within a struct are allocated in reverse order.
++This is useful with legacy code that depends on the (inherently
++non-portable) ordering of bitfields via a union. Given:
++
++@smallexample
++struct inner
++@{
++ unsigned int a:1;
++ unsigned int b:31;
++@};
++
++union outer
++@{
++ struct inner inner;
++ unsigned int val;
++@};
++
++unsigned int f()
++@{
++ union outer o;
++ o.inner.a = 1;
++ o.inner.b = 0;
++ return o.val;
++@}
++@end smallexample
++
++a call to @code{f} will return 1 when compiled with
++@option{-mno-reverse-bitfields} (the default), or 2147483648 when
++compiled with @option{-mreverse-bitfields}.
++
++For structures that are a multiple of 32 bits wide, the reversal is
++done 32 bits at a time. For structures that are an odd multiple of 16
++bits wide, the reversal is done 16 bits at a time. For structures
++that are an odd multiple of 8 bits wide, the reversal is done 8 bits
++at a time. The size of a structure (as measured by the @code{sizeof}
++operator) never changes between @option{-mno-reverse-bitfields} and
++@option{-mreverse-bitfields}. Nonetheless, there can be some
++confusing corner cases with structs where the compiler has to add
++additional padding to meet alignment restrictions. Consider:
++
++@smallexample
++struct inner
++@{
++ unsigned int a:1;
++ unsigned int b:15;
++@};
++
++union outer
++@{
++ struct inner inner;
++ unsigned int val;
++@};
++
++unsigned int f()
++@{
++ union outer o;
++ o.val = 0;
++ o.inner.b = 1;
++ return o.val;
++@}
++@end smallexample
++
++a call to @code{f} will return 2 when compiled with
++@option{-mno-reverse-bitfields} (the default), or 65536 when compiled
++with @option{-mreverse-bitfields}. This is because @code{sizeof
++(inner)} is 4 in both cases. In the @option{-mno-reverse-bitfields}
++case, the compiler pads the struct at the end to be 4 bytes long,
++effectively doing:
++
++@smallexample
++struct inner
++@{
++ unsigned int a:1;
++ unsigned int b:15;
++ unsigned int padding:16;
++@};
++@end smallexample
++
++In the @option{-mreverse-bitfields} case, the hidden padding is
++reversed along with everything else, yielding the equivalent of:
++
++@smallexample
++struct inner
++@{
++ unsigned int padding:16;
++ unsigned int b:15;
++ unsigned int a:1;
++@};
++@end smallexample
++
++Of course, if we would rather that @code{sizeof (inner)} was 2, we could
++write the struct as:
++
++@smallexample
++struct inner
++@{
++ unsigned short a:1;
++ unsigned short b:15;
++@};
++@end smallexample
++
++and the padding would go away.
++
++In some cases, especially when using the @code{__packed__} attribute,
++there is no well-defined bit reversal that is possible: the compiler
++will issue an error message in this case. Consider:
++
++@smallexample
++struct invalid
++@{
++ unsigned int f1:1;
++ unsigned int f2:15;
++ unsigned int f3:4;
++ unsigned int f4:4;
++@} __attribute__ ((__packed__));
++@end smallexample
++
++Since @code{sizeof (invalid)} is 3, we are forced to try reversing
++individual bytes in the struct. But f2 is more than a byte wide, so
++we can't reverse it and still have it be contiguous. Similar cases
++occur when dealing with arrays or other large contiguous objects:
++
++@smallexample
++struct invalid2
++@{
++ unsigned char f1[5];
++ unsigned char f2[3];
++@};
++@end smallexample
++
++You'll have to rewrite the affected structs to say exactly what you
++mean in odd cases like that.
++
++Finally, note that individual fields are sized as a whole. The structs
++
++@smallexample
++struct array1
++@{
++ unsigned char f1[3];
++ unsigned char f2;
++@}
++@end smallexample
++
++and:
++
++@smallexample
++struct array2
++@{
++ unsigned char f1a;
++ unsigned char f1b;
++ unsigned char f1c;
++ unsigned char f2;
++@}
++@end smallexample
++
++are not equivalent. When compiled with @option{-mreverse-bitfields},
++they behave the same as:
++
++@smallexample
++struct array1r
++@{
++ unsigned char f2;
++ unsigned char f1[3];
++@}
++@end smallexample
++
++and:
++
++@smallexample
++struct array2r
++@{
++ unsigned char f2;
++ unsigned char f1c;
++ unsigned char f1b;
++ unsigned char f1a;
++@}
++@end smallexample
++
++would, respectively, when compiled with
++@option{-mno-reverse-bitfields}. In particular, f1 is treated as a
++single contiguous 24-bit object for purposes of reversal, while f1a,
++f1b, and f1c are treated as individual 8-bit objects that need not
++(and do not) remain contiguous. Use caution.
++
+@end table
+
+
@node M680x0 Options
@subsection M680x0 Options
@cindex M680x0 options
---- gcc-3.4.3/gcc/doc/md.texi
-+++ gcc-3.4.3-nios2/gcc/doc/md.texi
-@@ -1335,6 +1335,49 @@ However, here is a summary of the machin
+diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
+index b73f325..4a134b2 100644
+--- a/gcc/doc/md.texi
++++ b/gcc/doc/md.texi
+@@ -1337,6 +1337,58 @@ However, here is a summary of the machine-dependent constraints
available on some particular machines.
@table @emph
@@ -10203,9 +13801,577 @@
+data section and therefore can be added to @code{gp}
+as a 16-bit immediate to re-create their 32-bit value.
+
++@item D@var{nn}
++For a given two digit @var{nn} constrains the operand
++to the corresponding register. Example: D02 forces the
++operand into register r2. The side effect of using this
++operand constraint is that reload may not be able to
++meet the constraint. If reload fails, an error message
++about failing to find any register to spill in the
++D@var{nn}_REG register class will be emitted.
++
+@end table
+
+
@item ARM family---@file{arm.h}
@table @code
@item f
+diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
+index 4527fe4..e7cc581 100644
+--- a/gcc/stor-layout.c
++++ b/gcc/stor-layout.c
+@@ -1435,6 +1435,355 @@ finalize_type_size (tree type)
+ }
+ }
+
++static void
++reverse_bitfield_layout (record_layout_info rli)
++{
++ tree field;
++ tree rev_size;
++ unsigned int rev_size_int;
++
++ /*
++ * The size of the words we'll be reversing. Normally, we reverse
++ * entire SImode words. However, if the entire struct's size isn't an
++ * exact multiple of the size of SImode, we can reverse HImode or even
++ * QImode pieces. In the examples below, assume SImode/int is 32
++ * bits, HImode/short is 16 bits, and QImode/char is 8 bits.
++ * Consider:
++ *
++ * struct s1
++ * {
++ * int f1:1;
++ * int f2:31;
++ * };
++ *
++ * struct s2
++ * {
++ * int f1:1;
++ * int f2:15;
++ * } __attribute__ ((__packed__));
++ *
++ * struct s3
++ * {
++ * short f1:1;
++ * short f2:15;
++ * };
++ *
++ * struct s4
++ * {
++ * int f1:1;
++ * int f2:15;
++ * };
++ *
++ * struct s5
++ * {
++ * int f1:8;
++ * int f2:8;
++ * int f3:4;
++ * int f4:4;
++ * } __attribute__ ((__packed__));
++ *
++ * struct s6
++ * {
++ * int f1:1;
++ * int f2:15;
++ * int f3:4;
++ * int f4:4;
++ * int f5:8;
++ * };
++ *
++ * struct s7
++ * {
++ * int f1:1;
++ * int f2:15;
++ * int f3:4;
++ * int f4:4;
++ * } __attribute__ ((__packed__));
++ *
++ * struct s8
++ * {
++ * char f1;
++ * short f2;
++ * char f3;
++ * };
++ *
++ * struct s9
++ * {
++ * char f1;
++ * short f2;
++ * char f3;
++ * } __attribute__ ((__packed__));
++ *
++ * struct s10
++ * {
++ * char f1;
++ * short f2;
++ * char f3;
++ * short f4;
++ * };
++ *
++ * struct s11
++ * {
++ * char f1[5];
++ * int f2;
++ * };
++ *
++ * struct s12
++ * {
++ * char f1[5];
++ * char f2[3];
++ * int f3;
++ * };
++ *
++ * struct s13
++ * {
++ * char f1[3];
++ * int f2;
++ * };
++ *
++ * struct s14
++ * {
++ * char f1a;
++ * char f1b;
++ * char f1c;
++ * int f2;
++ * };
++ *
++ * Then we have:
++ *
++ * sizeof (struct s1) == 4
++ * sizeof (struct s2) == 2
++ * sizeof (struct s3) == 2
++ * sizeof (struct s4) == 4
++ * sizeof (struct s5) == 3
++ * sizeof (struct s6) == 4
++ * sizeof (struct s7) == 3
++ * sizeof (struct s8) == 6
++ * sizeof (struct s9) == 4
++ * sizeof (struct s10) == 8
++ * sizeof (struct s11) == 12
++ * sizeof (struct s12) == 12
++ *
++ * We want the equivalent reversed bitfield structs to be:
++ *
++ * struct s1r
++ * {
++ * int f2:31;
++ * int f1:1;
++ * };
++ *
++ * struct s2r
++ * {
++ * int f2:15;
++ * int f1:1;
++ * } __attribute__ ((__packed__));
++ *
++ * struct s3r
++ * {
++ * short f2:15;
++ * short f1:1;
++ * };
++ *
++ * struct s4r
++ * {
++ * int unnamed:16;
++ * int f2:15;
++ * int f1:1;
++ * };
++ *
++ * struct s5r
++ * {
++ * int f1:8;
++ * int f2:8;
++ * int f4:4;
++ * int f3:4;
++ * } __attribute__ ((__packed__));
++ *
++ * struct s6r
++ * {
++ * int f5:8;
++ * int f4:4;
++ * int f3:4;
++ * int f2:15;
++ * int f1:1;
++ * };
++ *
++ * struct s7r
++ * {
++ * #error cannot reverse bitfield
++ * } __attribute__ ((__packed__));
++ *
++ * struct s8r
++ * {
++ * char unnamed1;
++ * char f1;
++ * short f2;
++ * char unnamed2;
++ * char f3;
++ * };
++ *
++ * struct s9r
++ * {
++ * char f3;
++ * short f2;
++ * char f1;
++ * } __attribute__ ((__packed__));
++ *
++ * struct s10r
++ * {
++ * short f2;
++ * char unnamed1;
++ * char f1;
++ * short f4;
++ * char unnamed2;
++ * char f3;
++ * };
++ *
++ * struct s11r
++ * {
++ * char f1[5];
++ * int f2;
++ * };
++ *
++ * struct s12r
++ * {
++ * #error cannot reverse bitfield
++ * };
++ *
++ * struct s13r
++ * {
++ * char unnamed;
++ * char f1[3];
++ * int f2;
++ * };
++ *
++ * struct s14r
++ * {
++ * char unnamed;
++ * char f1c;
++ * char f1b;
++ * char f1a;
++ * int f2;
++ * };
++ *
++ * Note that the s4, s8, s10, s13, and s14 cases produce somewhat
++ * suprising results: the normally hidden padding bytes the compiler
++ * adds are also reversed. Further note that s13 and s14 are not
++ * equivalent: the f1 field in s13 is 24-bits wide, and is reversed
++ * accordingly, while the three fields f1a, f1b, and f1c in s14 are
++ * reversed as individual bytes.
++ *
++ * The s7 and s12 cases produce an error: we can't reverse a bitfield
++ * that is larger than word size we're reversing. The error is
++ * suppressed in the s11 case since the field in question and the
++ * field that follows are both word aligned.
++ */
++
++ /*
++ * First, figure out what size words to reverse. We look at the total
++ * number of bits currently in use by the struct, rounded up to the
++ * next multiple of rli->record_align, to decide.
++ */
++ {
++ int bits_in_use = TREE_INT_CST_LOW (round_up (rli_size_so_far (rli),
++ rli->record_align));
++ unsigned int size;
++ for (size = GET_MODE_BITSIZE (SImode);
++ size >= GET_MODE_BITSIZE (QImode);
++ size /= 2)
++ {
++ if (bits_in_use % size == 0)
++ {
++ break;
++ }
++ }
++ if (size < GET_MODE_BITSIZE (QImode))
++ {
++ /*
++ * rli->record_align should never be less than QImode, even
++ * for packed structs.
++ */
++ abort ();
++ }
++ rev_size = size_int_type (size, bitsizetype);
++ rev_size_int = size;
++ }
++
++ /*
++ * Then, iterate over the fields, reversing them as we go.
++ */
++ for (field = TYPE_FIELDS (rli->t); field; field = TREE_CHAIN (field))
++ {
++ tree type = TREE_TYPE (field);
++ if (TREE_CODE (field) != FIELD_DECL)
++ {
++ continue;
++ }
++ if (TREE_CODE (field) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK)
++ {
++ return;
++ }
++ {
++ tree offset = DECL_FIELD_OFFSET (field);
++ tree offset_type = TREE_TYPE (offset);
++ tree bit_offset = DECL_FIELD_BIT_OFFSET (field);
++ tree bit_offset_type = TREE_TYPE (bit_offset);
++ tree bit = bit_from_pos (offset, bit_offset);
++ tree true_size = DECL_SIZE (field);
++ pos_from_bit (&offset, &bit_offset, rev_size_int, bit);
++ bit_offset = size_binop (MINUS_EXPR,
++ size_binop (MINUS_EXPR, rev_size, true_size),
++ bit_offset);
++ if (TREE_INT_CST_HIGH (bit_offset) != 0)
++ {
++ /*
++ * This happens when a field spans a rev_size boundary (see
++ * example s7 above): rather than try to come up with some
++ * well-defined, but non-intuitive definition for this case,
++ * just issue an error. It can also happen for large fields,
++ * e.g. arrays or other structs: if these large fields were
++ * already aligned, leave them be; otherwise issue the error
++ * in this case as well.
++ */
++ if ((TREE_INT_CST_HIGH (true_size) != 0
++ || TREE_INT_CST_LOW (true_size) > rev_size_int)
++ && TREE_INT_CST_HIGH (DECL_FIELD_BIT_OFFSET (field)) == 0
++ && TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)) == 0)
++ {
++ tree next_field = TREE_CHAIN (field);
++ if (!next_field)
++ {
++ /* No following field, so we're ok. */
++ continue;
++ }
++ else
++ {
++ tree next_offset = DECL_FIELD_OFFSET (next_field);
++ tree next_bit_offset = DECL_FIELD_BIT_OFFSET (next_field);
++ tree next_bit = bit_from_pos (next_offset, next_bit_offset);
++ pos_from_bit (&next_offset, &next_bit_offset, rev_size_int,
++ next_bit);
++ if (TREE_INT_CST_HIGH (next_bit_offset) == 0
++ && TREE_INT_CST_LOW (next_bit_offset) == 0)
++ {
++ /* Following field is aligned wrt rev_size_int boundary,
++ so we're ok. */
++ continue;
++ }
++ }
++ }
++ error ("unable to reverse bitfields in structure");
++ return;
++ }
++ bit = bit_from_pos (offset, bit_offset);
++ pos_from_bit (&offset, &bit_offset, rli->offset_align, bit);
++ TREE_TYPE (offset) = offset_type;
++ DECL_FIELD_OFFSET (field) = offset;
++ TREE_TYPE (bit_offset) = bit_offset_type;
++ DECL_FIELD_BIT_OFFSET (field) = bit_offset;
++ }
++ }
++}
++
+ /* Do all of the work required to layout the type indicated by RLI,
+ once the fields have been laid out. This function will call `free'
+ for RLI, unless FREE_P is false. Passing a value other than false
+@@ -1444,6 +1793,12 @@ finalize_type_size (tree type)
+ void
+ finish_record_layout (record_layout_info rli, int free_p)
+ {
++ /* Optionally reverse the placement of bitfields within the record */
++ if ((* targetm.reverse_bitfield_layout_p) (rli->t))
++ {
++ reverse_bitfield_layout (rli);
++ }
++
+ /* Compute the final size. */
+ finalize_record_size (rli);
+
+diff --git a/gcc/target-def.h b/gcc/target-def.h
+index 32d00ae..bdea4d4 100644
+--- a/gcc/target-def.h
++++ b/gcc/target-def.h
+@@ -300,6 +300,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ #define TARGET_INSERT_ATTRIBUTES hook_void_tree_treeptr
+ #define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P hook_bool_tree_false
+ #define TARGET_MS_BITFIELD_LAYOUT_P hook_bool_tree_false
++#define TARGET_REVERSE_BITFIELD_LAYOUT_P hook_bool_tree_false
+ #define TARGET_RTX_COSTS hook_bool_rtx_int_int_intp_false
+ #define TARGET_MANGLE_FUNDAMENTAL_TYPE hook_constcharptr_tree_null
+
+@@ -368,6 +369,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ TARGET_INSERT_ATTRIBUTES, \
+ TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P, \
+ TARGET_MS_BITFIELD_LAYOUT_P, \
++ TARGET_REVERSE_BITFIELD_LAYOUT_P, \
+ TARGET_INIT_BUILTINS, \
+ TARGET_EXPAND_BUILTIN, \
+ TARGET_MANGLE_FUNDAMENTAL_TYPE, \
+diff --git a/gcc/target.h b/gcc/target.h
+index 59788f9..97bde5f 100644
+--- a/gcc/target.h
++++ b/gcc/target.h
+@@ -295,6 +295,10 @@ struct gcc_target
+ Microsoft Visual C++ bitfield layout rules. */
+ bool (* ms_bitfield_layout_p) (tree record_type);
+
++ /* Return true if bitfields in RECORD_TYPE should be allocated
++ within their base type's bytes starting at the opposite end. */
++ bool (* reverse_bitfield_layout_p) (tree record_type);
++
+ /* Set up target-specific built-in functions. */
+ void (* init_builtins) (void);
+
+diff --git a/gcc/varasm.c b/gcc/varasm.c
+index 33307e5..d4ed0fc 100644
+--- a/gcc/varasm.c
++++ b/gcc/varasm.c
+@@ -3912,6 +3912,107 @@ array_size_for_constructor (tree val)
+ return tree_low_cst (i, 1);
+ }
+
++struct reorder_bitfields_key
++{
++ tree field;
++ tree value;
++};
++
++static int
++reorder_bitfields_compare (const void *x1, const void *x2)
++{
++ const struct reorder_bitfields_key *key1 = x1;
++ const struct reorder_bitfields_key *key2 = x2;
++ int pos1 = int_bit_position (key1->field);
++ int pos2 = int_bit_position (key2->field);
++
++ if (pos1 < pos2)
++ {
++ return -1;
++ }
++ else if (pos1 > pos2)
++ {
++ return 1;
++ }
++ else
++ {
++ /*
++ * No two fields should ever have the same bit_position, so
++ * something is horribly wrong.
++ */
++ abort ();
++ }
++}
++
++static void
++reorder_bitfields (tree *first_field, tree *first_value)
++{
++ struct reorder_bitfields_key *keys;
++ size_t field_count;
++ tree field;
++ tree value;
++ size_t i;
++
++ /*
++ * Find out how many fields are in this record, and allocate an array
++ * of keys to hold them all.
++ */
++ field_count = 0;
++ for (field = *first_field; field; field = TREE_CHAIN (field))
++ {
++ field_count++;
++ }
++ if (field_count < 2)
++ {
++ return;
++ }
++ keys = xmalloc (sizeof (struct reorder_bitfields_key) * field_count);
++
++ /*
++ * Make copies of the existing fields and values (using signed integer
++ * zeros for missing values) in the array of keys.
++ */
++ field = *first_field;
++ value = *first_value;
++ for (i = 0; i < field_count; i++)
++ {
++ keys[i].field = copy_node (field);
++ field = TREE_CHAIN (field);
++ if (value)
++ {
++ keys[i].value = copy_node (value);
++ TREE_PURPOSE (keys[i].value) = keys[i].field;
++ value = TREE_CHAIN (value);
++ }
++ else
++ {
++ keys[i].value = tree_cons (keys[i].field, ssize_int (0), 0);
++ }
++ }
++
++ /*
++ * Sort the array based on position of the fields in the record.
++ */
++ qsort (keys, field_count, sizeof (struct reorder_bitfields_key),
++ reorder_bitfields_compare);
++
++ /*
++ * Build new lists out of the sorted array.
++ */
++ for (i = 0; i < field_count - 1; i++)
++ {
++ TREE_CHAIN (keys[i].field) = keys[i+1].field;
++ TREE_CHAIN (keys[i].value) = keys[i+1].value;
++ }
++ *first_field = keys[0].field;
++ *first_value = keys[0].value;
++
++ /*
++ * Get rid of our array of keys and we're done.
++ */
++ free (keys);
++}
++
+ /* Subroutine of output_constant, used for CONSTRUCTORs (aggregate constants).
+ Generate at least SIZE bytes, padding if necessary. */
+
+@@ -3928,12 +4029,29 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
+ /* Nonzero means BYTE contains part of a byte, to be output. */
+ int byte_buffer_in_use = 0;
+ int byte = 0;
++ tree first_link = CONSTRUCTOR_ELTS (exp);
+
+ if (HOST_BITS_PER_WIDE_INT < BITS_PER_UNIT)
+ abort ();
+
+ if (TREE_CODE (type) == RECORD_TYPE)
++ {
++ if ((*targetm.reverse_bitfield_layout_p) (type))
++ {
++ /*
++ * If we're reversing bitfields, we have to reverse the order in
++ * which constructors containing bitfields are output. The
++ * easiest way to do that is to reorder the constructor elements
++ * and fields to be in memory-order.
++ */
+ field = TYPE_FIELDS (type);
++ reorder_bitfields (&field, &first_link);
++ }
++ else
++ {
++ field = TYPE_FIELDS (type);
++ }
++ }
+
+ if (TREE_CODE (type) == ARRAY_TYPE
+ && TYPE_DOMAIN (type) != 0)
+@@ -3948,7 +4066,7 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
+ There is always a maximum of one element in the chain LINK for unions
+ (even if the initializer in a source program incorrectly contains
+ more one). */
+- for (link = CONSTRUCTOR_ELTS (exp);
++ for (link = first_link;
+ link;
+ link = TREE_CHAIN (link),
+ field = field ? TREE_CHAIN (field) : 0)
diff --git a/toolchain/gcc/3.4.6/901-nios2-ctor_dtor.patch b/toolchain/gcc/3.4.6/901-nios2-ctor_dtor.patch
index 87145ad5e..e69de29bb 100644
--- a/toolchain/gcc/3.4.6/901-nios2-ctor_dtor.patch
+++ b/toolchain/gcc/3.4.6/901-nios2-ctor_dtor.patch
@@ -1,52 +0,0 @@
-Index: gcc/gcc/config/nios2/nios2.h
-===================================================================
---- gcc/gcc/config/nios2/nios2.h (revision 195)
-+++ gcc/gcc/config/nios2/nios2.h (revision 196)
-@@ -88,8 +88,6 @@
- N_("All ld/st instructins do not use io variants (default)") }, \
- { "smallc", 0, \
- N_("Link with a limited version of the C library") }, \
-- { "ctors-in-init", 0, \
-- "" /* undocumented: N_("Link with static constructors and destructors in init") */ }, \
- { "", TARGET_DEFAULT, 0 } \
- }
-
-@@ -140,12 +138,12 @@
- #define STARTFILE_SPEC \
- "%{msys-crt0=*: %*} %{!msys-crt0=*: crt1%O%s} \
- %{msys-crt0=: %eYou need a C startup file for -msys-crt0=} \
-- %{mctors-in-init: crti%O%s crtbegin%O%s} \
-+ crti%O%s crtbegin%O%s \
- "
-
- #undef ENDFILE_SPEC
- #define ENDFILE_SPEC \
-- "%{mctors-in-init: crtend%O%s crtn%O%s}"
-+ " crtend%O%s crtn%O%s"
-
-
- /***********************
-Index: gcc/gcc/config/nios2/t-nios2
-===================================================================
---- gcc/gcc/config/nios2/t-nios2 (revision 195)
-+++ gcc/gcc/config/nios2/t-nios2 (revision 196)
-@@ -36,18 +36,8 @@
- echo '' > ${DPBIT}
- cat $(srcdir)/config/fp-bit.c >> ${DPBIT}
-
--EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
-+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o
-
--# Assemble startup files.
--$(T)crti.o: $(srcdir)/config/nios2/crti.asm $(GCC_PASSES)
-- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
-- -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/nios2/crti.asm
--
--$(T)crtn.o: $(srcdir)/config/nios2/crtn.asm $(GCC_PASSES)
-- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
-- -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/nios2/crtn.asm
--
--
- ## You may need to provide additional #defines at the beginning of
- ## fp-bit.c and dp-bit.c to control target endianness and other options
- ##
diff --git a/toolchain/gcc/3.4.6/nios2-config-fix.patch.conditional b/toolchain/gcc/3.4.6/nios2-config-fix.patch.conditional
index 9f1c37868..e69de29bb 100644
--- a/toolchain/gcc/3.4.6/nios2-config-fix.patch.conditional
+++ b/toolchain/gcc/3.4.6/nios2-config-fix.patch.conditional
@@ -1,19 +0,0 @@
---- gcc-3.4.6/gcc/config/t-linux-uclibc 2007-11-07 14:50:34.000000000 +0100
-+++ /dev/null 2007-11-02 12:35:37.750656579 +0100
-@@ -1,5 +0,0 @@
--# Remove glibc specific files added in t-linux
--SHLIB_MAPFILES := $(filter-out $(srcdir)/config/libgcc-glibc.ver, $(SHLIB_MAPFILES))
--
--# Use unwind-dw2-fde instead of unwind-dw2-fde-glibc
--LIB2ADDEH := $(subst unwind-dw2-fde-glibc.c,unwind-dw2-fde.c,$(LIB2ADDEH))
---- gcc-3.4.6/gcc/config.gcc.orig 2007-11-07 14:50:34.000000000 +0100
-+++ gcc-3.4.6/gcc/config.gcc 2007-11-07 15:32:31.000000000 +0100
-@@ -2334,7 +2334,7 @@
- # Rather than hook into each target, just do it after all the linux
- # targets have been processed
- case ${target} in
--*-linux-uclibc*) tm_defines="${tm_defines} USE_UCLIBC" ; tmake_file="${tmake_file} t-linux-uclibc"
-+*-linux-uclibc*) tm_defines="${tm_defines} USE_UCLIBC"
- esac
-
- # Support for --with-cpu and related options (and a few unrelated options,
diff --git a/toolchain/gcc/gcc-uclibc-3.x.mk b/toolchain/gcc/gcc-uclibc-3.x.mk
index c6c622a0c..e2210d06c 100644
--- a/toolchain/gcc/gcc-uclibc-3.x.mk
+++ b/toolchain/gcc/gcc-uclibc-3.x.mk
@@ -168,9 +168,6 @@ endif
#toolchain/patch-kernel.sh $(GCC_DIR) toolchain/gcc i386-gcc-soft-float.patch
#endif
endif
-ifeq ("$(strip $(ARCH))","nios2")
- toolchain/patch-kernel.sh $(GCC_DIR) toolchain/gcc/$(GCC_VERSION) nios2-config-fix.patch.conditional
-endif
touch $@
# The --without-headers option stopped working with gcc 3.0 and has never been