diff mbox

[1/5] Altera Nios II: GCC backend patches

Message ID 51926C0F.2010206@codesourcery.com
State New
Headers show

Commit Message

Chung-Lin Tang May 14, 2013, 4:53 p.m. UTC
On 13/4/26 4:29 AM, Joseph S. Myers wrote:
>> +/* Define built-in preprocessor macros.  */
>> +#define TARGET_CPU_CPP_BUILTINS()                   \
>> +  do                                                \
>> +    {                                               \
>> +      builtin_define_std ("NIOS2");                 \
>> +      builtin_define_std ("nios2");                 \
>> +      if (TARGET_BIG_ENDIAN)                        \
>> +        builtin_define_std ("nios2_big_endian");    \
>> +      else                                          \
>> +        builtin_define_std ("nios2_little_endian"); \
>> +    }                                               \
>> +  while (0)
> 
> Do you really need the macro variants in the user namespace, or could you 
> just use builtin_define with implementation-namespace variants only (like 
> newer ports tend to do, e.g. AArch64 defines __aarch64__, __AARCH64EB__, 
> __AARCH64EL__ as appropriate, but never any variants without the leading 
> __)?

This should be inherited from the older Altera sources. I do not
see any use of nios2/NIOS2 names without '__' acround, but if not a
pressing issue, I would like to leave it as is. The nios2 toolchain is
being upstreamed only now, but has been in use for several years, so
preserving this bit of old behavior may be prudent.

>> Index: gcc/config/nios2/linux.h
>> ===================================================================
>> --- gcc/config/nios2/linux.h	(revision 0)
>> +++ gcc/config/nios2/linux.h	(revision 409063)
> 
>> +#undef LIB_SPEC
>> +#define LIB_SPEC "-lc \
>> + %{pthread:-lpthread}"
> 
> What's wrong with using the GNU_USER_TARGET_LIB_SPEC value from 
> gnu-user.h?  (If the header ordering means another header has overridden 
> that definition by now, you can just redefine LIB_SPEC to 
> GNU_USER_TARGET_LIB_SPEC here.)
> 

Corrected, thanks.

>> +#undef SYSROOT_SUFFIX_SPEC
>> +#define SYSROOT_SUFFIX_SPEC \
>> +  "%{EB:/EB}"
> 
> Normally, if SYSROOT_SUFFIX_SPEC is desired it isn't hardcoded like this; 
> instead, ./sysroot-suffix.h is listed in tm_file and t-sysroot-suffix in 
> tmake_file is used to generate sysroot-suffix.h.

The big-endian support for nios2 is not fully complete (nor publicized?)
yet. So I'm removing this altogether. Sysroot suffix support with be
added in the proper manner in the future if needed.

>> +  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");
> 
> This sounds like a case for sorry () rather than internal_error () to me - 
> as I understand it, it's a matter of a known valid source-code construct 
> not handled by the port, as opposed to a should-never-happen condition 
> that indicates a condition you didn't think any source code could 
> generate.
> 
> Note that diagnostics should start with a lowercase letter, here and 
> elsewhere.

This has been replaced with simply gcc_assert().

>> +## 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.
> 
> Don't include such long comments that just repeat the standard definition 
> of some interface and say nothing Nios II-specific.
> 
>> +## 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
> 
> I don't know where DEV_HOST_OS is supposed to come from, but this doesn't 
> appear to make much sense for FSF GCC anyway.  If you want options to have 
> various possible sets of multilibs, model them on e.g. SH 
> --with-multilib-list rather than having this Nios II-specific approach.

I have changed config/nios2/t-nios2 to a minimal file with a possible
set of multilib options, currently commented out. Such support is still
unclear, and even the Mentor toolchains don't support them ATM.

Other formatting, function comment, etc. issues have been dealt with.
Updated patches attached.

Thanks,
Chung-Lin
diff mbox

Patch

Index: gcc/common/config/nios2/nios2-common.c
===================================================================
--- gcc/common/config/nios2/nios2-common.c	(revision 0)
+++ gcc/common/config/nios2/nios2-common.c	(revision 0)
@@ -0,0 +1,44 @@ 
+/* Common hooks for Altera Nios II.
+   Copyright (C) 2012-2013 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "diagnostic-core.h"
+#include "tm.h"
+#include "common/common-target.h"
+#include "common/common-target-def.h"
+#include "opts.h"
+#include "flags.h"
+
+/* Implement TARGET_OPTION_OPTIMIZATION_TABLE.  */
+static const struct default_options nios2_option_optimization_table[] =
+  {
+    { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
+    { OPT_LEVELS_3_PLUS, OPT_mfast_sw_div, NULL, 1 },
+    { OPT_LEVELS_NONE, 0, NULL, 0 }
+  };
+
+#undef TARGET_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
+
+#undef TARGET_OPTION_OPTIMIZATION_TABLE
+#define TARGET_OPTION_OPTIMIZATION_TABLE nios2_option_optimization_table
+
+struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
Index: gcc/config/nios2/nios2-protos.h
===================================================================
--- gcc/config/nios2/nios2-protos.h	(revision 0)
+++ gcc/config/nios2/nios2-protos.h	(revision 0)
@@ -0,0 +1,62 @@ 
+/* Subroutine declarations for Altera Nios II target support.
+   Copyright (C) 2012-2013 Free Software Foundation, Inc.
+   Contributed by Jonah Graham (jgraham@altera.com).
+   Contributed by Mentor Graphics, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_NIOS2_PROTOS_H
+#define GCC_NIOS2_PROTOS_H
+
+extern int nios2_initial_elimination_offset (int, int);
+extern int nios2_can_use_return_insn (void);
+extern void expand_prologue (void);
+extern void expand_epilogue (bool);
+extern void nios2_function_profiler (FILE *, int);
+
+#ifdef RTX_CODE
+extern int nios2_emit_move_sequence (rtx *, enum machine_mode);
+extern int nios2_emit_expensive_div (rtx *, enum machine_mode);
+extern void nios2_adjust_call_address (rtx *);
+
+extern rtx nios2_get_return_address (int);
+extern void nios2_set_return_address (rtx, rtx);
+
+extern bool nios2_supported_compare_p (enum machine_mode);
+extern bool nios2_validate_compare (enum machine_mode, rtx*, rtx*, rtx*);
+
+extern bool nios2_fpu_insn_enabled (enum n2fpu_code);
+extern const char* nios2_fpu_insn_asm (enum n2fpu_code);
+
+extern bool nios2_legitimate_pic_operand_p (rtx x);
+extern bool nios2_regno_ok_for_base_p (int, bool);
+extern bool nios2_regno_ok_for_index_p (int, bool);
+extern bool nios2_unspec_reloc_p (rtx);
+
+#ifdef TREE_CODE
+#ifdef ARGS_SIZE_RTX
+/* expr.h defines both ARGS_SIZE_RTX and `enum direction' */
+extern enum direction nios2_function_arg_padding (enum machine_mode, const_tree);
+extern enum direction nios2_block_reg_padding (enum machine_mode, tree, int);
+#endif /* ARGS_SIZE_RTX */
+
+extern void nios2_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
+
+#endif /* TREE_CODE */
+#endif /* RTX_CODE */
+
+#endif /* GCC_NIOS2_PROTOS_H */
Index: gcc/config/nios2/linux.h
===================================================================
--- gcc/config/nios2/linux.h	(revision 0)
+++ gcc/config/nios2/linux.h	(revision 0)
@@ -0,0 +1,38 @@ 
+/* Definitions of target support for Altera Nios II systems
+   running GNU/Linux with ELF format.
+   Copyright (C) 2012-2013 Free Software Foundation, Inc.
+   Contributed by Mentor Graphics, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#define TARGET_OS_CPP_BUILTINS()                \
+  do                                            \
+    {                                           \
+      GNU_USER_TARGET_OS_CPP_BUILTINS();           \
+    }                                           \
+  while (0)
+
+#undef LINK_SPEC
+#define LINK_SPEC LINK_SPEC_ENDIAN \
+  " %{shared:-shared} \
+    %{static:-Bstatic} \
+    %{rdynamic:-export-dynamic}"
+
+/* This toolchain implements the ABI for Linux Systems documented in the
+   Nios II Processor Reference Handbook.  */
+#define TARGET_LINUX_ABI 1
+
Index: gcc/config/nios2/constraints.md
===================================================================
--- gcc/config/nios2/constraints.md	(revision 0)
+++ gcc/config/nios2/constraints.md	(revision 0)
@@ -0,0 +1,124 @@ 
+;; Constraint definitions for Altera Nios II.
+;; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+;; Contributed by Chung-Lin Tang <cltang@codesourcery.com>
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+;; 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)
+
+;; Register constraints
+
+(define_register_constraint "j" "SIB_REGS"
+  "A register suitable for an indirect sibcall.")
+
+;; These are documented for use in inline asm.
+(define_register_constraint "D00" "D00_REG" "Hard register 0.")
+(define_register_constraint "D01" "D01_REG" "Hard register 1.")
+(define_register_constraint "D02" "D02_REG" "Hard register 2.")
+(define_register_constraint "D03" "D03_REG" "Hard register 3.")
+(define_register_constraint "D04" "D04_REG" "Hard register 4.")
+(define_register_constraint "D05" "D05_REG" "Hard register 5.")
+(define_register_constraint "D06" "D06_REG" "Hard register 6.")
+(define_register_constraint "D07" "D07_REG" "Hard register 7.")
+(define_register_constraint "D08" "D08_REG" "Hard register 8.")
+(define_register_constraint "D09" "D09_REG" "Hard register 9.")
+(define_register_constraint "D10" "D10_REG" "Hard register 10.")
+(define_register_constraint "D11" "D11_REG" "Hard register 11.")
+(define_register_constraint "D12" "D12_REG" "Hard register 12.")
+(define_register_constraint "D13" "D13_REG" "Hard register 13.")
+(define_register_constraint "D14" "D14_REG" "Hard register 14.")
+(define_register_constraint "D15" "D15_REG" "Hard register 15.")
+(define_register_constraint "D16" "D16_REG" "Hard register 16.")
+(define_register_constraint "D17" "D17_REG" "Hard register 17.")
+(define_register_constraint "D18" "D18_REG" "Hard register 18.")
+(define_register_constraint "D19" "D19_REG" "Hard register 19.")
+(define_register_constraint "D20" "D20_REG" "Hard register 20.")
+(define_register_constraint "D21" "D21_REG" "Hard register 21.")
+(define_register_constraint "D22" "D22_REG" "Hard register 22.")
+(define_register_constraint "D23" "D23_REG" "Hard register 23.")
+(define_register_constraint "D24" "D24_REG" "Hard register 24.")
+(define_register_constraint "D25" "D25_REG" "Hard register 25.")
+(define_register_constraint "D26" "D26_REG" "Hard register 26.")
+(define_register_constraint "D27" "D27_REG" "Hard register 27.")
+(define_register_constraint "D28" "D28_REG" "Hard register 28.")
+(define_register_constraint "D29" "D29_REG" "Hard register 29.")
+(define_register_constraint "D30" "D30_REG" "Hard register 30.")
+(define_register_constraint "D31" "D31_REG" "Hard register 31.")
+
+;; Integer constraints
+
+(define_constraint "I"
+  "A signed 16-bit constant (for arithmetic instructions)."
+  (and (match_code "const_int")
+       (match_test "SMALL_INT (ival)")))
+
+(define_constraint "J"
+  "An unsigned 16-bit constant (for logical instructions)."
+  (and (match_code "const_int")
+       (match_test "SMALL_INT_UNSIGNED (ival)")))
+
+(define_constraint "K"
+  "An unsigned 16-bit high constant (for logical instructions)."
+  (and (match_code "const_int")
+       (match_test "UPPER16_INT (ival)")))
+
+(define_constraint "L"
+  "An unsigned 5-bit constant (for shift counts)."
+  (and (match_code "const_int")
+       (match_test "ival >= 0 && ival <= 31")))
+
+(define_constraint "M"
+  "Integer zero."
+  (and (match_code "const_int")
+       (match_test "ival == 0")))
+
+(define_constraint "N"
+  "An unsigned 8-bit constant (for custom instruction codes)."
+  (and (match_code "const_int")
+       (match_test "ival >= 0 && ival <= 255")))
+
+(define_constraint "O"
+  "An unsigned 5-bit constant (for control register numbers)."
+  (and (match_code "const_int")
+       (match_test "ival >= 0 && ival <= 31")))
+
+(define_constraint "S"
+  "An immediate stored in small data, accessible by GP."
+  (and (match_code "symbol_ref")
+       (match_test "SYMBOL_REF_IN_NIOS2_SMALL_DATA_P (op)")))
+
+(define_constraint "T"
+  "A constant unspec offset representing a relocation."
+  (match_test "nios2_unspec_reloc_p (op)"))
Index: gcc/config/nios2/elf.opt
===================================================================
--- gcc/config/nios2/elf.opt	(revision 0)
+++ gcc/config/nios2/elf.opt	(revision 0)
@@ -0,0 +1,38 @@ 
+; Options for the Altera Nios II port of the compiler.
+; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+; Contributed by Altera and Mentor Graphics, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 3, or (at your option)
+; any later version.
+;
+; GCC is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING3.  If not see
+; <http://www.gnu.org/licenses/>.
+
+; These additional options are supported for ELF (bare-metal) Nios II
+; toolchains.
+
+msmallc
+Target Report RejectNegative
+Link with a limited version of the C library
+
+msys-lib=
+Target RejectNegative Joined Var(nios2_sys_lib_string)
+Name of system library to link against
+
+msys-crt0=
+Target RejectNegative Joined Var(nios2_sys_crt0_string)
+Name of the startfile
+
+mhal
+Target Report RejectNegative
+Link with HAL BSP
Index: gcc/config/nios2/nios2.md
===================================================================
--- gcc/config/nios2/nios2.md	(revision 0)
+++ gcc/config/nios2/nios2.md	(revision 0)
@@ -0,0 +1,1020 @@ 
+;; Machine Description for Altera Nios II.
+;; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+;; Contributed by Jonah Graham (jgraham@altera.com) and 
+;; Will Reece (wreece@altera.com).
+;; Contributed by Mentor Graphics, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+
+;; Enumeration of UNSPECs
+
+(define_c_enum "unspecv" [
+  UNSPECV_BLOCKAGE
+  UNSPECV_WRCTL
+  UNSPECV_RDCTL
+  UNSPECV_TRAP
+  UNSPECV_STACK_OVERFLOW_DETECT_AND_TRAP
+  UNSPECV_FWRX
+  UNSPECV_FWRY
+  UNSPECV_FRDXLO
+  UNSPECV_FRDXHI
+  UNSPECV_FRDY
+  UNSPECV_CUSTOM_NXX
+  UNSPECV_CUSTOM_XNXX
+  UNSPECV_LDXIO
+  UNSPECV_STXIO
+])
+
+(define_c_enum "unspec" [
+  UNSPEC_FCOS
+  UNSPEC_FSIN
+  UNSPEC_FTAN
+  UNSPEC_FATAN
+  UNSPEC_FEXP
+  UNSPEC_FLOG
+  UNSPEC_LOAD_GOT_REGISTER
+  UNSPEC_PIC_SYM
+  UNSPEC_PIC_CALL_SYM
+  UNSPEC_TLS
+  UNSPEC_TLS_LDM
+  UNSPEC_LOAD_TLS_IE
+  UNSPEC_ADD_TLS_LE
+  UNSPEC_ADD_TLS_GD
+  UNSPEC_ADD_TLS_LDM
+  UNSPEC_ADD_TLS_LDO
+  UNSPEC_EH_RETURN
+  UNSPEC_SYNC
+])
+
+
+;;  Instruction scheduler
+
+; No schedule info is currently available, using an assumption that no
+; instruction can use the results of the previous instruction without
+; incuring a stall.
+
+; length of an instruction (in bytes)
+(define_attr "length" "" (const_int 4))
+(define_attr "type" 
+  "unknown,complex,control,alu,cond_alu,st,ld,shift,mul,div,custom" 
+  (const_string "complex"))
+
+(define_asm_attributes
+ [(set_attr "length" "4")
+  (set_attr "type" "complex")])
+
+(define_automaton "nios2")
+(automata_option "v")
+;(automata_option "no-minimization")
+(automata_option "ndfa")
+
+; The nios2 pipeline is fairly straightforward for the fast model.
+; Every alu operation is pipelined so that an instruction can
+; be issued every cycle. However, there are still potential
+; stalls which this description tries to deal with.
+
+(define_cpu_unit "cpu" "nios2")
+
+(define_insn_reservation "complex" 1
+  (eq_attr "type" "complex")
+  "cpu")
+
+(define_insn_reservation "control" 1
+  (eq_attr "type" "control")
+  "cpu")
+
+(define_insn_reservation "alu" 1
+  (eq_attr "type" "alu")
+  "cpu")
+
+(define_insn_reservation "cond_alu" 1
+  (eq_attr "type" "cond_alu")
+  "cpu")
+
+(define_insn_reservation "st" 1
+  (eq_attr "type" "st")
+  "cpu")
+  
+(define_insn_reservation "custom" 1
+  (eq_attr "type" "custom")
+  "cpu")
+
+; shifts, muls and lds have three cycle latency
+(define_insn_reservation "ld" 3
+  (eq_attr "type" "ld")
+  "cpu")
+
+(define_insn_reservation "shift" 3
+  (eq_attr "type" "shift")
+  "cpu")
+
+(define_insn_reservation "mul" 3
+  (eq_attr "type" "mul")
+  "cpu")
+
+(define_insn_reservation "div" 1
+  (eq_attr "type" "div")
+  "cpu")
+
+(include "predicates.md")
+(include "constraints.md")
+
+
+;; Move instructions
+
+(define_mode_iterator M [QI HI SI])
+
+(define_expand "mov<mode>"
+  [(set (match_operand:M 0 "nonimmediate_operand" "")
+        (match_operand:M 1 "general_operand" ""))]
+  ""
+{
+  if (nios2_emit_move_sequence (operands, <MODE>mode))
+    DONE;
+})
+
+(define_insn "movqi_internal"
+  [(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)
+    || reg_or_0_operand (operands[1], QImode))"
+  "@
+    stb%o0\\t%z1, %0
+    ldbu%o1\\t%0, %1
+    mov\\t%0, %z1
+    movi\\t%0, %1"
+  [(set_attr "type" "st,ld,alu,alu")])
+
+(define_insn "movhi_internal"
+  [(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)
+    || reg_or_0_operand (operands[1], HImode))"
+  "@
+    sth%o0\\t%z1, %0
+    ldhu%o1\\t%0, %1
+    mov\\t%0, %z1
+    movi\\t%0, %1
+    movui\\t%0, %1"
+  [(set_attr "type" "st,ld,alu,alu,alu")])
+
+(define_insn "movsi_internal"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=m, r,r, r,r,r,r,r")
+        (match_operand:SI 1 "general_operand"       "rM,m,rM,I,J,K,S,i"))]
+  "(register_operand (operands[0], SImode)
+    || reg_or_0_operand (operands[1], SImode))"
+  "@
+    stw%o0\\t%z1, %0
+    ldw%o1\\t%0, %1
+    mov\\t%0, %z1
+    movi\\t%0, %1
+    movui\\t%0, %1
+    movhi\\t%0, %H1
+    addi\\t%0, gp, %%gprel(%1)
+    movhi\\t%0, %H1\;addi\\t%0, %0, %L1"
+  [(set_attr "type" "st,ld,alu,alu,alu,alu,alu,alu")
+   (set_attr "length" "4,4,4,4,4,4,4,8")])
+
+
+(define_mode_iterator BH [QI HI])
+(define_mode_iterator BHW [QI HI SI])
+(define_mode_attr bh [(QI "b") (HI "h")])
+(define_mode_attr bhw [(QI "b") (HI "h") (SI "w")])
+(define_mode_attr bhw_uns [(QI "bu") (HI "hu") (SI "w")])
+
+(define_insn "ld<bhw_uns>io"
+  [(set (match_operand:BHW 0 "register_operand" "=r")
+        (unspec_volatile:BHW
+          [(match_operand:BHW 1 "memory_operand" "m")] UNSPECV_LDXIO))]
+  ""
+  "ld<bhw_uns>io\\t%0, %1"
+  [(set_attr "type" "ld")])
+
+(define_expand "ld<bh>io"
+  [(set (match_operand:BH 0 "register_operand" "=r")
+        (match_operand:BH 1 "memory_operand" "m"))]
+  ""
+{
+  rtx tmp = gen_reg_rtx (SImode);
+  emit_insn (gen_ld<bh>io_signed (tmp, operands[1]));
+  emit_insn (gen_mov<mode> (operands[0], gen_lowpart (<MODE>mode, tmp)));
+  DONE;
+})
+
+(define_insn "ld<bh>io_signed"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (sign_extend:SI
+          (unspec_volatile:BH
+            [(match_operand:BH 1 "memory_operand" "m")] UNSPECV_LDXIO)))]
+  ""
+  "ld<bh>io\\t%0, %1"
+  [(set_attr "type" "ld")])
+
+(define_insn "st<bhw>io"
+  [(set (match_operand:BHW 0 "memory_operand" "=m")
+        (unspec_volatile:BHW
+          [(match_operand:BHW 1 "reg_or_0_operand" "rM")] UNSPECV_STXIO))]
+  ""
+  "st<bhw>io\\t%z1, %0"
+  [(set_attr "type" "st")])
+
+
+;; QI to [HI, SI] extension patterns are collected together
+(define_mode_iterator QX [HI SI])
+
+;; Zero extension patterns
+(define_insn "zero_extendhisi2"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+        (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
+  ""
+  "@
+    andi\\t%0, %1, 0xffff
+    ldhu%o1\\t%0, %1"
+  [(set_attr "type"     "alu,ld")])
+
+(define_insn "zero_extendqi<mode>2"
+  [(set (match_operand:QX 0 "register_operand" "=r,r")
+        (zero_extend:QX (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
+  ""
+  "@
+    andi\\t%0, %1, 0xff
+    ldbu%o1\\t%0, %1"
+  [(set_attr "type"     "alu,ld")])
+
+;; Sign extension patterns
+
+(define_insn "extendhisi2"
+  [(set (match_operand:SI 0 "register_operand"                     "=r,r")
+        (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand"  "r,m")))]
+  ""
+  "@
+   #
+   ldh%o1\\t%0, %1"
+  [(set_attr "type" "alu,ld")])
+
+(define_insn "extendqi<mode>2"
+  [(set (match_operand:QX 0 "register_operand"                     "=r,r")
+        (sign_extend:QX (match_operand:QI 1 "nonimmediate_operand"  "r,m")))]
+  ""
+  "@
+   #
+   ldb%o1\\t%0, %1"
+  [(set_attr "type" "alu,ld")])
+
+;; Split patterns for register alternative cases.
+(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_split
+  [(set (match_operand:QX 0 "register_operand" "")
+        (sign_extend:QX (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]);")
+
+
+;; Arithmetic Operations
+
+(define_insn "addsi3"
+  [(set (match_operand:SI 0 "register_operand"          "=r")
+        (plus:SI (match_operand:SI 1 "register_operand" "%r")
+                 (match_operand:SI 2 "arith_operand"   "rIT")))]
+  ""
+  "add%i2\\t%0, %1, %z2"
+  [(set_attr "type" "alu")])
+
+(define_insn "subsi3"
+  [(set (match_operand:SI 0 "register_operand"           "=r")
+        (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
+                  (match_operand:SI 2 "register_operand" "r")))]
+  ""
+  "sub\\t%0, %z1, %2"
+  [(set_attr "type" "alu")])
+
+(define_insn "mulsi3"
+  [(set (match_operand:SI 0 "register_operand"          "=r")
+        (mult:SI (match_operand:SI 1 "register_operand" "%r")
+                 (match_operand:SI 2 "arith_operand"    "rI")))]
+  "TARGET_HAS_MUL"
+  "mul%i2\\t%0, %1, %z2"
+  [(set_attr "type" "mul")])
+
+(define_expand "divsi3"
+  [(set (match_operand:SI 0 "register_operand"          "=r")
+        (div:SI (match_operand:SI 1 "register_operand"   "r")
+                (match_operand:SI 2 "register_operand"   "r")))]
+  ""
+{
+  if (!TARGET_HAS_DIV)
+    {
+      if (!TARGET_FAST_SW_DIV)
+        FAIL;
+      else
+        {
+          if (nios2_emit_expensive_div (operands, SImode))
+            DONE;
+        }
+    }
+})
+
+(define_insn "divsi3_insn"
+  [(set (match_operand:SI 0 "register_operand"            "=r")
+        (div:SI (match_operand:SI 1 "register_operand"     "r")
+                (match_operand:SI 2 "register_operand"     "r")))]
+  "TARGET_HAS_DIV"
+  "div\\t%0, %1, %2"
+  [(set_attr "type" "div")])
+
+(define_insn "udivsi3"
+  [(set (match_operand:SI 0 "register_operand"            "=r")
+        (udiv:SI (match_operand:SI 1 "register_operand"    "r")
+                 (match_operand:SI 2 "register_operand"    "r")))]
+  "TARGET_HAS_DIV"
+  "divu\\t%0, %1, %2"
+  [(set_attr "type" "div")])
+
+(define_code_iterator EXTEND [sign_extend zero_extend])
+(define_code_attr us [(sign_extend "s") (zero_extend "u")])
+(define_code_attr mul [(sign_extend "mul") (zero_extend "umul")])
+
+(define_insn "<us>mulsi3_highpart"
+  [(set (match_operand:SI 0 "register_operand"                       "=r")
+        (truncate:SI
+         (lshiftrt:DI
+          (mult:DI (EXTEND:DI (match_operand:SI 1 "register_operand"  "r"))
+                   (EXTEND:DI (match_operand:SI 2 "register_operand"  "r")))
+          (const_int 32))))]
+  "TARGET_HAS_MULX"
+  "mulx<us><us>\\t%0, %1, %2"
+  [(set_attr "type" "mul")])
+
+(define_expand "<mul>sidi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(mult:DI (EXTEND:DI (match_operand:SI 1 "register_operand" ""))
+		 (EXTEND:DI (match_operand:SI 2 "register_operand" ""))))]
+  "TARGET_HAS_MULX"
+{
+  rtx hi = gen_reg_rtx (SImode);
+  rtx lo = gen_reg_rtx (SImode);
+
+  emit_insn (gen_<us>mulsi3_highpart (hi, operands[1], operands[2]));
+  emit_insn (gen_mulsi3 (lo, operands[1], operands[2]));
+  emit_move_insn (gen_lowpart (SImode, operands[0]), lo);
+  emit_move_insn (gen_highpart (SImode, operands[0]), hi);
+  DONE;
+})
+
+
+;;  Negate and ones complement
+
+(define_insn "negsi2"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+        (neg:SI (match_operand:SI 1 "register_operand" "r")))]
+  ""
+  "sub\\t%0, zero, %1"
+  [(set_attr "type" "alu")])
+
+(define_insn "one_cmplsi2"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+        (not:SI (match_operand:SI 1 "register_operand" "r")))]
+  ""
+  "nor\\t%0, zero, %1"
+  [(set_attr "type" "alu")])
+
+
+;;  Integer logical Operations
+
+(define_code_iterator LOGICAL [and ior xor])
+(define_code_attr logical_asm [(and "and") (ior "or") (xor "xor")])
+
+(define_insn "<code>si3"
+  [(set (match_operand:SI 0 "register_operand"             "=r,r,r")
+        (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r,r")
+                    (match_operand:SI 2 "logical_operand"  "rM,J,K")))]
+  ""
+  "@
+    <logical_asm>\\t%0, %1, %z2
+    <logical_asm>%i2\\t%0, %1, %2
+    <logical_asm>h%i2\\t%0, %1, %U2"
+  [(set_attr "type" "alu")])
+
+(define_insn "*norsi3"
+  [(set (match_operand:SI 0 "register_operand"                  "=r")
+        (and:SI (not:SI (match_operand:SI 1 "register_operand"  "%r"))
+                (not:SI (match_operand:SI 2 "reg_or_0_operand"  "rM"))))]
+  ""
+  "nor\\t%0, %1, %z2"
+  [(set_attr "type" "alu")])
+
+
+;;  Shift instructions
+
+(define_code_iterator SHIFT  [ashift ashiftrt lshiftrt rotate])
+(define_code_attr shift_op   [(ashift "ashl") (ashiftrt "ashr")
+                              (lshiftrt "lshr") (rotate "rotl")])
+(define_code_attr shift_asm  [(ashift "sll") (ashiftrt "sra")
+                              (lshiftrt "srl") (rotate "rol")])
+
+(define_insn "<shift_op>si3"
+  [(set (match_operand:SI 0 "register_operand"          "=r")
+        (SHIFT:SI (match_operand:SI 1 "register_operand" "r")
+                  (match_operand:SI 2 "shift_operand"    "rL")))]
+  ""
+  "<shift_asm>%i2\\t%0, %1, %z2"
+  [(set_attr "type" "shift")])
+
+(define_insn "rotrsi3"
+  [(set (match_operand:SI 0 "register_operand"             "=r")
+        (rotatert:SI (match_operand:SI 1 "register_operand" "r")
+                     (match_operand:SI 2 "register_operand" "r")))]
+  ""
+  "ror\\t%0, %1, %2"
+  [(set_attr "type" "shift")])
+
+
+
+;; Floating point instructions
+
+;; Mode iterator for single/double float
+(define_mode_iterator F [SF DF])
+(define_mode_attr f [(SF "s") (DF "d")])
+
+;; Basic arithmetic instructions
+(define_code_iterator FOP3 [plus minus mult div])
+(define_code_attr fop3 [(plus "add") (minus "sub") (mult "mul") (div "div")])
+
+(define_insn "<fop3><mode>3"
+  [(set (match_operand:F 0 "register_operand"        "=r")
+        (FOP3:F (match_operand:F 1 "register_operand" "r")
+                (match_operand:F 2 "register_operand" "r")))]
+  "nios2_fpu_insn_enabled (n2fpu_f<fop3><f>)"
+  "* return nios2_fpu_insn_asm (n2fpu_f<fop3><f>);"
+  [(set_attr "type" "custom")])
+
+;; Floating point min/max operations
+(define_code_iterator SMINMAX [smin smax])
+(define_code_attr minmax [(smin "min") (smax "max")])
+(define_insn "<code><mode>3"
+  [(set (match_operand:F 0 "register_operand" "=r")
+        (SMINMAX:F (match_operand:F 1 "register_operand" "r")
+                   (match_operand:F 2 "register_operand" "r")))]
+  "nios2_fpu_insn_enabled (n2fpu_f<minmax><f>)"
+  "* return nios2_fpu_insn_asm (n2fpu_f<minmax><f>);"
+  [(set_attr "type" "custom")])
+
+;; These 2-operand FP operations can be collected together
+(define_code_iterator FOP2 [abs neg sqrt])
+(define_insn "<code><mode>2"
+  [(set (match_operand:F 0 "register_operand" "=r")
+        (FOP2:F (match_operand:F 1 "register_operand" "r")))]
+  "nios2_fpu_insn_enabled (n2fpu_f<code><f>)"
+  "* return nios2_fpu_insn_asm (n2fpu_f<code><f>);"
+  [(set_attr "type" "custom")])
+
+;; X, Y register access instructions
+(define_insn "nios2_fwrx"
+  [(unspec_volatile [(match_operand:DF 0 "register_operand" "r")] UNSPECV_FWRX)]
+  "nios2_fpu_insn_enabled (n2fpu_fwrx)"
+  "* return nios2_fpu_insn_asm (n2fpu_fwrx);"
+  [(set_attr "type" "custom")])
+
+(define_insn "nios2_fwry"
+  [(unspec_volatile [(match_operand:SF 0 "register_operand" "r")] UNSPECV_FWRY)]
+  "nios2_fpu_insn_enabled (n2fpu_fwry)"
+  "* return nios2_fpu_insn_asm (n2fpu_fwry);"
+  [(set_attr "type" "custom")])
+
+;; The X, Y read insns uses an int iterator
+(define_int_iterator UNSPEC_READ_XY [UNSPECV_FRDXLO UNSPECV_FRDXHI
+                                     UNSPECV_FRDY])
+(define_int_attr read_xy [(UNSPECV_FRDXLO "frdxlo") (UNSPECV_FRDXHI "frdxhi")
+                          (UNSPECV_FRDY "frdy")])
+(define_insn "nios2_<read_xy>"
+  [(set (match_operand:SF 0 "register_operand" "=r")
+        (unspec_volatile:SF [(const_int 0)] UNSPEC_READ_XY))]
+  "nios2_fpu_insn_enabled (n2fpu_<read_xy>)"
+  "* return nios2_fpu_insn_asm (n2fpu_<read_xy>);"
+  [(set_attr "type" "custom")])
+
+;; Various math functions
+(define_int_iterator MATHFUNC
+  [UNSPEC_FCOS UNSPEC_FSIN UNSPEC_FTAN UNSPEC_FATAN UNSPEC_FEXP UNSPEC_FLOG])
+(define_int_attr mathfunc [(UNSPEC_FCOS "cos") (UNSPEC_FSIN "sin")
+                           (UNSPEC_FTAN "tan") (UNSPEC_FATAN "atan")
+                           (UNSPEC_FEXP "exp") (UNSPEC_FLOG "log")])
+
+(define_insn "<mathfunc><mode>2"
+  [(set (match_operand:F 0 "register_operand" "=r")
+        (unspec:F [(match_operand:F 1 "register_operand" "r")] MATHFUNC))]
+  "nios2_fpu_insn_enabled (n2fpu_f<mathfunc><f>)"
+  "* return nios2_fpu_insn_asm (n2fpu_f<mathfunc><f>);"
+  [(set_attr "type" "custom")])
+
+;; Converting between floating point and fixed point
+
+(define_code_iterator FLOAT [float unsigned_float])
+(define_code_iterator FIX [fix unsigned_fix])
+
+(define_code_attr conv_op [(float "float") (unsigned_float "floatuns")
+                           (fix "fix") (unsigned_fix "fixuns")])
+(define_code_attr i [(float "i") (unsigned_float "u")
+                     (fix "i") (unsigned_fix "u")])
+
+;; Integer to float conversions
+(define_insn "<conv_op>si<mode>2"
+  [(set (match_operand:F 0 "register_operand" "=r")
+        (FLOAT:F (match_operand:SI 1 "register_operand" "r")))]
+  "nios2_fpu_insn_enabled (n2fpu_float<i><f>)"
+  "* return nios2_fpu_insn_asm (n2fpu_float<i><f>);"
+  [(set_attr "type" "custom")])
+
+;; Float to integer conversions
+(define_insn "<conv_op>_trunc<mode>si2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (FIX:SI (match_operand:F 1 "general_operand" "r")))]
+  "nios2_fpu_insn_enabled (n2fpu_fix<f><i>)"
+  "* return nios2_fpu_insn_asm (n2fpu_fix<f><i>);"
+  [(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_insn_enabled (n2fpu_fextsd)"
+  "* return nios2_fpu_insn_asm (n2fpu_fextsd);"
+  [(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_insn_enabled (n2fpu_ftruncds)"
+  "* return nios2_fpu_insn_asm (n2fpu_ftruncds);"
+  [(set_attr "type" "custom")])
+
+
+
+;; Prologue, Epilogue and Return
+
+(define_expand "prologue"
+  [(const_int 1)]
+  ""
+{
+  expand_prologue ();
+  DONE;
+})
+
+(define_expand "epilogue"
+  [(return)]
+  ""
+{
+  expand_epilogue (false);
+  DONE;
+})
+
+(define_expand "sibcall_epilogue"
+  [(return)]
+  ""
+{
+  expand_epilogue (true);
+  DONE;
+})
+
+(define_insn "return"
+  [(return)]
+  "nios2_can_use_return_insn ()"
+  "ret"
+)
+
+(define_insn "return_from_epilogue"
+  [(use (match_operand 0 "pmode_register_operand" ""))
+   (return)]
+  "reload_completed"
+  "ret"
+)
+
+;; Block any insns from being moved before this point, since the
+;; profiling call to mcount can use various registers that aren't
+;; saved or used to pass arguments.
+
+(define_insn "blockage"
+  [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
+  ""
+  ""
+  [(set_attr "type" "unknown")
+   (set_attr "length" "0")])
+
+;; This is used in compiling the unwind routines.
+(define_expand "eh_return"
+  [(use (match_operand 0 "general_operand"))]
+  ""
+{
+  if (GET_MODE (operands[0]) != Pmode)
+    operands[0] = convert_to_mode (Pmode, operands[0], 0);
+  emit_insn (gen_eh_set_ra (operands[0]));
+
+  DONE;
+})
+
+;; Clobber the return address on the stack.  We can't expand this
+;; until we know where it will be put in the stack frame.
+
+(define_insn "eh_set_ra"
+  [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
+   (clobber (match_scratch:SI 1 "=&r"))]
+ ""
+  "#")
+
+(define_split
+  [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN)
+   (clobber (match_scratch 1))]
+  "reload_completed"
+  [(const_int 0)]
+{
+  nios2_set_return_address (operands[0], operands[1]);
+  DONE;
+})
+
+
+;;  Jumps and calls
+
+; Note that the assembler fixes up any out-of-range branch instructions not
+; caught by the compiler branch shortening code.  The sequence emitted by
+; the assembler can be very inefficient, but it is correct for PIC code.
+; For non-PIC we are better off converting to an absolute JMPI.
+;
+; Direct calls and sibcalls use the CALL and JMPI instructions, respectively.
+; These instructions have an immediate operand that specifies the low 28 bits
+; of the PC, effectively allowing direct calls within a 256MB memory segment.
+; Per the Nios II Processor Reference Handbook, the linker is not required to
+; check or adjust for overflow.
+
+(define_insn "indirect_jump"
+  [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
+  ""
+  "jmp\\t%0"
+  [(set_attr "type" "control")])
+
+(define_insn "jump"
+  [(set (pc)
+        (label_ref (match_operand 0 "" "")))]
+  ""
+  {
+    if (flag_pic || get_attr_length (insn) == 4)
+      return "br\\t%0";
+    else
+      return "jmpi\\t%0";
+  }
+  [(set_attr "type" "control")
+   (set (attr "length") 
+        (if_then_else
+	    (and (ge (minus (match_dup 0) (pc)) (const_int -32768))
+	         (le (minus (match_dup 0) (pc)) (const_int 32764)))
+	    (const_int 4)
+	    (const_int 8)))])
+
+
+(define_expand "call"
+  [(parallel [(call (match_operand 0 "" "")
+                    (match_operand 1 "" ""))
+              (clobber (reg:SI 31))])]
+  ""
+  "nios2_adjust_call_address (&operands[0]);"
+)
+
+(define_expand "call_value"
+  [(parallel [(set (match_operand 0 "" "")
+                   (call (match_operand 1 "" "")
+                         (match_operand 2 "" "")))
+              (clobber (reg:SI 31))])]
+  ""
+  "nios2_adjust_call_address (&operands[1]);"
+)
+
+(define_insn "*call"
+  [(call (mem:QI (match_operand:SI 0 "call_operand" "i,r"))
+         (match_operand 1 "" ""))
+   (clobber (reg:SI 31))]
+  ""
+  "@
+   call\\t%0
+   callr\\t%0"
+  [(set_attr "type" "control,control")])
+
+(define_insn "*call_value"
+  [(set (match_operand 0 "" "")
+        (call (mem:QI (match_operand:SI 1 "call_operand" "i,r"))
+              (match_operand 2 "" "")))
+   (clobber (reg:SI 31))]
+  ""
+  "@
+   call\\t%1
+   callr\\t%1"
+  [(set_attr "type" "control,control")])
+
+(define_expand "sibcall"
+  [(parallel [(call (match_operand 0 "" "")
+                    (match_operand 1 "" ""))
+              (return)])]
+  ""
+  "nios2_adjust_call_address (&operands[0]);"
+)
+
+(define_expand "sibcall_value"
+  [(parallel [(set (match_operand 0 "" "")
+                   (call (match_operand 1 "" "")
+                         (match_operand 2 "" "")))
+              (return)])]
+  ""
+  "nios2_adjust_call_address (&operands[1]);"
+)
+
+(define_insn "*sibcall"
+ [(call (mem:QI (match_operand:SI 0 "call_operand" "i,j"))
+        (match_operand 1 "" ""))
+  (return)]
+  ""
+  "@
+   jmpi\\t%0
+   jmp\\t%0"
+)
+
+(define_insn "*sibcall_value"
+ [(set (match_operand 0 "register_operand" "")
+       (call (mem:QI (match_operand:SI 1 "call_operand" "i,j"))
+             (match_operand 2 "" "")))
+  (return)]
+  ""
+  "@
+   jmpi\\t%1
+   jmp\\t%1"
+)
+
+(define_expand "tablejump"
+  [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
+              (use (label_ref (match_operand 1 "" "")))])]
+  ""
+  {
+    if (flag_pic)
+      {
+        /* Hopefully, CSE will eliminate this copy.  */
+        rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
+        rtx reg2 = gen_reg_rtx (SImode);
+
+        emit_insn (gen_addsi3 (reg2, operands[0], reg1));
+        operands[0] = reg2;
+      }
+  }
+)
+
+(define_insn "*tablejump"
+  [(set (pc)
+        (match_operand:SI 0 "register_operand" "r"))
+   (use (label_ref (match_operand 1 "" "")))]
+  ""
+  "jmp\\t%0"
+  [(set_attr "type" "control")])
+
+
+
+;; cstore, cbranch patterns
+
+(define_mode_iterator CM [SI SF DF])
+
+(define_expand "cstore<mode>4"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (match_operator:SI 1 "comparison_operator"
+	  [(match_operand:CM 2 "register_operand")
+	   (match_operand:CM 3 "nonmemory_operand")]))]
+  "nios2_supported_compare_p (<MODE>mode)"
+  {
+    if (!nios2_validate_compare (<MODE>mode, &operands[1], &operands[2],
+                                 &operands[3]))
+      FAIL;
+  })
+
+(define_expand "cbranch<mode>4"
+  [(set (pc)
+     (if_then_else
+       (match_operator 0 "comparison_operator"
+         [(match_operand:CM 1 "register_operand")
+          (match_operand:CM 2 "nonmemory_operand")])
+       (label_ref (match_operand 3 ""))
+       (pc)))]
+  "nios2_supported_compare_p (<MODE>mode)"
+  {
+    if (!nios2_validate_compare (<MODE>mode, &operands[0], &operands[1],
+                                 &operands[2]))
+      FAIL;
+    if (GET_MODE_CLASS (<MODE>mode) == MODE_FLOAT
+        || !reg_or_0_operand (operands[2], <MODE>mode))
+      {
+        rtx condreg = gen_reg_rtx (SImode);
+        emit_insn (gen_cstore<mode>4
+                    (condreg, operands[0], operands[1], operands[2]));
+        operands[1] = condreg;
+        operands[2] = const0_rtx;
+        operands[0] = gen_rtx_fmt_ee (NE, VOIDmode, condreg, const0_rtx);
+      }
+  })
+
+(define_insn "nios2_cbranch"
+  [(set (pc)
+     (if_then_else
+       (match_operator 0 "comparison_operator"
+         [(match_operand:SI 1 "reg_or_0_operand" "rM")
+          (match_operand:SI 2 "reg_or_0_operand" "rM")])
+       (label_ref (match_operand 3 "" ""))
+       (pc)))]
+  ""
+  {
+    if (flag_pic || get_attr_length (insn) == 4)
+      return "b%0\t%z1, %z2, %l3";
+    else
+      return "b%R0\t%z1, %z2, .+8;jmpi\t%l3";
+  }
+  [(set_attr "type" "control")
+   (set (attr "length") 
+        (if_then_else
+	    (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
+	         (le (minus (match_dup 1) (pc)) (const_int 32764)))
+	    (const_int 4) (const_int 8)))])
+
+;; Floating point comparisons
+(define_code_iterator FCMP [eq ne gt ge le lt])
+(define_insn "nios2_s<code><mode>"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+        (FCMP:SI (match_operand:F 1 "register_operand" "r")
+                 (match_operand:F 2 "register_operand" "r")))]
+  "nios2_fpu_insn_enabled (n2fpu_fcmp<code><f>)"
+  "* return nios2_fpu_insn_asm (n2fpu_fcmp<code><f>);"
+  [(set_attr "type" "custom")])
+
+;; Integer comparisons
+
+(define_code_iterator EQNE [eq ne])
+(define_insn "nios2_cmp<code>"
+  [(set (match_operand:SI 0 "register_operand"           "=r")
+        (EQNE:SI (match_operand:SI 1 "reg_or_0_operand" "%rM")
+                 (match_operand:SI 2 "arith_operand"     "rI")))]
+  ""
+  "cmp<code>%i2\\t%0, %z1, %z2"
+  [(set_attr "type" "alu")])
+
+(define_code_iterator SCMP [ge lt])
+(define_insn "nios2_cmp<code>"
+  [(set (match_operand:SI 0 "register_operand"           "=r")
+        (SCMP:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
+                 (match_operand:SI 2 "arith_operand"     "rI")))]
+  ""
+  "cmp<code>%i2\\t%0, %z1, %z2"
+  [(set_attr "type" "alu")])
+
+(define_code_iterator UCMP [geu ltu])
+(define_insn "nios2_cmp<code>"
+  [(set (match_operand:SI 0 "register_operand"           "=r")
+        (UCMP:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
+                 (match_operand:SI 2 "uns_arith_operand" "rJ")))]
+  ""
+  "cmp<code>%i2\\t%0, %z1, %z2"
+  [(set_attr "type" "alu")])
+
+
+
+;; Custom instruction patterns. The operands are intentionally
+;; mode-less, to serve as generic carriers of all Altera defined
+;; built-in instruction/function types.
+
+(define_insn "custom_nxx"
+  [(unspec_volatile [(match_operand 0 "custom_insn_opcode" "N")
+                     (match_operand 1 "reg_or_0_operand"  "rM")
+                     (match_operand 2 "reg_or_0_operand"  "rM")]
+    UNSPECV_CUSTOM_NXX)]
+  ""
+  "custom\\t%0, zero, %z1, %z2"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_xnxx"
+  [(set (match_operand 0 "register_operand"   "=r")
+        (unspec_volatile [(match_operand 1 "custom_insn_opcode" "N")
+                          (match_operand 2 "reg_or_0_operand"  "rM")
+                          (match_operand 3 "reg_or_0_operand"  "rM")] 
+	 UNSPECV_CUSTOM_XNXX))]
+  ""
+  "custom\\t%1, %0, %z2, %z3"
+  [(set_attr "type" "custom")])
+
+
+;;  Misc. patterns
+
+(define_insn "nop"
+  [(const_int 0)]
+  ""
+  "nop"
+  [(set_attr "type" "alu")])
+
+;; Connect 'sync' to 'memory_barrier' standard expand name
+(define_expand "memory_barrier"
+  [(const_int 0)]
+  ""
+{
+  emit_insn (gen_sync ());
+  DONE;
+})
+
+;; For the nios2 __builtin_sync built-in function
+(define_expand "sync"
+  [(set (match_dup 0)
+	(unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
+  ""
+{
+  operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
+  MEM_VOLATILE_P (operands[0]) = 1;
+})
+
+(define_insn "*sync_insn"
+  [(set (match_operand:BLK 0 "" "")
+	(unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
+  ""
+  "sync"
+  [(set_attr "type" "control")])
+
+(define_insn "rdctl"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O")] 
+	 UNSPECV_RDCTL))]
+  ""
+  "rdctl\\t%0, ctl%1"
+  [(set_attr "type" "control")])
+
+(define_insn "wrctl"
+  [(unspec_volatile:SI [(match_operand:SI 0 "rdwrctl_operand"  "O")
+                        (match_operand:SI 1 "reg_or_0_operand" "rM")] 
+    UNSPECV_WRCTL)]
+  ""
+  "wrctl\\tctl%0, %z1"
+  [(set_attr "type" "control")])
+
+;; Used to signal a stack overflow 
+(define_insn "trap"
+  [(unspec_volatile [(const_int 0)] UNSPECV_TRAP)]
+  ""
+  "break\\t3"
+  [(set_attr "type" "control")])
+  
+(define_insn "stack_overflow_detect_and_trap"
+  [(unspec_volatile [(const_int 0)] UNSPECV_STACK_OVERFLOW_DETECT_AND_TRAP)]
+  ""
+  "bgeu\\tsp, et, 1f\;break\\t3\;1:"
+  [(set_attr "type" "control")
+   (set_attr "length" "8")])
+
+;; Load the GOT register.
+(define_insn "load_got_register"
+  [(set (match_operand:SI 0 "register_operand" "=&r")
+	 (unspec:SI [(const_int 0)] UNSPEC_LOAD_GOT_REGISTER))
+   (set (match_operand:SI 1 "register_operand" "=r")
+	 (unspec:SI [(const_int 0)] UNSPEC_LOAD_GOT_REGISTER))]
+  ""
+  "nextpc\\t%0
+\\t1:
+\\tmovhi\\t%1, %%hiadj(_GLOBAL_OFFSET_TABLE_ - 1b)
+\\taddi\\t%1, %1, %%lo(_GLOBAL_OFFSET_TABLE_ - 1b)"
+  [(set_attr "length" "12")])
+
+;; Read thread pointer register
+(define_expand "get_thread_pointersi"
+  [(match_operand:SI 0 "register_operand" "=r")]
+  "TARGET_LINUX_ABI"
+{
+  emit_move_insn (operands[0], gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM));
+  DONE;
+})
Index: gcc/config/nios2/nios2.c
===================================================================
--- gcc/config/nios2/nios2.c	(revision 0)
+++ gcc/config/nios2/nios2.c	(revision 0)
@@ -0,0 +1,3212 @@ 
+/* Target machine subroutines for Altera Nios II.
+   Copyright (C) 2012-2013 Free Software Foundation, Inc.
+   Contributed by Jonah Graham (jgraham@altera.com), 
+   Will Reece (wreece@altera.com), and Jeff DaSilva (jdasilva@altera.com).
+   Contributed by Mentor Graphics, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "tree.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "output.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "recog.h"
+#include "expr.h"
+#include "optabs.h"
+#include "function.h"
+#include "ggc.h"
+#include "basic-block.h"
+#include "diagnostic-core.h"
+#include "toplev.h"
+#include "target.h"
+#include "target-def.h"
+#include "tm_p.h"
+#include "langhooks.h"
+#include "df.h"
+#include "debug.h"
+#include "real.h"
+#include "reload.h"
+
+/* Local prototypes.  */
+static bool nios2_rtx_costs (rtx, int, int, int, int *, bool);
+static reg_class_t nios2_preferred_reload_class (rtx, reg_class_t);
+static void nios2_print_operand (FILE *, rtx, int);
+static void nios2_print_operand_address (FILE *, rtx);
+static bool nios2_output_addr_const_extra (FILE *, rtx);
+static const char* nios2_unspec_reloc_name (int);
+static void nios2_asm_function_prologue (FILE *, HOST_WIDE_INT);
+static int nios2_issue_rate (void);
+static struct machine_function *nios2_init_machine_status (void);
+static bool nios2_in_small_data_p (const_tree);
+static void dump_frame_size (FILE *);
+static HOST_WIDE_INT compute_frame_size (void);
+static void save_reg (int, unsigned);
+static void restore_reg (int, unsigned);
+static unsigned int nios2_section_type_flags (tree, const char *, int);
+static bool nios2_can_eliminate (const int, const int);
+static void nios2_load_pic_register (void);
+static rtx nios2_load_pic_address (rtx, int);
+static bool nios2_cannot_force_const_mem (enum machine_mode, rtx);
+static rtx nios2_legitimize_constant_address (rtx);
+static bool nios2_legitimate_constant_p (enum machine_mode, rtx);
+static rtx nios2_legitimize_address (rtx, rtx, enum machine_mode);
+static bool nios2_legitimate_address_p (enum machine_mode, rtx, bool);
+static bool nios2_tls_symbol_p (rtx);
+static void nios2_init_builtins (void);
+static rtx nios2_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
+static void nios2_init_libfuncs (void);
+static rtx nios2_function_arg (cumulative_args_t, enum machine_mode,
+			       const_tree, bool);
+static void nios2_function_arg_advance (cumulative_args_t, enum machine_mode,
+					const_tree, bool);
+static void nios2_setup_incoming_varargs (cumulative_args_t, enum machine_mode, 
+					  tree, int *, int);
+static int nios2_arg_partial_bytes (cumulative_args_t,
+				    enum machine_mode, tree, bool);
+static void nios2_trampoline_init (rtx, tree, rtx);
+static rtx nios2_function_value (const_tree, const_tree, bool);
+static rtx nios2_libcall_value (enum machine_mode, const_rtx);
+static bool nios2_function_value_regno_p (const unsigned int);
+static bool nios2_return_in_memory (const_tree, const_tree);
+static void nios2_encode_section_info (tree, rtx, int);
+static void nios2_output_dwarf_dtprel (FILE *, int, rtx);
+static void nios2_option_override (void);
+static void nios2_option_save (struct cl_target_option*);
+static void nios2_option_restore (struct cl_target_option*);
+static void nios2_set_current_function (tree);
+static bool nios2_valid_target_attribute_p (tree, tree, tree, int);
+static bool nios2_pragma_target_parse (tree, tree);
+static tree nios2_merge_decl_attributes (tree, tree);
+static void nios2_custom_check_insns (void);
+static void nios2_handle_custom_fpu_cfg (const char*, bool);
+static void nios2_handle_custom_fpu_insn_option (int);
+static void nios2_register_custom_code (unsigned int, enum nios2_ccs_code, int);
+static void nios2_deregister_custom_code (unsigned int);
+
+/* Initialize the GCC target structure.  */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE nios2_asm_function_prologue
+
+#undef TARGET_SCHED_ISSUE_RATE
+#define TARGET_SCHED_ISSUE_RATE nios2_issue_rate
+#undef TARGET_IN_SMALL_DATA_P
+#define TARGET_IN_SMALL_DATA_P nios2_in_small_data_p
+#undef  TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO nios2_encode_section_info
+#undef  TARGET_SECTION_TYPE_FLAGS
+#define TARGET_SECTION_TYPE_FLAGS  nios2_section_type_flags
+
+#undef TARGET_INIT_BUILTINS
+#define TARGET_INIT_BUILTINS nios2_init_builtins
+#undef TARGET_EXPAND_BUILTIN
+#define TARGET_EXPAND_BUILTIN nios2_expand_builtin
+
+#undef TARGET_INIT_LIBFUNCS
+#define TARGET_INIT_LIBFUNCS nios2_init_libfuncs
+
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL hook_bool_tree_tree_true
+
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE nios2_can_eliminate
+
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG nios2_function_arg
+
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE nios2_function_arg_advance
+
+#undef TARGET_ARG_PARTIAL_BYTES
+#define TARGET_ARG_PARTIAL_BYTES nios2_arg_partial_bytes
+
+#undef TARGET_TRAMPOLINE_INIT
+#define TARGET_TRAMPOLINE_INIT nios2_trampoline_init
+
+#undef TARGET_FUNCTION_VALUE
+#define TARGET_FUNCTION_VALUE nios2_function_value
+
+#undef TARGET_LIBCALL_VALUE
+#define TARGET_LIBCALL_VALUE nios2_libcall_value
+
+#undef TARGET_FUNCTION_VALUE_REGNO_P
+#define TARGET_FUNCTION_VALUE_REGNO_P nios2_function_value_regno_p
+
+#undef TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY nios2_return_in_memory
+
+#undef TARGET_PROMOTE_PROTOTYPES
+#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
+
+#undef TARGET_SETUP_INCOMING_VARARGS
+#define TARGET_SETUP_INCOMING_VARARGS nios2_setup_incoming_varargs
+
+#undef TARGET_MUST_PASS_IN_STACK
+#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
+
+#undef TARGET_LEGITIMATE_CONSTANT_P
+#define TARGET_LEGITIMATE_CONSTANT_P nios2_legitimate_constant_p
+
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS nios2_legitimize_address
+
+#undef TARGET_LEGITIMATE_ADDRESS_P
+#define TARGET_LEGITIMATE_ADDRESS_P nios2_legitimate_address_p
+
+#undef TARGET_PREFERRED_RELOAD_CLASS
+#define TARGET_PREFERRED_RELOAD_CLASS nios2_preferred_reload_class
+
+#undef TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS nios2_rtx_costs
+
+#undef TARGET_HAVE_TLS
+#define TARGET_HAVE_TLS TARGET_LINUX_ABI
+
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM nios2_cannot_force_const_mem
+
+#undef TARGET_ASM_OUTPUT_DWARF_DTPREL
+#define TARGET_ASM_OUTPUT_DWARF_DTPREL nios2_output_dwarf_dtprel
+
+#undef TARGET_PRINT_OPERAND
+#define TARGET_PRINT_OPERAND nios2_print_operand
+
+#undef TARGET_PRINT_OPERAND_ADDRESS
+#define TARGET_PRINT_OPERAND_ADDRESS nios2_print_operand_address
+
+#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
+#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA nios2_output_addr_const_extra
+
+#undef TARGET_OPTION_OVERRIDE
+#define TARGET_OPTION_OVERRIDE nios2_option_override
+
+#undef TARGET_OPTION_SAVE
+#define TARGET_OPTION_SAVE nios2_option_save
+
+#undef TARGET_OPTION_RESTORE
+#define TARGET_OPTION_RESTORE nios2_option_restore
+
+#undef TARGET_SET_CURRENT_FUNCTION
+#define TARGET_SET_CURRENT_FUNCTION nios2_set_current_function
+
+#undef TARGET_OPTION_VALID_ATTRIBUTE_P
+#define TARGET_OPTION_VALID_ATTRIBUTE_P nios2_valid_target_attribute_p
+
+#undef TARGET_OPTION_PRAGMA_PARSE
+#define TARGET_OPTION_PRAGMA_PARSE nios2_pragma_target_parse
+
+#undef TARGET_MERGE_DECL_ATTRIBUTES
+#define TARGET_MERGE_DECL_ATTRIBUTES nios2_merge_decl_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;
+
+
+/* Threshold for data being put into the small data/bss area, instead
+   of the normal data area (references to the small data/bss area take
+   1 instruction, and use the global pointer, references to the normal
+   data area takes 2 instructions).  */
+unsigned HOST_WIDE_INT nios2_section_threshold = NIOS2_DEFAULT_GVALUE;
+
+struct GTY (()) machine_function
+{
+  /* Current frame information, to be filled in by compute_frame_size
+     with register save masks, and offsets for the current function.  */
+
+  unsigned HOST_WIDE_INT save_mask; /* Mask of registers to save.  */
+  long total_size;       /* # bytes that the entire frame takes up.  */
+  long var_size;         /* # bytes that variables take up.  */
+  long args_size;        /* # bytes that outgoing arguments take up.  */
+  int save_reg_size;     /* # bytes needed to store gp regs.  */
+  long save_regs_offset; /* Offset from new sp to store gp registers.  */
+  int initialized;       /* != 0 if frame size already calculated.  */
+};
+
+/* State to track the assignment of custom codes to FPU/custom builtins.  */
+static enum nios2_ccs_code custom_code_status[256];
+static int custom_code_index[256];
+/* Set to true if any conflicts (re-use of a code between 0-255) are found.  */
+static bool custom_code_conflict = false;
+
+
+
+/* Definition of builtin function types for nios2.  */
+
+#define N2_FTYPES				\
+  N2_FTYPE(1, (SF))				\
+  N2_FTYPE(1, (VOID))				\
+  N2_FTYPE(2, (DF, DF))				\
+  N2_FTYPE(3, (DF, DF, DF))			\
+  N2_FTYPE(2, (DF, SF))				\
+  N2_FTYPE(2, (DF, SI))				\
+  N2_FTYPE(2, (DF, UI))				\
+  N2_FTYPE(2, (SF, DF))				\
+  N2_FTYPE(2, (SF, SF))				\
+  N2_FTYPE(3, (SF, SF, SF))			\
+  N2_FTYPE(2, (SF, SI))				\
+  N2_FTYPE(2, (SF, UI))				\
+  N2_FTYPE(2, (SI, CVPTR))			\
+  N2_FTYPE(2, (SI, DF))				\
+  N2_FTYPE(3, (SI, DF, DF))			\
+  N2_FTYPE(2, (SI, SF))				\
+  N2_FTYPE(3, (SI, SF, SF))			\
+  N2_FTYPE(2, (SI, SI))				\
+  N2_FTYPE(2, (UI, CVPTR))			\
+  N2_FTYPE(2, (UI, DF))				\
+  N2_FTYPE(2, (UI, SF))				\
+  N2_FTYPE(2, (VOID, DF))			\
+  N2_FTYPE(2, (VOID, SF))			\
+  N2_FTYPE(3, (VOID, SI, SI))			\
+  N2_FTYPE(3, (VOID, VPTR, SI))
+
+#define N2_FTYPE_OP1(R)         N2_FTYPE_ ## R ## _VOID
+#define N2_FTYPE_OP2(R, A1)     N2_FTYPE_ ## R ## _ ## A1
+#define N2_FTYPE_OP3(R, A1, A2) N2_FTYPE_ ## R ## _ ## A1 ## _ ## A2
+
+/* Expand ftcode enumeration.  */
+enum nios2_ftcode {
+#define N2_FTYPE(N,ARGS) N2_FTYPE_OP ## N ARGS,
+N2_FTYPES
+#undef N2_FTYPE
+N2_FTYPE_MAX
+};
+
+/* Return the tree function type, based on the ftcode.  */
+static tree
+nios2_ftype (enum nios2_ftcode ftcode)
+{
+  static tree types[(int) N2_FTYPE_MAX];
+
+  tree N2_TYPE_SF = float_type_node;
+  tree N2_TYPE_DF = double_type_node;
+  tree N2_TYPE_SI = integer_type_node;
+  tree N2_TYPE_UI = unsigned_type_node;
+  tree N2_TYPE_VOID = void_type_node;
+
+  static const_tree N2_TYPE_CVPTR, N2_TYPE_VPTR;
+  if (!N2_TYPE_CVPTR)
+    {
+      /* const volatile void * */
+      N2_TYPE_CVPTR
+	= build_pointer_type (build_qualified_type (void_type_node,
+						    (TYPE_QUAL_CONST
+						     | TYPE_QUAL_VOLATILE)));
+      /* volatile void * */
+      N2_TYPE_VPTR
+	= build_pointer_type (build_qualified_type (void_type_node,
+						    TYPE_QUAL_VOLATILE));
+    }
+  if (types[(int) ftcode] == NULL_TREE)
+    switch (ftcode)
+      {
+#define N2_FTYPE_ARGS1(R) N2_TYPE_ ## R
+#define N2_FTYPE_ARGS2(R,A1) N2_TYPE_ ## R, N2_TYPE_ ## A1
+#define N2_FTYPE_ARGS3(R,A1,A2) N2_TYPE_ ## R, N2_TYPE_ ## A1, N2_TYPE_ ## A2
+#define N2_FTYPE(N,ARGS)						\
+  case N2_FTYPE_OP ## N ARGS:						\
+    types[(int) ftcode]							\
+      = build_function_type_list (N2_FTYPE_ARGS ## N ARGS, NULL_TREE); \
+    break;
+	N2_FTYPES
+#undef N2_FTYPE
+      default: gcc_unreachable ();
+      }
+  return types[(int) ftcode];
+}
+
+
+
+/* Definition of FPU instruction descriptions.  */
+
+struct nios2_fpu_insn_info
+{
+  const char *name;
+  int num_operands, *optvar;
+  int opt, no_opt;
+#define N2F_DF            0x1
+#define N2F_DFREQ         0x2
+#define N2F_UNSAFE        0x4
+#define N2F_FINITE        0x8
+  unsigned int flags;
+  enum insn_code icode;
+  enum nios2_ftcode ftcode;
+};
+
+/* Base macro for defining FPU instructions.  */
+#define N2FPU_INSN_DEF_BASE(insn, nop, flags, icode, args)	\
+  { #insn, nop, &nios2_custom_ ## insn, OPT_mcustom_##insn##_,	\
+    OPT_mno_custom_##insn, flags, CODE_FOR_ ## icode,		\
+    N2_FTYPE_OP ## nop args }
+
+/* Arithmetic and math functions; 2 or 3 operand FP operations.  */
+#define N2FPU_OP2(mode) (mode, mode)
+#define N2FPU_OP3(mode) (mode, mode, mode)
+#define N2FPU_INSN_DEF(code, icode, nop, flags, m, M)			\
+  N2FPU_INSN_DEF_BASE (f ## code ## m, nop, flags,			\
+		       icode ## m ## f ## nop, N2FPU_OP ## nop (M ## F))
+#define N2FPU_INSN_SF(code, nop, flags)		\
+  N2FPU_INSN_DEF (code, code, nop, flags, s, S)
+#define N2FPU_INSN_DF(code, nop, flags)		\
+  N2FPU_INSN_DEF (code, code, nop, flags | N2F_DF, d, D)
+
+/* Compare instructions, 3 operand FP operation with a SI result.  */
+#define N2FPU_CMP_DEF(code, flags, m, M)				\
+  N2FPU_INSN_DEF_BASE (fcmp ## code ## m, 3, flags,			\
+		       nios2_s ## code ## m ## f, (SI, M ## F, M ## F))
+#define N2FPU_CMP_SF(code) N2FPU_CMP_DEF (code, 0, s, S)
+#define N2FPU_CMP_DF(code) N2FPU_CMP_DEF (code, N2F_DF, d, D)
+
+/* The order of definition needs to be maintained consistent with
+   enum n2fpu_code in nios2-opts.h.  */
+struct nios2_fpu_insn_info nios2_fpu_insn[] =
+  {
+    /* Single precision instructions.  */
+    N2FPU_INSN_SF (add, 3, 0),
+    N2FPU_INSN_SF (sub, 3, 0),
+    N2FPU_INSN_SF (mul, 3, 0),
+    N2FPU_INSN_SF (div, 3, 0),
+    /* Due to textual difference between min/max and smin/smax.  */
+    N2FPU_INSN_DEF (min, smin, 3, N2F_FINITE, s, S),
+    N2FPU_INSN_DEF (max, smax, 3, N2F_FINITE, s, S),
+    N2FPU_INSN_SF (neg, 2, 0),
+    N2FPU_INSN_SF (abs, 2, 0),
+    N2FPU_INSN_SF (sqrt, 2, 0),
+    N2FPU_INSN_SF (sin, 2, N2F_UNSAFE),
+    N2FPU_INSN_SF (cos, 2, N2F_UNSAFE),
+    N2FPU_INSN_SF (tan, 2, N2F_UNSAFE),
+    N2FPU_INSN_SF (atan, 2, N2F_UNSAFE),
+    N2FPU_INSN_SF (exp, 2, N2F_UNSAFE),
+    N2FPU_INSN_SF (log, 2, N2F_UNSAFE),
+    /* Single precision compares.  */
+    N2FPU_CMP_SF (ne), N2FPU_CMP_SF (eq),
+    N2FPU_CMP_SF (lt), N2FPU_CMP_SF (le),
+    N2FPU_CMP_SF (gt), N2FPU_CMP_SF (ge),
+
+    /* Double precision instructions.  */
+    N2FPU_INSN_DF (add, 3, 0),
+    N2FPU_INSN_DF (sub, 3, 0),
+    N2FPU_INSN_DF (mul, 3, 0),
+    N2FPU_INSN_DF (div, 3, 0),
+    /* Due to textual difference between min/max and smin/smax.  */
+    N2FPU_INSN_DEF (min, smin, 3, N2F_FINITE, d, D),
+    N2FPU_INSN_DEF (max, smax, 3, N2F_FINITE, d, D),
+    N2FPU_INSN_DF (neg, 2, 0),
+    N2FPU_INSN_DF (abs, 2, 0),
+    N2FPU_INSN_DF (sqrt, 2, 0),
+    N2FPU_INSN_DF (sin, 2, N2F_UNSAFE),
+    N2FPU_INSN_DF (cos, 2, N2F_UNSAFE),
+    N2FPU_INSN_DF (tan, 2, N2F_UNSAFE),
+    N2FPU_INSN_DF (atan, 2, N2F_UNSAFE),
+    N2FPU_INSN_DF (exp, 2, N2F_UNSAFE),
+    N2FPU_INSN_DF (log, 2, N2F_UNSAFE),
+    /* Double precision compares.  */
+    N2FPU_CMP_DF (ne), N2FPU_CMP_DF (eq),
+    N2FPU_CMP_DF (lt), N2FPU_CMP_DF (le),
+    N2FPU_CMP_DF (gt), N2FPU_CMP_DF (ge),
+
+    /* Conversion instructions.  */
+    N2FPU_INSN_DEF_BASE (floatis,  2, 0, floatsisf2,    (SF, SI)),
+    N2FPU_INSN_DEF_BASE (floatus,  2, 0, floatunssisf2, (SF, UI)),
+    N2FPU_INSN_DEF_BASE (floatid,  2, 0, floatsidf2,    (DF, SI)),
+    N2FPU_INSN_DEF_BASE (floatud,  2, 0, floatunssidf2, (DF, UI)),
+    N2FPU_INSN_DEF_BASE (fixsi,    2, 0, fix_truncsfsi2,      (SI, SF)),
+    N2FPU_INSN_DEF_BASE (fixsu,    2, 0, fixuns_truncsfsi2,   (UI, SF)),
+    N2FPU_INSN_DEF_BASE (fixdi,    2, 0, fix_truncdfsi2,      (SI, DF)),
+    N2FPU_INSN_DEF_BASE (fixdu,    2, 0, fixuns_truncdfsi2,   (UI, DF)),
+    N2FPU_INSN_DEF_BASE (fextsd,   2, 0, extendsfdf2,   (DF, SF)),
+    N2FPU_INSN_DEF_BASE (ftruncds, 2, 0, truncdfsf2,    (SF, DF)),
+
+    /* X, Y access instructions.  */
+    N2FPU_INSN_DEF_BASE (fwrx,     2, N2F_DFREQ, nios2_fwrx,   (VOID, DF)),
+    N2FPU_INSN_DEF_BASE (fwry,     2, N2F_DFREQ, nios2_fwry,   (VOID, SF)),
+    N2FPU_INSN_DEF_BASE (frdxlo,   1, N2F_DFREQ, nios2_frdxlo, (SF)),
+    N2FPU_INSN_DEF_BASE (frdxhi,   1, N2F_DFREQ, nios2_frdxhi, (SF)),
+    N2FPU_INSN_DEF_BASE (frdy,     1, N2F_DFREQ, nios2_frdy,   (SF))
+  };
+
+/* Some macros for ease of access.  */
+#define N2FPU(code) nios2_fpu_insn[(int) code]
+#define N2FPU_ENABLED_P(code) (N2FPU_N(code) >= 0)
+#define N2FPU_N(code) (*N2FPU(code).optvar)
+#define N2FPU_NAME(code) (N2FPU(code).name)
+#define N2FPU_ICODE(code) (N2FPU(code).icode)
+#define N2FPU_FTCODE(code) (N2FPU(code).ftcode)
+#define N2FPU_FINITE_P(code) (N2FPU(code).flags & N2F_FINITE)
+#define N2FPU_UNSAFE_P(code) (N2FPU(code).flags & N2F_UNSAFE)
+#define N2FPU_DOUBLE_P(code) (N2FPU(code).flags & N2F_DF)
+#define N2FPU_DOUBLE_REQUIRED_P(code) (N2FPU(code).flags & N2F_DFREQ)
+
+/* Same as above, but for cases where using only the op part is shorter.  */
+#define N2FPU_OP(op) N2FPU(n2fpu_ ## op)
+#define N2FPU_OP_NAME(op) N2FPU_NAME(n2fpu_ ## op)
+#define N2FPU_OP_ENABLED_P(op) N2FPU_ENABLED_P(n2fpu_ ## op)
+
+/* Export the FPU insn enabled predicate to nios2.md.  */
+bool
+nios2_fpu_insn_enabled (enum n2fpu_code code)
+{
+  return N2FPU_ENABLED_P (code);
+}
+
+/* Return true if COND comparison for mode MODE is enabled under current
+   settings.  */
+
+static bool
+nios2_fpu_compare_enabled (enum rtx_code cond, enum machine_mode mode)
+{
+  if (mode == SFmode)
+    switch (cond) 
+      {
+      case EQ: return N2FPU_OP_ENABLED_P (fcmpeqs);
+      case NE: return N2FPU_OP_ENABLED_P (fcmpnes);
+      case GT: return N2FPU_OP_ENABLED_P (fcmpgts);
+      case GE: return N2FPU_OP_ENABLED_P (fcmpges);
+      case LT: return N2FPU_OP_ENABLED_P (fcmplts);
+      case LE: return N2FPU_OP_ENABLED_P (fcmples);
+      default: break;
+      }
+  else if (mode == DFmode)
+    switch (cond) 
+      {
+      case EQ: return N2FPU_OP_ENABLED_P (fcmpeqd);
+      case NE: return N2FPU_OP_ENABLED_P (fcmpned);
+      case GT: return N2FPU_OP_ENABLED_P (fcmpgtd);
+      case GE: return N2FPU_OP_ENABLED_P (fcmpged);
+      case LT: return N2FPU_OP_ENABLED_P (fcmpltd);
+      case LE: return N2FPU_OP_ENABLED_P (fcmpled);
+      default: break;
+      }
+  return false;
+}
+
+
+/* Stack Layout and Calling Conventions */
+
+#define TOO_BIG_OFFSET(X) ((X) > ((1 << 15) - 1))
+#define TEMP_REG_NUM 8
+
+static void
+save_reg (int regno, unsigned offset)
+{
+  rtx reg = gen_rtx_REG (SImode, regno);
+  rtx addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+			   gen_int_mode (offset, Pmode));
+
+  rtx pattern = gen_rtx_SET (SImode, gen_frame_mem (Pmode, addr), reg);
+  rtx insn = emit_insn (pattern);
+  RTX_FRAME_RELATED_P (insn) = 1;
+}
+
+static void
+restore_reg (int regno, unsigned offset)
+{
+  rtx reg = gen_rtx_REG (SImode, regno);
+  rtx addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+			   gen_int_mode (offset, Pmode));
+
+  rtx pattern = gen_rtx_SET (SImode, reg, gen_frame_mem (Pmode, addr));
+  emit_insn (pattern);
+}
+
+void
+expand_prologue (void)
+{
+  int ix;
+  HOST_WIDE_INT total_frame_size = compute_frame_size ();
+  int sp_offset;	/* offset from base_reg to final stack value.  */
+  int fp_offset;	/* offset from base_reg to final fp value.  */
+  int save_offset;
+  rtx insn;
+  unsigned HOST_WIDE_INT save_mask;
+
+  total_frame_size = compute_frame_size ();
+  if (flag_stack_usage_info)
+    current_function_static_stack_size = total_frame_size;
+
+  /* Decrement the stack pointer */
+  if (TOO_BIG_OFFSET (total_frame_size))
+    {
+      /* We need an intermediary point, this will point at the spill
+	 block.  */
+      insn = emit_insn
+	(gen_add3_insn (stack_pointer_rtx,
+			stack_pointer_rtx,
+			gen_int_mode (cfun->machine->save_regs_offset
+				      - total_frame_size, Pmode)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+
+      fp_offset = 0;
+      sp_offset = -cfun->machine->save_regs_offset;
+    }
+  else if (total_frame_size)
+    {
+      insn = emit_insn (gen_add3_insn (stack_pointer_rtx,
+				       stack_pointer_rtx,
+				       gen_int_mode (-total_frame_size,
+						     Pmode)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+      fp_offset = cfun->machine->save_regs_offset;
+      sp_offset = 0;
+    }
+  else
+    fp_offset = sp_offset = 0;
+
+  if (crtl->limit_stack)
+    emit_insn (gen_stack_overflow_detect_and_trap ());
+
+  save_offset = fp_offset + cfun->machine->save_reg_size;
+  save_mask = cfun->machine->save_mask;
+  
+  for (ix = 32; ix--;)
+    if (save_mask & ((unsigned HOST_WIDE_INT)1 << ix))
+      {
+	save_offset -= 4;
+	save_reg (ix, save_offset);
+      }
+
+  if (frame_pointer_needed)
+    {
+      insn = emit_insn (gen_add3_insn (hard_frame_pointer_rtx,
+				       stack_pointer_rtx,
+				       gen_int_mode (fp_offset, Pmode)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+  if (sp_offset)
+    {
+      rtx sp_adjust
+	= gen_rtx_SET (Pmode, stack_pointer_rtx,
+		       gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+				     gen_int_mode (sp_offset, Pmode)));
+      if (SMALL_INT (sp_offset))
+	insn = emit_insn (sp_adjust);
+      else
+	{
+	  rtx tmp = gen_rtx_REG (Pmode, TEMP_REG_NUM);
+	  emit_insn (gen_rtx_SET (Pmode, tmp, gen_int_mode (sp_offset, Pmode)));
+	  insn = emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
+					   tmp));
+	  /* Attach the sp_adjust as a note indicating what happened.  */
+	  REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR,
+					      sp_adjust, REG_NOTES (insn));
+	}
+      RTX_FRAME_RELATED_P (insn) = 1;
+
+      if (crtl->limit_stack)
+	emit_insn (gen_stack_overflow_detect_and_trap ());
+    }
+
+  /* Load the PIC register if needed.  */
+  if (crtl->uses_pic_offset_table)
+    nios2_load_pic_register ();
+
+  /* If we are profiling, make sure no instructions are scheduled before
+     the call to mcount.  */
+  if (crtl->profile)
+    emit_insn (gen_blockage ());
+}
+
+void
+expand_epilogue (bool sibcall_p)
+{
+  int ix;
+  HOST_WIDE_INT total_frame_size = compute_frame_size ();
+  unsigned HOST_WIDE_INT save_mask;
+  int sp_adjust;
+  int save_offset;
+ 
+  if (!sibcall_p && nios2_can_use_return_insn ())
+    {
+      emit_jump_insn (gen_return ());
+      return;
+    }
+
+  emit_insn (gen_blockage ());
+
+  if (frame_pointer_needed)
+    {
+      /* Recover the stack pointer.  */
+      emit_insn (gen_rtx_SET (Pmode, stack_pointer_rtx,
+			      hard_frame_pointer_rtx));
+      save_offset = 0;
+      sp_adjust = total_frame_size - cfun->machine->save_regs_offset;
+    }
+  else if (TOO_BIG_OFFSET (total_frame_size))
+    {
+      rtx tmp = gen_rtx_REG (Pmode, TEMP_REG_NUM);
+
+      emit_insn
+	(gen_rtx_SET (Pmode, tmp,
+		      gen_int_mode (cfun->machine->save_regs_offset,
+				    Pmode)));
+      emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, tmp));
+      save_offset = 0;
+      sp_adjust = total_frame_size - cfun->machine->save_regs_offset;
+    }
+  else
+    {
+      save_offset = cfun->machine->save_regs_offset;
+      sp_adjust = total_frame_size;
+    }
+  
+  save_mask = cfun->machine->save_mask;
+  save_offset += cfun->machine->save_reg_size;
+  
+  for (ix = 32; ix--;)
+    if (save_mask & ((unsigned HOST_WIDE_INT)1 << ix))
+      {
+	save_offset -= 4;
+	restore_reg (ix, save_offset);
+      }
+
+  if (sp_adjust)
+    emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
+			      gen_int_mode (sp_adjust, Pmode)));
+
+  /* Add in the __builtin_eh_return stack adjustment.  */
+  if (crtl->calls_eh_return)
+    emit_insn (gen_add3_insn (stack_pointer_rtx,
+			      stack_pointer_rtx,
+			      EH_RETURN_STACKADJ_RTX));
+
+  if (!sibcall_p)
+    emit_jump_insn (gen_return_from_epilogue (gen_rtx_REG (Pmode, RA_REGNO)));
+}
+
+/* Implement RETURN_ADDR_RTX.  Note, we do not support moving
+   back to a previous frame.  */
+rtx
+nios2_get_return_address (int count)
+{
+  if (count != 0)
+    return const0_rtx;
+
+  return get_hard_reg_initial_val (Pmode, RA_REGNO);
+}
+
+/* Emit code to change the current function's return address to
+   ADDRESS.  SCRATCH is available as a scratch register, if needed.
+   ADDRESS and SCRATCH are both word-mode GPRs.  */
+void
+nios2_set_return_address (rtx address, rtx scratch)
+{
+  compute_frame_size ();
+  if ((cfun->machine->save_mask >> RA_REGNO) & 1)
+    {
+      unsigned offset = cfun->machine->save_reg_size - 4;
+      rtx base;
+      
+      if (frame_pointer_needed)
+	base = hard_frame_pointer_rtx;
+      else
+	{
+	  base = stack_pointer_rtx;
+	  offset += cfun->machine->save_regs_offset;
+	  
+	  if (TOO_BIG_OFFSET (offset))
+	    {
+	      emit_insn (gen_rtx_SET (Pmode, scratch,
+				      gen_int_mode (offset, Pmode)));
+	      emit_insn (gen_add3_insn (scratch, scratch, base));
+	      base = scratch;
+	      offset = 0;
+	    }
+	}
+      if (offset)
+	base = gen_rtx_PLUS (Pmode, base, gen_int_mode (offset, Pmode));
+      emit_insn (gen_rtx_SET (Pmode, gen_rtx_MEM (Pmode, base), address));
+    }
+  else
+    emit_insn (gen_rtx_SET (Pmode, gen_rtx_REG (Pmode, RA_REGNO), address));
+}
+
+
+
+/* Implement FUNCTION_PROFILER macro.  */
+void
+nios2_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
+{
+  fprintf (file, "\tmov\tr8, ra\n");
+  if (flag_pic)
+    {
+      fprintf (file, "\tnextpc\tr2\n");
+      fprintf (file, "\t1: movhi\tr3, %%hiadj(_GLOBAL_OFFSET_TABLE_ - 1b)\n");
+      fprintf (file, "\taddi\tr3, r3, %%lo(_GLOBAL_OFFSET_TABLE_ - 1b)\n");
+      fprintf (file, "\tadd\tr2, r2, r3\n");
+      fprintf (file, "\tldw\tr2, %%call(_mcount)(r2)\n");
+      fprintf (file, "\tcallr\tr2\n");
+    }
+  else
+    fprintf (file, "\tcall\t_mcount\n");
+  fprintf (file, "\tmov\tra, r8\n");
+}
+
+/* Stack Layout.  */
+static void
+dump_frame_size (FILE *file)
+{
+  fprintf (file, "\t%s Current Frame Info\n", ASM_COMMENT_START);
+
+  fprintf (file, "\t%s total_size = %ld\n", ASM_COMMENT_START,
+           cfun->machine->total_size);
+  fprintf (file, "\t%s var_size = %ld\n", ASM_COMMENT_START,
+           cfun->machine->var_size);
+  fprintf (file, "\t%s args_size = %ld\n", ASM_COMMENT_START,
+           cfun->machine->args_size);
+  fprintf (file, "\t%s save_reg_size = %d\n", ASM_COMMENT_START,
+           cfun->machine->save_reg_size);
+  fprintf (file, "\t%s initialized = %d\n", ASM_COMMENT_START,
+           cfun->machine->initialized);
+  fprintf (file, "\t%s save_regs_offset = %ld\n", ASM_COMMENT_START,
+           cfun->machine->save_regs_offset);
+  fprintf (file, "\t%s is_leaf = %d\n", ASM_COMMENT_START,
+           crtl->is_leaf);
+  fprintf (file, "\t%s frame_pointer_needed = %d\n", ASM_COMMENT_START,
+           frame_pointer_needed);
+  fprintf (file, "\t%s pretend_args_size = %d\n", ASM_COMMENT_START,
+           crtl->args.pretend_args_size);
+
+}
+
+/* Return true if REGNO should be saved in a prologue.  */
+static bool
+save_reg_p (unsigned regno)
+{
+  gcc_assert (GP_REGNO_P (regno));
+  
+  if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
+    return true;
+
+  if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
+    return true;
+
+  if (regno == PIC_OFFSET_TABLE_REGNUM && crtl->uses_pic_offset_table)
+    return true;
+
+  if (regno == RA_REGNO && df_regs_ever_live_p (RA_REGNO))
+    return true;
+
+  return false;
+}
+
+/* Return the bytes needed to compute the frame pointer from the current
+   stack pointer.  */
+static HOST_WIDE_INT
+compute_frame_size (void)
+{
+  unsigned int regno;
+  HOST_WIDE_INT var_size;       /* # of var. bytes allocated.  */
+  HOST_WIDE_INT total_size;     /* # bytes that the entire frame takes up.  */
+  HOST_WIDE_INT save_reg_size;  /* # bytes needed to store callee save regs.  */
+  HOST_WIDE_INT out_args_size;  /* # bytes needed for outgoing args. */
+  unsigned HOST_WIDE_INT save_mask = 0;
+
+  if (cfun->machine->initialized)
+    return cfun->machine->total_size;
+  
+  save_reg_size = 0;
+  var_size = STACK_ALIGN (get_frame_size ());
+  out_args_size = STACK_ALIGN (crtl->outgoing_args_size);
+
+  total_size = var_size + out_args_size;
+
+  /* Calculate space needed for gp registers.  */
+  for (regno = 0; GP_REGNO_P (regno); regno++)
+    if (save_reg_p (regno))
+      {
+	save_mask |= (unsigned HOST_WIDE_INT)1 << regno;
+	save_reg_size += 4;
+      }
+
+  /* If we call eh_return, we need to save the EH data registers.  */
+  if (crtl->calls_eh_return)
+    {
+      unsigned i;
+      unsigned r;
+      
+      for (i = 0; (r = EH_RETURN_DATA_REGNO (i)) != INVALID_REGNUM; i++)
+	if (!(save_mask & (1 << r)))
+	  {
+	    save_mask |= 1 << r;
+	    save_reg_size += 4;
+	  }
+    }
+
+  save_reg_size = STACK_ALIGN (save_reg_size);
+  total_size += save_reg_size;
+
+  total_size += STACK_ALIGN (crtl->args.pretend_args_size);
+
+  /* Save other computed information.  */
+  cfun->machine->save_mask = save_mask;
+  cfun->machine->total_size = total_size;
+  cfun->machine->var_size = var_size;
+  cfun->machine->args_size = out_args_size;
+  cfun->machine->save_reg_size = save_reg_size;
+  cfun->machine->initialized = reload_completed;
+  cfun->machine->save_regs_offset = out_args_size + var_size;
+
+  return total_size;
+}
+
+/* Implement TARGET_CAN_ELIMINATE.  */
+static bool
+nios2_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+  if (to == STACK_POINTER_REGNUM)
+    return !frame_pointer_needed;
+  return true;
+}
+
+/* Implement INITIAL_ELIMINATION_OFFSET macro.  */
+int
+nios2_initial_elimination_offset (int from, int to)
+{
+  int offset;
+
+  compute_frame_size ();
+
+  /* Set OFFSET to the offset from the stack pointer.  */
+  switch (from)
+    {
+    case FRAME_POINTER_REGNUM:
+      offset = cfun->machine->args_size;
+      break;
+
+    case ARG_POINTER_REGNUM:
+      offset = cfun->machine->total_size;
+      offset -= crtl->args.pretend_args_size;
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+    /* If we are asked for the frame pointer offset, then adjust OFFSET
+       by the offset from the frame pointer to the stack pointer.  */
+    if (to == HARD_FRAME_POINTER_REGNUM)
+      offset -= cfun->machine->save_regs_offset;
+
+    return offset;
+}
+
+/* Return nonzero if this function is known to have a null epilogue.
+   This allows the optimizer to omit jumps to jumps if no stack
+   was created.  */
+int
+nios2_can_use_return_insn (void)
+{
+  if (!reload_completed)
+    return 0;
+
+  if (df_regs_ever_live_p (RA_REGNO) || crtl->profile)
+    return 0;
+
+  if (cfun->machine->initialized)
+    return cfun->machine->total_size == 0;
+
+  return compute_frame_size () == 0;
+}
+
+
+
+/* Check and signal some warnings/errors on FPU insn options.  */
+static void
+nios2_custom_check_insns (void)
+{
+  unsigned int i, j;
+  bool errors = false;
+
+  for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
+    if (N2FPU_ENABLED_P (i) && N2FPU_DOUBLE_P (i))
+      {
+	for (j = 0; j < ARRAY_SIZE (nios2_fpu_insn); j++)
+	  if (N2FPU_DOUBLE_REQUIRED_P (j) && ! N2FPU_ENABLED_P (j))
+	    {
+	      error ("switch %<-mcustom-%s%> is required for double precision "
+		     "floating point", N2FPU_NAME (j));
+	      errors = true;
+	    }
+	break;
+      }
+
+  /* Warn if the user has certain exotic operations that won't get used
+     without -funsafe-math-optimizations.  See expand_builtin () in
+     builtins.c.  */
+  if (!flag_unsafe_math_optimizations)
+    for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
+      if (N2FPU_ENABLED_P (i) && N2FPU_UNSAFE_P (i))
+	warning (0, "switch %<-mcustom-%s%> has no effect unless "
+		 "-funsafe-math-optimizations is specified", N2FPU_NAME (i));
+
+  /* Warn if the user is trying to use -mcustom-fmins et. al, that won't
+     get used without -ffinite-math-only.  See fold_builtin_fmin_fmax ()
+     in builtins.c.  */
+  if (!flag_finite_math_only)
+    for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
+      if (N2FPU_ENABLED_P (i) && N2FPU_FINITE_P (i))
+	warning (0, "switch %<-mcustom-%s%> has no effect unless "
+		 "-ffinite-math-only is specified", N2FPU_NAME (i));
+
+  if (errors || custom_code_conflict)
+    fatal_error ("conflicting use of -mcustom switches, target attributes, "
+		 "and/or __builtin_custom_ functions");
+}
+
+static void
+nios2_set_fpu_custom_code (enum n2fpu_code code, int N, bool override_p)
+{
+  if (override_p || N2FPU_N (code) == -1)
+    N2FPU_N (code) = N;
+  nios2_register_custom_code (N, CCS_FPU, (int) code);
+}
+
+static void
+nios2_handle_custom_fpu_cfg (const char *cfg, bool override_p)
+{
+  if (!strcasecmp (cfg, "60-1"))
+    {
+      nios2_set_fpu_custom_code (n2fpu_fmuls, 252, override_p);
+      nios2_set_fpu_custom_code (n2fpu_fadds, 253, override_p);
+      nios2_set_fpu_custom_code (n2fpu_fsubs, 254, override_p);
+      flag_single_precision_constant = 1;
+    }
+  else if (!strcasecmp (cfg, "60-2"))
+    {
+      nios2_set_fpu_custom_code (n2fpu_fmuls, 252, override_p);
+      nios2_set_fpu_custom_code (n2fpu_fadds, 253, override_p);
+      nios2_set_fpu_custom_code (n2fpu_fsubs, 254, override_p);
+      nios2_set_fpu_custom_code (n2fpu_fdivs, 255, override_p);
+      flag_single_precision_constant = 1;
+    }
+  else if (!strcasecmp (cfg, "72-3"))
+    {
+      nios2_set_fpu_custom_code (n2fpu_floatus, 243, override_p);
+      nios2_set_fpu_custom_code (n2fpu_fixsi, 244, override_p);
+      nios2_set_fpu_custom_code (n2fpu_floatis, 245, override_p);
+      nios2_set_fpu_custom_code (n2fpu_fcmpgts, 246, override_p);
+      nios2_set_fpu_custom_code (n2fpu_fcmples, 249, override_p);
+      nios2_set_fpu_custom_code (n2fpu_fcmpeqs, 250, override_p);
+      nios2_set_fpu_custom_code (n2fpu_fcmpnes, 251, override_p);
+      nios2_set_fpu_custom_code (n2fpu_fmuls, 252, override_p);
+      nios2_set_fpu_custom_code (n2fpu_fadds, 253, override_p);
+      nios2_set_fpu_custom_code (n2fpu_fsubs, 254, override_p);
+      nios2_set_fpu_custom_code (n2fpu_fdivs, 255, override_p);
+      flag_single_precision_constant = 1;
+    }
+  else
+    warning (0, "ignoring unrecognized switch %<-mcustom-fpu-cfg%> value %<%s%>",
+	     cfg);
+
+  /* Guard against errors in the standard configurations.  */
+  nios2_custom_check_insns ();
+}
+
+/* Check individual FPU insn options, and register custom code.  */
+static void
+nios2_handle_custom_fpu_insn_option (int fpu_insn_index)
+{
+  int param = N2FPU_N (fpu_insn_index);
+
+  if (0 <= param && param <= 255)
+    nios2_register_custom_code (param, CCS_FPU, fpu_insn_index);
+
+  /* Valid values are 0-255, but also allow -1 so that the
+     -mno-custom-<opt> switches work.  */
+  else if (param != -1)
+    error ("switch %<-mcustom-%s%> value %d must be between 0 and 255",
+	   N2FPU_NAME (fpu_insn_index), param);
+}
+
+/* Implement TARGET_OPTION_OVERRIDE.  */
+static void
+nios2_option_override (void)
+{
+  unsigned int i;
+
+#ifdef SUBTARGET_OVERRIDE_OPTIONS
+  SUBTARGET_OVERRIDE_OPTIONS;
+#endif
+
+  /* Check for unsupported options.  */
+  if (flag_pic && !TARGET_LINUX_ABI)
+    error ("position-independent code requires the Linux ABI");
+
+  /* Function to allocate machine-dependent function status.  */
+  init_machine_status = &nios2_init_machine_status;
+
+  nios2_section_threshold
+    = (global_options_set.x_g_switch_value
+       ? g_switch_value : NIOS2_DEFAULT_GVALUE);
+
+  /* If we don't have mul, we don't have mulx either!  */
+  if (!TARGET_HAS_MUL && TARGET_HAS_MULX)
+    target_flags &= ~MASK_HAS_MULX;
+
+  /* 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.
+
+     This behavior of prioritization of individual -mcustom-<insn>=
+     options before the -mcustom-fpu-cfg= switch is maintained for
+     compatibility.  */
+  if (nios2_custom_fpu_cfg_string && *nios2_custom_fpu_cfg_string)
+    nios2_handle_custom_fpu_cfg (nios2_custom_fpu_cfg_string, false);
+
+  /* Handle options for individual FPU insns.  */
+  for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
+    nios2_handle_custom_fpu_insn_option (i);
+
+  nios2_custom_check_insns ();
+
+  /* Save the initial options in case the user does function specific options */
+  target_option_default_node = target_option_current_node
+    = build_target_option_node ();
+}
+
+/* Allocate a chunk of memory for per-function machine-dependent data.  */
+static struct machine_function *
+nios2_init_machine_status (void)
+{
+  return ggc_alloc_cleared_machine_function ();
+}
+
+
+/* Return true if CST is a constant within range of movi/movui/movhi.  */
+static bool
+nios2_simple_const_p (const_rtx cst)
+{
+  HOST_WIDE_INT val = INTVAL (cst);
+  return (SMALL_INT (val) || SMALL_INT_UNSIGNED (val) || UPPER16_INT (val));
+}
+
+/* Compute a (partial) cost for rtx X.  Return true if the complete
+   cost has been computed, and false if subexpressions should be
+   scanned.  In either case, *TOTAL contains the cost result.  */
+static bool
+nios2_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
+		 int opno ATTRIBUTE_UNUSED,
+		 int *total, bool speed ATTRIBUTE_UNUSED)
+{
+  switch (code)
+    {
+      case CONST_INT:
+        if (INTVAL (x) == 0)
+          {
+            *total = COSTS_N_INSNS (0);
+            return true;
+          }
+        else if (nios2_simple_const_p (x))
+          {
+            *total = COSTS_N_INSNS (2);
+            return true;
+          }
+        else
+          {
+            *total = COSTS_N_INSNS (4);
+            return true;
+          }
+
+      case LABEL_REF:
+      case SYMBOL_REF:
+        /* ??? gp relative stuff will fit in here.  */
+        /* fall through */
+      case CONST:
+      case CONST_DOUBLE:
+        {
+          *total = COSTS_N_INSNS (4);
+          return true;
+        }
+
+      case AND:
+	{
+	  /* Recognize 'nor' insn pattern.  */
+	  if (GET_CODE (XEXP (x, 0)) == NOT
+	      && GET_CODE (XEXP (x, 1)) == NOT)
+	    {
+	      *total = COSTS_N_INSNS (1);
+	      return true;
+	    }
+	  return false;
+	}
+
+      case MULT:
+        {
+          *total = COSTS_N_INSNS (1);
+          return false;
+        }
+      case SIGN_EXTEND:
+        {
+          *total = COSTS_N_INSNS (3);
+          return false;
+        }
+      case ZERO_EXTEND:
+        {
+          *total = COSTS_N_INSNS (1);
+          return false;
+        }
+
+      default:
+        return false;
+    }
+}
+
+/* Implement TARGET_PREFERRED_RELOAD_CLASS.  */
+
+static reg_class_t
+nios2_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, reg_class_t regclass)
+{
+  return (regclass == NO_REGS ? GENERAL_REGS : regclass);
+}
+
+/* Implement TARGET_CANNOT_FORCE_CONST_MEM.  */
+
+static bool
+nios2_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+{
+  return nios2_legitimate_constant_p (mode, x) == false;
+}
+
+/* Emit a call to __tls_get_addr.  TI is the argument to this function.
+   RET is an RTX for the return value location.  The entire insn sequence
+   is returned.  */
+static GTY(()) rtx nios2_tls_symbol;
+
+static rtx
+nios2_call_tls_get_addr (rtx ti)
+{
+  rtx arg = gen_rtx_REG (Pmode, FIRST_ARG_REGNO);
+  rtx ret = gen_rtx_REG (Pmode, FIRST_RETVAL_REGNO);
+  rtx fn, insn;
+  
+  if (!nios2_tls_symbol)
+    nios2_tls_symbol = init_one_libfunc ("__tls_get_addr");
+
+  emit_insn (gen_rtx_SET (Pmode, arg, ti));
+  fn = gen_rtx_MEM (QImode, nios2_tls_symbol);
+  insn = emit_call_insn (gen_call_value (ret, fn, const0_rtx));
+  RTL_CONST_CALL_P (insn) = 1;
+  use_reg (&CALL_INSN_FUNCTION_USAGE (insn), ret);
+  use_reg (&CALL_INSN_FUNCTION_USAGE (insn), arg);
+
+  return ret;
+}
+
+static rtx
+nios2_unspec_address (rtx loc, rtx base_reg, int unspec)
+{
+  rtx unspec_offset =
+    gen_rtx_CONST (Pmode, gen_rtx_UNSPEC (Pmode, gen_rtvec (1, loc),
+					  unspec));
+  return gen_rtx_PLUS (Pmode, base_reg, unspec_offset);
+}
+
+static rtx
+nios2_got_address (rtx loc, int unspec)
+{
+  crtl->uses_pic_offset_table = 1;
+  return nios2_unspec_address (loc, pic_offset_table_rtx, unspec);
+}
+
+/* Generate the code to access LOC, a thread local SYMBOL_REF.  The
+   return value will be a valid address and move_operand (either a REG
+   or a LO_SUM).  */
+static rtx
+nios2_legitimize_tls_address (rtx loc)
+{
+  rtx tmp, mem, tp;
+  enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
+
+  switch (model)
+    {
+    case TLS_MODEL_GLOBAL_DYNAMIC:
+      tmp = gen_reg_rtx (Pmode);
+      emit_move_insn (tmp, nios2_got_address (loc, UNSPEC_ADD_TLS_GD));
+      return nios2_call_tls_get_addr (tmp);
+
+    case TLS_MODEL_LOCAL_DYNAMIC:
+      tmp = gen_reg_rtx (Pmode);
+      emit_move_insn (tmp, nios2_got_address (loc, UNSPEC_ADD_TLS_LDM));
+      return nios2_unspec_address (loc, nios2_call_tls_get_addr (tmp),
+				   UNSPEC_ADD_TLS_LDO);
+
+    case TLS_MODEL_INITIAL_EXEC:
+      tmp = gen_reg_rtx (Pmode);
+      mem = gen_const_mem (Pmode, nios2_got_address (loc, UNSPEC_LOAD_TLS_IE));
+      emit_move_insn (tmp, mem);
+      tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
+      return gen_rtx_PLUS (Pmode, tp, tmp);
+
+    case TLS_MODEL_LOCAL_EXEC:
+      tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
+      return nios2_unspec_address (loc, tp, UNSPEC_ADD_TLS_LE);
+
+    default:
+      gcc_unreachable ();
+    }
+}
+
+int
+nios2_emit_move_sequence (rtx *operands, enum machine_mode mode)
+{
+  rtx to = operands[0];
+  rtx from = operands[1];
+
+  if (!register_operand (to, mode) && !reg_or_0_operand (from, mode))
+    {
+      gcc_assert (can_create_pseudo_p ());
+      from = copy_to_mode_reg (mode, from);
+    }
+
+  if (GET_CODE (from) == SYMBOL_REF || GET_CODE (from) == LABEL_REF
+      || GET_CODE (from) == CONST)
+    from = nios2_legitimize_constant_address (from);
+
+  operands[0] = to;
+  operands[1] = from;
+  return 0;
+}
+
+/* Divide Support */
+
+/*
+  If -O3 is used, we want to output a table lookup for
+  divides between small numbers (both num and den >= 0
+  and < 0x10).  The overhead of this method in the worse
+  case is 40 bytes in the text section (10 insns) and
+  256 bytes in the data section.  Additional divides do
+  not incur additional penalties in the data section.
+
+  Code speed is improved for small divides by about 5x
+  when using this method in the worse case (~9 cycles
+  vs ~45).  And in the worse case divides not within the
+  table are penalized by about 10% (~5 cycles vs ~45).
+  However in the typical case the penalty is not as bad
+  because doing the long divide in only 45 cycles is
+  quite optimistic.
+
+  ??? It would be nice to have some benchmarks other
+  than Dhrystone to back this up.
+
+  This bit of expansion is to create this instruction
+  sequence as rtl.
+        or      $8, $4, $5
+        slli    $9, $4, 4
+        cmpgeui $3, $8, 16
+        beq     $3, $0, .L3
+        or      $10, $9, $5
+        add     $12, $11, divide_table
+        ldbu    $2, 0($12)
+        br      .L1
+.L3:
+        call    slow_div
+.L1:
+#       continue here with result in $2
+
+  ??? Ideally I would like the emit libcall block to contain
+  all of this code, but I don't know how to do that.  What it
+  means is that if the divide can be eliminated, it may not
+  completely disappear.
+
+  ??? The __divsi3_table label should ideally be moved out
+  of this block and into a global.  If it is placed into the
+  sdata section we can save even more cycles by doing things
+  gp relative.
+*/
+int
+nios2_emit_expensive_div (rtx *operands, enum machine_mode mode)
+{
+  rtx or_result, shift_left_result;
+  rtx lookup_value;
+  rtx lab1, lab3;
+  rtx insns;
+  rtx libfunc;
+  rtx final_result;
+  rtx tmp;
+  rtx table;
+
+  /* It may look a little generic, but only SImode
+     is supported for now.  */
+  gcc_assert (mode == SImode);
+  libfunc = optab_libfunc (sdiv_optab, SImode);
+
+  lab1 = gen_label_rtx ();
+  lab3 = gen_label_rtx ();
+
+  or_result = expand_simple_binop (SImode, IOR,
+                                   operands[1], operands[2],
+                                   0, 0, OPTAB_LIB_WIDEN);
+
+  emit_cmp_and_jump_insns (or_result, GEN_INT (15), GTU, 0,
+                           GET_MODE (or_result), 0, lab3);
+  JUMP_LABEL (get_last_insn ()) = lab3;
+
+  shift_left_result = expand_simple_binop (SImode, ASHIFT,
+                                           operands[1], GEN_INT (4),
+                                           0, 0, OPTAB_LIB_WIDEN);
+
+  lookup_value = expand_simple_binop (SImode, IOR,
+                                      shift_left_result, operands[2],
+                                      0, 0, OPTAB_LIB_WIDEN);
+  table = gen_rtx_PLUS (SImode, lookup_value,
+			gen_rtx_SYMBOL_REF (SImode, "__divsi3_table"));
+  convert_move (operands[0], gen_rtx_MEM (QImode, table), 1);
+
+  tmp = emit_jump_insn (gen_jump (lab1));
+  JUMP_LABEL (tmp) = lab1;
+  emit_barrier ();
+
+  emit_label (lab3);
+  LABEL_NUSES (lab3) = 1;
+
+  start_sequence ();
+  final_result = emit_library_call_value (libfunc, NULL_RTX,
+                                          LCT_CONST, SImode, 2,
+                                          operands[1], SImode,
+                                          operands[2], SImode);
+
+  insns = get_insns ();
+  end_sequence ();
+  emit_libcall_block (insns, operands[0], final_result,
+                      gen_rtx_DIV (SImode, operands[1], operands[2]));
+
+  emit_label (lab1);
+  LABEL_NUSES (lab1) = 1;
+  return 1;
+}
+
+/* The function with address *ADDR is being called.  If the address
+   needs to be loaded from the GOT, emit the instruction to do so and
+   update *ADDR to point to the rtx for the loaded value.  */
+void
+nios2_adjust_call_address (rtx *call_op)
+{
+  rtx addr;
+  gcc_assert (MEM_P (*call_op));
+  addr = XEXP (*call_op, 0);
+  if (flag_pic && CONSTANT_P (addr))
+    {
+      rtx reg = gen_reg_rtx (Pmode);
+      emit_move_insn (reg, nios2_load_pic_address (addr, UNSPEC_PIC_CALL_SYM));
+      XEXP (*call_op, 0) = reg;
+    }
+}
+
+
+
+/* Branches/Compares.  */
+
+/* Return in *ALT_CODE and *ALT_OP, an alternate equivalent constant
+   comparision, e.g. >= 1 into > 0.  */
+static void
+nios2_alternate_compare_const (enum rtx_code code, rtx op,
+			       enum rtx_code *alt_code, rtx *alt_op,
+			       enum machine_mode mode)
+{
+  HOST_WIDE_INT opval = INTVAL (op);
+  enum rtx_code scode = signed_condition (code);
+  *alt_code = ((code == EQ || code == NE) ? code
+	       /* The required conversion between [>,>=] and [<,<=] is captured
+		  by a reverse + swap of condition codes.  */
+	       : reverse_condition (swap_condition (code)));
+  *alt_op = ((scode == LT || scode == GE) ? gen_int_mode (opval - 1, mode)
+	     : (scode == LE || scode == GT) ? gen_int_mode (opval + 1, mode)
+	     : gen_int_mode (opval, mode));
+}
+
+/* Return true if the constant comparison is supported by nios2.  */
+static bool
+nios2_valid_compare_const_p (enum rtx_code code, rtx op)
+{
+  switch (code)
+    {
+    case EQ: case NE: case GE: case LT:
+      return SMALL_INT (INTVAL (op));
+    case GEU: case LTU:
+      return SMALL_INT_UNSIGNED (INTVAL (op));
+    default:
+      return false;
+    }
+}
+
+/* Return true if compares in MODE is supported, mainly for floating-point
+   modes.  */
+bool
+nios2_supported_compare_p (enum machine_mode mode)
+{
+  switch (mode)
+    {
+    case SFmode:
+      return (N2FPU_OP_ENABLED_P (fcmpeqs) && N2FPU_OP_ENABLED_P (fcmpnes)
+	      && (N2FPU_OP_ENABLED_P (fcmplts) || N2FPU_OP_ENABLED_P (fcmpgts))
+	      && (N2FPU_OP_ENABLED_P (fcmpges) || N2FPU_OP_ENABLED_P (fcmples)));
+
+    case DFmode:
+      return (N2FPU_OP_ENABLED_P (fcmpeqd) && N2FPU_OP_ENABLED_P (fcmpned)
+	      && (N2FPU_OP_ENABLED_P (fcmpltd) || N2FPU_OP_ENABLED_P (fcmpgtd))
+	      && (N2FPU_OP_ENABLED_P (fcmpged) || N2FPU_OP_ENABLED_P (fcmpled)));
+    default:
+      return true;
+    }
+}
+
+/* Checks and modifies the comparison in *CMP, *OP1, and *OP2 into valid
+   nios2 supported form. Returns true if success.  */
+bool
+nios2_validate_compare (enum machine_mode mode, rtx *cmp, rtx *op1, rtx *op2)
+{
+  enum rtx_code code = GET_CODE (*cmp);
+  enum rtx_code alt_code;
+  rtx alt_op2;
+
+  if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+    {
+      if (nios2_fpu_compare_enabled (code, mode))
+	{
+	  *op2 = force_reg (mode, *op2);
+	  goto rebuild_cmp;
+	}
+      else
+	{
+	  enum rtx_code rev_code = swap_condition (code);
+	  if (nios2_fpu_compare_enabled (rev_code, mode))
+	    {
+	      rtx t = *op1; *op1 = *op2; *op2 = t;
+	      code = rev_code;
+	      goto rebuild_cmp;
+	    }
+	  else
+	    return false;
+	}
+    }
+
+  if (!reg_or_0_operand (*op2, mode))
+    {
+      /* Create alternate constant compare.  */
+      nios2_alternate_compare_const (code, *op2, &alt_code, &alt_op2, mode);
+
+      /* If alterate op2 is zero(0), we can use it directly, possibly
+	 swapping the compare code.  */
+      if (alt_op2 == const0_rtx)
+	{
+	  code = alt_code;
+	  *op2 = alt_op2;
+	  goto check_rebuild_cmp;
+	}
+
+      /* Check if either constant compare can be used.  */
+      if (nios2_valid_compare_const_p (code, *op2))
+	return true;
+      else if (nios2_valid_compare_const_p (alt_code, alt_op2))
+	{
+	  code = alt_code;
+	  *op2 = alt_op2;
+	  goto rebuild_cmp;
+	}
+
+      /* We have to force op2 into a register now. Try to pick one
+	 with a lower cost.  */
+      if (! nios2_simple_const_p (*op2)
+	  && nios2_simple_const_p (alt_op2))
+	{
+	  code = alt_code;
+	  *op2 = alt_op2;
+	}
+      *op2 = force_reg (SImode, *op2);
+    }
+ check_rebuild_cmp:
+  if (code == GT || code == GTU || code == LE || code == LEU)
+    {
+      rtx t = *op1; *op1 = *op2; *op2 = t;
+      code = swap_condition (code);
+    }
+ rebuild_cmp:
+  *cmp = gen_rtx_fmt_ee (code, mode, *op1, *op2);
+  return true;
+}
+
+
+/* Addressing Modes.  */
+
+/* Implement TARGET_LEGITIMATE_CONSTANT_P.  */
+static bool
+nios2_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+{
+  rtx base, offset;
+  split_const (x, &base, &offset);
+  return (GET_CODE (base) != SYMBOL_REF || !SYMBOL_REF_TLS_MODEL (base));
+}
+
+/* Return true if register REGNO is a valid base register.
+   STRICT_P is true if REG_OK_STRICT is in effect.  */
+
+bool
+nios2_regno_ok_for_base_p (int regno, bool strict_p)
+{
+  if (!HARD_REGISTER_NUM_P (regno))
+    {
+      if (!strict_p)
+	return true;
+
+      if (!reg_renumber)
+	return false;
+
+      regno = reg_renumber[regno];
+    }
+
+  /* The fake registers will be eliminated to either the stack or
+     hard frame pointer, both of which are usually valid base registers.
+     Reload deals with the cases where the eliminated form isn't valid.  */
+  return (GP_REGNO_P (regno)
+	  || regno == FRAME_POINTER_REGNUM
+	  || regno == ARG_POINTER_REGNUM);
+}
+
+/* Return true if register REGNO is a valid index register.
+   STRICT_P is true if REG_OK_STRICT is in effect.  */
+
+bool
+nios2_regno_ok_for_index_p (int regno, bool strict_p)
+{
+  if (!HARD_REGISTER_NUM_P (regno))
+    {
+      if (!strict_p)
+	return true;
+
+      if (!reg_renumber)
+	return false;
+
+      regno = reg_renumber[regno];
+    }
+  return GP_REGNO_P (regno);
+}
+
+/* Return true if the address expression formed by BASE + OFFSET is
+   valid.  */
+static bool
+nios2_valid_addr_expr_p (rtx base, rtx offset, bool strict_p)
+{
+  if (!strict_p && GET_CODE (base) == SUBREG)
+    base = SUBREG_REG (base);
+  return (REG_P (base)
+	  && nios2_regno_ok_for_base_p (REGNO (base), strict_p)
+	  && (offset == NULL_RTX
+	      || const_arith_operand (offset, Pmode)
+	      || nios2_unspec_reloc_p (offset)));
+}
+
+/* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
+static bool
+nios2_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+			    rtx operand, bool strict_p)
+{
+  bool ret_val = false;
+
+  switch (GET_CODE (operand))
+    {
+      /* Direct.  */
+    case SYMBOL_REF:
+      if (SYMBOL_REF_TLS_MODEL (operand))
+	break;
+      
+      if (SYMBOL_REF_IN_NIOS2_SMALL_DATA_P (operand))
+        {
+          ret_val = true;
+          break;
+        }
+      /* Else, fall through.  */
+    case LABEL_REF:
+    case CONST_INT:
+    case CONST:
+    case CONST_DOUBLE:
+      /* ??? In here I need to add gp addressing.  */
+      ret_val = false;
+
+      break;
+
+      /* Register indirect.  */
+    case REG:
+      ret_val = nios2_regno_ok_for_base_p (REGNO (operand), strict_p);
+      break;
+
+      /* Register indirect with displacement.  */
+    case PLUS:
+      {
+        rtx op0 = XEXP (operand, 0);
+        rtx op1 = XEXP (operand, 1);
+
+	ret_val = (nios2_valid_addr_expr_p (op0, op1, strict_p)
+		   || nios2_valid_addr_expr_p (op1, op0, strict_p));
+      }
+      break;
+
+    default:
+      ret_val = false;
+      break;
+    }
+  return ret_val;
+}
+
+/* Return true if EXP should be placed in the small data section.  */
+static bool
+nios2_in_small_data_p (const_tree exp)
+{
+  /* We want to merge strings, so we never consider them small data.  */
+  if (TREE_CODE (exp) == STRING_CST)
+    return false;
+
+  if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
+    {
+      const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp));
+      /* ??? these string names need moving into
+         an array in some header file */
+      if (nios2_section_threshold > 0
+          && (strcmp (section, ".sbss") == 0
+              || strncmp (section, ".sbss.", 6) == 0
+              || strcmp (section, ".sdata") == 0
+              || strncmp (section, ".sdata.", 7) == 0))
+        return true;
+    }
+  else if (TREE_CODE (exp) == VAR_DECL)
+    {
+      HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
+
+      /* 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 && (unsigned HOST_WIDE_INT)size <= nios2_section_threshold)
+        return true;
+    }
+
+  return false;
+}
+
+/* Implement TARGET_ENCODE_SECTION_INFO.  */
+
+static void
+nios2_encode_section_info (tree decl, rtx rtl, int first)
+{
+  rtx symbol;
+  int flags;
+
+  default_encode_section_info (decl, rtl, first);
+
+  /* Careful not to prod global register variables.  */
+  if (GET_CODE (rtl) != MEM)
+    return;
+  symbol = XEXP (rtl, 0);
+  if (GET_CODE (symbol) != SYMBOL_REF)
+    return;
+
+  flags = SYMBOL_REF_FLAGS (symbol);
+
+  /* We don't want weak variables to be addressed with gp in case they end up 
+     with value 0 which is not within 2^15 of $gp.  */
+  if (DECL_P (decl) && DECL_WEAK (decl))
+    flags |= SYMBOL_FLAG_WEAK_DECL;
+
+  SYMBOL_REF_FLAGS (symbol) = flags;
+}
+
+/* Implement TARGET_SECTION_TYPE_FLAGS.  */
+
+static unsigned int
+nios2_section_type_flags (tree decl, const char *name, int reloc)
+{
+  unsigned int flags;
+
+  flags = default_section_type_flags (decl, name, reloc);
+
+  if (strcmp (name, ".sbss") == 0
+      || strncmp (name, ".sbss.", 6) == 0
+      || strcmp (name, ".sdata") == 0
+      || strncmp (name, ".sdata.", 7) == 0)
+    flags |= SECTION_SMALL;
+
+  return flags;
+}
+
+
+/* Position Independent Code related.  */
+
+/* Emit code to load the PIC register.  */
+static void
+nios2_load_pic_register (void)
+{
+  rtx tmp = gen_rtx_REG (Pmode, TEMP_REG_NUM);
+
+  emit_insn (gen_load_got_register (pic_offset_table_rtx, tmp));
+  emit_insn (gen_add3_insn (pic_offset_table_rtx, pic_offset_table_rtx, tmp));
+}
+
+/* Generate a PIC address as a MEM rtx.  */
+static rtx
+nios2_load_pic_address (rtx sym, int unspec)
+{
+  rtx gotaddr = nios2_got_address (sym, unspec);
+  return gen_const_mem (Pmode, gotaddr);
+}
+
+/* Nonzero if the constant value X is a legitimate general operand
+   when generating PIC code.  It is given that flag_pic is on and
+   that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */
+bool
+nios2_legitimate_pic_operand_p (rtx x)
+{
+  return ! (GET_CODE (x) == SYMBOL_REF
+	    || GET_CODE (x) == LABEL_REF || GET_CODE (x) == CONST);
+}
+
+/* Return TRUE if X is a thread-local symbol.  */
+static bool
+nios2_tls_symbol_p (rtx x)
+{
+  return (TARGET_HAVE_TLS && GET_CODE (x) == SYMBOL_REF
+	  && SYMBOL_REF_TLS_MODEL (x) != 0);
+}
+
+/* Legitimize addresses that are CONSTANT_P expressions.  */
+static rtx
+nios2_legitimize_constant_address (rtx addr)
+{
+  rtx base, offset;
+  split_const (addr, &base, &offset);
+
+  if (nios2_tls_symbol_p (base))
+    base = nios2_legitimize_tls_address (base);
+  else if (flag_pic)
+    base = nios2_load_pic_address (base, UNSPEC_PIC_SYM);
+  else
+    return addr;
+
+  if (offset != const0_rtx)
+    {
+      gcc_assert (can_create_pseudo_p ());
+      return gen_rtx_PLUS (Pmode, force_reg (Pmode, base),
+			   (CONST_INT_P (offset)
+			    ? (SMALL_INT (INTVAL (offset))
+			       ? offset : force_reg (Pmode, offset))
+			    : offset));
+    }
+  return base;
+}
+
+/* Implement TARGET_LEGITIMIZE_ADDRESS.  */
+static rtx
+nios2_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
+			  enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  if (CONSTANT_P (x))
+    return nios2_legitimize_constant_address (x);
+
+  /* For the TLS LE (Local Exec) model, the compiler may try to
+     combine constant offsets with unspec relocs, creating address RTXs
+     looking like this:
+     (plus:SI (reg:SI 23 r23)
+              (const:SI
+                (plus:SI
+                  (unspec:SI [(symbol_ref:SI ("var"))] UNSPEC_ADD_TLS_LE)
+                  (const_int 48 [0x30]))))
+
+     This usually happens when 'var' is a thread-local struct variable,
+     and access of a field in var causes the addend.
+
+     We typically want this combining, so transform the above into this
+     form, which is allowed:
+     (plus:SI (reg:SI 23 r23)
+              (const:SI
+                (unspec:SI
+                  [(const:SI
+                     (plus:SI (symbol_ref:SI ("var"))
+                              (const_int 48 [0x30])))] UNSPEC_ADD_TLS_LE)))
+
+     Which will be output as '%tls_le(var+48)(r23)' in assembly.  */
+  if (GET_CODE (x) == PLUS
+      && GET_CODE (XEXP (x, 0)) == REG
+      && GET_CODE (XEXP (x, 1)) == CONST)
+    {
+      rtx unspec, offset, reg = XEXP (x, 0);
+      split_const (XEXP (x, 1), &unspec, &offset);
+      if (GET_CODE (unspec) == UNSPEC
+	  && nios2_unspec_reloc_name (XINT (unspec, 1)) != NULL
+	  && offset != const0_rtx)
+	{
+	  unspec = copy_rtx (unspec);
+	  XVECEXP (unspec, 0, 0)
+	    = plus_constant (Pmode, XVECEXP (unspec, 0, 0), INTVAL (offset));
+	  x = gen_rtx_PLUS (Pmode, reg, gen_rtx_CONST (Pmode, unspec));
+	}
+    }
+
+  return x;
+}
+
+
+/* Output assembly language related definitions.  */
+
+/* Print the operand OP to file stream
+   FILE modified by LETTER. LETTER
+   can be one of:
+     i: print "i" if OP is an immediate, except 0
+     o: print "io" if OP is volatile
+
+     z: for const0_rtx print $0 instead of 0
+     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
+     R: prints reverse condition.  */
+
+static void
+nios2_print_operand (FILE *file, rtx op, int letter)
+{
+
+  switch (letter)
+    {
+    case 'i':
+      if (CONSTANT_P (op) && (op != const0_rtx))
+        fprintf (file, "i");
+      return;
+
+    case 'o':
+      if (GET_CODE (op) == MEM
+	  && ((MEM_VOLATILE_P (op) && TARGET_BYPASS_CACHE_VOLATILE)
+	      || TARGET_BYPASS_CACHE))
+        fprintf (file, "io");
+      return;
+
+    default:
+      break;
+    }
+
+  if (comparison_operator (op, VOIDmode))
+    {
+      enum rtx_code cond = GET_CODE (op);
+      if (letter == 0)
+	{
+	  fprintf (file, "%s", GET_RTX_NAME (cond));
+	  return;
+	}
+      if (letter == 'R')
+	{
+	  fprintf (file, "%s", GET_RTX_NAME (reverse_condition (cond)));
+	  return;
+	}
+    }
+
+  switch (GET_CODE (op))
+    {
+    case REG:
+      if (letter == 0 || letter == 'z')
+        {
+          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')
+        {
+          fprintf (file, "zero");
+          return;
+        }
+      else if (letter == 'U')
+        {
+          HOST_WIDE_INT val = INTVAL (op);
+          rtx new_op;
+          val = (val / 65536) & 0xFFFF;
+          new_op = gen_int_mode (val, SImode);
+          output_addr_const (file, new_op);
+          return;
+        }
+      /* Else, fall through.  */
+
+    case CONST:
+    case LABEL_REF:
+    case SYMBOL_REF:
+    case CONST_DOUBLE:
+      if (letter == 0 || letter == 'z')
+        {
+          output_addr_const (file, op);
+          return;
+        }
+      else if (letter == 'H')
+        {
+          fprintf (file, "%%hiadj(");
+          output_addr_const (file, op);
+          fprintf (file, ")");
+          return;
+        }
+      else if (letter == 'L')
+        {
+          fprintf (file, "%%lo(");
+          output_addr_const (file, op);
+          fprintf (file, ")");
+          return;
+        }
+      break;
+
+    case SUBREG:
+    case MEM:
+      if (letter == 0)
+        {
+          output_address (op);
+          return;
+        }
+      break;
+
+    case CODE_LABEL:
+      if (letter == 0)
+        {
+          output_addr_const (file, op);
+          return;
+        }
+      break;
+
+    default:
+      break;
+    }
+
+  fprintf (stderr, "Missing way to print (%c) ", letter);
+  debug_rtx (op);
+  gcc_unreachable ();
+}
+
+/* Return true if this is a GP-relative accessible reference.  */
+static bool
+gprel_constant_p (rtx op)
+{
+  if (GET_CODE (op) == SYMBOL_REF
+      && SYMBOL_REF_IN_NIOS2_SMALL_DATA_P (op))
+    return true;
+  else if (GET_CODE (op) == CONST
+           && GET_CODE (XEXP (op, 0)) == PLUS)
+    return gprel_constant_p (XEXP (XEXP (op, 0), 0));
+
+  return false;
+}
+
+/* Return the name string for a supported unspec reloc offset  */
+static const char*
+nios2_unspec_reloc_name (int unspec)
+{
+  switch (unspec)
+    {
+    case UNSPEC_PIC_SYM:
+      return "got";
+    case UNSPEC_PIC_CALL_SYM:
+      return "call";
+    case UNSPEC_LOAD_TLS_IE:
+      return "tls_ie";
+    case UNSPEC_ADD_TLS_LE:
+      return "tls_le";
+    case UNSPEC_ADD_TLS_GD:
+      return "tls_gd";
+    case UNSPEC_ADD_TLS_LDM:
+      return "tls_ldm";
+    case UNSPEC_ADD_TLS_LDO:
+      return "tls_ldo";
+    default:
+      return NULL;
+    }
+}
+
+/* Return true for conforming unspec relocations. Also used in
+   constraints.md and predicates.md.  */
+bool
+nios2_unspec_reloc_p (rtx op)
+{
+  return (GET_CODE (op) == CONST
+	  && GET_CODE (XEXP (op, 0)) == UNSPEC
+	  && nios2_unspec_reloc_name (XINT (XEXP (op, 0), 1)) != NULL);
+}
+
+/* Implement TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA.  */
+static bool
+nios2_output_addr_const_extra (FILE *file, rtx op)
+{
+  const char *name;
+  gcc_assert (GET_CODE (op) == UNSPEC);
+
+  /* Support for printing out const unspec relocations.  */
+  name = nios2_unspec_reloc_name (XINT (op, 1));
+  if (name)
+    {
+      fprintf (file, "%%%s(", name);
+      output_addr_const (file, XVECEXP (op, 0, 0));
+      fprintf (file, ")");
+      return true;
+    }
+  return false;
+}
+
+/* Implement TARGET_PRINT_OPERAND_ADDRESS.  */
+static void
+nios2_print_operand_address (FILE *file, rtx op)
+{
+  switch (GET_CODE (op))
+    {
+    case CONST:
+    case CONST_INT:
+    case LABEL_REF:
+    case CONST_DOUBLE:
+    case SYMBOL_REF:
+      if (gprel_constant_p (op))
+        {
+          fprintf (file, "%%gprel(");
+          output_addr_const (file, op);
+          fprintf (file, ")(%s)", reg_names[GP_REGNO]);
+          return;
+        }
+
+      break;
+
+    case PLUS:
+      {
+        rtx op0 = XEXP (op, 0);
+        rtx op1 = XEXP (op, 1);
+
+        if (REG_P (op0) && CONSTANT_P (op1))
+          {
+            output_addr_const (file, op1);
+            fprintf (file, "(%s)", reg_names[REGNO (op0)]);
+            return;
+          }
+        else if (REG_P (op1) && CONSTANT_P (op0))
+          {
+            output_addr_const (file, op0);
+            fprintf (file, "(%s)", reg_names[REGNO (op1)]);
+            return;
+          }
+      }
+      break;
+
+    case REG:
+      fprintf (file, "0(%s)", reg_names[REGNO (op)]);
+      return;
+
+    case MEM:
+      {
+        rtx base = XEXP (op, 0);
+        nios2_print_operand_address (file, base);
+        return;
+      }
+    default:
+      break;
+    }
+
+  fprintf (stderr, "Missing way to print address\n");
+  debug_rtx (op);
+  gcc_unreachable ();
+}
+
+/* Implement TARGET_ASM_OUTPUT_DWARF_DTPREL.  */
+static void
+nios2_output_dwarf_dtprel (FILE *file, int size, rtx x)
+{
+  gcc_assert (size == 4);
+  fprintf (file, "\t.4byte\t%%tls_ldo(");
+  output_addr_const (file, x);
+  fprintf (file, ")");
+}
+
+/* Implement TARGET_ASM_FUNCTION_PROLOGUE.  */
+static void
+nios2_asm_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
+{
+  if (flag_verbose_asm || flag_debug_asm)
+    {
+      compute_frame_size ();
+      dump_frame_size (file);
+    }
+}
+
+/* Emit assembly of custom FPU instructions.  */
+const char*
+nios2_fpu_insn_asm (enum n2fpu_code code)
+{
+  static char buf[256];
+  const char *op1, *op2, *op3;
+  int ln = 256, n = 0;
+  
+  int N = N2FPU_N (code);
+  int num_operands = N2FPU (code).num_operands;
+  const char* insn_name = N2FPU_NAME (code);
+  tree ftype = nios2_ftype (N2FPU_FTCODE (code));
+  enum machine_mode dst_mode = TYPE_MODE (TREE_TYPE (ftype));
+  enum machine_mode src_mode = TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (ftype)));
+
+  /* Prepare X register for DF input operands.  */
+  if (GET_MODE_SIZE (src_mode) == 8 && num_operands == 3)
+    n = snprintf (buf, ln, "custom\t%d, zero, %%1, %%D1 # fwrx %%1\n\t",
+		  N2FPU_N (n2fpu_fwrx));
+
+  if (src_mode == SFmode)
+    {
+      if (dst_mode == VOIDmode)
+	{
+	  /* The fwry case.  */
+	  op1 = op3 = "zero";
+	  op2 = "%0";
+	  num_operands -= 1;
+	}
+      else
+	{
+	  op1 = "%0"; op2 = "%1";
+	  op3 = (num_operands == 2 ? "zero" : "%2");
+	}
+    }
+  else if (src_mode == DFmode)
+    {
+      if (dst_mode == VOIDmode)
+	{
+	  /* The fwrx case.  */
+	  op1 = "zero";
+	  op2 = "%0";
+	  op3 = "%D0";
+	  num_operands -= 1;
+	}
+      else
+	{
+	  op1 = (dst_mode == DFmode ? "%D0" : "%0");
+	  op2 = (num_operands == 2 ? "%1" : "%2");
+	  op3 = (num_operands == 2 ? "%D1" : "%D2");
+	}
+    }
+  else if (src_mode == VOIDmode)
+    {
+      /* frdxlo, frdxhi, frdy cases.  */
+      gcc_assert (dst_mode == SFmode);
+      op1 = "%0";
+      op2 = op3 = "zero";
+    }
+  else if (src_mode == SImode)
+    {
+      /* Conversion operators.  */
+      gcc_assert (num_operands == 2);
+      op1 = (dst_mode == DFmode ? "%D0" : "%0");
+      op2 = "%1";
+      op3 = "zero";
+    }
+  else
+    gcc_unreachable ();
+
+  /* Main instruction string.  */
+  n += snprintf (buf + n, ln - n, "custom\t%d, %s, %s, %s # %s %%0%s%s",
+		 N, op1, op2, op3, insn_name,
+		 (num_operands >= 2 ? ", %1" : ""),
+		 (num_operands == 3 ? ", %2" : ""));
+
+  /* Extraction of Y register for DF results.  */
+  if (dst_mode == DFmode)
+    snprintf (buf + n, ln - n, "\n\tcustom\t%d, %%0, zero, zero # frdy %%0",
+	      N2FPU_N (n2fpu_frdy));
+  return buf;
+}
+
+
+
+/* Instruction scheduler related.  */
+
+static int
+nios2_issue_rate (void)
+{
+#ifdef MAX_DFA_ISSUE_RATE
+  return MAX_DFA_ISSUE_RATE;
+#else
+  return 1;
+#endif
+}
+
+
+
+/* Function argument related.  */
+
+void
+nios2_init_cumulative_args (CUMULATIVE_ARGS *cum,
+			    tree fntype ATTRIBUTE_UNUSED,
+			    rtx libname ATTRIBUTE_UNUSED,
+			    tree fndecl ATTRIBUTE_UNUSED,
+			    int n_named_args ATTRIBUTE_UNUSED)
+{
+  cum->regs_used = 0;
+}
+
+/* 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.
+
+   MODE is the argument's machine mode.
+   TYPE is the data type of the argument (as a tree).
+   This is null for libcalls where that information may
+   not be available.
+   CUM is a variable of type CUMULATIVE_ARGS which gives info about
+   the preceding args and about the function being called.
+   NAMED is nonzero if this argument is a named parameter
+   (otherwise it is an extra parameter matching an ellipsis).  */
+
+static rtx
+nios2_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
+		    const_tree type ATTRIBUTE_UNUSED,
+		    bool named ATTRIBUTE_UNUSED)
+{
+  CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); 
+  rtx return_rtx = NULL_RTX;
+
+  if (cum->regs_used < NUM_ARG_REGS)
+    return_rtx = gen_rtx_REG (mode, FIRST_ARG_REGNO + cum->regs_used);
+
+  return return_rtx;
+}
+
+/* Return number of bytes, at the beginning of the argument, that must be
+   put in registers.  0 is the argument is entirely in registers or entirely
+   in memory.  */
+
+static int
+nios2_arg_partial_bytes (cumulative_args_t cum_v,
+                         enum machine_mode mode, tree type ATTRIBUTE_UNUSED,
+                         bool named ATTRIBUTE_UNUSED)
+{
+  CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); 
+  HOST_WIDE_INT param_size;
+
+  if (mode == BLKmode)
+    {
+      param_size = int_size_in_bytes (type);
+      gcc_assert (param_size >= 0);
+      /*
+      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 = (UNITS_PER_WORD - 1 + param_size) / UNITS_PER_WORD;
+
+  if (cum->regs_used < NUM_ARG_REGS
+      && cum->regs_used + param_size > NUM_ARG_REGS)
+    return (NUM_ARG_REGS - cum->regs_used) * UNITS_PER_WORD;
+  else
+    return 0;
+}
+
+/* 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.)  */
+
+static void
+nios2_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
+			    const_tree type ATTRIBUTE_UNUSED,
+			    bool named ATTRIBUTE_UNUSED)
+{
+  CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); 
+  HOST_WIDE_INT param_size;
+
+  if (mode == BLKmode)
+    {
+      param_size = int_size_in_bytes (type);
+      gcc_assert (param_size >= 0);
+      /*
+      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 = (UNITS_PER_WORD - 1 + param_size) / UNITS_PER_WORD;
+
+  if (cum->regs_used + param_size > NUM_ARG_REGS)
+    cum->regs_used = NUM_ARG_REGS;
+  else
+    cum->regs_used += param_size;
+
+  return;
+}
+
+enum direction
+nios2_function_arg_padding (enum machine_mode mode, const_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 upward;
+
+  /* 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 downward;
+
+  /* Arguments smaller than a stack slot are padded downward.  */
+  if (mode != BLKmode)
+    return (GET_MODE_BITSIZE (mode) >= PARM_BOUNDARY) ? upward : downward;
+  else
+    return ((int_size_in_bytes (type) >= (PARM_BOUNDARY / BITS_PER_UNIT))
+            ? upward : downward);
+}
+
+enum direction
+nios2_block_reg_padding (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 (mode, type);
+}
+
+
+/* Emit RTL insns to initialize the variable parts of a trampoline.
+   FNADDR is an RTX for the address of the function's pure code.
+   CXT is an RTX for the static chain value for the function.
+   On Nios II, we handle this by a library call.  */
+static void
+nios2_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt)
+{
+  rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
+  rtx ctx_reg = force_reg (Pmode, cxt);
+  rtx addr = force_reg (Pmode, XEXP (m_tramp, 0));
+
+  emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__trampoline_setup"),
+		     LCT_NORMAL, VOIDmode, 3,
+		     addr, Pmode,
+		     fnaddr, Pmode,
+		     ctx_reg, Pmode);
+}
+
+/* Implement TARGET_FUNCTION_VALUE.  */
+static rtx
+nios2_function_value (const_tree ret_type, const_tree fn ATTRIBUTE_UNUSED,
+		      bool outgoing ATTRIBUTE_UNUSED)
+{
+  return gen_rtx_REG (TYPE_MODE (ret_type), FIRST_RETVAL_REGNO);
+}
+
+/* Implement TARGET_LIBCALL_VALUE.  */
+static rtx
+nios2_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
+{
+  return gen_rtx_REG (mode, FIRST_RETVAL_REGNO);
+}
+
+/* Implement TARGET_FUNCTION_VALUE_REGNO_P.  */
+static bool
+nios2_function_value_regno_p (const unsigned int regno)
+{
+  return (regno == FIRST_RETVAL_REGNO);
+}
+
+/* Implement TARGET_RETURN_IN_MEMORY.  */
+static bool
+nios2_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
+{
+  return (int_size_in_bytes (type) > (2 * UNITS_PER_WORD)
+	  || int_size_in_bytes (type) == -1);
+}
+
+/* ??? It may be possible to eliminate the copyback and implement
+   my own va_arg type, but that is more work for now.  */
+static void
+nios2_setup_incoming_varargs (cumulative_args_t cum_v,
+                              enum machine_mode mode, tree type,
+                              int *pretend_size, int second_time)
+{
+  CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); 
+  CUMULATIVE_ARGS local_cum;
+  cumulative_args_t local_cum_v = pack_cumulative_args (&local_cum);
+  int regs_to_push;
+  int pret_size;
+
+  local_cum = *cum;
+  nios2_function_arg_advance (local_cum_v, mode, type, 1);
+
+  regs_to_push = NUM_ARG_REGS - local_cum.regs_used;
+
+  if (!second_time && regs_to_push > 0)
+    {
+      rtx ptr = virtual_incoming_args_rtx;
+      rtx mem = gen_rtx_MEM (BLKmode, ptr);
+      emit_insn (gen_blockage ());
+      move_block_from_reg (local_cum.regs_used + FIRST_ARG_REGNO, mem,
+			   regs_to_push);
+      emit_insn (gen_blockage ());
+    }
+
+  pret_size = regs_to_push * UNITS_PER_WORD;
+
+  if (pret_size)
+    *pretend_size = pret_size;
+}
+
+
+
+/* Init FPU builtins.  */
+static void
+nios2_init_fpu_builtins (int start_code)
+{
+  char builtin_name[64] = "__builtin_custom_";
+  unsigned int i, n = strlen ("__builtin_custom_");
+
+  for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
+    {
+      snprintf (builtin_name + n, sizeof (builtin_name) - n,
+		"%s", N2FPU_NAME (i));
+      add_builtin_function (builtin_name, nios2_ftype (N2FPU_FTCODE (i)),
+			    start_code + i, BUILT_IN_MD, NULL, NULL_TREE);
+    }
+}
+
+/* Helper function for expanding FPU builtins.  */
+static rtx
+nios2_expand_fpu_builtin (tree exp, unsigned int code, rtx target)
+{
+  struct expand_operand ops[MAX_RECOG_OPERANDS];
+  enum insn_code icode = N2FPU_ICODE (code);
+  int nargs, argno, opno = 0;
+  int num_operands = N2FPU (code).num_operands;
+  enum machine_mode dst_mode = TYPE_MODE (TREE_TYPE (exp));
+  bool has_target_p = (dst_mode != VOIDmode);
+
+  if (N2FPU_N (code) < 0)
+    fatal_error ("Cannot call %<__builtin_custom_%s%> without specifying switch"
+		 " %<-mcustom-%s%>", N2FPU_NAME (code), N2FPU_NAME (code));
+  if (has_target_p)
+    create_output_operand (&ops[opno++], target, dst_mode);
+  else
+    /* Subtract away the count of the VOID return, mainly for fwrx/fwry.   */
+    num_operands -= 1;
+  nargs = call_expr_nargs (exp);
+  for (argno = 0; argno < nargs; argno++)
+    {
+      tree arg = CALL_EXPR_ARG (exp, argno);
+      create_input_operand (&ops[opno++], expand_normal (arg),
+			    TYPE_MODE (TREE_TYPE (arg)));
+    }
+  if (!maybe_expand_insn (icode, num_operands, ops))
+    {
+      error ("invalid argument to built-in function");
+      return has_target_p ? gen_reg_rtx (ops[0].mode) : const0_rtx;
+    }
+  return has_target_p ? ops[0].value : const0_rtx;
+}
+
+
+/* Nios II has custom instruction built-in functions of the forms:
+   __builtin_custom_n
+   __builtin_custom_nX
+   __builtin_custom_nXX
+   __builtin_custom_Xn
+   __builtin_custom_XnX
+   __builtin_custom_XnXX
+
+   where each X could be either 'i' (int), 'f' (float), or 'p' (void*).
+   Therefore with 0-1 return values, and 0-2 arguments, we have a
+   total of (3 + 1) * (1 + 3 + 9) == 52 custom builtin functions.
+*/
+#define NUM_CUSTOM_BUILTINS ((3 + 1) * (1 + 3 + 9))
+static char custom_builtin_name[NUM_CUSTOM_BUILTINS][5];
+
+static void
+nios2_init_custom_builtins (int start_code)
+{
+  tree builtin_ftype, ret_type;
+  char builtin_name[32] = "__builtin_custom_";
+  int n = strlen ("__builtin_custom_");
+  int builtin_code = 0;
+  int lhs, rhs1, rhs2;
+
+  struct { tree type; const char* c; } op[4];
+  /* z */ op[0].c = "";  op[0].type = NULL_TREE;
+  /* f */ op[1].c = "f"; op[1].type = float_type_node;
+  /* i */ op[2].c = "i"; op[2].type = integer_type_node;
+  /* p */ op[3].c = "p"; op[3].type = ptr_type_node;
+
+  /* This way of constructing the function tree types will slightly 
+     overlap with the N2_FTYPES list used by other builtins.  */
+
+  for (lhs = 0; lhs < 4; lhs++)
+    for (rhs1 = 0; rhs1 < 4; rhs1++)
+      for (rhs2 = 0; rhs2 < 4; rhs2++)
+	{
+	  if (rhs1 == 0 && rhs2 != 0)
+	    continue;
+	  ret_type = (op[lhs].type ? op[lhs].type : void_type_node);
+	  builtin_ftype
+	    = build_function_type_list (ret_type, integer_type_node,
+					op[rhs1].type, op[rhs2].type,
+					NULL_TREE);
+	  snprintf (builtin_name + n, 32 - n, "%sn%s%s",
+		    op[lhs].c, op[rhs1].c, op[rhs2].c);
+	  /* Save copy of parameter string into custom_builtin_name[].  */
+	  strncpy (custom_builtin_name[builtin_code], builtin_name + n, 5);
+	  add_builtin_function (builtin_name, builtin_ftype,
+				start_code + builtin_code,
+				BUILT_IN_MD, NULL, NULL_TREE);
+	  builtin_code += 1;
+	}
+}
+
+/* Helper function for expanding custom builtins.  */
+static rtx
+nios2_expand_custom_builtin (tree exp, unsigned int index, rtx target)
+{
+  bool has_target_p = (TREE_TYPE (exp) != void_type_node);
+  enum machine_mode tmode = VOIDmode;
+  int nargs, argno;
+  rtx value, insn, unspec_args[3];
+  tree arg;
+
+  /* XnXX form.  */
+  if (has_target_p)
+    {
+      tmode = TYPE_MODE (TREE_TYPE (exp));
+      if (!target || GET_MODE (target) != tmode)
+	target = gen_reg_rtx (tmode);
+    }
+
+  nargs = call_expr_nargs (exp);
+  for (argno = 0; argno < nargs; argno++)
+    {
+      arg = CALL_EXPR_ARG (exp, argno);
+      value = expand_normal (arg);
+      unspec_args[argno] = value;
+      if (argno == 0)
+	{
+	  if (custom_insn_opcode (value, VOIDmode))
+	    nios2_register_custom_code (INTVAL (value), CCS_BUILTIN_CALL,
+					index);
+	  else
+	    error ("Custom instruction opcode must be compile time "
+		   "constant in the range 0-255 for __builtin_custom_%s",
+		   custom_builtin_name[index]);
+	}
+      else
+	/* For other arguments, force into a register.  */
+	unspec_args[argno] = force_reg (TYPE_MODE (TREE_TYPE (arg)),
+					unspec_args[argno]);
+    }
+  /* Fill remaining unspec operands with zero.  */
+  for (; argno < 3; argno++)
+    unspec_args[argno] = const0_rtx;
+
+  insn = (has_target_p
+	  ? gen_rtx_SET (VOIDmode, target,
+			 gen_rtx_UNSPEC_VOLATILE (tmode,
+						  gen_rtvec_v (3, unspec_args),
+						  UNSPECV_CUSTOM_XNXX))
+	  : gen_rtx_UNSPEC_VOLATILE (VOIDmode, gen_rtvec_v (3, unspec_args),
+				     UNSPECV_CUSTOM_NXX));
+  emit_insn (insn);
+  return has_target_p ? target : const0_rtx;
+}
+
+
+
+
+/* Main definition of built-in functions. Nios II has a small number of fixed
+   builtins, plus a large number of FPU insn builtins, and builtins for
+   generating custom instructions.  */
+
+struct nios2_builtin_desc
+{
+  enum insn_code icode;
+  enum nios2_ftcode ftype;
+  const char* name;
+};
+
+#define N2_BUILTINS					\
+  N2_BUILTIN_DEF (sync,   N2_FTYPE_VOID_VOID)		\
+  N2_BUILTIN_DEF (ldbio,  N2_FTYPE_SI_CVPTR)		\
+  N2_BUILTIN_DEF (ldbuio, N2_FTYPE_UI_CVPTR)		\
+  N2_BUILTIN_DEF (ldhio,  N2_FTYPE_SI_CVPTR)		\
+  N2_BUILTIN_DEF (ldhuio, N2_FTYPE_UI_CVPTR)		\
+  N2_BUILTIN_DEF (ldwio,  N2_FTYPE_SI_CVPTR)		\
+  N2_BUILTIN_DEF (stbio,  N2_FTYPE_VOID_VPTR_SI)	\
+  N2_BUILTIN_DEF (sthio,  N2_FTYPE_VOID_VPTR_SI)	\
+  N2_BUILTIN_DEF (stwio,  N2_FTYPE_VOID_VPTR_SI)	\
+  N2_BUILTIN_DEF (rdctl,  N2_FTYPE_SI_SI)		\
+  N2_BUILTIN_DEF (wrctl,  N2_FTYPE_VOID_SI_SI)
+
+enum nios2_builtin_code {
+#define N2_BUILTIN_DEF(name, ftype) NIOS2_BUILTIN_ ## name,
+  N2_BUILTINS
+#undef N2_BUILTIN_DEF
+  NUM_FIXED_NIOS2_BUILTINS
+};
+
+static const struct nios2_builtin_desc nios2_builtins[] = {
+#define N2_BUILTIN_DEF(name, ftype)			\
+  { CODE_FOR_ ## name, ftype, "__builtin_" #name },
+  N2_BUILTINS
+#undef N2_BUILTIN_DEF
+};
+
+/* Start/ends of FPU/custom insn builtin index ranges.  */
+static unsigned int nios2_fpu_builtin_base;
+static unsigned int nios2_custom_builtin_base;
+static unsigned int nios2_custom_builtin_end;
+
+/* Implement TARGET_INIT_BUILTINS.  */
+static void
+nios2_init_builtins (void)
+{
+  unsigned int i;
+
+  /* Initialize fixed builtins.  */
+  for (i = 0; i < ARRAY_SIZE (nios2_builtins); i++)
+    {
+      const struct nios2_builtin_desc *d = &nios2_builtins[i];
+      add_builtin_function (d->name, nios2_ftype (d->ftype), i,
+			    BUILT_IN_MD, NULL, NULL);
+    }
+
+  /* Initialize FPU builtins.  */
+  nios2_fpu_builtin_base = ARRAY_SIZE (nios2_builtins);
+  nios2_init_fpu_builtins (nios2_fpu_builtin_base);
+
+  /* Initialize custom insn builtins.  */
+  nios2_custom_builtin_base
+    = nios2_fpu_builtin_base + ARRAY_SIZE (nios2_fpu_insn);
+  nios2_custom_builtin_end
+    = nios2_custom_builtin_base + NUM_CUSTOM_BUILTINS;
+  nios2_init_custom_builtins (nios2_custom_builtin_base);
+}
+
+/* Low-level built-in expand routine.  */
+static rtx
+nios2_expand_builtin_insn (const struct nios2_builtin_desc *d, int n,
+			   struct expand_operand* ops, bool has_target_p)
+{
+  if (maybe_expand_insn (d->icode, n, ops))
+    return has_target_p ? ops[0].value : const0_rtx;
+  else
+    {
+      error ("invalid argument to built-in function %s", d->name);
+      return has_target_p ? gen_reg_rtx (ops[0].mode) : const0_rtx;	  
+    } 
+}
+
+/* Expand ldio/stio form load-store instruction builtins.  */
+static rtx
+nios2_expand_ldstio_builtin  (tree exp, rtx target,
+			      const struct nios2_builtin_desc *d)
+{
+  bool has_target_p;
+  rtx addr, mem, val;
+  struct expand_operand ops[MAX_RECOG_OPERANDS];
+  enum machine_mode mode = insn_data[d->icode].operand[0].mode;
+
+  addr = expand_normal (CALL_EXPR_ARG (exp, 0));
+  mem = gen_rtx_MEM (mode, addr);
+
+  if (insn_data[d->icode].operand[0].allows_mem)
+    {
+      /* stxio  */
+      val = force_reg (mode, expand_normal (CALL_EXPR_ARG (exp, 1)));
+      val = simplify_gen_subreg (mode, val, GET_MODE (val), 0);
+      create_output_operand (&ops[0], mem, mode);
+      create_input_operand (&ops[1], val, mode);
+      has_target_p = false;
+    }
+  else
+    {
+      /* ldxio */
+      create_output_operand (&ops[0], target, mode);
+      create_input_operand (&ops[1], mem, mode);
+      has_target_p = true;
+    }
+  return nios2_expand_builtin_insn (d, 2, ops, has_target_p);
+}
+
+/* Expand rdctl/wrctl builtins.  */
+static rtx
+nios2_expand_rdwrctl_builtin (tree exp, rtx target,
+			     const struct nios2_builtin_desc *d)
+{
+  bool has_target_p = (insn_data[d->icode].operand[0].predicate
+		       == register_operand);
+  rtx ctlcode = expand_normal (CALL_EXPR_ARG (exp, 0));
+  struct expand_operand ops[MAX_RECOG_OPERANDS];
+  if (!rdwrctl_operand (ctlcode, VOIDmode))
+    {
+      error ("Control register number must be in range 0-31 for %s",
+	     d->name);
+      return has_target_p ? gen_reg_rtx (SImode) : const0_rtx;
+    }
+  if (has_target_p)
+    {
+      create_output_operand (&ops[0], target, SImode);
+      create_integer_operand (&ops[1], INTVAL (ctlcode));
+    }
+  else
+    {
+      rtx val = expand_normal (CALL_EXPR_ARG (exp, 1));
+      create_integer_operand (&ops[0], INTVAL (ctlcode));
+      create_input_operand (&ops[1], val, SImode);
+    }
+  return nios2_expand_builtin_insn (d, 2, ops, has_target_p);
+}
+
+/* Implement TARGET_EXPAND_BUILTIN. Expand an expression EXP that calls
+   a built-in function, with result going to TARGET if that's convenient
+   (and in mode MODE if that's convenient).
+   SUBTARGET may be used as the target for computing one of EXP's operands.
+   IGNORE is nonzero if the value is to be ignored.  */
+
+static rtx
+nios2_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
+                      enum machine_mode mode ATTRIBUTE_UNUSED,
+		      int ignore ATTRIBUTE_UNUSED)
+{
+  tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+  unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+
+  if (fcode < nios2_fpu_builtin_base)
+    {
+      const struct nios2_builtin_desc *d = &nios2_builtins[fcode];
+
+      switch (fcode)
+	{
+	case NIOS2_BUILTIN_sync:
+	  emit_insn (gen_sync ());
+	  return const0_rtx;
+
+	case NIOS2_BUILTIN_ldbio:
+	case NIOS2_BUILTIN_ldbuio:
+	case NIOS2_BUILTIN_ldhio:
+	case NIOS2_BUILTIN_ldhuio:
+	case NIOS2_BUILTIN_ldwio:
+	case NIOS2_BUILTIN_stbio:
+	case NIOS2_BUILTIN_sthio:
+	case NIOS2_BUILTIN_stwio:
+	  return nios2_expand_ldstio_builtin (exp, target, d);
+
+	case NIOS2_BUILTIN_rdctl:
+	case NIOS2_BUILTIN_wrctl:
+	  return nios2_expand_rdwrctl_builtin (exp, target, d);
+
+	default:
+	  gcc_unreachable ();
+	}
+    }
+  else if (fcode < nios2_custom_builtin_base)
+    /* FPU builtin range.  */
+    return nios2_expand_fpu_builtin (exp, fcode - nios2_fpu_builtin_base,
+				     target);
+  else if (fcode < nios2_custom_builtin_end)
+    /* Custom insn builtin range.  */
+    return nios2_expand_custom_builtin (exp, fcode - nios2_custom_builtin_base,
+					target);
+  else
+    gcc_unreachable ();
+}
+
+/* Implement TARGET_INIT_LIBFUNCS.  */
+static void
+nios2_init_libfuncs (void)
+{
+  /* For Linux, we have access to kernel support for atomic operations.  */
+  if (TARGET_LINUX_ABI)
+    init_sync_libfuncs (UNITS_PER_WORD);
+}
+
+
+
+
+/* Register a custom code use, and signal error if a conflict was found.  */
+static void
+nios2_register_custom_code (unsigned int N, enum nios2_ccs_code status,
+			    int index)
+{
+  gcc_assert (N <= 255);
+
+  if (status == CCS_FPU)
+    {
+      if (custom_code_status[N] == CCS_FPU && index != custom_code_index[N])
+	{
+	  custom_code_conflict = true;
+	  error ("switch %<-mcustom-%s%> conflicts with switch %<-mcustom-%s%>",
+		 N2FPU_NAME (custom_code_index[N]), N2FPU_NAME (index));
+	}
+      else if (custom_code_status[N] == CCS_BUILTIN_CALL)
+	{
+	  custom_code_conflict = true;
+	  error ("call to %<__builtin_custom_%s%> conflicts with switch "
+		 "%<-mcustom-%s%>", custom_builtin_name[custom_code_index[N]],
+		 N2FPU_NAME (index));
+	}
+    }
+  else if (status == CCS_BUILTIN_CALL)
+    {
+      if (custom_code_status[N] == CCS_FPU)
+	{
+	  custom_code_conflict = true;
+	  error ("call to %<__builtin_custom_%s%> conflicts with switch "
+		 "%<-mcustom-%s%>", custom_builtin_name[index],
+		 N2FPU_NAME (custom_code_index[N]));
+	}
+	  /* Code conflicts between different __builtin_custom_xnxx calls
+	     do not seem to be checked. ???  */
+    }
+  else
+    gcc_unreachable ();
+
+  custom_code_status[N] = status;
+  custom_code_index[N] = index;
+}
+
+/* Mark a custom code as not in use.  */
+static void
+nios2_deregister_custom_code (unsigned int N)
+{
+  if (N <= 255)
+    {
+      custom_code_status[N] = CCS_UNUSED;
+      custom_code_index[N] = 0;
+    }
+}
+
+/* Target attributes can affect per-function option state, so we need to
+   save/restore the custom code tracking info using the
+   TARGET_OPTION_SAVE/TARGET_OPTION_RESTORE hooks.  */
+
+static void
+nios2_option_save (struct cl_target_option *ptr)
+{
+  unsigned int i;
+  for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
+    ptr->saved_fpu_custom_code[i] = N2FPU_N (i);
+  memcpy (ptr->saved_custom_code_status, custom_code_status,
+	  sizeof (custom_code_status));
+  memcpy (ptr->saved_custom_code_index, custom_code_index,
+	  sizeof (custom_code_index));
+}
+
+static void
+nios2_option_restore (struct cl_target_option *ptr)
+{
+  unsigned int i;
+  for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
+    N2FPU_N (i) = ptr->saved_fpu_custom_code[i];
+  memcpy (custom_code_status, ptr->saved_custom_code_status,
+	  sizeof (custom_code_status));
+  memcpy (custom_code_index, ptr->saved_custom_code_index,
+	  sizeof (custom_code_index));
+}
+
+/* Inner function to process the attribute((target(...))), take an argument and
+   set the current options from the argument. If we have a list, recursively go
+   over the list.  */
+
+static bool
+nios2_valid_target_attribute_rec (tree args)
+{
+  if (TREE_CODE (args) == TREE_LIST)
+    {
+      bool ret = true;
+      for (; args; args = TREE_CHAIN (args))
+	if (TREE_VALUE (args)
+	    && !nios2_valid_target_attribute_rec (TREE_VALUE (args)))
+	  ret = false;
+      return ret;
+    }
+  else if (TREE_CODE (args) == STRING_CST)
+    {
+      char *argstr = ASTRDUP (TREE_STRING_POINTER (args));
+      while (argstr && *argstr != '\0')
+	{
+	  bool no_opt = false, end_p = false;
+	  char *eq = NULL, *p = argstr;
+	  while (*p != '\0' && *p != ',')
+	    {
+	      if (!eq && *p == '=')
+		eq = p;
+	      ++p;
+	    }
+	  if (*p == '\0')
+	    end_p = true;
+	  else
+	    *p = '\0';
+	  if (eq) *eq = '\0';
+
+	  if (!strncmp (argstr, "no-", 3))
+	    {
+	      no_opt = true;
+	      argstr += 3;
+	    }
+	  if (!strncmp (argstr, "custom-fpu-cfg", 14))
+	    {
+	      if (no_opt)
+		{
+		  error ("custom-fpu-cfg option does not support %<no-%>");
+		  return false;
+		}
+	      if (!eq)
+		{
+		  error ("custom-fpu-cfg option requires configuration argument");
+		  return false;
+		}
+	      nios2_handle_custom_fpu_cfg (argstr + 15, true);
+	    }
+	  else if (!strncmp (argstr, "custom-", 7))
+	    {
+	      int code = -1;
+	      unsigned int i;
+	      for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
+		if (!strcmp (argstr + 7, N2FPU_NAME (i)))
+		  {
+		    /* Found insn.  */
+		    code = i;
+		    break;
+		  }
+	      if (code >= 0)
+		{
+		  if (no_opt)
+		    {
+		      if (eq)
+			{
+			  error ("%<no-custom-%s%> does not accept arguments",
+				 N2FPU_NAME (code));
+			  return false;
+			}
+		      /* Disable option by setting to -1.  */
+		      nios2_deregister_custom_code (N2FPU_N (code));
+		      N2FPU_N (code) = -1;
+		    }
+		  else
+		    {
+		      char *t;
+		      if (!eq || p == eq + 1)
+			{
+			  error ("%<custom-%s=%> requires argument",
+				 N2FPU_NAME (code));
+			  return false;
+			}
+		      for (t = eq + 1; t != p; ++t)
+			if (!ISDIGIT (*t))
+			  {			 
+			    error ("%<custom-%s=%> argument requires numeric "
+				   "digits", N2FPU_NAME (code));
+			    return false;
+			  }
+		      /* Set option to argument.  */
+		      N2FPU_N (code) = atoi (eq + 1);
+		      nios2_handle_custom_fpu_insn_option (code);
+		    }
+		}
+	      else
+		{
+		  error ("%<custom-%s=%> is not recognised as FPU instruction",
+			 argstr + 7);
+		  return false;
+		}		
+	    }
+	  else
+	    {
+	      error ("%<%s%> is unknown", argstr);
+	      return false;
+	    }
+
+	  if (end_p)
+	    break;
+	  else
+	    argstr = p + 1;
+	}
+      return true;
+    }
+  else
+    gcc_unreachable ();
+}
+
+/* Return a TARGET_OPTION_NODE tree of the target options listed or NULL.  */
+
+static tree
+nios2_valid_target_attribute_tree (tree args)
+{
+  if (!nios2_valid_target_attribute_rec (args))
+    return NULL_TREE;
+  nios2_custom_check_insns ();
+  return build_target_option_node ();
+}
+
+/* Hook to validate attribute((target("string"))).  */
+
+static bool
+nios2_valid_target_attribute_p (tree fndecl,
+				tree ARG_UNUSED (name),
+				tree args,
+				int ARG_UNUSED (flags))
+{
+  struct cl_target_option cur_target;
+  bool ret = true;
+  tree old_optimize = build_optimization_node ();
+  tree new_target, new_optimize;
+  tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
+
+  /* If the function changed the optimization levels as well as setting target
+     options, start with the optimizations specified.  */
+  if (func_optimize && func_optimize != old_optimize)
+    cl_optimization_restore (&global_options,
+			     TREE_OPTIMIZATION (func_optimize));
+
+  /* The target attributes may also change some optimization flags, so update
+     the optimization options if necessary.  */
+  cl_target_option_save (&cur_target, &global_options);
+  new_target = nios2_valid_target_attribute_tree (args);
+  new_optimize = build_optimization_node ();
+
+  if (!new_target)
+    ret = false;
+
+  else if (fndecl)
+    {
+      DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_target;
+
+      if (old_optimize != new_optimize)
+	DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize;
+    }
+
+  cl_target_option_restore (&global_options, &cur_target);
+
+  if (old_optimize != new_optimize)
+    cl_optimization_restore (&global_options,
+			     TREE_OPTIMIZATION (old_optimize));
+  return ret;
+}
+
+/* Remember the last target of nios2_set_current_function.  */
+static GTY(()) tree nios2_previous_fndecl;
+
+/* Establish appropriate back-end context for processing the function
+   FNDECL.  The argument might be NULL to indicate processing at top
+   level, outside of any function scope.  */
+static void
+nios2_set_current_function (tree fndecl)
+{
+  tree old_tree = (nios2_previous_fndecl
+		   ? DECL_FUNCTION_SPECIFIC_TARGET (nios2_previous_fndecl)
+		   : NULL_TREE);
+
+  tree new_tree = (fndecl
+		   ? DECL_FUNCTION_SPECIFIC_TARGET (fndecl)
+		   : NULL_TREE);
+
+  if (fndecl && fndecl != nios2_previous_fndecl)
+    {
+      nios2_previous_fndecl = fndecl;
+      if (old_tree == new_tree)
+	;
+
+      else if (new_tree)
+	{
+	  cl_target_option_restore (&global_options,
+				    TREE_TARGET_OPTION (new_tree));
+	  target_reinit ();
+	}
+
+      else if (old_tree)
+	{
+	  struct cl_target_option *def
+	    = TREE_TARGET_OPTION (target_option_current_node);
+
+	  cl_target_option_restore (&global_options, def);
+	  target_reinit ();
+	}
+    }
+}
+
+/* Hook to validate the current #pragma GCC target and set the FPU custom
+   code option state.  If ARGS is NULL, then POP_TARGET is used to reset
+   the options.  */
+
+static bool
+nios2_pragma_target_parse (tree args, tree pop_target)
+{
+  tree cur_tree;
+  if (! args)
+    {
+      cur_tree = ((pop_target)
+		  ? pop_target
+		  : target_option_default_node);
+      cl_target_option_restore (&global_options,
+				TREE_TARGET_OPTION (cur_tree));
+    }
+  else
+    {
+      cur_tree = nios2_valid_target_attribute_tree (args);
+      if (!cur_tree)
+	return false;
+    }
+
+  target_option_current_node = cur_tree;
+  return true;
+}
+
+/* Implement TARGET_MERGE_DECL_ATTRIBUTES.
+   We are just using this hook to add some additional error checking to
+   the default behavior.  GCC does not provide a target hook for merging
+   the target options, and only correctly handles merging empty vs non-empty
+   option data; see merge_decls() in c-decl.c.
+   So here we require either that at least one of the decls has empty
+   target options, or that the target options/data be identical.  */
+static tree
+nios2_merge_decl_attributes (tree olddecl, tree newdecl)
+{
+  tree oldopts = lookup_attribute ("target", DECL_ATTRIBUTES (olddecl));
+  tree newopts = lookup_attribute ("target", DECL_ATTRIBUTES (newdecl));
+  if (newopts && oldopts && newopts != oldopts)
+    {
+      tree oldtree = DECL_FUNCTION_SPECIFIC_TARGET (olddecl);
+      tree newtree = DECL_FUNCTION_SPECIFIC_TARGET (newdecl);
+      if (oldtree && newtree && oldtree != newtree)
+	{
+	  struct cl_target_option *olddata = TREE_TARGET_OPTION (oldtree);
+	  struct cl_target_option *newdata = TREE_TARGET_OPTION (newtree);
+	  if (olddata != newdata
+	      && memcmp (olddata, newdata, sizeof (struct cl_target_option)))
+	    error ("%qE redeclared with conflicting %qs attributes",
+		   DECL_NAME (newdecl), "target");
+	}
+    }
+  return merge_attributes (DECL_ATTRIBUTES (olddecl),
+			   DECL_ATTRIBUTES (newdecl));
+}
+
+#include "gt-nios2.h"
Index: gcc/config/nios2/t-nios2
===================================================================
--- gcc/config/nios2/t-nios2	(revision 0)
+++ gcc/config/nios2/t-nios2	(revision 0)
@@ -0,0 +1,27 @@ 
+# Target Makefile Fragment for Altera Nios II.
+# Copyright (C) 2013 Free Software Foundation, Inc.
+# Contributed by Altera and Mentor Graphics, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published
+# by the Free Software Foundation; either version 3, or (at your
+# option) any later version.
+#
+# GCC is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# MULTILIB_OPTIONS = mno-hw-mul/mhw-mulx mcustom-fpu-cfg=60-1/mcustom-fpu-cfg=60-2
+# MULTILIB_DIRNAMES = nomul mulx fpu-60-1 fpu-60-2
+# MULTILIB_EXCEPTIONS = 
+
+# MULTILIB_OPTIONS += EL/EB
+# MULTILIB_DIRNAMES += le be
+# MULTILIB_MATCHES += EL=mel EB=meb
Index: gcc/config/nios2/nios2.opt
===================================================================
--- gcc/config/nios2/nios2.opt	(revision 0)
+++ gcc/config/nios2/nios2.opt	(revision 0)
@@ -0,0 +1,527 @@ 
+; Options for the Altera Nios II port of the compiler.
+; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+; Contributed by Altera and Mentor Graphics, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 3, or (at your option)
+; any later version.
+;
+; GCC is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING3.  If not see
+; <http://www.gnu.org/licenses/>.
+
+HeaderInclude
+config/nios2/nios2-opts.h
+
+TargetSave
+int saved_fpu_custom_code[n2fpu_code_num]
+
+TargetSave
+enum nios2_ccs_code saved_custom_code_status[256]
+
+TargetSave
+int saved_custom_code_index[256]
+
+mhw-div
+Target Report Mask(HAS_DIV)
+Enable DIV, DIVU
+
+mhw-mul
+Target Report Mask(HAS_MUL)
+Enable MUL instructions
+
+mhw-mulx
+Target Report Mask(HAS_MULX)
+Enable MULX instructions, assume fast shifter
+
+mfast-sw-div
+Target Report Mask(FAST_SW_DIV)
+Use table based fast divide (default at -O3)
+
+mbypass-cache
+Target Report Mask(BYPASS_CACHE)
+All memory accesses use I/O load/store instructions
+
+mno-cache-volatile
+Target Report RejectNegative Mask(BYPASS_CACHE_VOLATILE)
+Volatile memory accesses use I/O load/store instructions
+
+mcache-volatile
+Target Report RejectNegative Undocumented InverseMask(BYPASS_CACHE_VOLATILE)
+Volatile memory accesses do not use I/O load/store instructions
+
+meb
+Target Report RejectNegative Mask(BIG_ENDIAN)
+Use big-endian byte order
+
+mel
+Target Report RejectNegative InverseMask(BIG_ENDIAN)
+Use little-endian byte order
+
+mcustom-fpu-cfg=
+Target RejectNegative Joined Var(nios2_custom_fpu_cfg_string)
+Floating point custom instruction configuration name
+
+mno-custom-ftruncds
+Target Report RejectNegative Var(nios2_custom_ftruncds, -1)
+Do not use the ftruncds custom instruction
+
+mcustom-ftruncds=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_ftruncds) Init(-1)
+Integer id (N) of ftruncds custom instruction
+
+mno-custom-fextsd
+Target Report RejectNegative Var(nios2_custom_fextsd, -1)
+Do not use the fextsd custom instruction
+
+mcustom-fextsd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fextsd) Init(-1)
+Integer id (N) of fextsd custom instruction
+
+mno-custom-fixdu
+Target Report RejectNegative Var(nios2_custom_fixdu, -1)
+Do not use the fixdu custom instruction
+
+mcustom-fixdu=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fixdu) Init(-1)
+Integer id (N) of fixdu custom instruction
+
+mno-custom-fixdi
+Target Report RejectNegative Var(nios2_custom_fixdi, -1)
+Do not use the fixdi custom instruction
+
+mcustom-fixdi=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fixdi) Init(-1)
+Integer id (N) of fixdi custom instruction
+
+mno-custom-fixsu
+Target Report RejectNegative Var(nios2_custom_fixsu, -1)
+Do not use the fixsu custom instruction
+
+mcustom-fixsu=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fixsu) Init(-1)
+Integer id (N) of fixsu custom instruction
+
+mno-custom-fixsi
+Target Report RejectNegative Var(nios2_custom_fixsi, -1)
+Do not use the fixsi custom instruction
+
+mcustom-fixsi=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fixsi) Init(-1)
+Integer id (N) of fixsi custom instruction
+
+mno-custom-floatud
+Target Report RejectNegative Var(nios2_custom_floatud, -1)
+Do not use the floatud custom instruction
+
+mcustom-floatud=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_floatud) Init(-1)
+Integer id (N) of floatud custom instruction
+
+mno-custom-floatid
+Target Report RejectNegative Var(nios2_custom_floatid, -1)
+Do not use the floatid custom instruction
+
+mcustom-floatid=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_floatid) Init(-1)
+Integer id (N) of floatid custom instruction
+
+mno-custom-floatus
+Target Report RejectNegative Var(nios2_custom_floatus, -1)
+Do not use the floatus custom instruction
+
+mcustom-floatus=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_floatus) Init(-1)
+Integer id (N) of floatus custom instruction
+
+mno-custom-floatis
+Target Report RejectNegative Var(nios2_custom_floatis, -1)
+Do not use the floatis custom instruction
+
+mcustom-floatis=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_floatis) Init(-1)
+Integer id (N) of floatis custom instruction
+
+mno-custom-fcmpned
+Target Report RejectNegative Var(nios2_custom_fcmpned, -1)
+Do not use the fcmpned custom instruction
+
+mcustom-fcmpned=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpned) Init(-1)
+Integer id (N) of fcmpned custom instruction
+
+mno-custom-fcmpeqd
+Target Report RejectNegative Var(nios2_custom_fcmpeqd, -1)
+Do not use the fcmpeqd custom instruction
+
+mcustom-fcmpeqd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpeqd) Init(-1)
+Integer id (N) of fcmpeqd custom instruction
+
+mno-custom-fcmpged
+Target Report RejectNegative Var(nios2_custom_fcmpged, -1)
+Do not use the fcmpged custom instruction
+
+mcustom-fcmpged=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpged) Init(-1)
+Integer id (N) of fcmpged custom instruction
+
+mno-custom-fcmpgtd
+Target Report RejectNegative Var(nios2_custom_fcmpgtd, -1)
+Do not use the fcmpgtd custom instruction
+
+mcustom-fcmpgtd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpgtd) Init(-1)
+Integer id (N) of fcmpgtd custom instruction
+
+mno-custom-fcmpled
+Target Report RejectNegative Var(nios2_custom_fcmpled, -1)
+Do not use the fcmpled custom instruction
+
+mcustom-fcmpled=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpled) Init(-1)
+Integer id (N) of fcmpled custom instruction
+
+mno-custom-fcmpltd
+Target Report RejectNegative Var(nios2_custom_fcmpltd, -1)
+Do not use the fcmpltd custom instruction
+
+mcustom-fcmpltd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpltd) Init(-1)
+Integer id (N) of fcmpltd custom instruction
+
+mno-custom-flogd
+Target Report RejectNegative Var(nios2_custom_flogd, -1)
+Do not use the flogd custom instruction
+
+mcustom-flogd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_flogd) Init(-1)
+Integer id (N) of flogd custom instruction
+
+mno-custom-fexpd
+Target Report RejectNegative Var(nios2_custom_fexpd, -1)
+Do not use the fexpd custom instruction
+
+mcustom-fexpd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fexpd) Init(-1)
+Integer id (N) of fexpd custom instruction
+
+mno-custom-fatand
+Target Report RejectNegative Var(nios2_custom_fatand, -1)
+Do not use the fatand custom instruction
+
+mcustom-fatand=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fatand) Init(-1)
+Integer id (N) of fatand custom instruction
+
+mno-custom-ftand
+Target Report RejectNegative Var(nios2_custom_ftand, -1)
+Do not use the ftand custom instruction
+
+mcustom-ftand=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_ftand) Init(-1)
+Integer id (N) of ftand custom instruction
+
+mno-custom-fsind
+Target Report RejectNegative Var(nios2_custom_fsind, -1)
+Do not use the fsind custom instruction
+
+mcustom-fsind=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fsind) Init(-1)
+Integer id (N) of fsind custom instruction
+
+mno-custom-fcosd
+Target Report RejectNegative Var(nios2_custom_fcosd, -1)
+Do not use the fcosd custom instruction
+
+mcustom-fcosd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcosd) Init(-1)
+Integer id (N) of fcosd custom instruction
+
+mno-custom-fsqrtd
+Target Report RejectNegative Var(nios2_custom_fsqrtd, -1)
+Do not use the fsqrtd custom instruction
+
+mcustom-fsqrtd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fsqrtd) Init(-1)
+Integer id (N) of fsqrtd custom instruction
+
+mno-custom-fabsd
+Target Report RejectNegative Var(nios2_custom_fabsd, -1)
+Do not use the fabsd custom instruction
+
+mcustom-fabsd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fabsd) Init(-1)
+Integer id (N) of fabsd custom instruction
+
+mno-custom-fnegd
+Target Report RejectNegative Var(nios2_custom_fnegd, -1)
+Do not use the fnegd custom instruction
+
+mcustom-fnegd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fnegd) Init(-1)
+Integer id (N) of fnegd custom instruction
+
+mno-custom-fmaxd
+Target Report RejectNegative Var(nios2_custom_fmaxd, -1)
+Do not use the fmaxd custom instruction
+
+mcustom-fmaxd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fmaxd) Init(-1)
+Integer id (N) of fmaxd custom instruction
+
+mno-custom-fmind
+Target Report RejectNegative Var(nios2_custom_fmind, -1)
+Do not use the fmind custom instruction
+
+mcustom-fmind=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fmind) Init(-1)
+Integer id (N) of fmind custom instruction
+
+mno-custom-fdivd
+Target Report RejectNegative Var(nios2_custom_fdivd, -1)
+Do not use the fdivd custom instruction
+
+mcustom-fdivd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fdivd) Init(-1)
+Integer id (N) of fdivd custom instruction
+
+mno-custom-fmuld
+Target Report RejectNegative Var(nios2_custom_fmuld, -1)
+Do not use the fmuld custom instruction
+
+mcustom-fmuld=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fmuld) Init(-1)
+Integer id (N) of fmuld custom instruction
+
+mno-custom-fsubd
+Target Report RejectNegative Var(nios2_custom_fsubd, -1)
+Do not use the fsubd custom instruction
+
+mcustom-fsubd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fsubd) Init(-1)
+Integer id (N) of fsubd custom instruction
+
+mno-custom-faddd
+Target Report RejectNegative Var(nios2_custom_faddd, -1)
+Do not use the faddd custom instruction
+
+mcustom-faddd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_faddd) Init(-1)
+Integer id (N) of faddd custom instruction
+
+mno-custom-fcmpnes
+Target Report RejectNegative Var(nios2_custom_fcmpnes, -1)
+Do not use the fcmpnes custom instruction
+
+mcustom-fcmpnes=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpnes) Init(-1)
+Integer id (N) of fcmpnes custom instruction
+
+mno-custom-fcmpeqs
+Target Report RejectNegative Var(nios2_custom_fcmpeqs, -1)
+Do not use the fcmpeqs custom instruction
+
+mcustom-fcmpeqs=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpeqs) Init(-1)
+Integer id (N) of fcmpeqs custom instruction
+
+mno-custom-fcmpges
+Target Report RejectNegative Var(nios2_custom_fcmpges, -1)
+Do not use the fcmpges custom instruction
+
+mcustom-fcmpges=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpges) Init(-1)
+Integer id (N) of fcmpges custom instruction
+
+mno-custom-fcmpgts
+Target Report RejectNegative Var(nios2_custom_fcmpgts, -1)
+Do not use the fcmpgts custom instruction
+
+mcustom-fcmpgts=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpgts) Init(-1)
+Integer id (N) of fcmpgts custom instruction
+
+mno-custom-fcmples
+Target Report RejectNegative Var(nios2_custom_fcmples, -1)
+Do not use the fcmples custom instruction
+
+mcustom-fcmples=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmples) Init(-1)
+Integer id (N) of fcmples custom instruction
+
+mno-custom-fcmplts
+Target Report RejectNegative Var(nios2_custom_fcmplts, -1)
+Do not use the fcmplts custom instruction
+
+mcustom-fcmplts=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmplts) Init(-1)
+Integer id (N) of fcmplts custom instruction
+
+mno-custom-flogs
+Target Report RejectNegative Var(nios2_custom_flogs, -1)
+Do not use the flogs custom instruction
+
+mcustom-flogs=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_flogs) Init(-1)
+Integer id (N) of flogs custom instruction
+
+mno-custom-fexps
+Target Report RejectNegative Var(nios2_custom_fexps, -1)
+Do not use the fexps custom instruction
+
+mcustom-fexps=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fexps) Init(-1)
+Integer id (N) of fexps custom instruction
+
+mno-custom-fatans
+Target Report RejectNegative Var(nios2_custom_fatans, -1)
+Do not use the fatans custom instruction
+
+mcustom-fatans=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fatans) Init(-1)
+Integer id (N) of fatans custom instruction
+
+mno-custom-ftans
+Target Report RejectNegative Var(nios2_custom_ftans, -1)
+Do not use the ftans custom instruction
+
+mcustom-ftans=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_ftans) Init(-1)
+Integer id (N) of ftans custom instruction
+
+mno-custom-fsins
+Target Report RejectNegative Var(nios2_custom_fsins, -1)
+Do not use the fsins custom instruction
+
+mcustom-fsins=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fsins) Init(-1)
+Integer id (N) of fsins custom instruction
+
+mno-custom-fcoss
+Target Report RejectNegative Var(nios2_custom_fcoss, -1)
+Do not use the fcoss custom instruction
+
+mcustom-fcoss=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcoss) Init(-1)
+Integer id (N) of fcoss custom instruction
+
+mno-custom-fsqrts
+Target Report RejectNegative Var(nios2_custom_fsqrts, -1)
+Do not use the fsqrts custom instruction
+
+mcustom-fsqrts=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fsqrts) Init(-1)
+Integer id (N) of fsqrts custom instruction
+
+mno-custom-fabss
+Target Report RejectNegative Var(nios2_custom_fabss, -1)
+Do not use the fabss custom instr
+
+mcustom-fabss=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fabss) Init(-1)
+Integer id (N) of fabss custom instruction
+
+mno-custom-fnegs
+Target Report RejectNegative Var(nios2_custom_fnegs, -1)
+Do not use the fnegs custom instruction
+
+mcustom-fnegs=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fnegs) Init(-1)
+Integer id (N) of fnegs custom instruction
+
+mno-custom-fmaxs
+Target Report RejectNegative Var(nios2_custom_fmaxs, -1)
+Do not use the fmaxs custom instruction
+
+mcustom-fmaxs=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fmaxs) Init(-1)
+Integer id (N) of fmaxs custom instruction
+
+mno-custom-fmins
+Target Report RejectNegative Var(nios2_custom_fmins, -1)
+Do not use the fmins custom instruction
+
+mcustom-fmins=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fmins) Init(-1)
+Integer id (N) of fmins custom instruction
+
+mno-custom-fdivs
+Target Report RejectNegative Var(nios2_custom_fdivs, -1)
+Do not use the fdivs custom instruction
+
+mcustom-fdivs=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fdivs) Init(-1)
+Integer id (N) of fdivs custom instruction
+
+mno-custom-fmuls
+Target Report RejectNegative Var(nios2_custom_fmuls, -1)
+Do not use the fmuls custom instruction
+
+mcustom-fmuls=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fmuls) Init(-1)
+Integer id (N) of fmuls custom instruction
+
+mno-custom-fsubs
+Target Report RejectNegative Var(nios2_custom_fsubs, -1)
+Do not use the fsubs custom instruction
+
+mcustom-fsubs=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fsubs) Init(-1)
+Integer id (N) of fsubs custom instruction
+
+mno-custom-fadds
+Target Report RejectNegative Var(nios2_custom_fadds, -1)
+Do not use the fadds custom instruction
+
+mcustom-fadds=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fadds) Init(-1)
+Integer id (N) of fadds custom instruction
+
+mno-custom-frdy
+Target Report RejectNegative Var(nios2_custom_frdy, -1)
+Do not use the frdy custom instruction
+
+mcustom-frdy=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_frdy) Init(-1)
+Integer id (N) of frdy custom instruction
+
+mno-custom-frdxhi
+Target Report RejectNegative Var(nios2_custom_frdxhi, -1)
+Do not use the frdxhi custom instruction
+
+mcustom-frdxhi=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_frdxhi) Init(-1)
+Integer id (N) of frdxhi custom instruction
+
+mno-custom-frdxlo
+Target Report RejectNegative Var(nios2_custom_frdxlo, -1)
+Do not use the frdxlo custom instruction
+
+mcustom-frdxlo=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_frdxlo) Init(-1)
+Integer id (N) of frdxlo custom instruction
+
+mno-custom-fwry
+Target Report RejectNegative Var(nios2_custom_fwry, -1)
+Do not use the fwry custom instruction
+
+mcustom-fwry=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fwry) Init(-1)
+Integer id (N) of fwry custom instruction
+
+mno-custom-fwrx
+Target Report RejectNegative Var(nios2_custom_fwrx, -1)
+Do not use the fwrx custom instruction
+
+mcustom-fwrx=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fwrx) Init(-1)
+Integer id (N) of fwrx custom instruction
Index: gcc/config/nios2/elf.h
===================================================================
--- gcc/config/nios2/elf.h	(revision 0)
+++ gcc/config/nios2/elf.h	(revision 0)
@@ -0,0 +1,52 @@ 
+/* Definitions of ELF target support for Altera Nios II.
+   Copyright (C) 2012-2013 Free Software Foundation, Inc.
+   Contributed by Jonah Graham (jgraham@altera.com), 
+   Will Reece (wreece@altera.com), and Jeff DaSilva (jdasilva@altera.com).
+   Contributed by Mentor Graphics, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+
+/* Specs to support the additional command-line options for Nios II ELF
+   toolchains.  */
+
+/* -msmallc chooses an alternate C library.
+   -msys-lib= specifies an additional low-level system/hosting library and
+   is typically used to suck in a library provided by a HAL BSP.  */
+#undef LIB_SPEC
+#define LIB_SPEC \
+"--start-group %{msmallc: -lsmallc} %{!msmallc: -lc} -lgcc \
+ %{msys-lib=*: -l%*} \
+ --end-group \
+"
+
+/* Linking with -mhal suppresses inclusion of the GCC-provided crt* begin/end
+   code.  Normally in this case you also link with -msys-crt0= to specify
+   the startup code provided by the HAL BSP instead.  */
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC						\
+  "%{mhal:"							\
+  "%{msys-crt0=*:%*} %{!msys-crt0=*:crt0%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 "%{!mhal:crtend%O%s crtn%O%s}"
+
+/* The ELF target doesn't support the Nios II Linux ABI.  */
+#define TARGET_LINUX_ABI 0
+
Index: gcc/config/nios2/nios2.h
===================================================================
--- gcc/config/nios2/nios2.h	(revision 0)
+++ gcc/config/nios2/nios2.h	(revision 0)
@@ -0,0 +1,686 @@ 
+/* Definitions of target machine for Altera Nios II.
+   Copyright (C) 2012-2013 Free Software Foundation, Inc.
+   Contributed by Jonah Graham (jgraham@altera.com), 
+   Will Reece (wreece@altera.com), and Jeff DaSilva (jdasilva@altera.com).
+   Contributed by Mentor Graphics, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_NIOS2_H
+#define GCC_NIOS2_H
+
+/* FPU insn codes declared here.  */
+#include "config/nios2/nios2-opts.h"
+
+/* Define built-in preprocessor macros.  */
+#define TARGET_CPU_CPP_BUILTINS()                   \
+  do                                                \
+    {                                               \
+      builtin_define_std ("NIOS2");                 \
+      builtin_define_std ("nios2");                 \
+      if (TARGET_BIG_ENDIAN)                        \
+        builtin_define_std ("nios2_big_endian");    \
+      else                                          \
+        builtin_define_std ("nios2_little_endian"); \
+    }                                               \
+  while (0)
+
+/* We're little endian, unless otherwise specified by defining
+   BIG_ENDIAN_FLAG.  */
+#ifndef TARGET_ENDIAN_DEFAULT
+# define TARGET_ENDIAN_DEFAULT 0
+#endif
+
+/* Default target_flags if no switches specified.  */
+#ifndef TARGET_DEFAULT
+# define TARGET_DEFAULT (MASK_HAS_MUL | TARGET_ENDIAN_DEFAULT)
+#endif
+
+#define CC1_SPEC "%{G*}"
+
+#if TARGET_ENDIAN_DEFAULT == 0
+# define ASM_SPEC "%{!meb:-EL} %{meb:-EB}"
+# define LINK_SPEC_ENDIAN "%{!meb:-EL} %{meb:-EB}"
+# define MULTILIB_DEFAULTS { "EL" }
+#else
+# define ASM_SPEC "%{!mel:-EB} %{mel:-EL}"
+# define LINK_SPEC_ENDIAN "%{!mel:-EB} %{mel:-EL}"
+# define MULTILIB_DEFAULTS { "EB" }
+#endif
+
+#define LINK_SPEC LINK_SPEC_ENDIAN \
+  " %{shared:-shared} \
+    %{static:-Bstatic}"
+
+
+/* Storage Layout.  */
+
+#define DEFAULT_SIGNED_CHAR 1
+#define BITS_BIG_ENDIAN 0
+#define BYTES_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0)
+#define WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0)
+#define BITS_PER_UNIT 8
+#define BITS_PER_WORD 32
+#define UNITS_PER_WORD 4
+#define POINTER_SIZE 32
+#define BIGGEST_ALIGNMENT 32
+#define STRICT_ALIGNMENT 1
+#define FUNCTION_BOUNDARY 32
+#define PARM_BOUNDARY 32
+#define STACK_BOUNDARY 32
+#define PREFERRED_STACK_BOUNDARY 32
+#define MAX_FIXED_MODE_SIZE 64
+
+#define CONSTANT_ALIGNMENT(EXP, ALIGN)                          \
+  ((TREE_CODE (EXP) == STRING_CST)                              \
+   && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
+
+
+/* Layout of Source Language Data Types.  */
+
+#define INT_TYPE_SIZE 32
+#define SHORT_TYPE_SIZE 16
+#define LONG_TYPE_SIZE 32
+#define LONG_LONG_TYPE_SIZE 64
+#define FLOAT_TYPE_SIZE 32
+#define DOUBLE_TYPE_SIZE 64
+#define LONG_DOUBLE_TYPE_SIZE DOUBLE_TYPE_SIZE
+
+#undef SIZE_TYPE
+#define SIZE_TYPE "unsigned int"
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "int"
+
+
+/* Basic Characteristics of Registers:
+Register Number
+      Register Name
+          Alternate Name
+                Purpose
+0     r0  zero  always zero
+1     r1  at    Assembler Temporary
+2-3   r2-r3     Return Location
+4-7   r4-r7     Register Arguments
+8-15  r8-r15    Caller Saved Registers
+16-22 r16-r22   Callee Saved Registers
+22    r22       Global Offset Table pointer (Linux ABI only)
+23    r23       Thread pointer (Linux ABI only)
+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
+29    r29 ea    Exception Return Address
+30    r30 ba    Breakpoint Return Address
+31    r31 ra    Return Address
+
+32    ctl0 status
+33    ctl1 estatus STATUS saved by exception ?
+34    ctl2 bstatus STATUS saved by break ?
+35    ctl3 ipri    Interrupt Priority Mask ?
+36    ctl4 ecause  Exception Cause ?
+
+37    pc       Not an actual register
+
+38    fake_fp  Fake Frame Pointer which will always be eliminated.
+39    fake_ap  Fake Argument Pointer which will always be eliminated.
+
+40             First Pseudo Register
+
+In addition, r12 is used as the static chain register and r13, r14, and r15
+are clobbered by PLT code sequences.  
+
+The definitions for all the hard register numbers
+are located in nios2.md.
+*/
+
+#define ET_REGNO (24)
+#define GP_REGNO (26)
+#define SP_REGNO (27)
+#define FP_REGNO (28)
+#define EA_REGNO (29)
+#define RA_REGNO (31)
+#define FIRST_RETVAL_REGNO (2)
+#define LAST_RETVAL_REGNO (3)
+#define FIRST_ARG_REGNO (4)
+#define LAST_ARG_REGNO (7)
+#define SC_REGNO (12)
+#define PC_REGNO (37)
+#define FAKE_FP_REGNO (38)
+#define FAKE_AP_REGNO (39)
+
+#define FIRST_PSEUDO_REGISTER 40
+#define NUM_ARG_REGS (LAST_ARG_REGNO - FIRST_ARG_REGNO + 1)
+
+
+
+#define FIXED_REGISTERS                      \
+  {					     \
+/*        +0  1  2  3  4  5  6  7  8  9 */   \
+/*   0 */  1, 1, 0, 0, 0, 0, 0, 0, 0, 0,     \
+/*  10 */  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     \
+/*  20 */  0, 0, TARGET_LINUX_ABI, TARGET_LINUX_ABI, 1, 1, 1, 1, 0, 1,     \
+/*  30 */  1, 0, 1, 1, 1, 1, 1, 1, 1, 1,     \
+  }
+
+/* call used is the same as caller saved
+   + fixed regs + args + ret vals */
+#define CALL_USED_REGISTERS                  \
+  {					     \
+/*        +0  1  2  3  4  5  6  7  8  9 */   \
+/*   0 */  1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     \
+/*  10 */  1, 1, 1, 1, 1, 1, 0, 0, 0, 0,     \
+/*  20 */  0, 0, TARGET_LINUX_ABI, TARGET_LINUX_ABI, 1, 1, 1, 1, 0, 1,     \
+/*  30 */  1, 0, 1, 1, 1, 1, 1, 1, 1, 1,     \
+  }
+
+#define THREAD_POINTER_REGNUM 23
+
+#define HARD_REGNO_NREGS(REGNO, MODE)            \
+  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1)	 \
+   / UNITS_PER_WORD)
+
+#define HARD_REGNO_MODE_OK(REGNO, MODE) 1
+#define MODES_TIEABLE_P(MODE1, MODE2) 1
+
+/* Register Classes.  */
+
+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,
+  SIB_REGS,
+  GP_REGS,
+  ALL_REGS,
+  LIM_REG_CLASSES
+};
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+#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",           \
+     "SIB_REGS",	  \
+     "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},    \
+/* SIB_REGS */	      { 0xfe0c, 0}, 	\
+/* GP_REGS  */        {~0, 0},    \
+/* ALL_REGS */        {~0,~0}}    \
+
+#define GP_REGNO_FIRST 0
+#define GP_REGNO_LAST RA_REGNO
+#define GP_NREGS (GP_REGNO_LAST - GP_REGNO_FIRST + 1)
+#define GP_REGNO_P(REGNO) ((unsigned) ((REGNO) - GP_REGNO_FIRST) < GP_NREGS)
+#define REGNO_REG_CLASS(REGNO) (GP_REGNO_P (REGNO) ? GP_REGS : ALL_REGS)
+
+#define BASE_REG_CLASS ALL_REGS
+#define INDEX_REG_CLASS ALL_REGS
+
+#define REGNO_OK_FOR_BASE_P(REGNO)		\
+  nios2_regno_ok_for_base_p ((REGNO), true)
+#define REGNO_OK_FOR_INDEX_P(REGNO)		\
+  nios2_regno_ok_for_index_p ((REGNO), true)
+
+#define CLASS_MAX_NREGS(CLASS, MODE)             \
+  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1)	 \
+   / UNITS_PER_WORD)
+
+#define SMALL_INT(X) ((X) >= -0x8000 && (X) < 0x8000)
+#define SMALL_INT_UNSIGNED(X) ((X) >= 0 && (X) < 0x10000)
+#define UPPER16_INT(X) (((X) & 0xffff) == 0)
+#define SHIFT_INT(X) ((X) >= 0 && (X) <= 31)
+#define RDWRCTL_INT(X) ((X) >= 0 && (X) <= 31)
+#define CUSTOM_INSN_OPCODE(X) ((X) >= 0 && (X) <= 255)
+
+/* Say that the epilogue uses the return address register.  Note that
+   in the case of sibcalls, the values "used by the epilogue" are
+   considered live at the start of the called function.  */
+#define EPILOGUE_USES(REGNO) ((REGNO) == RA_REGNO)
+
+/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
+   the stack pointer does not matter.  The value is tested only in
+   functions that have frame pointers.
+   No definition is equivalent to always zero.  */
+
+#define EXIT_IGNORE_STACK 1
+
+/* Trampolines use a 5-instruction sequence.  */
+#define TRAMPOLINE_SIZE 20
+
+
+/* Stack Layout and Calling Conventions.  */
+
+/* The downward variants are used by the compiler,
+   the upward ones serve as documentation.  */
+#define STACK_GROWS_DOWNWARD
+#define FRAME_GROWS_UPWARD
+#define ARGS_GROW_UPWARD
+
+#define STARTING_FRAME_OFFSET 0
+#define FIRST_PARM_OFFSET(FUNDECL) 0
+
+/* Before the prologue, RA lives in r31.  */
+#define INCOMING_RETURN_ADDR_RTX  gen_rtx_REG (VOIDmode, RA_REGNO)
+#define RETURN_ADDR_RTX(C,F) nios2_get_return_address (C)
+
+/* Registers That Address the Stack Frame.  */
+#define STACK_POINTER_REGNUM SP_REGNO
+#define STATIC_CHAIN_REGNUM SC_REGNO
+#define PC_REGNUM PC_REGNO
+#define DWARF_FRAME_RETURN_COLUMN RA_REGNO
+
+/* Base register for access to local variables of the function.  We
+   pretend that the frame pointer is a non-existent hard register, and
+   then eliminate it to HARD_FRAME_POINTER_REGNUM. */
+#define FRAME_POINTER_REGNUM FAKE_FP_REGNO
+
+#define HARD_FRAME_POINTER_REGNUM FP_REGNO
+
+/* The argument pointer needs to always be eliminated
+   so it is set to a fake hard register.  */
+#define ARG_POINTER_REGNUM FAKE_AP_REGNO
+
+/* The CFA includes the pretend args.  */
+#define ARG_POINTER_CFA_OFFSET(FNDECL) \
+  (gcc_assert ((FNDECL) == current_function_decl), \
+   FIRST_PARM_OFFSET (FNDECL) + crtl->args.pretend_args_size)
+
+/* Frame/arg pointer elimination settings.  */
+#define ELIMINABLE_REGS                                                 \
+{{ ARG_POINTER_REGNUM,   STACK_POINTER_REGNUM},                         \
+ { ARG_POINTER_REGNUM,   HARD_FRAME_POINTER_REGNUM},                    \
+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},                         \
+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
+
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
+  (OFFSET) = nios2_initial_elimination_offset ((FROM), (TO))
+
+/* Treat LOC as a byte offset from the stack pointer and round it up
+   to the next fully-aligned offset.  */
+#define STACK_ALIGN(LOC)                                                \
+  (((LOC) + ((PREFERRED_STACK_BOUNDARY / 8) - 1))			\
+   & ~((PREFERRED_STACK_BOUNDARY / 8) - 1))
+
+/* Calling convention definitions.  */
+typedef struct nios2_args
+{
+  int regs_used;
+} CUMULATIVE_ARGS;
+
+/* This is to initialize the above unused CUM data type.  */
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
+  (nios2_init_cumulative_args (&CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS))
+
+#define FUNCTION_ARG_PADDING(MODE, TYPE) \
+  (nios2_function_arg_padding ((MODE), (TYPE)))
+
+#define PAD_VARARGS_DOWN \
+  (FUNCTION_ARG_PADDING (TYPE_MODE (type), type) == downward)
+
+#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
+  (nios2_block_reg_padding ((MODE), (TYPE), (FIRST)))
+
+#define FUNCTION_ARG_REGNO_P(REGNO) \
+  ((REGNO) >= FIRST_ARG_REGNO && (REGNO) <= LAST_ARG_REGNO)
+
+/* Passing Function Arguments on the Stack.  */
+#define PUSH_ARGS 0
+#define ACCUMULATE_OUTGOING_ARGS 1
+
+/* We define TARGET_RETURN_IN_MEMORY, so set to zero.  */
+#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/* Profiling.  */
+#define PROFILE_BEFORE_PROLOGUE
+#define NO_PROFILE_COUNTERS 1
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+  nios2_function_profiler ((FILE), (LABELNO))
+
+/* Addressing Modes.  */
+
+#define CONSTANT_ADDRESS_P(X) \
+  (CONSTANT_P (X) && memory_address_p (SImode, X))
+
+#define MAX_REGS_PER_ADDRESS 1
+
+#ifndef REG_OK_STRICT
+#define REG_OK_FOR_BASE_P(X)   REGNO_OK_FOR_BASE_P2 (REGNO (X), 0)
+#define REG_OK_FOR_INDEX_P(X)  REGNO_OK_FOR_INDEX_P2 (REGNO (X), 0)
+#else
+#define REG_OK_FOR_BASE_P(X)   REGNO_OK_FOR_BASE_P2 (REGNO (X), 1)
+#define REG_OK_FOR_INDEX_P(X)  REGNO_OK_FOR_INDEX_P2 (REGNO (X), 1)
+#endif
+
+/* Set if this has a weak declaration.  */
+#define SYMBOL_FLAG_WEAK_DECL   (1 << SYMBOL_FLAG_MACH_DEP_SHIFT)
+#define SYMBOL_REF_WEAK_DECL_P(RTX) \
+  ((SYMBOL_REF_FLAGS (RTX) & SYMBOL_FLAG_WEAK_DECL) != 0)
+
+
+/* True if a symbol is both small and not weak.  In this case, GP-relative
+   access can be used.  GP-relative access cannot be used in
+   position-independent code.  GP-relative access cannot be used for externally
+   defined symbols, because the compilation unit that defines the symbol may
+   place it in a section that cannot be reached from GP.  */
+#define SYMBOL_REF_IN_NIOS2_SMALL_DATA_P(RTX) \
+  (!flag_pic && SYMBOL_REF_SMALL_P (RTX)      \
+   && !SYMBOL_REF_WEAK_DECL_P (RTX)	      \
+   && !SYMBOL_REF_EXTERNAL_P (RTX)	      \
+   && SYMBOL_REF_TLS_MODEL (RTX) == 0)
+
+/* Describing Relative Costs of Operations.  */
+#define MOVE_MAX 4
+#define SLOW_BYTE_ACCESS 1
+
+/* It is as good to call a constant function address as to call an address
+   kept in a register.
+   ??? Not true anymore really. Now that call cannot address full range
+   of memory callr may need to be used */
+
+#define NO_FUNCTION_CSE
+
+/* Position Independent Code.  */
+
+#define PIC_OFFSET_TABLE_REGNUM 22
+#define LEGITIMATE_PIC_OPERAND_P(X) nios2_legitimate_pic_operand_p (X)
+
+/* Define output assembler language.  */
+
+#define ASM_APP_ON "#APP\n"
+#define ASM_APP_OFF "#NO_APP\n"
+
+#define ASM_COMMENT_START "# "
+
+#define GLOBAL_ASM_OP "\t.global\t"
+
+#define REGISTER_NAMES \
+  {		       \
+    "zero", \
+    "at", \
+    "r2", \
+    "r3", \
+    "r4", \
+    "r5", \
+    "r6", \
+    "r7", \
+    "r8", \
+    "r9", \
+    "r10", \
+    "r11", \
+    "r12", \
+    "r13", \
+    "r14", \
+    "r15", \
+    "r16", \
+    "r17", \
+    "r18", \
+    "r19", \
+    "r20", \
+    "r21", \
+    "r22", \
+    "r23", \
+    "et", \
+    "bt", \
+    "gp", \
+    "sp", \
+    "fp", \
+    "ta", \
+    "ba", \
+    "ra", \
+    "status", \
+    "estatus", \
+    "bstatus", \
+    "ipri", \
+    "ecause", \
+    "pc", \
+    "fake_fp", \
+    "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_ADDR_VEC_ELT(FILE, VALUE)  \
+  do									\
+    {									\
+      fputs (integer_asm_op (POINTER_SIZE / BITS_PER_UNIT, TRUE), FILE); \
+      fprintf (FILE, ".L%u\n", (unsigned) (VALUE));			\
+    }									\
+  while (0)
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL)\
+  do									\
+    {									\
+      fputs (integer_asm_op (POINTER_SIZE / BITS_PER_UNIT, TRUE), STREAM); \
+      fprintf (STREAM, ".L%u-.L%u\n", (unsigned) (VALUE), (unsigned) (REL)); \
+    }									\
+  while (0)
+
+
+/* Section directives.  */
+
+/* Output before read-only data.  */
+#define TEXT_SECTION_ASM_OP "\t.section\t.text"
+
+/* Output before writable data.  */
+#define DATA_SECTION_ASM_OP "\t.section\t.data"
+
+/* Output before uninitialized data.  */
+#define BSS_SECTION_ASM_OP "\t.section\t.bss"
+
+/* Output before 'small' uninitialized data.  */
+#define SBSS_SECTION_ASM_OP "\t.section\t.sbss"
+
+#ifndef IN_LIBGCC2
+/* Default the definition of "small data" to 8 bytes. */
+extern unsigned HOST_WIDE_INT nios2_section_threshold;
+#endif
+
+#define NIOS2_DEFAULT_GVALUE 8
+
+/* This says how to output assembler code to declare an
+   uninitialized external linkage data object.  Under SVR4,
+   the linker seems to want the alignment of data objects
+   to depend on their types.  We do exactly that here.  */
+#undef COMMON_ASM_OP
+#define COMMON_ASM_OP   "\t.comm\t"
+
+#define ASM_OUTPUT_ALIGN(FILE, LOG)		     \
+  do {						     \
+    fprintf ((FILE), "%s%d\n", ALIGN_ASM_OP, (LOG)); \
+  } while (0)
+
+#undef  ASM_OUTPUT_ALIGNED_COMMON
+#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN)              \
+do                                                                      \
+  {									\
+    fprintf ((FILE), "%s", COMMON_ASM_OP);				\
+    assemble_name ((FILE), (NAME));					\
+    fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED",%u\n", (SIZE),	\
+	     (ALIGN) / BITS_PER_UNIT);					\
+  }									\
+while (0)
+
+
+/* This says how to output assembler code to declare an
+   uninitialized internal linkage data object.  Under SVR4,
+   the linker seems to want the alignment of data objects
+   to depend on their types.  We do exactly that here.  */
+
+#undef  ASM_OUTPUT_ALIGNED_LOCAL
+#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN)               \
+do {                                                                    \
+  if ((SIZE) <= nios2_section_threshold)                                \
+    switch_to_section (sbss_section);					\
+  else                                                                  \
+    switch_to_section (bss_section);					\
+  ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object");                     \
+  if (!flag_inhibit_size_directive)                                     \
+    ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, SIZE);                       \
+  ASM_OUTPUT_ALIGN ((FILE), exact_log2((ALIGN) / BITS_PER_UNIT));       \
+  ASM_OUTPUT_LABEL(FILE, NAME);                                         \
+  ASM_OUTPUT_SKIP((FILE), (SIZE) ? (SIZE) : 1);                         \
+} while (0)
+
+/* Put the jump tables in .text because when using position-independent code,
+   Nios II elf has no relocation that can represent arbitrary differences
+   between symbols in different sections.  */
+#define JUMP_TABLES_IN_TEXT_SECTION 1
+
+/* Exception Handling */
+
+/* Describe __builtin_eh_return.  */
+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, LAST_RETVAL_REGNO)
+#define EH_RETURN_DATA_REGNO(N) ((N) <= (LAST_ARG_REGNO - FIRST_ARG_REGNO) \
+				 ? (N) + FIRST_ARG_REGNO : INVALID_REGNUM)
+
+/* Nios II has no appropriate relocations for a 32-bit PC-relative or
+   section-relative pointer encoding.  This therefore always chooses an
+   absolute representation for pointers.  An unfortunate consequence of
+   this is that ld complains about the absolute fde encoding when linking
+   with -shared or -fpie, but the warning is harmless and there seems to
+   be no good way to suppress it.  */
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL)		\
+  (flag_pic ? DW_EH_PE_aligned : DW_EH_PE_sdata4)
+
+/* Misc. Parameters.  */
+
+#define STORE_FLAG_VALUE 1
+#define Pmode SImode
+#define FUNCTION_MODE QImode
+
+#define CASE_VECTOR_MODE Pmode
+
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+
+#define LOAD_EXTEND_OP(MODE) (ZERO_EXTEND)
+
+#define WORD_REGISTER_OPERATIONS
+
+#endif /* GCC_NIOS2_H */
Index: gcc/config/nios2/predicates.md
===================================================================
--- gcc/config/nios2/predicates.md	(revision 0)
+++ gcc/config/nios2/predicates.md	(revision 0)
@@ -0,0 +1,73 @@ 
+;; Predicate definitions for Altera Nios II.
+;; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+;; Contributed by Chung-Lin Tang <cltang@codesourcery.com>
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+(define_predicate "const_0_operand"
+  (and (match_code "const_int,const_double,const_vector")
+       (match_test "op == CONST0_RTX (GET_MODE (op))")))
+
+(define_predicate "reg_or_0_operand"
+  (ior (match_operand 0 "const_0_operand")
+       (match_operand 0 "register_operand")))
+
+(define_predicate "const_uns_arith_operand"
+  (and (match_code "const_int")
+       (match_test "SMALL_INT_UNSIGNED (INTVAL (op))")))
+
+(define_predicate "uns_arith_operand"
+  (ior (match_operand 0 "const_uns_arith_operand")
+       (match_operand 0 "register_operand")))
+
+(define_predicate "const_arith_operand"
+  (and (match_code "const_int")
+       (match_test "SMALL_INT (INTVAL (op))")))
+
+(define_predicate "arith_operand"
+  (ior (match_operand 0 "const_arith_operand")
+       (match_operand 0 "register_operand")
+       (match_test "nios2_unspec_reloc_p (op)")))
+
+(define_predicate "const_logical_operand"
+  (and (match_code "const_int")
+       (match_test "(INTVAL (op) & 0xffff) == 0
+                    || (INTVAL (op) & 0xffff0000) == 0")))
+
+(define_predicate "logical_operand"
+  (ior (match_operand 0 "const_logical_operand")
+       (match_operand 0 "register_operand")))
+
+(define_predicate "const_shift_operand"
+  (and (match_code "const_int")
+       (match_test "SHIFT_INT (INTVAL (op))")))
+
+(define_predicate "shift_operand"
+  (ior (match_operand 0 "const_shift_operand")
+       (match_operand 0 "register_operand")))
+
+(define_predicate "call_operand"
+  (ior (match_operand 0 "immediate_operand")
+       (match_operand 0 "register_operand")))
+
+(define_predicate "rdwrctl_operand"
+  (and (match_code "const_int")
+       (match_test "RDWRCTL_INT (INTVAL (op))")))
+
+(define_predicate "custom_insn_opcode"
+  (and (match_code "const_int")
+       (match_test "CUSTOM_INSN_OPCODE (INTVAL (op))")))
Index: gcc/config/nios2/nios2-opts.h
===================================================================
--- gcc/config/nios2/nios2-opts.h	(revision 0)
+++ gcc/config/nios2/nios2-opts.h	(revision 0)
@@ -0,0 +1,69 @@ 
+/* Definitions for option handling for Nios II.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef NIOS2_OPTS_H
+#define NIOS2_OPTS_H
+
+/* Enumeration of all FPU insn codes.  */
+#define N2FPU_ALL_CODES							\
+  N2FPU_CODE(fadds) N2FPU_CODE(fsubs) N2FPU_CODE(fmuls) N2FPU_CODE(fdivs) \
+  N2FPU_CODE(fmins) N2FPU_CODE(fmaxs)					\
+  N2FPU_CODE(fnegs) N2FPU_CODE(fabss) N2FPU_CODE(fsqrts)		\
+  N2FPU_CODE(fsins) N2FPU_CODE(fcoss) N2FPU_CODE(ftans) N2FPU_CODE(fatans) \
+  N2FPU_CODE(fexps) N2FPU_CODE(flogs)					\
+  N2FPU_CODE(fcmpeqs) N2FPU_CODE(fcmpnes)				\
+  N2FPU_CODE(fcmplts) N2FPU_CODE(fcmples)				\
+  N2FPU_CODE(fcmpgts) N2FPU_CODE(fcmpges)				\
+  									\
+  N2FPU_CODE(faddd) N2FPU_CODE(fsubd) N2FPU_CODE(fmuld) N2FPU_CODE(fdivd) \
+  N2FPU_CODE(fmind) N2FPU_CODE(fmaxd)					\
+  N2FPU_CODE(fnegd) N2FPU_CODE(fabsd) N2FPU_CODE(fsqrtd)		\
+  N2FPU_CODE(fsind) N2FPU_CODE(fcosd) N2FPU_CODE(ftand) N2FPU_CODE(fatand) \
+  N2FPU_CODE(fexpd) N2FPU_CODE(flogd)					\
+  N2FPU_CODE(fcmpeqd) N2FPU_CODE(fcmpned)				\
+  N2FPU_CODE(fcmpltd) N2FPU_CODE(fcmpled)				\
+  N2FPU_CODE(fcmpgtd) N2FPU_CODE(fcmpged)				\
+  									\
+  N2FPU_CODE(floatis) N2FPU_CODE(floatus)				\
+  N2FPU_CODE(floatid) N2FPU_CODE(floatud)				\
+  N2FPU_CODE(fixsi) N2FPU_CODE(fixsu)					\
+  N2FPU_CODE(fixdi) N2FPU_CODE(fixdu)					\
+  N2FPU_CODE(fextsd) N2FPU_CODE(ftruncds)				\
+									\
+  N2FPU_CODE(fwrx) N2FPU_CODE(fwry)					\
+  N2FPU_CODE(frdxlo) N2FPU_CODE(frdxhi) N2FPU_CODE(frdy)
+
+enum n2fpu_code {
+#define N2FPU_CODE(name) n2fpu_ ## name,
+  N2FPU_ALL_CODES
+#undef N2FPU_CODE
+  n2fpu_code_num
+};
+
+/* An enumeration to indicate the custom code status; if values within 0--255
+   are registered to an FPU insn, or custom insn.  */
+enum nios2_ccs_code
+{
+  CCS_UNUSED,
+  CCS_FPU,
+  CCS_BUILTIN_CALL
+};
+
+#endif
+
Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(revision 198891)
+++ gcc/config.gcc	(working copy)
@@ -415,6 +415,10 @@  mips*-*-*)
 	extra_headers="loongson.h"
 	extra_options="${extra_options} g.opt mips/mips-tables.opt"
 	;;
+nios2-*-*)
+	cpu_type=nios2
+	extra_options="${extra_options} g.opt"
+	;;	
 picochip-*-*)
         cpu_type=picochip
         ;;
@@ -1983,6 +1987,19 @@  mn10300-*-*)
 	use_collect2=no
 	use_gcc_stdint=wrap
 	;;
+nios2-*-*)
+	tm_file="elfos.h ${tm_file}"
+        tmake_file="${tmake_file} nios2/t-nios2"
+        case ${target} in
+        nios2-*-linux*)
+                tm_file="${tm_file} gnu-user.h linux.h glibc-stdint.h nios2/linux.h "
+                ;;
+	nios2-*-elf*)
+		tm_file="${tm_file} newlib-stdint.h nios2/elf.h"
+		extra_options="${extra_options} nios2/elf.opt"
+		;;
+        esac
+	;;
 pdp11-*-*)
 	tm_file="${tm_file} newlib-stdint.h"
 	use_gcc_stdint=wrap
Index: gcc/configure
===================================================================
--- gcc/configure	(revision 198891)
+++ gcc/configure	(working copy)
@@ -23255,6 +23255,13 @@  foo:
 	tls_first_minor=19
 	tls_as_opt='--fatal-warnings'
 	;;
+  nios2-*-*)
+      conftest_s='
+	.section ".tdata","awT",@progbits'
+	tls_first_major=2
+	tls_first_minor=23
+	tls_as_opt="--fatal-warnings"
+	;;
   aarch64*-*-*)
     conftest_s='
 	.section ".tdata","awT",%progbits
@@ -25983,6 +25990,7 @@  esac
 # version to the per-target configury.
 case "$cpu_type" in
   alpha | arm | avr | bfin | cris | i386 | m32c | m68k | microblaze | mips \
+  | nios2 \
   | pa | rs6000 | score | sparc | spu | tilegx | tilepro | xstormy16 | xtensa)
     insn="nop"
     ;;
Index: gcc/configure.ac
===================================================================
--- gcc/configure.ac	(revision 198891)
+++ gcc/configure.ac	(working copy)
@@ -3014,6 +3014,13 @@  foo:
 	tls_first_minor=19
 	tls_as_opt='--fatal-warnings'
 	;;
+  nios2-*-*)
+      conftest_s='
+	.section ".tdata","awT",@progbits'
+	tls_first_major=2
+	tls_first_minor=23
+	tls_as_opt="--fatal-warnings"
+	;;
   aarch64*-*-*)
     conftest_s='
 	.section ".tdata","awT",%progbits
@@ -4195,6 +4202,7 @@  esac
 # version to the per-target configury.
 case "$cpu_type" in
   alpha | arm | avr | bfin | cris | i386 | m32c | m68k | microblaze | mips \
+  | nios2 \
   | pa | rs6000 | score | sparc | spu | tilegx | tilepro | xstormy16 | xtensa)
     insn="nop"
     ;;
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 198891)
+++ gcc/doc/extend.texi	(working copy)
@@ -3674,6 +3674,14 @@  int core2_func (void) __attribute__ ((__target__ (
 int sse3_func (void) __attribute__ ((__target__ ("sse3")));
 @end smallexample
 
+You can either use multiple
+strings to specify multiple options, or separate the options
+with a comma (@samp{,}).
+
+The @code{target} attribute is presently implemented for
+i386/x86_64, PowerPC, and Nios II targets only.
+The options supported are specific to each target.
+
 On the 386, the following options are allowed:
 
 @table @samp
@@ -3995,20 +4003,36 @@  compilation tunes for the @var{CPU} architecture,
 default tuning specified on the command line.
 @end table
 
-On the 386/x86_64 and PowerPC back ends, you can use either multiple
-strings to specify multiple options, or you can separate the option
-with a comma (@code{,}).
+When compiling for Nios II, the following options are allowed:
 
+@table @samp
+@item custom-@var{insn}=@var{N}
+@itemx no-custom-@var{insn}
+@cindex @code{target("custom-@var{insn}=@var{N}")} attribute
+@cindex @code{target("no-custom-@var{insn}")} attribute
+Each @samp{custom-@var{insn}=@var{N}} attribute locally enables use of a
+custom instruction with encoding @var{N} when generating code that uses 
+@var{insn}.  Similarly, @samp{no-custom-@var{insn}} locally inhibits use of
+the custom instruction @var{insn}.
+These target attributes correspond to the
+@option{-mcustom-@var{insn}=@var{N}} and @option{-mno-custom-@var{insn}}
+command-line options, and support the same set of @var{insn} keywords.
+@xref{Nios II Options}, for more information.
+
+@item custom-fpu-cfg=@var{name}
+@cindex @code{target("custom-fpu-cfg=@var{name}")} attribute
+This attribute corresponds to the @option{-mcustom-fpu-cfg=@var{name}}
+command-line option, to select a predefined set of custom instructions
+named @var{name}.
+@xref{Nios II Options}, for more information.
+@end table
+
 On the 386/x86_64 and PowerPC back ends, the inliner does not inline a
 function that has different target options than the caller, unless the
 callee has a subset of the target options of the caller.  For example
 a function declared with @code{target("sse3")} can inline a function
 with @code{target("sse2")}, since @code{-msse3} implies @code{-msse2}.
 
-The @code{target} attribute is not implemented in GCC versions earlier
-than 4.4 for the i386/x86_64 and 4.6 for the PowerPC back ends.  It is
-not currently implemented for other back ends.
-
 @item tiny_data
 @cindex tiny data section on the H8/300H and H8S
 Use this attribute on the H8/300H and H8S to indicate that the specified
@@ -8797,6 +8821,7 @@  instructions, but allow the compiler to schedule t
 
 @menu
 * Alpha Built-in Functions::
+* Altera Nios II Built-in Functions::
 * ARM iWMMXt Built-in Functions::
 * ARM NEON Intrinsics::
 * AVR Built-in Functions::
@@ -8902,6 +8927,110 @@  void *__builtin_thread_pointer (void)
 void __builtin_set_thread_pointer (void *)
 @end smallexample
 
+@node Altera Nios II Built-in Functions
+@subsection Altera Nios II Built-in Functions
+
+These built-in functions are available for the Altera Nios II
+family of processors.
+
+The following built-in functions are always available.  They
+all generate the machine instruction that is part of the name.
+
+@example
+int __builtin_ldbio (volatile const void *)
+int __builtin_ldbuio (volatile const void *)
+int __builtin_ldhio (volatile const void *)
+int __builtin_ldhuio (volatile const void *)
+int __builtin_ldwio (volatile const void *)
+void __builtin_stbio (volatile void *, int)
+void __builtin_sthio (volatile void *, int)
+void __builtin_stwio (volatile void *, int)
+void __builtin_sync (void)
+int __builtin_rdctl (int) 
+void __builtin_wrctl (int, int)
+@end example
+
+The following built-in functions are always available.  They
+all generate a Nios II Custom Instruction. The name of the
+function represents the types that the function takes and
+returns. The letter before the @code{n} is the return type
+or void if absent. The @code{n} represnts the first parameter
+to all the custom instructions, the custom instruction number.
+The two letters after the @code{n} represent the up to two
+parameters to the function.
+
+The letters reprsent the following data types:
+@table @code
+@item <no letter>
+@code{void} for return type and no parameter for parameter types.
+
+@item i
+@code{int} for return type and parameter type
+
+@item f
+@code{float} for return type and parameter type
+
+@item p
+@code{void *} for return type and parameter type
+
+@end table
+
+And the function names are:
+@example
+void __builtin_custom_n (void)
+void __builtin_custom_ni (int)
+void __builtin_custom_nf (float)
+void __builtin_custom_np (void *)
+void __builtin_custom_nii (int, int)
+void __builtin_custom_nif (int, float)
+void __builtin_custom_nip (int, void *)
+void __builtin_custom_nfi (float, int)
+void __builtin_custom_nff (float, float)
+void __builtin_custom_nfp (float, void *)
+void __builtin_custom_npi (void *, int)
+void __builtin_custom_npf (void *, float)
+void __builtin_custom_npp (void *, void *)
+int __builtin_custom_in (void)
+int __builtin_custom_ini (int)
+int __builtin_custom_inf (float)
+int __builtin_custom_inp (void *)
+int __builtin_custom_inii (int, int)
+int __builtin_custom_inif (int, float)
+int __builtin_custom_inip (int, void *)
+int __builtin_custom_infi (float, int)
+int __builtin_custom_inff (float, float)
+int __builtin_custom_infp (float, void *)
+int __builtin_custom_inpi (void *, int)
+int __builtin_custom_inpf (void *, float)
+int __builtin_custom_inpp (void *, void *)
+float __builtin_custom_fn (void)
+float __builtin_custom_fni (int)
+float __builtin_custom_fnf (float)
+float __builtin_custom_fnp (void *)
+float __builtin_custom_fnii (int, int)
+float __builtin_custom_fnif (int, float)
+float __builtin_custom_fnip (int, void *)
+float __builtin_custom_fnfi (float, int)
+float __builtin_custom_fnff (float, float)
+float __builtin_custom_fnfp (float, void *)
+float __builtin_custom_fnpi (void *, int)
+float __builtin_custom_fnpf (void *, float)
+float __builtin_custom_fnpp (void *, void *)
+void * __builtin_custom_pn (void)
+void * __builtin_custom_pni (int)
+void * __builtin_custom_pnf (float)
+void * __builtin_custom_pnp (void *)
+void * __builtin_custom_pnii (int, int)
+void * __builtin_custom_pnif (int, float)
+void * __builtin_custom_pnip (int, void *)
+void * __builtin_custom_pnfi (float, int)
+void * __builtin_custom_pnff (float, float)
+void * __builtin_custom_pnfp (float, void *)
+void * __builtin_custom_pnpi (void *, int)
+void * __builtin_custom_pnpf (void *, float)
+void * __builtin_custom_pnpp (void *, void *)
+@end example
+
 @node ARM iWMMXt Built-in Functions
 @subsection ARM iWMMXt Built-in Functions
 
@@ -14930,9 +15059,8 @@  function.  The parenthesis around the options is o
 @xref{Function Attributes}, for more information about the
 @code{target} attribute and the attribute syntax.
 
-The @code{#pragma GCC target} attribute is not implemented in GCC versions earlier
-than 4.4 for the i386/x86_64 and 4.6 for the PowerPC back ends.  At
-present, it is not implemented for other back ends.
+The @code{#pragma GCC target} pragma is presently implemented for
+i386/x86_64, PowerPC, and Nios II targets only.
 @end table
 
 @table @code
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 198891)
+++ gcc/doc/invoke.texi	(working copy)
@@ -795,6 +795,16 @@  Objective-C and Objective-C++ Dialects}.
 @emph{Moxie Options}
 @gccoptlist{-meb -mel -mno-crt0}
 
+@emph{Nios II Options}
+@gccoptlist{-G @var{num} -mel -meb @gol
+-mno-bypass-cache -mbypass-cache @gol
+-mno-cache-volatile -mcache-volatile @gol
+-mno-fast-sw-div -mfast-sw-div @gol
+-mhw-mul -mno-hw-mul -mhw-mulx -mno-hw-mulx -mno-hw-div -mhw-div @gol
+-mcustom-@var{insn}=@var{N} -mno-custom-@var{insn} @gol
+-mcustom-fpu-cfg=@var{name} @gol
+-mhal -msmallc -msys-crt0=@var{name} -msys-lib=@var{name}}
+
 @emph{PDP-11 Options}
 @gccoptlist{-mfpu  -msoft-float  -mac0  -mno-ac0  -m40  -m45  -m10 @gol
 -mbcopy  -mbcopy-builtin  -mint32  -mno-int16 @gol
@@ -10918,6 +10928,7 @@  platform.
 * MMIX Options::
 * MN10300 Options::
 * Moxie Options::
+* Nios II Options::
 * PDP-11 Options::
 * picoChip Options::
 * PowerPC Options::
@@ -17044,6 +17055,270 @@  Do not link in the C run-time initialization objec
 
 @end table
 
+@node Nios II Options
+@subsection Nios II Options
+@cindex Nios II options
+@cindex Altera Nios II options
+
+These are the options defined for the Altera Nios II processor.
+
+@table @gcctabopt
+
+@item -G @var{num}
+@opindex G
+@cindex smaller data references
+Put global and static objects less than or equal to @var{num} bytes
+into the small data or BSS sections instead of the normal data or BSS
+sections.  The default value of @var{num} is 8.
+
+@item -mel
+@itemx -meb
+@opindex mel
+@opindex meb
+Generate little-endian (default) or big-endian (experimental) code,
+respectively.
+
+@item -mbypass-cache
+@itemx -mno-bypass-cache
+@opindex mno-bypass-cache
+@opindex mbypass-cache
+Force all load and store instructions to always bypass cache by 
+using I/O variants of the instructions. The default is not to
+bypass the cache.
+
+@item -mno-cache-volatile 
+@itemx -mcache-volatile       
+@opindex mcache-volatile 
+@opindex mno-cache-volatile
+Volatile memory access bypass the cache using the I/O variants of 
+the load and store instructions. The default is not to bypass the cache.
+
+@item -mno-fast-sw-div
+@itemx -mfast-sw-div
+@opindex mno-fast-sw-div
+@opindex mfast-sw-div
+Do not use table-based fast divide for small numbers. The default 
+is to use the fast divide at @option{-O3} and above.
+
+@item -mno-hw-mul
+@itemx -mhw-mul
+@itemx -mno-hw-mulx
+@itemx -mhw-mulx
+@itemx -mno-hw-div
+@itemx -mhw-div
+@opindex mno-hw-mul
+@opindex mhw-mul
+@opindex mno-hw-mulx
+@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}.
+
+@item -mcustom-@var{insn}=@var{N}
+@itemx -mno-custom-@var{insn}
+@opindex mcustom-@var{insn}
+@opindex mno-custom-@var{insn}
+Each @option{-mcustom-@var{insn}=@var{N}} option enables use of a
+custom instruction with encoding @var{N} when generating code that uses 
+@var{insn}.  For example, @code{-mcustom-fadds=253} generates custom
+instruction 253 for single-precision floating-point add operations instead
+of the default behavior of using a library call.
+
+The following values of @var{insn} are supported.  Except as otherwise
+noted, floating-point operations are expected to be implemented with
+normal IEEE 754 semantics and correspond directly to the C operators or the
+equivalent GCC built-in functions (@pxref{Other Builtins}).
+
+Single-precision floating point:
+@table @asis
+
+@item @samp{fadds}, @samp{fsubs}, @samp{fdivs}, @samp{fmuls}
+Binary arithmetic operations.
+
+@item @samp{fnegs}
+Unary negation.
+
+@item @samp{fabss}
+Unary absolute value.
+
+@item @samp{fcmpeqs}, @samp{fcmpges}, @samp{fcmpgts}, @samp{fcmples}, @samp{fcmplts}, @samp{fcmpnes}
+Comparison operations.
+
+@item @samp{fmins}, @samp{fmaxs}
+Floating-point minimum and maximum.  These instructions are only
+generated if @option{-ffinite-math-only} is specified.
+
+@item @samp{fsqrts}
+Unary square root operation.
+
+@item @samp{fcoss}, @samp{fsins}, @samp{ftans}, @samp{fatans}, @samp{fexps}, @samp{flogs}
+Floating-point trigonometric and exponential functions.  These instructions
+are only generated if @option{-funsafe-math-optimizations} is also specified.
+
+@end table
+
+Double-precision floating point:
+@table @asis
+
+@item @samp{faddd}, @samp{fsubd}, @samp{fdivd}, @samp{fmuld}
+Binary arithmetic operations.
+
+@item @samp{fnegd}
+Unary negation.
+
+@item @samp{fabsd}
+Unary absolute value.
+
+@item @samp{fcmpeqd}, @samp{fcmpged}, @samp{fcmpgtd}, @samp{fcmpled}, @samp{fcmpltd}, @samp{fcmpned}
+Comparison operations.
+
+@item @samp{fmind}, @samp{fmaxd}
+Double-precision minimum and maximum.  These instructions are only
+generated if @option{-ffinite-math-only} is specified.
+
+@item @samp{fsqrtd}
+Unary square root operation.
+
+@item @samp{fcosd}, @samp{fsind}, @samp{ftand}, @samp{fatand}, @samp{fexpd}, @samp{flogd}
+Double-precision trigonometric and exponential functions.  These instructions
+are only generated if @option{-funsafe-math-optimizations} is also specified.
+
+@end table
+
+Conversions:
+@table @asis
+@item @samp{fextsd}
+Conversion from single precision to double precision.
+
+@item @samp{ftruncds}
+Conversion from double precision to single precision.
+
+@item @samp{fixsi}, @samp{fixsu}, @samp{fixdi}, @samp{fixdu}
+Conversion from floating point to signed or unsigned integer types, with
+truncation towards zero.
+
+@item @samp{floatis}, @samp{floatus}, @samp{floatid}, @samp{floatud}
+Conversion from signed or unsigned integer types to floating-point types.
+
+@end table
+
+In addition, all of the following transfer instructions for internal
+registers X and Y must be provided to use any of the double-precision
+floating-point instructions.  Custom instructions taking two
+double-precision source operands expect the first operand in the
+64-bit register X.  The other operand (or only operand of a unary
+operation) is given to the custom arithmetic instruction with the
+least significant half in source register @var{src1} and the most
+significant half in @var{src2}.  A custom instruction that returns a
+double-precision result returns the most significant 32 bits in the
+destination register and the other half in 32-bit register Y.  
+GCC automatically generates the necessary code sequences to write
+register X and/or read register Y when double-precision floating-point
+instructions are used.
+
+@table @asis
+
+@item @samp{fwrx}
+Write @var{src1} into the least significant half of X and @var{src2} into
+the most significant half of X.
+
+@item @samp{fwry}
+Write @var{src1} into Y.
+
+@item @samp{frdxhi}, @samp{frdxlo}
+Read the most or least (respectively) significant half of X and store it in
+@var{dest}.
+
+@item @samp{frdy}
+Read the value of Y and store it into @var{dest}.
+@end table
+
+Note that you can gain more local control over generation of Nios II custom
+instructions by using the @code{target("custom-@var{insn}=@var{N}")}
+and @code{target("no-custom-@var{insn}")} function attributes
+(@pxref{Function Attributes})
+or pragmas (@pxref{Function Specific Option Pragmas}).
+
+@item -mcustom-fpu-cfg=@var{name}
+@opindex mcustom-fpu-cfg
+
+This option enables a predefined, named set of custom instruction encodings
+(see @option{-mcustom-@var{insn}} above).  
+Currently, the following sets are defined:
+
+@option{-mcustom-fpu-cfg=60-1} is equivalent to:
+@gccoptlist{-mcustom-fmuls=252 @gol
+-mcustom-fadds=253 @gol
+-mcustom-fsubs=254 @gol
+-fsingle-precision-constant}
+
+@option{-mcustom-fpu-cfg=60-2} is equivalent to:
+@gccoptlist{-mcustom-fmuls=252 @gol
+-mcustom-fadds=253 @gol
+-mcustom-fsubs=254 @gol
+-mcustom-fdivs=255 @gol
+-fsingle-precision-constant}
+
+@option{-mcustom-fpu-cfg=72-3} is equivalent to:
+@gccoptlist{-mcustom-floatus=243 @gol
+-mcustom-fixsi=244 @gol
+-mcustom-floatis=245 @gol
+-mcustom-fcmpgts=246 @gol
+-mcustom-fcmples=249 @gol
+-mcustom-fcmpeqs=250 @gol
+-mcustom-fcmpnes=251 @gol
+-mcustom-fmuls=252 @gol
+-mcustom-fadds=253 @gol
+-mcustom-fsubs=254 @gol
+-mcustom-fdivs=255 @gol
+-fsingle-precision-constant}
+
+Custom instruction assignments given by individual
+@option{-mcustom-@var{insn}=} options override those given by
+@option{-mcustom-fpu-cfg=}, regardless of the
+order of the options on the command line.
+
+Note that you can gain more local control over selection of a FPU
+configuration by using the @code{target("custom-fpu-cfg=@var{name}")}
+function attribute (@pxref{Function Attributes})
+or pragma (@pxref{Function Specific Option Pragmas}).
+
+@end table
+
+These additional @samp{-m} options are available for the Altera Nios II
+ELF (bare-metal) target:
+
+@table @gcctabopt
+
+@item -mhal
+@opindex mhal
+Link with HAL BSP.  This suppresses linking with the GCC-provided C runtime
+startup and termination code, and is typically used in conjunction with
+@option{-msys-crt0=} to specify the location of the alternate startup code
+provided by the HAL BSP.
+
+@item -msmallc
+@opindex msmallc
+Link with a limited version of the C library, @option{-lsmallc}, rather than
+Newlib.
+
+@item -msys-crt0=@var{startfile}
+@opindex msys-crt0
+@var{startfile} is the file name of the startfile (crt0) to use 
+when linking.  This option is only useful in conjunction with @option{-mhal}.
+
+@item -msys-lib=@var{systemlib}
+@opindex msys-lib
+@var{systemlib} is the library name of the library that provides
+low-level system calls required by the C library,
+e.g. @code{read} and @code{write}.
+This option is typically used to link with a library provided by a HAL BSP.
+
+@end table
+
+
 @node PDP-11 Options
 @subsection PDP-11 Options
 @cindex PDP-11 Options
Index: gcc/doc/md.texi
===================================================================
--- gcc/doc/md.texi	(revision 198891)
+++ gcc/doc/md.texi	(working copy)
@@ -3053,6 +3053,59 @@  A constant in the range of 0 to @minus{}255.
 
 @end table
 
+@item Nios II family---@file{config/nios2/nios2.h}
+@table @code
+
+@item I
+Integer that is valid as an immediate operand in an
+instruction taking a signed 16-bit number. Range
+@minus{}32768 to 32767.
+
+@item J
+Integer that is valid as an immediate operand in an
+instruction taking an unsigned 16-bit number. Range
+0 to 65535.
+
+@item K
+Integer that is valid as an immediate operand in an
+instruction taking only the upper 16-bits of a
+32-bit number. Range 32-bit numbers with the lower
+16-bits being 0.
+
+@item L
+Integer that is valid as an immediate operand for a 
+shift instruction. Range 0 to 31.
+
+@item M
+Integer that is valid as an immediate operand for
+only the value 0. Can be used in conjunction with
+the format modifier @code{z} to use @code{r0}
+instead of @code{0} in the assembly output.
+
+@item N
+Integer that is valid as an immediate operand for
+a custom instruction opcode. Range 0 to 255.
+
+@item S
+Matches immediates which are addresses in the small
+data section and therefore can be added to @code{gp}
+as a 16-bit immediate to re-create their 32-bit value.
+
+@item T
+A @code{const} wrapped @code{UNSPEC} expression,
+representing a supported PIC or TLS relocation.
+
+@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 PDP-11---@file{config/pdp11/constraints.md}
 @table @code
 @item a