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