From 7eb9574e2b79b0f23b945850c59c1695bd3d9dca Mon Sep 17 00:00:00 2001 From: Ivan Kuten Date: Fri, 23 Nov 2007 10:32:50 +0000 Subject: update the nios2-patches for binutils-2.15 and gcc-3.4.6 with the latest sources from Altera, and removes obsolete patches --- toolchain/gcc/3.4.6/900-nios2.patch | 5118 ++++++++++++++++++-- toolchain/gcc/3.4.6/901-nios2-ctor_dtor.patch | 52 - .../gcc/3.4.6/nios2-config-fix.patch.conditional | 19 - 3 files changed, 4642 insertions(+), 547 deletions(-) (limited to 'toolchain/gcc/3.4.6') 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_ ++ * 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- 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,12 +6164,226 @@ + 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_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; ++ } + -+/***************************************** -+ * Defining the Output Assembler Language -+ *****************************************/ ++ 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_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))); ++} ++ ++ ++/***************************************** ++ * Defining the Output Assembler Language ++ *****************************************/ + +/* -------------- * + * Output of Data @@ -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- 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")]) ++ ++(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 ++ ++;***************************************************************************** ++;* ++;* 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. */ @@ -8594,13 +11545,35 @@ +}) + + -+(define_insn "*seq" ++(define_insn "*seq" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (eq:SI (match_operand:SI 1 "reg_or_0_operand" "%rM") ++ (match_operand:SI 2 "arith_operand" "rI")))] ++ "" ++ "cmpeq%i2\\t%0, %z1, %z2" ++ [(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:SI 1 "reg_or_0_operand" "%rM") -+ (match_operand:SI 2 "arith_operand" "rI")))] -+ "" -+ "cmpeq%i2\\t%0, %z1, %z2" -+ [(set_attr "type" "alu")]) ++ (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" @@ -8609,7 +11582,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. */ @@ -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) @@ -9672,92 +12786,291 @@ + "custom\\t%1, %0, %2, %3" + [(set_attr "type" "custom")]) + -+(define_insn "custom_pnfp" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SF 2 "register_operand" "r") -+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNFP))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) ++(define_insn "custom_pnfp" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") ++ (match_operand:SF 2 "register_operand" "r") ++ (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNFP))] ++ "" ++ "custom\\t%1, %0, %2, %3" ++ [(set_attr "type" "custom")]) ++ ++(define_insn "custom_pnpi" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") ++ (match_operand:SI 2 "register_operand" "r") ++ (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNPI))] ++ "" ++ "custom\\t%1, %0, %2, %3" ++ [(set_attr "type" "custom")]) ++ ++(define_insn "custom_pnpf" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") ++ (match_operand:SI 2 "register_operand" "r") ++ (match_operand:SF 3 "register_operand" "r")] CUSTOM_PNPF))] ++ "" ++ "custom\\t%1, %0, %2, %3" ++ [(set_attr "type" "custom")]) ++ ++(define_insn "custom_pnpp" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") ++ (match_operand:SI 2 "register_operand" "r") ++ (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNPP))] ++ "" ++ "custom\\t%1, %0, %2, %3" ++ [(set_attr "type" "custom")]) ++ ++ ++ ++ ++ ++ ++;***************************************************************************** ++;* ++;* Misc ++;* ++;***************************************************************************** ++ ++(define_insn "nop" ++ [(const_int 0)] ++ "" ++ "nop\\t" ++ [(set_attr "type" "alu")]) ++ ++(define_insn "sync" ++ [(unspec_volatile [(const_int 0)] UNSPEC_SYNC)] ++ "" ++ "sync\\t" ++ [(set_attr "type" "control")]) ++ ++ ++(define_insn "rdctl" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O")] UNSPEC_RDCTL))] ++ "" ++ "rdctl\\t%0, ctl%1" ++ [(set_attr "type" "control")]) ++ ++(define_insn "wrctl" ++ [(unspec_volatile:SI [(match_operand:SI 0 "rdwrctl_operand" "O") ++ (match_operand:SI 1 "reg_or_0_operand" "rM")] UNSPEC_WRCTL)] ++ "" ++ "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")]) ++ ++ ++;***************************************************************************** ++;* ++;* Peepholes ++;* ++;***************************************************************************** ++ ++ ++;; 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. ++## ++## 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 crti.o crtn.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 ++## ++## 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. ++ + -+(define_insn "custom_pnpi" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r") -+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNPI))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) ++## 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. + -+(define_insn "custom_pnpf" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r") -+ (match_operand:SF 3 "register_operand" "r")] CUSTOM_PNPF))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) ++# 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 + -+(define_insn "custom_pnpp" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r") -+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNPP))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) ++#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 + -+ -+;***************************************************************************** -+;* -+;* Misc -+;* -+;***************************************************************************** ++#Add the big endian flag to the multilib variable if required ++ifeq ($(BUILD_BE_MULTILIB), 1) ++MULTILIB_OPTIONS += EB/EL ++endif + -+(define_insn "nop" -+ [(const_int 0)] -+ "" -+ "nop\\t" -+ [(set_attr "type" "alu")]) ++endif + -+(define_insn "sync" -+ [(unspec_volatile [(const_int 0)] UNSPEC_SYNC)] -+ "" -+ "sync\\t" -+ [(set_attr "type" "control")]) ++## 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 = + -+(define_insn "rdctl" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O")] UNSPEC_RDCTL))] -+ "" -+ "rdctl\\t%0, ctl%1" -+ [(set_attr "type" "control")]) ++## 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. + -+(define_insn "wrctl" -+ [(unspec_volatile:SI [(match_operand:SI 0 "rdwrctl_operand" "O") -+ (match_operand:SI 1 "register_operand" "r")] UNSPEC_WRCTL)] -+ "" -+ "wrctl\\tctl%0, %1" -+ [(set_attr "type" "control")]) ++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* ++## + -+ -+;***************************************************************************** -+;* -+;* Peepholes -+;* -+;***************************************************************************** ++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. ++## + ---- gcc-3.4.3/gcc/config/nios2/t-nios2 -+++ gcc-3.4.3-nios2/gcc/config/nios2/t-nios2 -@@ -0,0 +1,123 @@ +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. +## @@ -9790,23 +13103,19 @@ + +$(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 -+ -+# 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 -+ ++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 @@ -9837,7 +13146,31 @@ +## 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, 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 @@ -9858,6 +13191,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 +13212,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 +13223,11 @@ +## 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/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, -- cgit v1.2.3