diff options
author | Nigel Kukard <nkukard@lbsd.net> | 2008-03-30 08:05:22 +0000 |
---|---|---|
committer | Nigel Kukard <nkukard@lbsd.net> | 2008-03-30 08:05:22 +0000 |
commit | 2c9c9bcdf2c527e6a6772d90323dd02ea27e53a6 (patch) | |
tree | 94ec7c1d68b409c48b0340f04ac31722382765a5 /toolchain/gcc/3.4.4/900-nios2.patch | |
parent | 5929cc768b9aa897888340d9b5821e8af9a1ce2e (diff) |
* Remove legacy GCC 3.4.x versions
Diffstat (limited to 'toolchain/gcc/3.4.4/900-nios2.patch')
-rw-r--r-- | toolchain/gcc/3.4.4/900-nios2.patch | 10211 |
1 files changed, 0 insertions, 10211 deletions
diff --git a/toolchain/gcc/3.4.4/900-nios2.patch b/toolchain/gcc/3.4.4/900-nios2.patch deleted file mode 100644 index bfa06a21c..000000000 --- a/toolchain/gcc/3.4.4/900-nios2.patch +++ /dev/null @@ -1,10211 +0,0 @@ ---- gcc-3.4.3/gcc/Makefile.in -+++ gcc-3.4.3-nios2/gcc/Makefile.in -@@ -3085,7 +3085,7 @@ install-mkheaders: stmp-int-hdrs $(STMP_ - $(INSTALL_DATA) $(srcdir)/README-fixinc \ - $(DESTDIR)$(itoolsdatadir)/include/README ; \ - $(INSTALL_SCRIPT) fixinc.sh $(DESTDIR)$(itoolsdir)/fixinc.sh ; \ -- $(INSTALL_PROGRAM) fixinc/fixincl $(DESTDIR)$(itoolsdir)/fixincl ; \ -+ $(INSTALL_PROGRAM) fixinc/fixincl$(build_exeext) $(DESTDIR)$(itoolsdir)/fixincl$(build_exeext) ; \ - $(INSTALL_DATA) $(srcdir)/gsyslimits.h \ - $(DESTDIR)$(itoolsdatadir)/gsyslimits.h ; \ - else :; fi ---- gcc-3.4.3/gcc/combine.c -+++ gcc-3.4.3-nios2/gcc/combine.c -@@ -4380,6 +4380,14 @@ combine_simplify_rtx (rtx x, enum machin - mode); - } - -+#ifndef __nios2__ -+/* This screws up Nios II in this test case: -+ -+if (x & 1) -+ return 2; -+else -+ return 3; -+*/ - else if (STORE_FLAG_VALUE == 1 - && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT - && op1 == const0_rtx -@@ -4391,6 +4399,7 @@ combine_simplify_rtx (rtx x, enum machin - gen_lowpart_for_combine (mode, op0), - const1_rtx); - } -+#endif - - else if (STORE_FLAG_VALUE == 1 - && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT ---- gcc-3.4.3/gcc/config/nios2/crti.asm -+++ gcc-3.4.3-nios2/gcc/config/nios2/crti.asm -@@ -0,0 +1,88 @@ -+/* -+ Copyright (C) 2003 -+ by Jonah Graham (jgraham@altera.com) -+ -+This file is free software; you can redistribute it and/or modify it -+under the terms of the GNU General Public License as published by the -+Free Software Foundation; either version 2, or (at your option) any -+later version. -+ -+In addition to the permissions in the GNU General Public License, the -+Free Software Foundation gives you unlimited permission to link the -+compiled version of this file with other programs, and to distribute -+those programs without any restriction coming from the use of this -+file. (The General Public License restrictions do apply in other -+respects; for example, they cover modification of the file, and -+distribution when not linked into another program.) -+ -+This file 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 this program; see the file COPYING. If not, write to -+the Free Software Foundation, 59 Temple Place - Suite 330, -+Boston, MA 02111-1307, USA. -+ -+ As a special exception, if you link this library with files -+ compiled with GCC to produce an executable, this does not cause -+ the resulting executable to be covered by the GNU General Public License. -+ This exception does not however invalidate any other reasons why -+ the executable file might be covered by the GNU General Public License. -+ -+ -+This file just make a stack frame for the contents of the .fini and -+.init sections. Users may put any desired instructions in those -+sections. -+ -+ -+While technically any code can be put in the init and fini sections -+most stuff will not work other than stuff which obeys the call frame -+and ABI. All the call-preserved registers are saved, the call clobbered -+registers should have been saved by the code calling init and fini. -+ -+See crtstuff.c for an example of code that inserts itself in the -+init and fini sections. -+ -+See crt0.s for the code that calls init and fini. -+*/ -+ -+ .file "crti.asm" -+ -+ .section ".init" -+ .align 2 -+ .global _init -+_init: -+ addi sp, sp, -48 -+ stw ra, 44(sp) -+ stw r23, 40(sp) -+ stw r22, 36(sp) -+ stw r21, 32(sp) -+ stw r20, 28(sp) -+ stw r19, 24(sp) -+ stw r18, 20(sp) -+ stw r17, 16(sp) -+ stw r16, 12(sp) -+ stw fp, 8(sp) -+ mov fp, sp -+ -+ -+ .section ".fini" -+ .align 2 -+ .global _fini -+_fini: -+ addi sp, sp, -48 -+ stw ra, 44(sp) -+ stw r23, 40(sp) -+ stw r22, 36(sp) -+ stw r21, 32(sp) -+ stw r20, 28(sp) -+ stw r19, 24(sp) -+ stw r18, 20(sp) -+ stw r17, 16(sp) -+ stw r16, 12(sp) -+ stw fp, 8(sp) -+ mov fp, sp -+ -+ ---- gcc-3.4.3/gcc/config/nios2/crtn.asm -+++ gcc-3.4.3-nios2/gcc/config/nios2/crtn.asm -@@ -0,0 +1,70 @@ -+/* -+ Copyright (C) 2003 -+ by Jonah Graham (jgraham@altera.com) -+ -+This file is free software; you can redistribute it and/or modify it -+under the terms of the GNU General Public License as published by the -+Free Software Foundation; either version 2, or (at your option) any -+later version. -+ -+In addition to the permissions in the GNU General Public License, the -+Free Software Foundation gives you unlimited permission to link the -+compiled version of this file with other programs, and to distribute -+those programs without any restriction coming from the use of this -+file. (The General Public License restrictions do apply in other -+respects; for example, they cover modification of the file, and -+distribution when not linked into another program.) -+ -+This file 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 this program; see the file COPYING. If not, write to -+the Free Software Foundation, 59 Temple Place - Suite 330, -+Boston, MA 02111-1307, USA. -+ -+ As a special exception, if you link this library with files -+ compiled with GCC to produce an executable, this does not cause -+ the resulting executable to be covered by the GNU General Public License. -+ This exception does not however invalidate any other reasons why -+ the executable file might be covered by the GNU General Public License. -+ -+ -+This file just makes sure that the .fini and .init sections do in -+fact return. Users may put any desired instructions in those sections. -+This file is the last thing linked into any executable. -+*/ -+ .file "crtn.asm" -+ -+ -+ -+ .section ".init" -+ ldw ra, 44(sp) -+ ldw r23, 40(sp) -+ ldw r22, 36(sp) -+ ldw r21, 32(sp) -+ ldw r20, 28(sp) -+ ldw r19, 24(sp) -+ ldw r18, 20(sp) -+ ldw r17, 16(sp) -+ ldw r16, 12(sp) -+ ldw fp, 8(sp) -+ addi sp, sp, -48 -+ ret -+ -+ .section ".fini" -+ ldw ra, 44(sp) -+ ldw r23, 40(sp) -+ ldw r22, 36(sp) -+ ldw r21, 32(sp) -+ ldw r20, 28(sp) -+ ldw r19, 24(sp) -+ ldw r18, 20(sp) -+ ldw r17, 16(sp) -+ ldw r16, 12(sp) -+ ldw fp, 8(sp) -+ addi sp, sp, -48 -+ ret -+ ---- gcc-3.4.3/gcc/config/nios2/lib2-divmod-hi.c -+++ gcc-3.4.3-nios2/gcc/config/nios2/lib2-divmod-hi.c -@@ -0,0 +1,123 @@ -+ -+/* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is -+ supposedly valid even though this is a "target" file. */ -+#include "auto-host.h" -+ -+ -+#include "tconfig.h" -+#include "tsystem.h" -+#include "coretypes.h" -+#include "tm.h" -+ -+ -+/* Don't use `fancy_abort' here even if config.h says to use it. */ -+#ifdef abort -+#undef abort -+#endif -+ -+ -+#ifdef HAVE_GAS_HIDDEN -+#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden"))) -+#else -+#define ATTRIBUTE_HIDDEN -+#endif -+ -+#include "libgcc2.h" -+ -+extern HItype __modhi3 (HItype, HItype); -+extern HItype __divhi3 (HItype, HItype); -+extern HItype __umodhi3 (HItype, HItype); -+extern HItype __udivhi3 (HItype, HItype); -+ -+static UHItype udivmodhi4(UHItype, UHItype, word_type); -+ -+static UHItype -+udivmodhi4(UHItype num, UHItype den, word_type modwanted) -+{ -+ UHItype bit = 1; -+ UHItype res = 0; -+ -+ while (den < num && bit && !(den & (1L<<15))) -+ { -+ den <<=1; -+ bit <<=1; -+ } -+ while (bit) -+ { -+ if (num >= den) -+ { -+ num -= den; -+ res |= bit; -+ } -+ bit >>=1; -+ den >>=1; -+ } -+ if (modwanted) return num; -+ return res; -+} -+ -+ -+HItype -+__divhi3 (HItype a, HItype b) -+{ -+ word_type neg = 0; -+ HItype res; -+ -+ if (a < 0) -+ { -+ a = -a; -+ neg = !neg; -+ } -+ -+ if (b < 0) -+ { -+ b = -b; -+ neg = !neg; -+ } -+ -+ res = udivmodhi4 (a, b, 0); -+ -+ if (neg) -+ res = -res; -+ -+ return res; -+} -+ -+ -+HItype -+__modhi3 (HItype a, HItype b) -+{ -+ word_type neg = 0; -+ HItype res; -+ -+ if (a < 0) -+ { -+ a = -a; -+ neg = 1; -+ } -+ -+ if (b < 0) -+ b = -b; -+ -+ res = udivmodhi4 (a, b, 1); -+ -+ if (neg) -+ res = -res; -+ -+ return res; -+} -+ -+ -+HItype -+__udivhi3 (HItype a, HItype b) -+{ -+ return udivmodhi4 (a, b, 0); -+} -+ -+ -+HItype -+__umodhi3 (HItype a, HItype b) -+{ -+ return udivmodhi4 (a, b, 1); -+} -+ ---- gcc-3.4.3/gcc/config/nios2/lib2-divmod.c -+++ gcc-3.4.3-nios2/gcc/config/nios2/lib2-divmod.c -@@ -0,0 +1,126 @@ -+ -+/* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is -+ supposedly valid even though this is a "target" file. */ -+#include "auto-host.h" -+ -+ -+#include "tconfig.h" -+#include "tsystem.h" -+#include "coretypes.h" -+#include "tm.h" -+ -+ -+/* Don't use `fancy_abort' here even if config.h says to use it. */ -+#ifdef abort -+#undef abort -+#endif -+ -+ -+#ifdef HAVE_GAS_HIDDEN -+#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden"))) -+#else -+#define ATTRIBUTE_HIDDEN -+#endif -+ -+#include "libgcc2.h" -+ -+extern SItype __modsi3 (SItype, SItype); -+extern SItype __divsi3 (SItype, SItype); -+extern SItype __umodsi3 (SItype, SItype); -+extern SItype __udivsi3 (SItype, SItype); -+ -+static USItype udivmodsi4(USItype, USItype, word_type); -+ -+/* 16-bit SI divide and modulo as used in NIOS */ -+ -+ -+static USItype -+udivmodsi4(USItype num, USItype den, word_type modwanted) -+{ -+ USItype bit = 1; -+ USItype res = 0; -+ -+ while (den < num && bit && !(den & (1L<<31))) -+ { -+ den <<=1; -+ bit <<=1; -+ } -+ while (bit) -+ { -+ if (num >= den) -+ { -+ num -= den; -+ res |= bit; -+ } -+ bit >>=1; -+ den >>=1; -+ } -+ if (modwanted) return num; -+ return res; -+} -+ -+ -+SItype -+__divsi3 (SItype a, SItype b) -+{ -+ word_type neg = 0; -+ SItype res; -+ -+ if (a < 0) -+ { -+ a = -a; -+ neg = !neg; -+ } -+ -+ if (b < 0) -+ { -+ b = -b; -+ neg = !neg; -+ } -+ -+ res = udivmodsi4 (a, b, 0); -+ -+ if (neg) -+ res = -res; -+ -+ return res; -+} -+ -+ -+SItype -+__modsi3 (SItype a, SItype b) -+{ -+ word_type neg = 0; -+ SItype res; -+ -+ if (a < 0) -+ { -+ a = -a; -+ neg = 1; -+ } -+ -+ if (b < 0) -+ b = -b; -+ -+ res = udivmodsi4 (a, b, 1); -+ -+ if (neg) -+ res = -res; -+ -+ return res; -+} -+ -+ -+SItype -+__udivsi3 (SItype a, SItype b) -+{ -+ return udivmodsi4 (a, b, 0); -+} -+ -+ -+SItype -+__umodsi3 (SItype a, SItype b) -+{ -+ return udivmodsi4 (a, b, 1); -+} -+ ---- gcc-3.4.3/gcc/config/nios2/lib2-divtable.c -+++ gcc-3.4.3-nios2/gcc/config/nios2/lib2-divtable.c -@@ -0,0 +1,46 @@ -+ -+/* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is -+ supposedly valid even though this is a "target" file. */ -+#include "auto-host.h" -+ -+ -+#include "tconfig.h" -+#include "tsystem.h" -+#include "coretypes.h" -+#include "tm.h" -+ -+ -+/* Don't use `fancy_abort' here even if config.h says to use it. */ -+#ifdef abort -+#undef abort -+#endif -+ -+ -+#ifdef HAVE_GAS_HIDDEN -+#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden"))) -+#else -+#define ATTRIBUTE_HIDDEN -+#endif -+ -+#include "libgcc2.h" -+ -+UQItype __divsi3_table[] = -+{ -+ 0, 0/1, 0/2, 0/3, 0/4, 0/5, 0/6, 0/7, 0/8, 0/9, 0/10, 0/11, 0/12, 0/13, 0/14, 0/15, -+ 0, 1/1, 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10, 1/11, 1/12, 1/13, 1/14, 1/15, -+ 0, 2/1, 2/2, 2/3, 2/4, 2/5, 2/6, 2/7, 2/8, 2/9, 2/10, 2/11, 2/12, 2/13, 2/14, 2/15, -+ 0, 3/1, 3/2, 3/3, 3/4, 3/5, 3/6, 3/7, 3/8, 3/9, 3/10, 3/11, 3/12, 3/13, 3/14, 3/15, -+ 0, 4/1, 4/2, 4/3, 4/4, 4/5, 4/6, 4/7, 4/8, 4/9, 4/10, 4/11, 4/12, 4/13, 4/14, 4/15, -+ 0, 5/1, 5/2, 5/3, 5/4, 5/5, 5/6, 5/7, 5/8, 5/9, 5/10, 5/11, 5/12, 5/13, 5/14, 5/15, -+ 0, 6/1, 6/2, 6/3, 6/4, 6/5, 6/6, 6/7, 6/8, 6/9, 6/10, 6/11, 6/12, 6/13, 6/14, 6/15, -+ 0, 7/1, 7/2, 7/3, 7/4, 7/5, 7/6, 7/7, 7/8, 7/9, 7/10, 7/11, 7/12, 7/13, 7/14, 7/15, -+ 0, 8/1, 8/2, 8/3, 8/4, 8/5, 8/6, 8/7, 8/8, 8/9, 8/10, 8/11, 8/12, 8/13, 8/14, 8/15, -+ 0, 9/1, 9/2, 9/3, 9/4, 9/5, 9/6, 9/7, 9/8, 9/9, 9/10, 9/11, 9/12, 9/13, 9/14, 9/15, -+ 0, 10/1, 10/2, 10/3, 10/4, 10/5, 10/6, 10/7, 10/8, 10/9, 10/10, 10/11, 10/12, 10/13, 10/14, 10/15, -+ 0, 11/1, 11/2, 11/3, 11/4, 11/5, 11/6, 11/7, 11/8, 11/9, 11/10, 11/11, 11/12, 11/13, 11/14, 11/15, -+ 0, 12/1, 12/2, 12/3, 12/4, 12/5, 12/6, 12/7, 12/8, 12/9, 12/10, 12/11, 12/12, 12/13, 12/14, 12/15, -+ 0, 13/1, 13/2, 13/3, 13/4, 13/5, 13/6, 13/7, 13/8, 13/9, 13/10, 13/11, 13/12, 13/13, 13/14, 13/15, -+ 0, 14/1, 14/2, 14/3, 14/4, 14/5, 14/6, 14/7, 14/8, 14/9, 14/10, 14/11, 14/12, 14/13, 14/14, 14/15, -+ 0, 15/1, 15/2, 15/3, 15/4, 15/5, 15/6, 15/7, 15/8, 15/9, 15/10, 15/11, 15/12, 15/13, 15/14, 15/15, -+}; -+ ---- gcc-3.4.3/gcc/config/nios2/lib2-mul.c -+++ gcc-3.4.3-nios2/gcc/config/nios2/lib2-mul.c -@@ -0,0 +1,103 @@ -+/* while we are debugging (ie compile outside of gcc build) -+ disable gcc specific headers */ -+#ifndef DEBUG_MULSI3 -+ -+ -+/* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is -+ supposedly valid even though this is a "target" file. */ -+#include "auto-host.h" -+ -+ -+#include "tconfig.h" -+#include "tsystem.h" -+#include "coretypes.h" -+#include "tm.h" -+ -+ -+/* Don't use `fancy_abort' here even if config.h says to use it. */ -+#ifdef abort -+#undef abort -+#endif -+ -+ -+#ifdef HAVE_GAS_HIDDEN -+#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden"))) -+#else -+#define ATTRIBUTE_HIDDEN -+#endif -+ -+#include "libgcc2.h" -+ -+#else -+#define SItype int -+#define USItype unsigned int -+#endif -+ -+ -+extern SItype __mulsi3 (SItype, SItype); -+ -+SItype -+__mulsi3 (SItype a, SItype b) -+{ -+ SItype res = 0; -+ USItype cnt = a; -+ -+ while (cnt) -+ { -+ if (cnt & 1) -+ { -+ res += b; -+ } -+ b <<= 1; -+ cnt >>= 1; -+ } -+ -+ return res; -+} -+/* -+TODO: Choose best alternative implementation. -+ -+SItype -+__divsi3 (SItype a, SItype b) -+{ -+ SItype res = 0; -+ USItype cnt = 0; -+ -+ while (cnt < 32) -+ { -+ if (a & (1L << cnt)) -+ { -+ res += b; -+ } -+ b <<= 1; -+ cnt++; -+ } -+ -+ return res; -+} -+*/ -+ -+ -+#ifdef DEBUG_MULSI3 -+ -+int -+main () -+{ -+ int i, j; -+ int error = 0; -+ -+ for (i = -1000; i < 1000; i++) -+ for (j = -1000; j < 1000; j++) -+ { -+ int expect = i * j; -+ int actual = A__divsi3 (i, j); -+ if (expect != actual) -+ { -+ printf ("error: %d * %d = %d not %d\n", i, j, expect, actual); -+ error = 1; -+ } -+ } -+ -+ return error; -+} -+#endif ---- gcc-3.4.3/gcc/config/nios2/nios2-dp-bit.c -+++ gcc-3.4.3-nios2/gcc/config/nios2/nios2-dp-bit.c -@@ -0,0 +1,1652 @@ -+ -+/* This is a software floating point library which can be used -+ for targets without hardware floating point. -+ Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004 -+ Free Software Foundation, Inc. -+ -+This file is free software; you can redistribute it and/or modify it -+under the terms of the GNU General Public License as published by the -+Free Software Foundation; either version 2, or (at your option) any -+later version. -+ -+In addition to the permissions in the GNU General Public License, the -+Free Software Foundation gives you unlimited permission to link the -+compiled version of this file with other programs, and to distribute -+those programs without any restriction coming from the use of this -+file. (The General Public License restrictions do apply in other -+respects; for example, they cover modification of the file, and -+distribution when not linked into another program.) -+ -+This file 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 this program; see the file COPYING. If not, write to -+the Free Software Foundation, 59 Temple Place - Suite 330, -+Boston, MA 02111-1307, USA. */ -+ -+/* As a special exception, if you link this library with other files, -+ some of which are compiled with GCC, to produce an executable, -+ this library does not by itself cause the resulting executable -+ to be covered by the GNU General Public License. -+ This exception does not however invalidate any other reasons why -+ the executable file might be covered by the GNU General Public License. */ -+ -+/* This implements IEEE 754 format arithmetic, but does not provide a -+ mechanism for setting the rounding mode, or for generating or handling -+ exceptions. -+ -+ The original code by Steve Chamberlain, hacked by Mark Eichin and Jim -+ Wilson, all of Cygnus Support. */ -+ -+/* The intended way to use this file is to make two copies, add `#define FLOAT' -+ to one copy, then compile both copies and add them to libgcc.a. */ -+ -+#include "tconfig.h" -+#include "coretypes.h" -+#include "tm.h" -+#include "config/fp-bit.h" -+ -+/* The following macros can be defined to change the behavior of this file: -+ FLOAT: Implement a `float', aka SFmode, fp library. If this is not -+ defined, then this file implements a `double', aka DFmode, fp library. -+ FLOAT_ONLY: Used with FLOAT, to implement a `float' only library, i.e. -+ don't include float->double conversion which requires the double library. -+ This is useful only for machines which can't support doubles, e.g. some -+ 8-bit processors. -+ CMPtype: Specify the type that floating point compares should return. -+ This defaults to SItype, aka int. -+ US_SOFTWARE_GOFAST: This makes all entry points use the same names as the -+ US Software goFast library. -+ _DEBUG_BITFLOAT: This makes debugging the code a little easier, by adding -+ two integers to the FLO_union_type. -+ NO_DENORMALS: Disable handling of denormals. -+ NO_NANS: Disable nan and infinity handling -+ SMALL_MACHINE: Useful when operations on QIs and HIs are faster -+ than on an SI */ -+ -+/* We don't currently support extended floats (long doubles) on machines -+ without hardware to deal with them. -+ -+ These stubs are just to keep the linker from complaining about unresolved -+ references which can be pulled in from libio & libstdc++, even if the -+ user isn't using long doubles. However, they may generate an unresolved -+ external to abort if abort is not used by the function, and the stubs -+ are referenced from within libc, since libgcc goes before and after the -+ system library. */ -+ -+#ifdef DECLARE_LIBRARY_RENAMES -+ DECLARE_LIBRARY_RENAMES -+#endif -+ -+#ifdef EXTENDED_FLOAT_STUBS -+extern void abort (void); -+void __extendsfxf2 (void) { abort(); } -+void __extenddfxf2 (void) { abort(); } -+void __truncxfdf2 (void) { abort(); } -+void __truncxfsf2 (void) { abort(); } -+void __fixxfsi (void) { abort(); } -+void __floatsixf (void) { abort(); } -+void __addxf3 (void) { abort(); } -+void __subxf3 (void) { abort(); } -+void __mulxf3 (void) { abort(); } -+void __divxf3 (void) { abort(); } -+void __negxf2 (void) { abort(); } -+void __eqxf2 (void) { abort(); } -+void __nexf2 (void) { abort(); } -+void __gtxf2 (void) { abort(); } -+void __gexf2 (void) { abort(); } -+void __lexf2 (void) { abort(); } -+void __ltxf2 (void) { abort(); } -+ -+void __extendsftf2 (void) { abort(); } -+void __extenddftf2 (void) { abort(); } -+void __trunctfdf2 (void) { abort(); } -+void __trunctfsf2 (void) { abort(); } -+void __fixtfsi (void) { abort(); } -+void __floatsitf (void) { abort(); } -+void __addtf3 (void) { abort(); } -+void __subtf3 (void) { abort(); } -+void __multf3 (void) { abort(); } -+void __divtf3 (void) { abort(); } -+void __negtf2 (void) { abort(); } -+void __eqtf2 (void) { abort(); } -+void __netf2 (void) { abort(); } -+void __gttf2 (void) { abort(); } -+void __getf2 (void) { abort(); } -+void __letf2 (void) { abort(); } -+void __lttf2 (void) { abort(); } -+#else /* !EXTENDED_FLOAT_STUBS, rest of file */ -+ -+/* IEEE "special" number predicates */ -+ -+#ifdef NO_NANS -+ -+#define nan() 0 -+#define isnan(x) 0 -+#define isinf(x) 0 -+#else -+ -+#if defined L_thenan_sf -+const fp_number_type __thenan_sf = { CLASS_SNAN, 0, 0, {(fractype) 0} }; -+#elif defined L_thenan_df -+const fp_number_type __thenan_df = { CLASS_SNAN, 0, 0, {(fractype) 0} }; -+#elif defined L_thenan_tf -+const fp_number_type __thenan_tf = { CLASS_SNAN, 0, 0, {(fractype) 0} }; -+#elif defined TFLOAT -+extern const fp_number_type __thenan_tf; -+#elif defined FLOAT -+extern const fp_number_type __thenan_sf; -+#else -+extern const fp_number_type __thenan_df; -+#endif -+ -+INLINE -+static fp_number_type * -+nan (void) -+{ -+ /* Discard the const qualifier... */ -+#ifdef TFLOAT -+ return (fp_number_type *) (& __thenan_tf); -+#elif defined FLOAT -+ return (fp_number_type *) (& __thenan_sf); -+#else -+ return (fp_number_type *) (& __thenan_df); -+#endif -+} -+ -+INLINE -+static int -+isnan ( fp_number_type * x) -+{ -+ return x->class == CLASS_SNAN || x->class == CLASS_QNAN; -+} -+ -+INLINE -+static int -+isinf ( fp_number_type * x) -+{ -+ return x->class == CLASS_INFINITY; -+} -+ -+#endif /* NO_NANS */ -+ -+INLINE -+static int -+iszero ( fp_number_type * x) -+{ -+ return x->class == CLASS_ZERO; -+} -+ -+INLINE -+static void -+flip_sign ( fp_number_type * x) -+{ -+ x->sign = !x->sign; -+} -+ -+extern FLO_type pack_d ( fp_number_type * ); -+ -+#if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf) -+FLO_type -+pack_d ( fp_number_type * src) -+{ -+ FLO_union_type dst; -+ fractype fraction = src->fraction.ll; /* wasn't unsigned before? */ -+ int sign = src->sign; -+ int exp = 0; -+ -+ if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && (isnan (src) || isinf (src))) -+ { -+ /* We can't represent these values accurately. By using the -+ largest possible magnitude, we guarantee that the conversion -+ of infinity is at least as big as any finite number. */ -+ exp = EXPMAX; -+ fraction = ((fractype) 1 << FRACBITS) - 1; -+ } -+ else if (isnan (src)) -+ { -+ exp = EXPMAX; -+ if (src->class == CLASS_QNAN || 1) -+ { -+#ifdef QUIET_NAN_NEGATED -+ fraction |= QUIET_NAN - 1; -+#else -+ fraction |= QUIET_NAN; -+#endif -+ } -+ } -+ else if (isinf (src)) -+ { -+ exp = EXPMAX; -+ fraction = 0; -+ } -+ else if (iszero (src)) -+ { -+ exp = 0; -+ fraction = 0; -+ } -+ else if (fraction == 0) -+ { -+ exp = 0; -+ } -+ else -+ { -+ if (src->normal_exp < NORMAL_EXPMIN) -+ { -+#ifdef NO_DENORMALS -+ /* Go straight to a zero representation if denormals are not -+ supported. The denormal handling would be harmless but -+ isn't unnecessary. */ -+ exp = 0; -+ fraction = 0; -+#else /* NO_DENORMALS */ -+ /* This number's exponent is too low to fit into the bits -+ available in the number, so we'll store 0 in the exponent and -+ shift the fraction to the right to make up for it. */ -+ -+ int shift = NORMAL_EXPMIN - src->normal_exp; -+ -+ exp = 0; -+ -+ if (shift > FRAC_NBITS - NGARDS) -+ { -+ /* No point shifting, since it's more that 64 out. */ -+ fraction = 0; -+ } -+ else -+ { -+ int lowbit = (fraction & (((fractype)1 << shift) - 1)) ? 1 : 0; -+ fraction = (fraction >> shift) | lowbit; -+ } -+ if ((fraction & GARDMASK) == GARDMSB) -+ { -+ if ((fraction & (1 << NGARDS))) -+ fraction += GARDROUND + 1; -+ } -+ else -+ { -+ /* Add to the guards to round up. */ -+ fraction += GARDROUND; -+ } -+ /* Perhaps the rounding means we now need to change the -+ exponent, because the fraction is no longer denormal. */ -+ if (fraction >= IMPLICIT_1) -+ { -+ exp += 1; -+ } -+ fraction >>= NGARDS; -+#endif /* NO_DENORMALS */ -+ } -+ else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) -+ && src->normal_exp > EXPBIAS) -+ { -+ exp = EXPMAX; -+ fraction = 0; -+ } -+ else -+ { -+ exp = src->normal_exp + EXPBIAS; -+ if (!ROUND_TOWARDS_ZERO) -+ { -+ /* IF the gard bits are the all zero, but the first, then we're -+ half way between two numbers, choose the one which makes the -+ lsb of the answer 0. */ -+ if ((fraction & GARDMASK) == GARDMSB) -+ { -+ if (fraction & (1 << NGARDS)) -+ fraction += GARDROUND + 1; -+ } -+ else -+ { -+ /* Add a one to the guards to round up */ -+ fraction += GARDROUND; -+ } -+ if (fraction >= IMPLICIT_2) -+ { -+ fraction >>= 1; -+ exp += 1; -+ } -+ } -+ fraction >>= NGARDS; -+ -+ if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp > EXPMAX) -+ { -+ /* Saturate on overflow. */ -+ exp = EXPMAX; -+ fraction = ((fractype) 1 << FRACBITS) - 1; -+ } -+ } -+ } -+ -+ /* We previously used bitfields to store the number, but this doesn't -+ handle little/big endian systems conveniently, so use shifts and -+ masks */ -+#ifdef FLOAT_BIT_ORDER_MISMATCH -+ dst.bits.fraction = fraction; -+ dst.bits.exp = exp; -+ dst.bits.sign = sign; -+#else -+# if defined TFLOAT && defined HALFFRACBITS -+ { -+ halffractype high, low, unity; -+ int lowsign, lowexp; -+ -+ unity = (halffractype) 1 << HALFFRACBITS; -+ -+ /* Set HIGH to the high double's significand, masking out the implicit 1. -+ Set LOW to the low double's full significand. */ -+ high = (fraction >> (FRACBITS - HALFFRACBITS)) & (unity - 1); -+ low = fraction & (unity * 2 - 1); -+ -+ /* Get the initial sign and exponent of the low double. */ -+ lowexp = exp - HALFFRACBITS - 1; -+ lowsign = sign; -+ -+ /* HIGH should be rounded like a normal double, making |LOW| <= -+ 0.5 ULP of HIGH. Assume round-to-nearest. */ -+ if (exp < EXPMAX) -+ if (low > unity || (low == unity && (high & 1) == 1)) -+ { -+ /* Round HIGH up and adjust LOW to match. */ -+ high++; -+ if (high == unity) -+ { -+ /* May make it infinite, but that's OK. */ -+ high = 0; -+ exp++; -+ } -+ low = unity * 2 - low; -+ lowsign ^= 1; -+ } -+ -+ high |= (halffractype) exp << HALFFRACBITS; -+ high |= (halffractype) sign << (HALFFRACBITS + EXPBITS); -+ -+ if (exp == EXPMAX || exp == 0 || low == 0) -+ low = 0; -+ else -+ { -+ while (lowexp > 0 && low < unity) -+ { -+ low <<= 1; -+ lowexp--; -+ } -+ -+ if (lowexp <= 0) -+ { -+ halffractype roundmsb, round; -+ int shift; -+ -+ shift = 1 - lowexp; -+ roundmsb = (1 << (shift - 1)); -+ round = low & ((roundmsb << 1) - 1); -+ -+ low >>= shift; -+ lowexp = 0; -+ -+ if (round > roundmsb || (round == roundmsb && (low & 1) == 1)) -+ { -+ low++; -+ if (low == unity) -+ /* LOW rounds up to the smallest normal number. */ -+ lowexp++; -+ } -+ } -+ -+ low &= unity - 1; -+ low |= (halffractype) lowexp << HALFFRACBITS; -+ low |= (halffractype) lowsign << (HALFFRACBITS + EXPBITS); -+ } -+ dst.value_raw = ((fractype) high << HALFSHIFT) | low; -+ } -+# else -+ dst.value_raw = fraction & ((((fractype)1) << FRACBITS) - (fractype)1); -+ dst.value_raw |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << FRACBITS; -+ dst.value_raw |= ((fractype) (sign & 1)) << (FRACBITS | EXPBITS); -+# endif -+#endif -+ -+#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT) -+#ifdef TFLOAT -+ { -+ qrtrfractype tmp1 = dst.words[0]; -+ qrtrfractype tmp2 = dst.words[1]; -+ dst.words[0] = dst.words[3]; -+ dst.words[1] = dst.words[2]; -+ dst.words[2] = tmp2; -+ dst.words[3] = tmp1; -+ } -+#else -+ { -+ halffractype tmp = dst.words[0]; -+ dst.words[0] = dst.words[1]; -+ dst.words[1] = tmp; -+ } -+#endif -+#endif -+ -+ return dst.value; -+} -+#endif -+ -+#if defined(L_unpack_df) || defined(L_unpack_sf) || defined(L_unpack_tf) -+void -+unpack_d (FLO_union_type * src, fp_number_type * dst) -+{ -+ /* We previously used bitfields to store the number, but this doesn't -+ handle little/big endian systems conveniently, so use shifts and -+ masks */ -+ fractype fraction; -+ int exp; -+ int sign; -+ -+#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT) -+ FLO_union_type swapped; -+ -+#ifdef TFLOAT -+ swapped.words[0] = src->words[3]; -+ swapped.words[1] = src->words[2]; -+ swapped.words[2] = src->words[1]; -+ swapped.words[3] = src->words[0]; -+#else -+ swapped.words[0] = src->words[1]; -+ swapped.words[1] = src->words[0]; -+#endif -+ src = &swapped; -+#endif -+ -+#ifdef FLOAT_BIT_ORDER_MISMATCH -+ fraction = src->bits.fraction; -+ exp = src->bits.exp; -+ sign = src->bits.sign; -+#else -+# if defined TFLOAT && defined HALFFRACBITS -+ { -+ halffractype high, low; -+ -+ high = src->value_raw >> HALFSHIFT; -+ low = src->value_raw & (((fractype)1 << HALFSHIFT) - 1); -+ -+ fraction = high & ((((fractype)1) << HALFFRACBITS) - 1); -+ fraction <<= FRACBITS - HALFFRACBITS; -+ exp = ((int)(high >> HALFFRACBITS)) & ((1 << EXPBITS) - 1); -+ sign = ((int)(high >> (((HALFFRACBITS + EXPBITS))))) & 1; -+ -+ if (exp != EXPMAX && exp != 0 && low != 0) -+ { -+ int lowexp = ((int)(low >> HALFFRACBITS)) & ((1 << EXPBITS) - 1); -+ int lowsign = ((int)(low >> (((HALFFRACBITS + EXPBITS))))) & 1; -+ int shift; -+ fractype xlow; -+ -+ xlow = low & ((((fractype)1) << HALFFRACBITS) - 1); -+ if (lowexp) -+ xlow |= (((halffractype)1) << HALFFRACBITS); -+ else -+ lowexp = 1; -+ shift = (FRACBITS - HALFFRACBITS) - (exp - lowexp); -+ if (shift > 0) -+ xlow <<= shift; -+ else if (shift < 0) -+ xlow >>= -shift; -+ if (sign == lowsign) -+ fraction += xlow; -+ else if (fraction >= xlow) -+ fraction -= xlow; -+ else -+ { -+ /* The high part is a power of two but the full number is lower. -+ This code will leave the implicit 1 in FRACTION, but we'd -+ have added that below anyway. */ -+ fraction = (((fractype) 1 << FRACBITS) - xlow) << 1; -+ exp--; -+ } -+ } -+ } -+# else -+ fraction = src->value_raw & ((((fractype)1) << FRACBITS) - 1); -+ exp = ((int)(src->value_raw >> FRACBITS)) & ((1 << EXPBITS) - 1); -+ sign = ((int)(src->value_raw >> (FRACBITS + EXPBITS))) & 1; -+# endif -+#endif -+ -+ dst->sign = sign; -+ if (exp == 0) -+ { -+ /* Hmm. Looks like 0 */ -+ if (fraction == 0 -+#ifdef NO_DENORMALS -+ || 1 -+#endif -+ ) -+ { -+ /* tastes like zero */ -+ dst->class = CLASS_ZERO; -+ } -+ else -+ { -+ /* Zero exponent with nonzero fraction - it's denormalized, -+ so there isn't a leading implicit one - we'll shift it so -+ it gets one. */ -+ dst->normal_exp = exp - EXPBIAS + 1; -+ fraction <<= NGARDS; -+ -+ dst->class = CLASS_NUMBER; -+#if 1 -+ while (fraction < IMPLICIT_1) -+ { -+ fraction <<= 1; -+ dst->normal_exp--; -+ } -+#endif -+ dst->fraction.ll = fraction; -+ } -+ } -+ else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp == EXPMAX) -+ { -+ /* Huge exponent*/ -+ if (fraction == 0) -+ { -+ /* Attached to a zero fraction - means infinity */ -+ dst->class = CLASS_INFINITY; -+ } -+ else -+ { -+ /* Nonzero fraction, means nan */ -+#ifdef QUIET_NAN_NEGATED -+ if ((fraction & QUIET_NAN) == 0) -+#else -+ if (fraction & QUIET_NAN) -+#endif -+ { -+ dst->class = CLASS_QNAN; -+ } -+ else -+ { -+ dst->class = CLASS_SNAN; -+ } -+ /* Keep the fraction part as the nan number */ -+ dst->fraction.ll = fraction; -+ } -+ } -+ else -+ { -+ /* Nothing strange about this number */ -+ dst->normal_exp = exp - EXPBIAS; -+ dst->class = CLASS_NUMBER; -+ dst->fraction.ll = (fraction << NGARDS) | IMPLICIT_1; -+ } -+} -+#endif /* L_unpack_df || L_unpack_sf */ -+ -+#if defined(L_addsub_sf) || defined(L_addsub_df) || defined(L_addsub_tf) -+static fp_number_type * -+_fpadd_parts (fp_number_type * a, -+ fp_number_type * b, -+ fp_number_type * tmp) -+{ -+ intfrac tfraction; -+ -+ /* Put commonly used fields in local variables. */ -+ int a_normal_exp; -+ int b_normal_exp; -+ fractype a_fraction; -+ fractype b_fraction; -+ -+ if (isnan (a)) -+ { -+ return a; -+ } -+ if (isnan (b)) -+ { -+ return b; -+ } -+ if (isinf (a)) -+ { -+ /* Adding infinities with opposite signs yields a NaN. */ -+ if (isinf (b) && a->sign != b->sign) -+ return nan (); -+ return a; -+ } -+ if (isinf (b)) -+ { -+ return b; -+ } -+ if (iszero (b)) -+ { -+ if (iszero (a)) -+ { -+ *tmp = *a; -+ tmp->sign = a->sign & b->sign; -+ return tmp; -+ } -+ return a; -+ } -+ if (iszero (a)) -+ { -+ return b; -+ } -+ -+ /* Got two numbers. shift the smaller and increment the exponent till -+ they're the same */ -+ { -+ int diff; -+ -+ a_normal_exp = a->normal_exp; -+ b_normal_exp = b->normal_exp; -+ a_fraction = a->fraction.ll; -+ b_fraction = b->fraction.ll; -+ -+ diff = a_normal_exp - b_normal_exp; -+ -+ if (diff < 0) -+ diff = -diff; -+ if (diff < FRAC_NBITS) -+ { -+ /* ??? This does shifts one bit at a time. Optimize. */ -+ while (a_normal_exp > b_normal_exp) -+ { -+ b_normal_exp++; -+ LSHIFT (b_fraction); -+ } -+ while (b_normal_exp > a_normal_exp) -+ { -+ a_normal_exp++; -+ LSHIFT (a_fraction); -+ } -+ } -+ else -+ { -+ /* Somethings's up.. choose the biggest */ -+ if (a_normal_exp > b_normal_exp) -+ { -+ b_normal_exp = a_normal_exp; -+ b_fraction = 0; -+ } -+ else -+ { -+ a_normal_exp = b_normal_exp; -+ a_fraction = 0; -+ } -+ } -+ } -+ -+ if (a->sign != b->sign) -+ { -+ if (a->sign) -+ { -+ tfraction = -a_fraction + b_fraction; -+ } -+ else -+ { -+ tfraction = a_fraction - b_fraction; -+ } -+ if (tfraction >= 0) -+ { -+ tmp->sign = 0; -+ tmp->normal_exp = a_normal_exp; -+ tmp->fraction.ll = tfraction; -+ } -+ else -+ { -+ tmp->sign = 1; -+ tmp->normal_exp = a_normal_exp; -+ tmp->fraction.ll = -tfraction; -+ } -+ /* and renormalize it */ -+ -+ while (tmp->fraction.ll < IMPLICIT_1 && tmp->fraction.ll) -+ { -+ tmp->fraction.ll <<= 1; -+ tmp->normal_exp--; -+ } -+ } -+ else -+ { -+ tmp->sign = a->sign; -+ tmp->normal_exp = a_normal_exp; -+ tmp->fraction.ll = a_fraction + b_fraction; -+ } -+ tmp->class = CLASS_NUMBER; -+ /* Now the fraction is added, we have to shift down to renormalize the -+ number */ -+ -+ if (tmp->fraction.ll >= IMPLICIT_2) -+ { -+ LSHIFT (tmp->fraction.ll); -+ tmp->normal_exp++; -+ } -+ return tmp; -+ -+} -+ -+FLO_type -+add (FLO_type arg_a, FLO_type arg_b) -+{ -+ fp_number_type a; -+ fp_number_type b; -+ fp_number_type tmp; -+ fp_number_type *res; -+ FLO_union_type au, bu; -+ -+ au.value = arg_a; -+ bu.value = arg_b; -+ -+ unpack_d (&au, &a); -+ unpack_d (&bu, &b); -+ -+ res = _fpadd_parts (&a, &b, &tmp); -+ -+ return pack_d (res); -+} -+ -+FLO_type -+sub (FLO_type arg_a, FLO_type arg_b) -+{ -+ fp_number_type a; -+ fp_number_type b; -+ fp_number_type tmp; -+ fp_number_type *res; -+ FLO_union_type au, bu; -+ -+ au.value = arg_a; -+ bu.value = arg_b; -+ -+ unpack_d (&au, &a); -+ unpack_d (&bu, &b); -+ -+ b.sign ^= 1; -+ -+ res = _fpadd_parts (&a, &b, &tmp); -+ -+ return pack_d (res); -+} -+#endif /* L_addsub_sf || L_addsub_df */ -+ -+#if defined(L_mul_sf) || defined(L_mul_df) || defined(L_mul_tf) -+static inline __attribute__ ((__always_inline__)) fp_number_type * -+_fpmul_parts ( fp_number_type * a, -+ fp_number_type * b, -+ fp_number_type * tmp) -+{ -+ fractype low = 0; -+ fractype high = 0; -+ -+ if (isnan (a)) -+ { -+ a->sign = a->sign != b->sign; -+ return a; -+ } -+ if (isnan (b)) -+ { -+ b->sign = a->sign != b->sign; -+ return b; -+ } -+ if (isinf (a)) -+ { -+ if (iszero (b)) -+ return nan (); -+ a->sign = a->sign != b->sign; -+ return a; -+ } -+ if (isinf (b)) -+ { -+ if (iszero (a)) -+ { -+ return nan (); -+ } -+ b->sign = a->sign != b->sign; -+ return b; -+ } -+ if (iszero (a)) -+ { -+ a->sign = a->sign != b->sign; -+ return a; -+ } -+ if (iszero (b)) -+ { -+ b->sign = a->sign != b->sign; -+ return b; -+ } -+ -+ /* Calculate the mantissa by multiplying both numbers to get a -+ twice-as-wide number. */ -+ { -+#if defined(NO_DI_MODE) || defined(TFLOAT) -+ { -+ fractype x = a->fraction.ll; -+ fractype ylow = b->fraction.ll; -+ fractype yhigh = 0; -+ int bit; -+ -+ /* ??? This does multiplies one bit at a time. Optimize. */ -+ for (bit = 0; bit < FRAC_NBITS; bit++) -+ { -+ int carry; -+ -+ if (x & 1) -+ { -+ carry = (low += ylow) < ylow; -+ high += yhigh + carry; -+ } -+ yhigh <<= 1; -+ if (ylow & FRACHIGH) -+ { -+ yhigh |= 1; -+ } -+ ylow <<= 1; -+ x >>= 1; -+ } -+ } -+#elif defined(FLOAT) -+ /* Multiplying two USIs to get a UDI, we're safe. */ -+ { -+ UDItype answer = (UDItype)a->fraction.ll * (UDItype)b->fraction.ll; -+ -+ high = answer >> BITS_PER_SI; -+ low = answer; -+ } -+#else -+ /* fractype is DImode, but we need the result to be twice as wide. -+ Assuming a widening multiply from DImode to TImode is not -+ available, build one by hand. */ -+ { -+ USItype nl = a->fraction.ll; -+ USItype nh = a->fraction.ll >> BITS_PER_SI; -+ USItype ml = b->fraction.ll; -+ USItype mh = b->fraction.ll >> BITS_PER_SI; -+ UDItype pp_ll = (UDItype) ml * nl; -+ UDItype pp_hl = (UDItype) mh * nl; -+ UDItype pp_lh = (UDItype) ml * nh; -+ UDItype pp_hh = (UDItype) mh * nh; -+ UDItype res2 = 0; -+ UDItype res0 = 0; -+ UDItype ps_hh__ = pp_hl + pp_lh; -+ if (ps_hh__ < pp_hl) -+ res2 += (UDItype)1 << BITS_PER_SI; -+ pp_hl = (UDItype)(USItype)ps_hh__ << BITS_PER_SI; -+ res0 = pp_ll + pp_hl; -+ if (res0 < pp_ll) -+ res2++; -+ res2 += (ps_hh__ >> BITS_PER_SI) + pp_hh; -+ high = res2; -+ low = res0; -+ } -+#endif -+ } -+ -+ tmp->normal_exp = a->normal_exp + b->normal_exp -+ + FRAC_NBITS - (FRACBITS + NGARDS); -+ tmp->sign = a->sign != b->sign; -+ while (high >= IMPLICIT_2) -+ { -+ tmp->normal_exp++; -+ if (high & 1) -+ { -+ low >>= 1; -+ low |= FRACHIGH; -+ } -+ high >>= 1; -+ } -+ while (high < IMPLICIT_1) -+ { -+ tmp->normal_exp--; -+ -+ high <<= 1; -+ if (low & FRACHIGH) -+ high |= 1; -+ low <<= 1; -+ } -+ /* rounding is tricky. if we only round if it won't make us round later. */ -+#if 0 -+ if (low & FRACHIGH2) -+ { -+ if (((high & GARDMASK) != GARDMSB) -+ && (((high + 1) & GARDMASK) == GARDMSB)) -+ { -+ /* don't round, it gets done again later. */ -+ } -+ else -+ { -+ high++; -+ } -+ } -+#endif -+ if (!ROUND_TOWARDS_ZERO && (high & GARDMASK) == GARDMSB) -+ { -+ if (high & (1 << NGARDS)) -+ { -+ /* half way, so round to even */ -+ high += GARDROUND + 1; -+ } -+ else if (low) -+ { -+ /* but we really weren't half way */ -+ high += GARDROUND + 1; -+ } -+ } -+ tmp->fraction.ll = high; -+ tmp->class = CLASS_NUMBER; -+ return tmp; -+} -+ -+FLO_type -+multiply (FLO_type arg_a, FLO_type arg_b) -+{ -+ fp_number_type a; -+ fp_number_type b; -+ fp_number_type tmp; -+ fp_number_type *res; -+ FLO_union_type au, bu; -+ -+ au.value = arg_a; -+ bu.value = arg_b; -+ -+ unpack_d (&au, &a); -+ unpack_d (&bu, &b); -+ -+ res = _fpmul_parts (&a, &b, &tmp); -+ -+ return pack_d (res); -+} -+#endif /* L_mul_sf || L_mul_df */ -+ -+#if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf) -+static inline __attribute__ ((__always_inline__)) fp_number_type * -+_fpdiv_parts (fp_number_type * a, -+ fp_number_type * b) -+{ -+ fractype bit; -+ fractype numerator; -+ fractype denominator; -+ fractype quotient; -+ -+ if (isnan (a)) -+ { -+ return a; -+ } -+ if (isnan (b)) -+ { -+ return b; -+ } -+ -+ a->sign = a->sign ^ b->sign; -+ -+ if (isinf (a) || iszero (a)) -+ { -+ if (a->class == b->class) -+ return nan (); -+ return a; -+ } -+ -+ if (isinf (b)) -+ { -+ a->fraction.ll = 0; -+ a->normal_exp = 0; -+ return a; -+ } -+ if (iszero (b)) -+ { -+ a->class = CLASS_INFINITY; -+ return a; -+ } -+ -+ /* Calculate the mantissa by multiplying both 64bit numbers to get a -+ 128 bit number */ -+ { -+ /* quotient = -+ ( numerator / denominator) * 2^(numerator exponent - denominator exponent) -+ */ -+ -+ a->normal_exp = a->normal_exp - b->normal_exp; -+ numerator = a->fraction.ll; -+ denominator = b->fraction.ll; -+ -+ if (numerator < denominator) -+ { -+ /* Fraction will be less than 1.0 */ -+ numerator *= 2; -+ a->normal_exp--; -+ } -+ bit = IMPLICIT_1; -+ quotient = 0; -+ /* ??? Does divide one bit at a time. Optimize. */ -+ while (bit) -+ { -+ if (numerator >= denominator) -+ { -+ quotient |= bit; -+ numerator -= denominator; -+ } -+ bit >>= 1; -+ numerator *= 2; -+ } -+ -+ if (!ROUND_TOWARDS_ZERO && (quotient & GARDMASK) == GARDMSB) -+ { -+ if (quotient & (1 << NGARDS)) -+ { -+ /* half way, so round to even */ -+ quotient += GARDROUND + 1; -+ } -+ else if (numerator) -+ { -+ /* but we really weren't half way, more bits exist */ -+ quotient += GARDROUND + 1; -+ } -+ } -+ -+ a->fraction.ll = quotient; -+ return (a); -+ } -+} -+ -+FLO_type -+divide (FLO_type arg_a, FLO_type arg_b) -+{ -+ fp_number_type a; -+ fp_number_type b; -+ fp_number_type *res; -+ FLO_union_type au, bu; -+ -+ au.value = arg_a; -+ bu.value = arg_b; -+ -+ unpack_d (&au, &a); -+ unpack_d (&bu, &b); -+ -+ res = _fpdiv_parts (&a, &b); -+ -+ return pack_d (res); -+} -+#endif /* L_div_sf || L_div_df */ -+ -+#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df) \ -+ || defined(L_fpcmp_parts_tf) -+/* according to the demo, fpcmp returns a comparison with 0... thus -+ a<b -> -1 -+ a==b -> 0 -+ a>b -> +1 -+ */ -+ -+int -+__fpcmp_parts (fp_number_type * a, fp_number_type * b) -+{ -+#if 0 -+ /* either nan -> unordered. Must be checked outside of this routine. */ -+ if (isnan (a) && isnan (b)) -+ { -+ return 1; /* still unordered! */ -+ } -+#endif -+ -+ if (isnan (a) || isnan (b)) -+ { -+ return 1; /* how to indicate unordered compare? */ -+ } -+ if (isinf (a) && isinf (b)) -+ { -+ /* +inf > -inf, but +inf != +inf */ -+ /* b \a| +inf(0)| -inf(1) -+ ______\+--------+-------- -+ +inf(0)| a==b(0)| a<b(-1) -+ -------+--------+-------- -+ -inf(1)| a>b(1) | a==b(0) -+ -------+--------+-------- -+ So since unordered must be nonzero, just line up the columns... -+ */ -+ return b->sign - a->sign; -+ } -+ /* but not both... */ -+ if (isinf (a)) -+ { -+ return a->sign ? -1 : 1; -+ } -+ if (isinf (b)) -+ { -+ return b->sign ? 1 : -1; -+ } -+ if (iszero (a) && iszero (b)) -+ { -+ return 0; -+ } -+ if (iszero (a)) -+ { -+ return b->sign ? 1 : -1; -+ } -+ if (iszero (b)) -+ { -+ return a->sign ? -1 : 1; -+ } -+ /* now both are "normal". */ -+ if (a->sign != b->sign) -+ { -+ /* opposite signs */ -+ return a->sign ? -1 : 1; -+ } -+ /* same sign; exponents? */ -+ if (a->normal_exp > b->normal_exp) -+ { -+ return a->sign ? -1 : 1; -+ } -+ if (a->normal_exp < b->normal_exp) -+ { -+ return a->sign ? 1 : -1; -+ } -+ /* same exponents; check size. */ -+ if (a->fraction.ll > b->fraction.ll) -+ { -+ return a->sign ? -1 : 1; -+ } -+ if (a->fraction.ll < b->fraction.ll) -+ { -+ return a->sign ? 1 : -1; -+ } -+ /* after all that, they're equal. */ -+ return 0; -+} -+#endif -+ -+#if defined(L_compare_sf) || defined(L_compare_df) || defined(L_compoare_tf) -+CMPtype -+compare (FLO_type arg_a, FLO_type arg_b) -+{ -+ fp_number_type a; -+ fp_number_type b; -+ FLO_union_type au, bu; -+ -+ au.value = arg_a; -+ bu.value = arg_b; -+ -+ unpack_d (&au, &a); -+ unpack_d (&bu, &b); -+ -+ return __fpcmp_parts (&a, &b); -+} -+#endif /* L_compare_sf || L_compare_df */ -+ -+#ifndef US_SOFTWARE_GOFAST -+ -+/* These should be optimized for their specific tasks someday. */ -+ -+#if defined(L_eq_sf) || defined(L_eq_df) || defined(L_eq_tf) -+CMPtype -+_eq_f2 (FLO_type arg_a, FLO_type arg_b) -+{ -+ fp_number_type a; -+ fp_number_type b; -+ FLO_union_type au, bu; -+ -+ au.value = arg_a; -+ bu.value = arg_b; -+ -+ unpack_d (&au, &a); -+ unpack_d (&bu, &b); -+ -+ if (isnan (&a) || isnan (&b)) -+ return 1; /* false, truth == 0 */ -+ -+ return __fpcmp_parts (&a, &b) ; -+} -+#endif /* L_eq_sf || L_eq_df */ -+ -+#if defined(L_ne_sf) || defined(L_ne_df) || defined(L_ne_tf) -+CMPtype -+_ne_f2 (FLO_type arg_a, FLO_type arg_b) -+{ -+ fp_number_type a; -+ fp_number_type b; -+ FLO_union_type au, bu; -+ -+ au.value = arg_a; -+ bu.value = arg_b; -+ -+ unpack_d (&au, &a); -+ unpack_d (&bu, &b); -+ -+ if (isnan (&a) || isnan (&b)) -+ return 1; /* true, truth != 0 */ -+ -+ return __fpcmp_parts (&a, &b) ; -+} -+#endif /* L_ne_sf || L_ne_df */ -+ -+#if defined(L_gt_sf) || defined(L_gt_df) || defined(L_gt_tf) -+CMPtype -+_gt_f2 (FLO_type arg_a, FLO_type arg_b) -+{ -+ fp_number_type a; -+ fp_number_type b; -+ FLO_union_type au, bu; -+ -+ au.value = arg_a; -+ bu.value = arg_b; -+ -+ unpack_d (&au, &a); -+ unpack_d (&bu, &b); -+ -+ if (isnan (&a) || isnan (&b)) -+ return -1; /* false, truth > 0 */ -+ -+ return __fpcmp_parts (&a, &b); -+} -+#endif /* L_gt_sf || L_gt_df */ -+ -+#if defined(L_ge_sf) || defined(L_ge_df) || defined(L_ge_tf) -+CMPtype -+_ge_f2 (FLO_type arg_a, FLO_type arg_b) -+{ -+ fp_number_type a; -+ fp_number_type b; -+ FLO_union_type au, bu; -+ -+ au.value = arg_a; -+ bu.value = arg_b; -+ -+ unpack_d (&au, &a); -+ unpack_d (&bu, &b); -+ -+ if (isnan (&a) || isnan (&b)) -+ return -1; /* false, truth >= 0 */ -+ return __fpcmp_parts (&a, &b) ; -+} -+#endif /* L_ge_sf || L_ge_df */ -+ -+#if defined(L_lt_sf) || defined(L_lt_df) || defined(L_lt_tf) -+CMPtype -+_lt_f2 (FLO_type arg_a, FLO_type arg_b) -+{ -+ fp_number_type a; -+ fp_number_type b; -+ FLO_union_type au, bu; -+ -+ au.value = arg_a; -+ bu.value = arg_b; -+ -+ unpack_d (&au, &a); -+ unpack_d (&bu, &b); -+ -+ if (isnan (&a) || isnan (&b)) -+ return 1; /* false, truth < 0 */ -+ -+ return __fpcmp_parts (&a, &b); -+} -+#endif /* L_lt_sf || L_lt_df */ -+ -+#if defined(L_le_sf) || defined(L_le_df) || defined(L_le_tf) -+CMPtype -+_le_f2 (FLO_type arg_a, FLO_type arg_b) -+{ -+ fp_number_type a; -+ fp_number_type b; -+ FLO_union_type au, bu; -+ -+ au.value = arg_a; -+ bu.value = arg_b; -+ -+ unpack_d (&au, &a); -+ unpack_d (&bu, &b); -+ -+ if (isnan (&a) || isnan (&b)) -+ return 1; /* false, truth <= 0 */ -+ -+ return __fpcmp_parts (&a, &b) ; -+} -+#endif /* L_le_sf || L_le_df */ -+ -+#endif /* ! US_SOFTWARE_GOFAST */ -+ -+#if defined(L_unord_sf) || defined(L_unord_df) || defined(L_unord_tf) -+CMPtype -+_unord_f2 (FLO_type arg_a, FLO_type arg_b) -+{ -+ fp_number_type a; -+ fp_number_type b; -+ FLO_union_type au, bu; -+ -+ au.value = arg_a; -+ bu.value = arg_b; -+ -+ unpack_d (&au, &a); -+ unpack_d (&bu, &b); -+ -+ return (isnan (&a) || isnan (&b)); -+} -+#endif /* L_unord_sf || L_unord_df */ -+ -+#if defined(L_si_to_sf) || defined(L_si_to_df) || defined(L_si_to_tf) -+FLO_type -+si_to_float (SItype arg_a) -+{ -+ fp_number_type in; -+ -+ in.class = CLASS_NUMBER; -+ in.sign = arg_a < 0; -+ if (!arg_a) -+ { -+ in.class = CLASS_ZERO; -+ } -+ else -+ { -+ in.normal_exp = FRACBITS + NGARDS; -+ if (in.sign) -+ { -+ /* Special case for minint, since there is no +ve integer -+ representation for it */ -+ if (arg_a == (- MAX_SI_INT - 1)) -+ { -+ return (FLO_type)(- MAX_SI_INT - 1); -+ } -+ in.fraction.ll = (-arg_a); -+ } -+ else -+ in.fraction.ll = arg_a; -+ -+ while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS))) -+ { -+ in.fraction.ll <<= 1; -+ in.normal_exp -= 1; -+ } -+ } -+ return pack_d (&in); -+} -+#endif /* L_si_to_sf || L_si_to_df */ -+ -+#if defined(L_usi_to_sf) || defined(L_usi_to_df) || defined(L_usi_to_tf) -+FLO_type -+usi_to_float (USItype arg_a) -+{ -+ fp_number_type in; -+ -+ in.sign = 0; -+ if (!arg_a) -+ { -+ in.class = CLASS_ZERO; -+ } -+ else -+ { -+ in.class = CLASS_NUMBER; -+ in.normal_exp = FRACBITS + NGARDS; -+ in.fraction.ll = arg_a; -+ -+ while (in.fraction.ll > ((fractype)1 << (FRACBITS + NGARDS))) -+ { -+ in.fraction.ll >>= 1; -+ in.normal_exp += 1; -+ } -+ while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS))) -+ { -+ in.fraction.ll <<= 1; -+ in.normal_exp -= 1; -+ } -+ } -+ return pack_d (&in); -+} -+#endif -+ -+#if defined(L_sf_to_si) || defined(L_df_to_si) || defined(L_tf_to_si) -+SItype -+float_to_si (FLO_type arg_a) -+{ -+ fp_number_type a; -+ SItype tmp; -+ FLO_union_type au; -+ -+ au.value = arg_a; -+ unpack_d (&au, &a); -+ -+ if (iszero (&a)) -+ return 0; -+ if (isnan (&a)) -+ return 0; -+ /* get reasonable MAX_SI_INT... */ -+ if (isinf (&a)) -+ return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT; -+ /* it is a number, but a small one */ -+ if (a.normal_exp < 0) -+ return 0; -+ if (a.normal_exp > BITS_PER_SI - 2) -+ return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT; -+ tmp = a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp); -+ return a.sign ? (-tmp) : (tmp); -+} -+#endif /* L_sf_to_si || L_df_to_si */ -+ -+#if defined(L_sf_to_usi) || defined(L_df_to_usi) || defined(L_tf_to_usi) -+#if defined US_SOFTWARE_GOFAST || defined(L_tf_to_usi) -+/* While libgcc2.c defines its own __fixunssfsi and __fixunsdfsi routines, -+ we also define them for GOFAST because the ones in libgcc2.c have the -+ wrong names and I'd rather define these here and keep GOFAST CYG-LOC's -+ out of libgcc2.c. We can't define these here if not GOFAST because then -+ there'd be duplicate copies. */ -+ -+USItype -+float_to_usi (FLO_type arg_a) -+{ -+ fp_number_type a; -+ FLO_union_type au; -+ -+ au.value = arg_a; -+ unpack_d (&au, &a); -+ -+ if (iszero (&a)) -+ return 0; -+ if (isnan (&a)) -+ return 0; -+ /* it is a negative number */ -+ if (a.sign) -+ return 0; -+ /* get reasonable MAX_USI_INT... */ -+ if (isinf (&a)) -+ return MAX_USI_INT; -+ /* it is a number, but a small one */ -+ if (a.normal_exp < 0) -+ return 0; -+ if (a.normal_exp > BITS_PER_SI - 1) -+ return MAX_USI_INT; -+ else if (a.normal_exp > (FRACBITS + NGARDS)) -+ return a.fraction.ll << (a.normal_exp - (FRACBITS + NGARDS)); -+ else -+ return a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp); -+} -+#endif /* US_SOFTWARE_GOFAST */ -+#endif /* L_sf_to_usi || L_df_to_usi */ -+ -+#if defined(L_negate_sf) || defined(L_negate_df) || defined(L_negate_tf) -+FLO_type -+negate (FLO_type arg_a) -+{ -+ fp_number_type a; -+ FLO_union_type au; -+ -+ au.value = arg_a; -+ unpack_d (&au, &a); -+ -+ flip_sign (&a); -+ return pack_d (&a); -+} -+#endif /* L_negate_sf || L_negate_df */ -+ -+#ifdef FLOAT -+ -+#if defined(L_make_sf) -+SFtype -+__make_fp(fp_class_type class, -+ unsigned int sign, -+ int exp, -+ USItype frac) -+{ -+ fp_number_type in; -+ -+ in.class = class; -+ in.sign = sign; -+ in.normal_exp = exp; -+ in.fraction.ll = frac; -+ return pack_d (&in); -+} -+#endif /* L_make_sf */ -+ -+#ifndef FLOAT_ONLY -+ -+/* This enables one to build an fp library that supports float but not double. -+ Otherwise, we would get an undefined reference to __make_dp. -+ This is needed for some 8-bit ports that can't handle well values that -+ are 8-bytes in size, so we just don't support double for them at all. */ -+ -+#if defined(L_sf_to_df) -+DFtype -+sf_to_df (SFtype arg_a) -+{ -+ fp_number_type in; -+ FLO_union_type au; -+ -+ au.value = arg_a; -+ unpack_d (&au, &in); -+ -+ return __make_dp (in.class, in.sign, in.normal_exp, -+ ((UDItype) in.fraction.ll) << F_D_BITOFF); -+} -+#endif /* L_sf_to_df */ -+ -+#if defined(L_sf_to_tf) && defined(TMODES) -+TFtype -+sf_to_tf (SFtype arg_a) -+{ -+ fp_number_type in; -+ FLO_union_type au; -+ -+ au.value = arg_a; -+ unpack_d (&au, &in); -+ -+ return __make_tp (in.class, in.sign, in.normal_exp, -+ ((UTItype) in.fraction.ll) << F_T_BITOFF); -+} -+#endif /* L_sf_to_df */ -+ -+#endif /* ! FLOAT_ONLY */ -+#endif /* FLOAT */ -+ -+#ifndef FLOAT -+ -+extern SFtype __make_fp (fp_class_type, unsigned int, int, USItype); -+ -+#if defined(L_make_df) -+DFtype -+__make_dp (fp_class_type class, unsigned int sign, int exp, UDItype frac) -+{ -+ fp_number_type in; -+ -+ in.class = class; -+ in.sign = sign; -+ in.normal_exp = exp; -+ in.fraction.ll = frac; -+ return pack_d (&in); -+} -+#endif /* L_make_df */ -+ -+#if defined(L_df_to_sf) -+SFtype -+df_to_sf (DFtype arg_a) -+{ -+ fp_number_type in; -+ USItype sffrac; -+ FLO_union_type au; -+ -+ au.value = arg_a; -+ unpack_d (&au, &in); -+ -+ sffrac = in.fraction.ll >> F_D_BITOFF; -+ -+ /* We set the lowest guard bit in SFFRAC if we discarded any non -+ zero bits. */ -+ if ((in.fraction.ll & (((USItype) 1 << F_D_BITOFF) - 1)) != 0) -+ sffrac |= 1; -+ -+ return __make_fp (in.class, in.sign, in.normal_exp, sffrac); -+} -+#endif /* L_df_to_sf */ -+ -+#if defined(L_df_to_tf) && defined(TMODES) \ -+ && !defined(FLOAT) && !defined(TFLOAT) -+TFtype -+df_to_tf (DFtype arg_a) -+{ -+ fp_number_type in; -+ FLO_union_type au; -+ -+ au.value = arg_a; -+ unpack_d (&au, &in); -+ -+ return __make_tp (in.class, in.sign, in.normal_exp, -+ ((UTItype) in.fraction.ll) << D_T_BITOFF); -+} -+#endif /* L_sf_to_df */ -+ -+#ifdef TFLOAT -+#if defined(L_make_tf) -+TFtype -+__make_tp(fp_class_type class, -+ unsigned int sign, -+ int exp, -+ UTItype frac) -+{ -+ fp_number_type in; -+ -+ in.class = class; -+ in.sign = sign; -+ in.normal_exp = exp; -+ in.fraction.ll = frac; -+ return pack_d (&in); -+} -+#endif /* L_make_tf */ -+ -+#if defined(L_tf_to_df) -+DFtype -+tf_to_df (TFtype arg_a) -+{ -+ fp_number_type in; -+ UDItype sffrac; -+ FLO_union_type au; -+ -+ au.value = arg_a; -+ unpack_d (&au, &in); -+ -+ sffrac = in.fraction.ll >> D_T_BITOFF; -+ -+ /* We set the lowest guard bit in SFFRAC if we discarded any non -+ zero bits. */ -+ if ((in.fraction.ll & (((UTItype) 1 << D_T_BITOFF) - 1)) != 0) -+ sffrac |= 1; -+ -+ return __make_dp (in.class, in.sign, in.normal_exp, sffrac); -+} -+#endif /* L_tf_to_df */ -+ -+#if defined(L_tf_to_sf) -+SFtype -+tf_to_sf (TFtype arg_a) -+{ -+ fp_number_type in; -+ USItype sffrac; -+ FLO_union_type au; -+ -+ au.value = arg_a; -+ unpack_d (&au, &in); -+ -+ sffrac = in.fraction.ll >> F_T_BITOFF; -+ -+ /* We set the lowest guard bit in SFFRAC if we discarded any non -+ zero bits. */ -+ if ((in.fraction.ll & (((UTItype) 1 << F_T_BITOFF) - 1)) != 0) -+ sffrac |= 1; -+ -+ return __make_fp (in.class, in.sign, in.normal_exp, sffrac); -+} -+#endif /* L_tf_to_sf */ -+#endif /* TFLOAT */ -+ -+#endif /* ! FLOAT */ -+#endif /* !EXTENDED_FLOAT_STUBS */ ---- gcc-3.4.3/gcc/config/nios2/nios2-fp-bit.c -+++ gcc-3.4.3-nios2/gcc/config/nios2/nios2-fp-bit.c -@@ -0,0 +1,1652 @@ -+#define FLOAT -+/* This is a software floating point library which can be used -+ for targets without hardware floating point. -+ Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004 -+ Free Software Foundation, Inc. -+ -+This file is free software; you can redistribute it and/or modify it -+under the terms of the GNU General Public License as published by the -+Free Software Foundation; either version 2, or (at your option) any -+later version. -+ -+In addition to the permissions in the GNU General Public License, the -+Free Software Foundation gives you unlimited permission to link the -+compiled version of this file with other programs, and to distribute -+those programs without any restriction coming from the use of this -+file. (The General Public License restrictions do apply in other -+respects; for example, they cover modification of the file, and -+distribution when not linked into another program.) -+ -+This file 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 this program; see the file COPYING. If not, write to -+the Free Software Foundation, 59 Temple Place - Suite 330, -+Boston, MA 02111-1307, USA. */ -+ -+/* As a special exception, if you link this library with other files, -+ some of which are compiled with GCC, to produce an executable, -+ this library does not by itself cause the resulting executable -+ to be covered by the GNU General Public License. -+ This exception does not however invalidate any other reasons why -+ the executable file might be covered by the GNU General Public License. */ -+ -+/* This implements IEEE 754 format arithmetic, but does not provide a -+ mechanism for setting the rounding mode, or for generating or handling -+ exceptions. -+ -+ The original code by Steve Chamberlain, hacked by Mark Eichin and Jim -+ Wilson, all of Cygnus Support. */ -+ -+/* The intended way to use this file is to make two copies, add `#define FLOAT' -+ to one copy, then compile both copies and add them to libgcc.a. */ -+ -+#include "tconfig.h" -+#include "coretypes.h" -+#include "tm.h" -+#include "config/fp-bit.h" -+ -+/* The following macros can be defined to change the behavior of this file: -+ FLOAT: Implement a `float', aka SFmode, fp library. If this is not -+ defined, then this file implements a `double', aka DFmode, fp library. -+ FLOAT_ONLY: Used with FLOAT, to implement a `float' only library, i.e. -+ don't include float->double conversion which requires the double library. -+ This is useful only for machines which can't support doubles, e.g. some -+ 8-bit processors. -+ CMPtype: Specify the type that floating point compares should return. -+ This defaults to SItype, aka int. -+ US_SOFTWARE_GOFAST: This makes all entry points use the same names as the -+ US Software goFast library. -+ _DEBUG_BITFLOAT: This makes debugging the code a little easier, by adding -+ two integers to the FLO_union_type. -+ NO_DENORMALS: Disable handling of denormals. -+ NO_NANS: Disable nan and infinity handling -+ SMALL_MACHINE: Useful when operations on QIs and HIs are faster -+ than on an SI */ -+ -+/* We don't currently support extended floats (long doubles) on machines -+ without hardware to deal with them. -+ -+ These stubs are just to keep the linker from complaining about unresolved -+ references which can be pulled in from libio & libstdc++, even if the -+ user isn't using long doubles. However, they may generate an unresolved -+ external to abort if abort is not used by the function, and the stubs -+ are referenced from within libc, since libgcc goes before and after the -+ system library. */ -+ -+#ifdef DECLARE_LIBRARY_RENAMES -+ DECLARE_LIBRARY_RENAMES -+#endif -+ -+#ifdef EXTENDED_FLOAT_STUBS -+extern void abort (void); -+void __extendsfxf2 (void) { abort(); } -+void __extenddfxf2 (void) { abort(); } -+void __truncxfdf2 (void) { abort(); } -+void __truncxfsf2 (void) { abort(); } -+void __fixxfsi (void) { abort(); } -+void __floatsixf (void) { abort(); } -+void __addxf3 (void) { abort(); } -+void __subxf3 (void) { abort(); } -+void __mulxf3 (void) { abort(); } -+void __divxf3 (void) { abort(); } -+void __negxf2 (void) { abort(); } -+void __eqxf2 (void) { abort(); } -+void __nexf2 (void) { abort(); } -+void __gtxf2 (void) { abort(); } -+void __gexf2 (void) { abort(); } -+void __lexf2 (void) { abort(); } -+void __ltxf2 (void) { abort(); } -+ -+void __extendsftf2 (void) { abort(); } -+void __extenddftf2 (void) { abort(); } -+void __trunctfdf2 (void) { abort(); } -+void __trunctfsf2 (void) { abort(); } -+void __fixtfsi (void) { abort(); } -+void __floatsitf (void) { abort(); } -+void __addtf3 (void) { abort(); } -+void __subtf3 (void) { abort(); } -+void __multf3 (void) { abort(); } -+void __divtf3 (void) { abort(); } -+void __negtf2 (void) { abort(); } -+void __eqtf2 (void) { abort(); } -+void __netf2 (void) { abort(); } -+void __gttf2 (void) { abort(); } -+void __getf2 (void) { abort(); } -+void __letf2 (void) { abort(); } -+void __lttf2 (void) { abort(); } -+#else /* !EXTENDED_FLOAT_STUBS, rest of file */ -+ -+/* IEEE "special" number predicates */ -+ -+#ifdef NO_NANS -+ -+#define nan() 0 -+#define isnan(x) 0 -+#define isinf(x) 0 -+#else -+ -+#if defined L_thenan_sf -+const fp_number_type __thenan_sf = { CLASS_SNAN, 0, 0, {(fractype) 0} }; -+#elif defined L_thenan_df -+const fp_number_type __thenan_df = { CLASS_SNAN, 0, 0, {(fractype) 0} }; -+#elif defined L_thenan_tf -+const fp_number_type __thenan_tf = { CLASS_SNAN, 0, 0, {(fractype) 0} }; -+#elif defined TFLOAT -+extern const fp_number_type __thenan_tf; -+#elif defined FLOAT -+extern const fp_number_type __thenan_sf; -+#else -+extern const fp_number_type __thenan_df; -+#endif -+ -+INLINE -+static fp_number_type * -+nan (void) -+{ -+ /* Discard the const qualifier... */ -+#ifdef TFLOAT -+ return (fp_number_type *) (& __thenan_tf); -+#elif defined FLOAT -+ return (fp_number_type *) (& __thenan_sf); -+#else -+ return (fp_number_type *) (& __thenan_df); -+#endif -+} -+ -+INLINE -+static int -+isnan ( fp_number_type * x) -+{ -+ return x->class == CLASS_SNAN || x->class == CLASS_QNAN; -+} -+ -+INLINE -+static int -+isinf ( fp_number_type * x) -+{ -+ return x->class == CLASS_INFINITY; -+} -+ -+#endif /* NO_NANS */ -+ -+INLINE -+static int -+iszero ( fp_number_type * x) -+{ -+ return x->class == CLASS_ZERO; -+} -+ -+INLINE -+static void -+flip_sign ( fp_number_type * x) -+{ -+ x->sign = !x->sign; -+} -+ -+extern FLO_type pack_d ( fp_number_type * ); -+ -+#if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf) -+FLO_type -+pack_d ( fp_number_type * src) -+{ -+ FLO_union_type dst; -+ fractype fraction = src->fraction.ll; /* wasn't unsigned before? */ -+ int sign = src->sign; -+ int exp = 0; -+ -+ if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && (isnan (src) || isinf (src))) -+ { -+ /* We can't represent these values accurately. By using the -+ largest possible magnitude, we guarantee that the conversion -+ of infinity is at least as big as any finite number. */ -+ exp = EXPMAX; -+ fraction = ((fractype) 1 << FRACBITS) - 1; -+ } -+ else if (isnan (src)) -+ { -+ exp = EXPMAX; -+ if (src->class == CLASS_QNAN || 1) -+ { -+#ifdef QUIET_NAN_NEGATED -+ fraction |= QUIET_NAN - 1; -+#else -+ fraction |= QUIET_NAN; -+#endif -+ } -+ } -+ else if (isinf (src)) -+ { -+ exp = EXPMAX; -+ fraction = 0; -+ } -+ else if (iszero (src)) -+ { -+ exp = 0; -+ fraction = 0; -+ } -+ else if (fraction == 0) -+ { -+ exp = 0; -+ } -+ else -+ { -+ if (src->normal_exp < NORMAL_EXPMIN) -+ { -+#ifdef NO_DENORMALS -+ /* Go straight to a zero representation if denormals are not -+ supported. The denormal handling would be harmless but -+ isn't unnecessary. */ -+ exp = 0; -+ fraction = 0; -+#else /* NO_DENORMALS */ -+ /* This number's exponent is too low to fit into the bits -+ available in the number, so we'll store 0 in the exponent and -+ shift the fraction to the right to make up for it. */ -+ -+ int shift = NORMAL_EXPMIN - src->normal_exp; -+ -+ exp = 0; -+ -+ if (shift > FRAC_NBITS - NGARDS) -+ { -+ /* No point shifting, since it's more that 64 out. */ -+ fraction = 0; -+ } -+ else -+ { -+ int lowbit = (fraction & (((fractype)1 << shift) - 1)) ? 1 : 0; -+ fraction = (fraction >> shift) | lowbit; -+ } -+ if ((fraction & GARDMASK) == GARDMSB) -+ { -+ if ((fraction & (1 << NGARDS))) -+ fraction += GARDROUND + 1; -+ } -+ else -+ { -+ /* Add to the guards to round up. */ -+ fraction += GARDROUND; -+ } -+ /* Perhaps the rounding means we now need to change the -+ exponent, because the fraction is no longer denormal. */ -+ if (fraction >= IMPLICIT_1) -+ { -+ exp += 1; -+ } -+ fraction >>= NGARDS; -+#endif /* NO_DENORMALS */ -+ } -+ else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) -+ && src->normal_exp > EXPBIAS) -+ { -+ exp = EXPMAX; -+ fraction = 0; -+ } -+ else -+ { -+ exp = src->normal_exp + EXPBIAS; -+ if (!ROUND_TOWARDS_ZERO) -+ { -+ /* IF the gard bits are the all zero, but the first, then we're -+ half way between two numbers, choose the one which makes the -+ lsb of the answer 0. */ -+ if ((fraction & GARDMASK) == GARDMSB) -+ { -+ if (fraction & (1 << NGARDS)) -+ fraction += GARDROUND + 1; -+ } -+ else -+ { -+ /* Add a one to the guards to round up */ -+ fraction += GARDROUND; -+ } -+ if (fraction >= IMPLICIT_2) -+ { -+ fraction >>= 1; -+ exp += 1; -+ } -+ } -+ fraction >>= NGARDS; -+ -+ if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp > EXPMAX) -+ { -+ /* Saturate on overflow. */ -+ exp = EXPMAX; -+ fraction = ((fractype) 1 << FRACBITS) - 1; -+ } -+ } -+ } -+ -+ /* We previously used bitfields to store the number, but this doesn't -+ handle little/big endian systems conveniently, so use shifts and -+ masks */ -+#ifdef FLOAT_BIT_ORDER_MISMATCH -+ dst.bits.fraction = fraction; -+ dst.bits.exp = exp; -+ dst.bits.sign = sign; -+#else -+# if defined TFLOAT && defined HALFFRACBITS -+ { -+ halffractype high, low, unity; -+ int lowsign, lowexp; -+ -+ unity = (halffractype) 1 << HALFFRACBITS; -+ -+ /* Set HIGH to the high double's significand, masking out the implicit 1. -+ Set LOW to the low double's full significand. */ -+ high = (fraction >> (FRACBITS - HALFFRACBITS)) & (unity - 1); -+ low = fraction & (unity * 2 - 1); -+ -+ /* Get the initial sign and exponent of the low double. */ -+ lowexp = exp - HALFFRACBITS - 1; -+ lowsign = sign; -+ -+ /* HIGH should be rounded like a normal double, making |LOW| <= -+ 0.5 ULP of HIGH. Assume round-to-nearest. */ -+ if (exp < EXPMAX) -+ if (low > unity || (low == unity && (high & 1) == 1)) -+ { -+ /* Round HIGH up and adjust LOW to match. */ -+ high++; -+ if (high == unity) -+ { -+ /* May make it infinite, but that's OK. */ -+ high = 0; -+ exp++; -+ } -+ low = unity * 2 - low; -+ lowsign ^= 1; -+ } -+ -+ high |= (halffractype) exp << HALFFRACBITS; -+ high |= (halffractype) sign << (HALFFRACBITS + EXPBITS); -+ -+ if (exp == EXPMAX || exp == 0 || low == 0) -+ low = 0; -+ else -+ { -+ while (lowexp > 0 && low < unity) -+ { -+ low <<= 1; -+ lowexp--; -+ } -+ -+ if (lowexp <= 0) -+ { -+ halffractype roundmsb, round; -+ int shift; -+ -+ shift = 1 - lowexp; -+ roundmsb = (1 << (shift - 1)); -+ round = low & ((roundmsb << 1) - 1); -+ -+ low >>= shift; -+ lowexp = 0; -+ -+ if (round > roundmsb || (round == roundmsb && (low & 1) == 1)) -+ { -+ low++; -+ if (low == unity) -+ /* LOW rounds up to the smallest normal number. */ -+ lowexp++; -+ } -+ } -+ -+ low &= unity - 1; -+ low |= (halffractype) lowexp << HALFFRACBITS; -+ low |= (halffractype) lowsign << (HALFFRACBITS + EXPBITS); -+ } -+ dst.value_raw = ((fractype) high << HALFSHIFT) | low; -+ } -+# else -+ dst.value_raw = fraction & ((((fractype)1) << FRACBITS) - (fractype)1); -+ dst.value_raw |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << FRACBITS; -+ dst.value_raw |= ((fractype) (sign & 1)) << (FRACBITS | EXPBITS); -+# endif -+#endif -+ -+#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT) -+#ifdef TFLOAT -+ { -+ qrtrfractype tmp1 = dst.words[0]; -+ qrtrfractype tmp2 = dst.words[1]; -+ dst.words[0] = dst.words[3]; -+ dst.words[1] = dst.words[2]; -+ dst.words[2] = tmp2; -+ dst.words[3] = tmp1; -+ } -+#else -+ { -+ halffractype tmp = dst.words[0]; -+ dst.words[0] = dst.words[1]; -+ dst.words[1] = tmp; -+ } -+#endif -+#endif -+ -+ return dst.value; -+} -+#endif -+ -+#if defined(L_unpack_df) || defined(L_unpack_sf) || defined(L_unpack_tf) -+void -+unpack_d (FLO_union_type * src, fp_number_type * dst) -+{ -+ /* We previously used bitfields to store the number, but this doesn't -+ handle little/big endian systems conveniently, so use shifts and -+ masks */ -+ fractype fraction; -+ int exp; -+ int sign; -+ -+#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT) -+ FLO_union_type swapped; -+ -+#ifdef TFLOAT -+ swapped.words[0] = src->words[3]; -+ swapped.words[1] = src->words[2]; -+ swapped.words[2] = src->words[1]; -+ swapped.words[3] = src->words[0]; -+#else -+ swapped.words[0] = src->words[1]; -+ swapped.words[1] = src->words[0]; -+#endif -+ src = &swapped; -+#endif -+ -+#ifdef FLOAT_BIT_ORDER_MISMATCH -+ fraction = src->bits.fraction; -+ exp = src->bits.exp; -+ sign = src->bits.sign; -+#else -+# if defined TFLOAT && defined HALFFRACBITS -+ { -+ halffractype high, low; -+ -+ high = src->value_raw >> HALFSHIFT; -+ low = src->value_raw & (((fractype)1 << HALFSHIFT) - 1); -+ -+ fraction = high & ((((fractype)1) << HALFFRACBITS) - 1); -+ fraction <<= FRACBITS - HALFFRACBITS; -+ exp = ((int)(high >> HALFFRACBITS)) & ((1 << EXPBITS) - 1); -+ sign = ((int)(high >> (((HALFFRACBITS + EXPBITS))))) & 1; -+ -+ if (exp != EXPMAX && exp != 0 && low != 0) -+ { -+ int lowexp = ((int)(low >> HALFFRACBITS)) & ((1 << EXPBITS) - 1); -+ int lowsign = ((int)(low >> (((HALFFRACBITS + EXPBITS))))) & 1; -+ int shift; -+ fractype xlow; -+ -+ xlow = low & ((((fractype)1) << HALFFRACBITS) - 1); -+ if (lowexp) -+ xlow |= (((halffractype)1) << HALFFRACBITS); -+ else -+ lowexp = 1; -+ shift = (FRACBITS - HALFFRACBITS) - (exp - lowexp); -+ if (shift > 0) -+ xlow <<= shift; -+ else if (shift < 0) -+ xlow >>= -shift; -+ if (sign == lowsign) -+ fraction += xlow; -+ else if (fraction >= xlow) -+ fraction -= xlow; -+ else -+ { -+ /* The high part is a power of two but the full number is lower. -+ This code will leave the implicit 1 in FRACTION, but we'd -+ have added that below anyway. */ -+ fraction = (((fractype) 1 << FRACBITS) - xlow) << 1; -+ exp--; -+ } -+ } -+ } -+# else -+ fraction = src->value_raw & ((((fractype)1) << FRACBITS) - 1); -+ exp = ((int)(src->value_raw >> FRACBITS)) & ((1 << EXPBITS) - 1); -+ sign = ((int)(src->value_raw >> (FRACBITS + EXPBITS))) & 1; -+# endif -+#endif -+ -+ dst->sign = sign; -+ if (exp == 0) -+ { -+ /* Hmm. Looks like 0 */ -+ if (fraction == 0 -+#ifdef NO_DENORMALS -+ || 1 -+#endif -+ ) -+ { -+ /* tastes like zero */ -+ dst->class = CLASS_ZERO; -+ } -+ else -+ { -+ /* Zero exponent with nonzero fraction - it's denormalized, -+ so there isn't a leading implicit one - we'll shift it so -+ it gets one. */ -+ dst->normal_exp = exp - EXPBIAS + 1; -+ fraction <<= NGARDS; -+ -+ dst->class = CLASS_NUMBER; -+#if 1 -+ while (fraction < IMPLICIT_1) -+ { -+ fraction <<= 1; -+ dst->normal_exp--; -+ } -+#endif -+ dst->fraction.ll = fraction; -+ } -+ } -+ else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp == EXPMAX) -+ { -+ /* Huge exponent*/ -+ if (fraction == 0) -+ { -+ /* Attached to a zero fraction - means infinity */ -+ dst->class = CLASS_INFINITY; -+ } -+ else -+ { -+ /* Nonzero fraction, means nan */ -+#ifdef QUIET_NAN_NEGATED -+ if ((fraction & QUIET_NAN) == 0) -+#else -+ if (fraction & QUIET_NAN) -+#endif -+ { -+ dst->class = CLASS_QNAN; -+ } -+ else -+ { -+ dst->class = CLASS_SNAN; -+ } -+ /* Keep the fraction part as the nan number */ -+ dst->fraction.ll = fraction; -+ } -+ } -+ else -+ { -+ /* Nothing strange about this number */ -+ dst->normal_exp = exp - EXPBIAS; -+ dst->class = CLASS_NUMBER; -+ dst->fraction.ll = (fraction << NGARDS) | IMPLICIT_1; -+ } -+} -+#endif /* L_unpack_df || L_unpack_sf */ -+ -+#if defined(L_addsub_sf) || defined(L_addsub_df) || defined(L_addsub_tf) -+static fp_number_type * -+_fpadd_parts (fp_number_type * a, -+ fp_number_type * b, -+ fp_number_type * tmp) -+{ -+ intfrac tfraction; -+ -+ /* Put commonly used fields in local variables. */ -+ int a_normal_exp; -+ int b_normal_exp; -+ fractype a_fraction; -+ fractype b_fraction; -+ -+ if (isnan (a)) -+ { -+ return a; -+ } -+ if (isnan (b)) -+ { -+ return b; -+ } -+ if (isinf (a)) -+ { -+ /* Adding infinities with opposite signs yields a NaN. */ -+ if (isinf (b) && a->sign != b->sign) -+ return nan (); -+ return a; -+ } -+ if (isinf (b)) -+ { -+ return b; -+ } -+ if (iszero (b)) -+ { -+ if (iszero (a)) -+ { -+ *tmp = *a; -+ tmp->sign = a->sign & b->sign; -+ return tmp; -+ } -+ return a; -+ } -+ if (iszero (a)) -+ { -+ return b; -+ } -+ -+ /* Got two numbers. shift the smaller and increment the exponent till -+ they're the same */ -+ { -+ int diff; -+ -+ a_normal_exp = a->normal_exp; -+ b_normal_exp = b->normal_exp; -+ a_fraction = a->fraction.ll; -+ b_fraction = b->fraction.ll; -+ -+ diff = a_normal_exp - b_normal_exp; -+ -+ if (diff < 0) -+ diff = -diff; -+ if (diff < FRAC_NBITS) -+ { -+ /* ??? This does shifts one bit at a time. Optimize. */ -+ while (a_normal_exp > b_normal_exp) -+ { -+ b_normal_exp++; -+ LSHIFT (b_fraction); -+ } -+ while (b_normal_exp > a_normal_exp) -+ { -+ a_normal_exp++; -+ LSHIFT (a_fraction); -+ } -+ } -+ else -+ { -+ /* Somethings's up.. choose the biggest */ -+ if (a_normal_exp > b_normal_exp) -+ { -+ b_normal_exp = a_normal_exp; -+ b_fraction = 0; -+ } -+ else -+ { -+ a_normal_exp = b_normal_exp; -+ a_fraction = 0; -+ } -+ } -+ } -+ -+ if (a->sign != b->sign) -+ { -+ if (a->sign) -+ { -+ tfraction = -a_fraction + b_fraction; -+ } -+ else -+ { -+ tfraction = a_fraction - b_fraction; -+ } -+ if (tfraction >= 0) -+ { -+ tmp->sign = 0; -+ tmp->normal_exp = a_normal_exp; -+ tmp->fraction.ll = tfraction; -+ } -+ else -+ { -+ tmp->sign = 1; -+ tmp->normal_exp = a_normal_exp; -+ tmp->fraction.ll = -tfraction; -+ } -+ /* and renormalize it */ -+ -+ while (tmp->fraction.ll < IMPLICIT_1 && tmp->fraction.ll) -+ { -+ tmp->fraction.ll <<= 1; -+ tmp->normal_exp--; -+ } -+ } -+ else -+ { -+ tmp->sign = a->sign; -+ tmp->normal_exp = a_normal_exp; -+ tmp->fraction.ll = a_fraction + b_fraction; -+ } -+ tmp->class = CLASS_NUMBER; -+ /* Now the fraction is added, we have to shift down to renormalize the -+ number */ -+ -+ if (tmp->fraction.ll >= IMPLICIT_2) -+ { -+ LSHIFT (tmp->fraction.ll); -+ tmp->normal_exp++; -+ } -+ return tmp; -+ -+} -+ -+FLO_type -+add (FLO_type arg_a, FLO_type arg_b) -+{ -+ fp_number_type a; -+ fp_number_type b; -+ fp_number_type tmp; -+ fp_number_type *res; -+ FLO_union_type au, bu; -+ -+ au.value = arg_a; -+ bu.value = arg_b; -+ -+ unpack_d (&au, &a); -+ unpack_d (&bu, &b); -+ -+ res = _fpadd_parts (&a, &b, &tmp); -+ -+ return pack_d (res); -+} -+ -+FLO_type -+sub (FLO_type arg_a, FLO_type arg_b) -+{ -+ fp_number_type a; -+ fp_number_type b; -+ fp_number_type tmp; -+ fp_number_type *res; -+ FLO_union_type au, bu; -+ -+ au.value = arg_a; -+ bu.value = arg_b; -+ -+ unpack_d (&au, &a); -+ unpack_d (&bu, &b); -+ -+ b.sign ^= 1; -+ -+ res = _fpadd_parts (&a, &b, &tmp); -+ -+ return pack_d (res); -+} -+#endif /* L_addsub_sf || L_addsub_df */ -+ -+#if defined(L_mul_sf) || defined(L_mul_df) || defined(L_mul_tf) -+static inline __attribute__ ((__always_inline__)) fp_number_type * -+_fpmul_parts ( fp_number_type * a, -+ fp_number_type * b, -+ fp_number_type * tmp) -+{ -+ fractype low = 0; -+ fractype high = 0; -+ -+ if (isnan (a)) -+ { -+ a->sign = a->sign != b->sign; -+ return a; -+ } -+ if (isnan (b)) -+ { -+ b->sign = a->sign != b->sign; -+ return b; -+ } -+ if (isinf (a)) -+ { -+ if (iszero (b)) -+ return nan (); -+ a->sign = a->sign != b->sign; -+ return a; -+ } -+ if (isinf (b)) -+ { -+ if (iszero (a)) -+ { -+ return nan (); -+ } -+ b->sign = a->sign != b->sign; -+ return b; -+ } -+ if (iszero (a)) -+ { -+ a->sign = a->sign != b->sign; -+ return a; -+ } -+ if (iszero (b)) -+ { -+ b->sign = a->sign != b->sign; -+ return b; -+ } -+ -+ /* Calculate the mantissa by multiplying both numbers to get a -+ twice-as-wide number. */ -+ { -+#if defined(NO_DI_MODE) || defined(TFLOAT) -+ { -+ fractype x = a->fraction.ll; -+ fractype ylow = b->fraction.ll; -+ fractype yhigh = 0; -+ int bit; -+ -+ /* ??? This does multiplies one bit at a time. Optimize. */ -+ for (bit = 0; bit < FRAC_NBITS; bit++) -+ { -+ int carry; -+ -+ if (x & 1) -+ { -+ carry = (low += ylow) < ylow; -+ high += yhigh + carry; -+ } -+ yhigh <<= 1; -+ if (ylow & FRACHIGH) -+ { -+ yhigh |= 1; -+ } -+ ylow <<= 1; -+ x >>= 1; -+ } -+ } -+#elif defined(FLOAT) -+ /* Multiplying two USIs to get a UDI, we're safe. */ -+ { -+ UDItype answer = (UDItype)a->fraction.ll * (UDItype)b->fraction.ll; -+ -+ high = answer >> BITS_PER_SI; -+ low = answer; -+ } -+#else -+ /* fractype is DImode, but we need the result to be twice as wide. -+ Assuming a widening multiply from DImode to TImode is not -+ available, build one by hand. */ -+ { -+ USItype nl = a->fraction.ll; -+ USItype nh = a->fraction.ll >> BITS_PER_SI; -+ USItype ml = b->fraction.ll; -+ USItype mh = b->fraction.ll >> BITS_PER_SI; -+ UDItype pp_ll = (UDItype) ml * nl; -+ UDItype pp_hl = (UDItype) mh * nl; -+ UDItype pp_lh = (UDItype) ml * nh; -+ UDItype pp_hh = (UDItype) mh * nh; -+ UDItype res2 = 0; -+ UDItype res0 = 0; -+ UDItype ps_hh__ = pp_hl + pp_lh; -+ if (ps_hh__ < pp_hl) -+ res2 += (UDItype)1 << BITS_PER_SI; -+ pp_hl = (UDItype)(USItype)ps_hh__ << BITS_PER_SI; -+ res0 = pp_ll + pp_hl; -+ if (res0 < pp_ll) -+ res2++; -+ res2 += (ps_hh__ >> BITS_PER_SI) + pp_hh; -+ high = res2; -+ low = res0; -+ } -+#endif -+ } -+ -+ tmp->normal_exp = a->normal_exp + b->normal_exp -+ + FRAC_NBITS - (FRACBITS + NGARDS); -+ tmp->sign = a->sign != b->sign; -+ while (high >= IMPLICIT_2) -+ { -+ tmp->normal_exp++; -+ if (high & 1) -+ { -+ low >>= 1; -+ low |= FRACHIGH; -+ } -+ high >>= 1; -+ } -+ while (high < IMPLICIT_1) -+ { -+ tmp->normal_exp--; -+ -+ high <<= 1; -+ if (low & FRACHIGH) -+ high |= 1; -+ low <<= 1; -+ } -+ /* rounding is tricky. if we only round if it won't make us round later. */ -+#if 0 -+ if (low & FRACHIGH2) -+ { -+ if (((high & GARDMASK) != GARDMSB) -+ && (((high + 1) & GARDMASK) == GARDMSB)) -+ { -+ /* don't round, it gets done again later. */ -+ } -+ else -+ { -+ high++; -+ } -+ } -+#endif -+ if (!ROUND_TOWARDS_ZERO && (high & GARDMASK) == GARDMSB) -+ { -+ if (high & (1 << NGARDS)) -+ { -+ /* half way, so round to even */ -+ high += GARDROUND + 1; -+ } -+ else if (low) -+ { -+ /* but we really weren't half way */ -+ high += GARDROUND + 1; -+ } -+ } -+ tmp->fraction.ll = high; -+ tmp->class = CLASS_NUMBER; -+ return tmp; -+} -+ -+FLO_type -+multiply (FLO_type arg_a, FLO_type arg_b) -+{ -+ fp_number_type a; -+ fp_number_type b; -+ fp_number_type tmp; -+ fp_number_type *res; -+ FLO_union_type au, bu; -+ -+ au.value = arg_a; -+ bu.value = arg_b; -+ -+ unpack_d (&au, &a); -+ unpack_d (&bu, &b); -+ -+ res = _fpmul_parts (&a, &b, &tmp); -+ -+ return pack_d (res); -+} -+#endif /* L_mul_sf || L_mul_df */ -+ -+#if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf) -+static inline __attribute__ ((__always_inline__)) fp_number_type * -+_fpdiv_parts (fp_number_type * a, -+ fp_number_type * b) -+{ -+ fractype bit; -+ fractype numerator; -+ fractype denominator; -+ fractype quotient; -+ -+ if (isnan (a)) -+ { -+ return a; -+ } -+ if (isnan (b)) -+ { -+ return b; -+ } -+ -+ a->sign = a->sign ^ b->sign; -+ -+ if (isinf (a) || iszero (a)) -+ { -+ if (a->class == b->class) -+ return nan (); -+ return a; -+ } -+ -+ if (isinf (b)) -+ { -+ a->fraction.ll = 0; -+ a->normal_exp = 0; -+ return a; -+ } -+ if (iszero (b)) -+ { -+ a->class = CLASS_INFINITY; -+ return a; -+ } -+ -+ /* Calculate the mantissa by multiplying both 64bit numbers to get a -+ 128 bit number */ -+ { -+ /* quotient = -+ ( numerator / denominator) * 2^(numerator exponent - denominator exponent) -+ */ -+ -+ a->normal_exp = a->normal_exp - b->normal_exp; -+ numerator = a->fraction.ll; -+ denominator = b->fraction.ll; -+ -+ if (numerator < denominator) -+ { -+ /* Fraction will be less than 1.0 */ -+ numerator *= 2; -+ a->normal_exp--; -+ } -+ bit = IMPLICIT_1; -+ quotient = 0; -+ /* ??? Does divide one bit at a time. Optimize. */ -+ while (bit) -+ { -+ if (numerator >= denominator) -+ { -+ quotient |= bit; -+ numerator -= denominator; -+ } -+ bit >>= 1; -+ numerator *= 2; -+ } -+ -+ if (!ROUND_TOWARDS_ZERO && (quotient & GARDMASK) == GARDMSB) -+ { -+ if (quotient & (1 << NGARDS)) -+ { -+ /* half way, so round to even */ -+ quotient += GARDROUND + 1; -+ } -+ else if (numerator) -+ { -+ /* but we really weren't half way, more bits exist */ -+ quotient += GARDROUND + 1; -+ } -+ } -+ -+ a->fraction.ll = quotient; -+ return (a); -+ } -+} -+ -+FLO_type -+divide (FLO_type arg_a, FLO_type arg_b) -+{ -+ fp_number_type a; -+ fp_number_type b; -+ fp_number_type *res; -+ FLO_union_type au, bu; -+ -+ au.value = arg_a; -+ bu.value = arg_b; -+ -+ unpack_d (&au, &a); -+ unpack_d (&bu, &b); -+ -+ res = _fpdiv_parts (&a, &b); -+ -+ return pack_d (res); -+} -+#endif /* L_div_sf || L_div_df */ -+ -+#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df) \ -+ || defined(L_fpcmp_parts_tf) -+/* according to the demo, fpcmp returns a comparison with 0... thus -+ a<b -> -1 -+ a==b -> 0 -+ a>b -> +1 -+ */ -+ -+int -+__fpcmp_parts (fp_number_type * a, fp_number_type * b) -+{ -+#if 0 -+ /* either nan -> unordered. Must be checked outside of this routine. */ -+ if (isnan (a) && isnan (b)) -+ { -+ return 1; /* still unordered! */ -+ } -+#endif -+ -+ if (isnan (a) || isnan (b)) -+ { -+ return 1; /* how to indicate unordered compare? */ -+ } -+ if (isinf (a) && isinf (b)) -+ { -+ /* +inf > -inf, but +inf != +inf */ -+ /* b \a| +inf(0)| -inf(1) -+ ______\+--------+-------- -+ +inf(0)| a==b(0)| a<b(-1) -+ -------+--------+-------- -+ -inf(1)| a>b(1) | a==b(0) -+ -------+--------+-------- -+ So since unordered must be nonzero, just line up the columns... -+ */ -+ return b->sign - a->sign; -+ } -+ /* but not both... */ -+ if (isinf (a)) -+ { -+ return a->sign ? -1 : 1; -+ } -+ if (isinf (b)) -+ { -+ return b->sign ? 1 : -1; -+ } -+ if (iszero (a) && iszero (b)) -+ { -+ return 0; -+ } -+ if (iszero (a)) -+ { -+ return b->sign ? 1 : -1; -+ } -+ if (iszero (b)) -+ { -+ return a->sign ? -1 : 1; -+ } -+ /* now both are "normal". */ -+ if (a->sign != b->sign) -+ { -+ /* opposite signs */ -+ return a->sign ? -1 : 1; -+ } -+ /* same sign; exponents? */ -+ if (a->normal_exp > b->normal_exp) -+ { -+ return a->sign ? -1 : 1; -+ } -+ if (a->normal_exp < b->normal_exp) -+ { -+ return a->sign ? 1 : -1; -+ } -+ /* same exponents; check size. */ -+ if (a->fraction.ll > b->fraction.ll) -+ { -+ return a->sign ? -1 : 1; -+ } -+ if (a->fraction.ll < b->fraction.ll) -+ { -+ return a->sign ? 1 : -1; -+ } -+ /* after all that, they're equal. */ -+ return 0; -+} -+#endif -+ -+#if defined(L_compare_sf) || defined(L_compare_df) || defined(L_compoare_tf) -+CMPtype -+compare (FLO_type arg_a, FLO_type arg_b) -+{ -+ fp_number_type a; -+ fp_number_type b; -+ FLO_union_type au, bu; -+ -+ au.value = arg_a; -+ bu.value = arg_b; -+ -+ unpack_d (&au, &a); -+ unpack_d (&bu, &b); -+ -+ return __fpcmp_parts (&a, &b); -+} -+#endif /* L_compare_sf || L_compare_df */ -+ -+#ifndef US_SOFTWARE_GOFAST -+ -+/* These should be optimized for their specific tasks someday. */ -+ -+#if defined(L_eq_sf) || defined(L_eq_df) || defined(L_eq_tf) -+CMPtype -+_eq_f2 (FLO_type arg_a, FLO_type arg_b) -+{ -+ fp_number_type a; -+ fp_number_type b; -+ FLO_union_type au, bu; -+ -+ au.value = arg_a; -+ bu.value = arg_b; -+ -+ unpack_d (&au, &a); -+ unpack_d (&bu, &b); -+ -+ if (isnan (&a) || isnan (&b)) -+ return 1; /* false, truth == 0 */ -+ -+ return __fpcmp_parts (&a, &b) ; -+} -+#endif /* L_eq_sf || L_eq_df */ -+ -+#if defined(L_ne_sf) || defined(L_ne_df) || defined(L_ne_tf) -+CMPtype -+_ne_f2 (FLO_type arg_a, FLO_type arg_b) -+{ -+ fp_number_type a; -+ fp_number_type b; -+ FLO_union_type au, bu; -+ -+ au.value = arg_a; -+ bu.value = arg_b; -+ -+ unpack_d (&au, &a); -+ unpack_d (&bu, &b); -+ -+ if (isnan (&a) || isnan (&b)) -+ return 1; /* true, truth != 0 */ -+ -+ return __fpcmp_parts (&a, &b) ; -+} -+#endif /* L_ne_sf || L_ne_df */ -+ -+#if defined(L_gt_sf) || defined(L_gt_df) || defined(L_gt_tf) -+CMPtype -+_gt_f2 (FLO_type arg_a, FLO_type arg_b) -+{ -+ fp_number_type a; -+ fp_number_type b; -+ FLO_union_type au, bu; -+ -+ au.value = arg_a; -+ bu.value = arg_b; -+ -+ unpack_d (&au, &a); -+ unpack_d (&bu, &b); -+ -+ if (isnan (&a) || isnan (&b)) -+ return -1; /* false, truth > 0 */ -+ -+ return __fpcmp_parts (&a, &b); -+} -+#endif /* L_gt_sf || L_gt_df */ -+ -+#if defined(L_ge_sf) || defined(L_ge_df) || defined(L_ge_tf) -+CMPtype -+_ge_f2 (FLO_type arg_a, FLO_type arg_b) -+{ -+ fp_number_type a; -+ fp_number_type b; -+ FLO_union_type au, bu; -+ -+ au.value = arg_a; -+ bu.value = arg_b; -+ -+ unpack_d (&au, &a); -+ unpack_d (&bu, &b); -+ -+ if (isnan (&a) || isnan (&b)) -+ return -1; /* false, truth >= 0 */ -+ return __fpcmp_parts (&a, &b) ; -+} -+#endif /* L_ge_sf || L_ge_df */ -+ -+#if defined(L_lt_sf) || defined(L_lt_df) || defined(L_lt_tf) -+CMPtype -+_lt_f2 (FLO_type arg_a, FLO_type arg_b) -+{ -+ fp_number_type a; -+ fp_number_type b; -+ FLO_union_type au, bu; -+ -+ au.value = arg_a; -+ bu.value = arg_b; -+ -+ unpack_d (&au, &a); -+ unpack_d (&bu, &b); -+ -+ if (isnan (&a) || isnan (&b)) -+ return 1; /* false, truth < 0 */ -+ -+ return __fpcmp_parts (&a, &b); -+} -+#endif /* L_lt_sf || L_lt_df */ -+ -+#if defined(L_le_sf) || defined(L_le_df) || defined(L_le_tf) -+CMPtype -+_le_f2 (FLO_type arg_a, FLO_type arg_b) -+{ -+ fp_number_type a; -+ fp_number_type b; -+ FLO_union_type au, bu; -+ -+ au.value = arg_a; -+ bu.value = arg_b; -+ -+ unpack_d (&au, &a); -+ unpack_d (&bu, &b); -+ -+ if (isnan (&a) || isnan (&b)) -+ return 1; /* false, truth <= 0 */ -+ -+ return __fpcmp_parts (&a, &b) ; -+} -+#endif /* L_le_sf || L_le_df */ -+ -+#endif /* ! US_SOFTWARE_GOFAST */ -+ -+#if defined(L_unord_sf) || defined(L_unord_df) || defined(L_unord_tf) -+CMPtype -+_unord_f2 (FLO_type arg_a, FLO_type arg_b) -+{ -+ fp_number_type a; -+ fp_number_type b; -+ FLO_union_type au, bu; -+ -+ au.value = arg_a; -+ bu.value = arg_b; -+ -+ unpack_d (&au, &a); -+ unpack_d (&bu, &b); -+ -+ return (isnan (&a) || isnan (&b)); -+} -+#endif /* L_unord_sf || L_unord_df */ -+ -+#if defined(L_si_to_sf) || defined(L_si_to_df) || defined(L_si_to_tf) -+FLO_type -+si_to_float (SItype arg_a) -+{ -+ fp_number_type in; -+ -+ in.class = CLASS_NUMBER; -+ in.sign = arg_a < 0; -+ if (!arg_a) -+ { -+ in.class = CLASS_ZERO; -+ } -+ else -+ { -+ in.normal_exp = FRACBITS + NGARDS; -+ if (in.sign) -+ { -+ /* Special case for minint, since there is no +ve integer -+ representation for it */ -+ if (arg_a == (- MAX_SI_INT - 1)) -+ { -+ return (FLO_type)(- MAX_SI_INT - 1); -+ } -+ in.fraction.ll = (-arg_a); -+ } -+ else -+ in.fraction.ll = arg_a; -+ -+ while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS))) -+ { -+ in.fraction.ll <<= 1; -+ in.normal_exp -= 1; -+ } -+ } -+ return pack_d (&in); -+} -+#endif /* L_si_to_sf || L_si_to_df */ -+ -+#if defined(L_usi_to_sf) || defined(L_usi_to_df) || defined(L_usi_to_tf) -+FLO_type -+usi_to_float (USItype arg_a) -+{ -+ fp_number_type in; -+ -+ in.sign = 0; -+ if (!arg_a) -+ { -+ in.class = CLASS_ZERO; -+ } -+ else -+ { -+ in.class = CLASS_NUMBER; -+ in.normal_exp = FRACBITS + NGARDS; -+ in.fraction.ll = arg_a; -+ -+ while (in.fraction.ll > ((fractype)1 << (FRACBITS + NGARDS))) -+ { -+ in.fraction.ll >>= 1; -+ in.normal_exp += 1; -+ } -+ while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS))) -+ { -+ in.fraction.ll <<= 1; -+ in.normal_exp -= 1; -+ } -+ } -+ return pack_d (&in); -+} -+#endif -+ -+#if defined(L_sf_to_si) || defined(L_df_to_si) || defined(L_tf_to_si) -+SItype -+float_to_si (FLO_type arg_a) -+{ -+ fp_number_type a; -+ SItype tmp; -+ FLO_union_type au; -+ -+ au.value = arg_a; -+ unpack_d (&au, &a); -+ -+ if (iszero (&a)) -+ return 0; -+ if (isnan (&a)) -+ return 0; -+ /* get reasonable MAX_SI_INT... */ -+ if (isinf (&a)) -+ return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT; -+ /* it is a number, but a small one */ -+ if (a.normal_exp < 0) -+ return 0; -+ if (a.normal_exp > BITS_PER_SI - 2) -+ return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT; -+ tmp = a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp); -+ return a.sign ? (-tmp) : (tmp); -+} -+#endif /* L_sf_to_si || L_df_to_si */ -+ -+#if defined(L_sf_to_usi) || defined(L_df_to_usi) || defined(L_tf_to_usi) -+#if defined US_SOFTWARE_GOFAST || defined(L_tf_to_usi) -+/* While libgcc2.c defines its own __fixunssfsi and __fixunsdfsi routines, -+ we also define them for GOFAST because the ones in libgcc2.c have the -+ wrong names and I'd rather define these here and keep GOFAST CYG-LOC's -+ out of libgcc2.c. We can't define these here if not GOFAST because then -+ there'd be duplicate copies. */ -+ -+USItype -+float_to_usi (FLO_type arg_a) -+{ -+ fp_number_type a; -+ FLO_union_type au; -+ -+ au.value = arg_a; -+ unpack_d (&au, &a); -+ -+ if (iszero (&a)) -+ return 0; -+ if (isnan (&a)) -+ return 0; -+ /* it is a negative number */ -+ if (a.sign) -+ return 0; -+ /* get reasonable MAX_USI_INT... */ -+ if (isinf (&a)) -+ return MAX_USI_INT; -+ /* it is a number, but a small one */ -+ if (a.normal_exp < 0) -+ return 0; -+ if (a.normal_exp > BITS_PER_SI - 1) -+ return MAX_USI_INT; -+ else if (a.normal_exp > (FRACBITS + NGARDS)) -+ return a.fraction.ll << (a.normal_exp - (FRACBITS + NGARDS)); -+ else -+ return a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp); -+} -+#endif /* US_SOFTWARE_GOFAST */ -+#endif /* L_sf_to_usi || L_df_to_usi */ -+ -+#if defined(L_negate_sf) || defined(L_negate_df) || defined(L_negate_tf) -+FLO_type -+negate (FLO_type arg_a) -+{ -+ fp_number_type a; -+ FLO_union_type au; -+ -+ au.value = arg_a; -+ unpack_d (&au, &a); -+ -+ flip_sign (&a); -+ return pack_d (&a); -+} -+#endif /* L_negate_sf || L_negate_df */ -+ -+#ifdef FLOAT -+ -+#if defined(L_make_sf) -+SFtype -+__make_fp(fp_class_type class, -+ unsigned int sign, -+ int exp, -+ USItype frac) -+{ -+ fp_number_type in; -+ -+ in.class = class; -+ in.sign = sign; -+ in.normal_exp = exp; -+ in.fraction.ll = frac; -+ return pack_d (&in); -+} -+#endif /* L_make_sf */ -+ -+#ifndef FLOAT_ONLY -+ -+/* This enables one to build an fp library that supports float but not double. -+ Otherwise, we would get an undefined reference to __make_dp. -+ This is needed for some 8-bit ports that can't handle well values that -+ are 8-bytes in size, so we just don't support double for them at all. */ -+ -+#if defined(L_sf_to_df) -+DFtype -+sf_to_df (SFtype arg_a) -+{ -+ fp_number_type in; -+ FLO_union_type au; -+ -+ au.value = arg_a; -+ unpack_d (&au, &in); -+ -+ return __make_dp (in.class, in.sign, in.normal_exp, -+ ((UDItype) in.fraction.ll) << F_D_BITOFF); -+} -+#endif /* L_sf_to_df */ -+ -+#if defined(L_sf_to_tf) && defined(TMODES) -+TFtype -+sf_to_tf (SFtype arg_a) -+{ -+ fp_number_type in; -+ FLO_union_type au; -+ -+ au.value = arg_a; -+ unpack_d (&au, &in); -+ -+ return __make_tp (in.class, in.sign, in.normal_exp, -+ ((UTItype) in.fraction.ll) << F_T_BITOFF); -+} -+#endif /* L_sf_to_df */ -+ -+#endif /* ! FLOAT_ONLY */ -+#endif /* FLOAT */ -+ -+#ifndef FLOAT -+ -+extern SFtype __make_fp (fp_class_type, unsigned int, int, USItype); -+ -+#if defined(L_make_df) -+DFtype -+__make_dp (fp_class_type class, unsigned int sign, int exp, UDItype frac) -+{ -+ fp_number_type in; -+ -+ in.class = class; -+ in.sign = sign; -+ in.normal_exp = exp; -+ in.fraction.ll = frac; -+ return pack_d (&in); -+} -+#endif /* L_make_df */ -+ -+#if defined(L_df_to_sf) -+SFtype -+df_to_sf (DFtype arg_a) -+{ -+ fp_number_type in; -+ USItype sffrac; -+ FLO_union_type au; -+ -+ au.value = arg_a; -+ unpack_d (&au, &in); -+ -+ sffrac = in.fraction.ll >> F_D_BITOFF; -+ -+ /* We set the lowest guard bit in SFFRAC if we discarded any non -+ zero bits. */ -+ if ((in.fraction.ll & (((USItype) 1 << F_D_BITOFF) - 1)) != 0) -+ sffrac |= 1; -+ -+ return __make_fp (in.class, in.sign, in.normal_exp, sffrac); -+} -+#endif /* L_df_to_sf */ -+ -+#if defined(L_df_to_tf) && defined(TMODES) \ -+ && !defined(FLOAT) && !defined(TFLOAT) -+TFtype -+df_to_tf (DFtype arg_a) -+{ -+ fp_number_type in; -+ FLO_union_type au; -+ -+ au.value = arg_a; -+ unpack_d (&au, &in); -+ -+ return __make_tp (in.class, in.sign, in.normal_exp, -+ ((UTItype) in.fraction.ll) << D_T_BITOFF); -+} -+#endif /* L_sf_to_df */ -+ -+#ifdef TFLOAT -+#if defined(L_make_tf) -+TFtype -+__make_tp(fp_class_type class, -+ unsigned int sign, -+ int exp, -+ UTItype frac) -+{ -+ fp_number_type in; -+ -+ in.class = class; -+ in.sign = sign; -+ in.normal_exp = exp; -+ in.fraction.ll = frac; -+ return pack_d (&in); -+} -+#endif /* L_make_tf */ -+ -+#if defined(L_tf_to_df) -+DFtype -+tf_to_df (TFtype arg_a) -+{ -+ fp_number_type in; -+ UDItype sffrac; -+ FLO_union_type au; -+ -+ au.value = arg_a; -+ unpack_d (&au, &in); -+ -+ sffrac = in.fraction.ll >> D_T_BITOFF; -+ -+ /* We set the lowest guard bit in SFFRAC if we discarded any non -+ zero bits. */ -+ if ((in.fraction.ll & (((UTItype) 1 << D_T_BITOFF) - 1)) != 0) -+ sffrac |= 1; -+ -+ return __make_dp (in.class, in.sign, in.normal_exp, sffrac); -+} -+#endif /* L_tf_to_df */ -+ -+#if defined(L_tf_to_sf) -+SFtype -+tf_to_sf (TFtype arg_a) -+{ -+ fp_number_type in; -+ USItype sffrac; -+ FLO_union_type au; -+ -+ au.value = arg_a; -+ unpack_d (&au, &in); -+ -+ sffrac = in.fraction.ll >> F_T_BITOFF; -+ -+ /* We set the lowest guard bit in SFFRAC if we discarded any non -+ zero bits. */ -+ if ((in.fraction.ll & (((UTItype) 1 << F_T_BITOFF) - 1)) != 0) -+ sffrac |= 1; -+ -+ return __make_fp (in.class, in.sign, in.normal_exp, sffrac); -+} -+#endif /* L_tf_to_sf */ -+#endif /* TFLOAT */ -+ -+#endif /* ! FLOAT */ -+#endif /* !EXTENDED_FLOAT_STUBS */ ---- gcc-3.4.3/gcc/config/nios2/nios2-protos.h -+++ gcc-3.4.3-nios2/gcc/config/nios2/nios2-protos.h -@@ -0,0 +1,70 @@ -+/* Subroutines for assembler code output for Altera NIOS 2G NIOS2 version. -+ Copyright (C) 2003 Altera -+ Contributed by Jonah Graham (jgraham@altera.com). -+ -+This file is part of GNU CC. -+ -+GNU CC is free software; you can redistribute it and/or modify -+it under the terms of the GNU General Public License as published by -+the Free Software Foundation; either version 2, or (at your option) -+any later version. -+ -+GNU CC is distributed in the hope that it will be useful, -+but WITHOUT ANY WARRANTY; without even the implied warranty of -+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+GNU General Public License for more details. -+ -+You should have received a copy of the GNU General Public License -+along with GNU CC; see the file COPYING. If not, write to -+the Free Software Foundation, 59 Temple Place - Suite 330, -+Boston, MA 02111-1307, USA. */ -+ -+extern void dump_frame_size (FILE *); -+extern HOST_WIDE_INT compute_frame_size (void); -+extern int nios2_initial_elimination_offset (int, int); -+extern void override_options (void); -+extern void optimization_options (int, int); -+extern int nios2_can_use_return_insn (void); -+extern void expand_prologue (void); -+extern void expand_epilogue (bool); -+extern void function_profiler (FILE *, int); -+ -+ -+#ifdef RTX_CODE -+extern int nios2_legitimate_address (rtx, enum machine_mode, int); -+extern void nios2_print_operand (FILE *, rtx, int); -+extern void nios2_print_operand_address (FILE *, rtx); -+ -+extern int nios2_emit_move_sequence (rtx *, enum machine_mode); -+extern int nios2_emit_expensive_div (rtx *, enum machine_mode); -+ -+extern void gen_int_relational (enum rtx_code, rtx, rtx, rtx, rtx); -+extern void gen_conditional_move (rtx *, enum machine_mode); -+extern const char *asm_output_opcode (FILE *, const char *); -+ -+/* predicates */ -+extern int arith_operand (rtx, enum machine_mode); -+extern int uns_arith_operand (rtx, enum machine_mode); -+extern int logical_operand (rtx, enum machine_mode); -+extern int shift_operand (rtx, enum machine_mode); -+extern int reg_or_0_operand (rtx, enum machine_mode); -+extern int equality_op (rtx, enum machine_mode); -+extern int custom_insn_opcode (rtx, enum machine_mode); -+extern int rdwrctl_operand (rtx, enum machine_mode); -+ -+# ifdef HAVE_MACHINE_MODES -+# if defined TREE_CODE -+extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, tree, int); -+extern rtx function_arg (const CUMULATIVE_ARGS *, enum machine_mode, tree, int); -+extern int function_arg_partial_nregs (const CUMULATIVE_ARGS *, enum machine_mode, tree, int); -+extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int); -+extern int nios2_setup_incoming_varargs (const CUMULATIVE_ARGS *, enum machine_mode, tree, int); -+ -+# endif /* TREE_CODE */ -+# endif /* HAVE_MACHINE_MODES */ -+#endif -+ -+#ifdef TREE_CODE -+extern int nios2_return_in_memory (tree); -+ -+#endif /* TREE_CODE */ ---- gcc-3.4.3/gcc/config/nios2/nios2.c -+++ gcc-3.4.3-nios2/gcc/config/nios2/nios2.c -@@ -0,0 +1,2853 @@ -+/* Subroutines for assembler code output for Altera NIOS 2G NIOS2 version. -+ Copyright (C) 2003 Altera -+ Contributed by Jonah Graham (jgraham@altera.com). -+ -+This file is part of GNU CC. -+ -+GNU CC is free software; you can redistribute it and/or modify -+it under the terms of the GNU General Public License as published by -+the Free Software Foundation; either version 2, or (at your option) -+any later version. -+ -+GNU CC is distributed in the hope that it will be useful, -+but WITHOUT ANY WARRANTY; without even the implied warranty of -+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+GNU General Public License for more details. -+ -+You should have received a copy of the GNU General Public License -+along with GNU CC; see the file COPYING. If not, write to -+the Free Software Foundation, 59 Temple Place - Suite 330, -+Boston, MA 02111-1307, USA. */ -+ -+ -+#include <stdio.h> -+#include "config.h" -+#include "system.h" -+#include "coretypes.h" -+#include "tm.h" -+#include "rtl.h" -+#include "tree.h" -+#include "tm_p.h" -+#include "regs.h" -+#include "hard-reg-set.h" -+#include "real.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 "toplev.h" -+#include "basic-block.h" -+#include "function.h" -+#include "ggc.h" -+#include "reload.h" -+#include "debug.h" -+#include "optabs.h" -+#include "target.h" -+#include "target-def.h" -+ -+/* local prototypes */ -+static bool nios2_rtx_costs (rtx, int, int, int *); -+ -+static void nios2_asm_function_prologue (FILE *, HOST_WIDE_INT); -+static int nios2_use_dfa_pipeline_interface (void); -+static int nios2_issue_rate (void); -+static struct machine_function *nios2_init_machine_status (void); -+static bool nios2_in_small_data_p (tree); -+static rtx save_reg (int, HOST_WIDE_INT, rtx); -+static rtx restore_reg (int, HOST_WIDE_INT); -+static unsigned int nios2_section_type_flags (tree, const char *, int); -+static void nios2_init_builtins (void); -+static rtx nios2_expand_builtin (tree, rtx, rtx, enum machine_mode, int); -+static bool nios2_function_ok_for_sibcall (tree, tree); -+static void nios2_encode_section_info (tree, rtx, int); -+ -+/* Initialize the GCC target structure. */ -+#undef TARGET_ASM_FUNCTION_PROLOGUE -+#define TARGET_ASM_FUNCTION_PROLOGUE nios2_asm_function_prologue -+ -+#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE -+#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE \ -+ nios2_use_dfa_pipeline_interface -+#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_FUNCTION_OK_FOR_SIBCALL -+#define TARGET_FUNCTION_OK_FOR_SIBCALL nios2_function_ok_for_sibcall -+ -+#undef TARGET_RTX_COSTS -+#define TARGET_RTX_COSTS nios2_rtx_costs -+ -+ -+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; -+ -+ -+/* Structure to be filled in by compute_frame_size with register -+ save masks, and offsets for the current function. */ -+ -+struct nios2_frame_info -+GTY (()) -+{ -+ 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 */ -+ int save_reg_rounded; /* # 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 */ -+ int num_regs; /* number of gp registers saved */ -+}; -+ -+struct machine_function -+GTY (()) -+{ -+ -+ /* Current frame information, calculated by compute_frame_size. */ -+ struct nios2_frame_info frame; -+}; -+ -+ -+/*************************************** -+ * Section encodings -+ ***************************************/ -+ -+ -+ -+ -+ -+/*************************************** -+ * Stack Layout and Calling Conventions -+ ***************************************/ -+ -+ -+#define TOO_BIG_OFFSET(X) ((X) > ((1 << 15) - 1)) -+#define TEMP_REG_NUM 8 -+ -+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); -+ } -+} -+ -+static rtx -+save_reg (int regno, HOST_WIDE_INT offset, rtx cfa_store_reg) -+{ -+ rtx insn, stack_slot; -+ -+ stack_slot = gen_rtx_PLUS (SImode, -+ cfa_store_reg, -+ GEN_INT (offset)); -+ -+ insn = emit_insn (gen_rtx_SET (SImode, -+ gen_rtx_MEM (SImode, stack_slot), -+ gen_rtx_REG (SImode, regno))); -+ -+ RTX_FRAME_RELATED_P (insn) = 1; -+ -+ return insn; -+} -+ -+static rtx -+restore_reg (int regno, HOST_WIDE_INT offset) -+{ -+ rtx insn, stack_slot; -+ -+ if (TOO_BIG_OFFSET (offset)) -+ { -+ stack_slot = gen_rtx_REG (SImode, TEMP_REG_NUM); -+ insn = emit_insn (gen_rtx_SET (SImode, -+ stack_slot, -+ GEN_INT (offset))); -+ -+ insn = emit_insn (gen_rtx_SET (SImode, -+ stack_slot, -+ gen_rtx_PLUS (SImode, -+ stack_slot, -+ stack_pointer_rtx))); -+ } -+ else -+ { -+ stack_slot = gen_rtx_PLUS (SImode, -+ stack_pointer_rtx, -+ GEN_INT (offset)); -+ } -+ -+ stack_slot = gen_rtx_MEM (SImode, stack_slot); -+ -+ insn = emit_move_insn (gen_rtx_REG (SImode, regno), stack_slot); -+ -+ return insn; -+} -+ -+ -+/* There are two possible paths for prologue expansion, -+- the first is if the total frame size is < 2^15-1. In that -+case all the immediates will fit into the 16-bit immediate -+fields. -+- the second is when the frame size is too big, in that -+case an additional temporary register is used, first -+as a cfa_temp to offset the sp, second as the cfa_store -+register. -+ -+See the comment above dwarf2out_frame_debug_expr in -+dwarf2out.c for more explanation of the "rules." -+ -+ -+Case 1: -+Rule # Example Insn Effect -+2 addi sp, sp, -total_frame_size cfa.reg=sp, cfa.offset=total_frame_size -+ cfa_store.reg=sp, cfa_store.offset=total_frame_size -+12 stw ra, offset(sp) -+12 stw r16, offset(sp) -+1 mov fp, sp -+ -+Case 2: -+Rule # Example Insn Effect -+6 movi r8, total_frame_size cfa_temp.reg=r8, cfa_temp.offset=total_frame_size -+2 sub sp, sp, r8 cfa.reg=sp, cfa.offset=total_frame_size -+ cfa_store.reg=sp, cfa_store.offset=total_frame_size -+5 add r8, r8, sp cfa_store.reg=r8, cfa_store.offset=0 -+12 stw ra, offset(r8) -+12 stw r16, offset(r8) -+1 mov fp, sp -+ -+*/ -+ -+void -+expand_prologue () -+{ -+ int i; -+ HOST_WIDE_INT total_frame_size; -+ int cfa_store_offset; -+ rtx insn; -+ rtx cfa_store_reg = 0; -+ -+ total_frame_size = compute_frame_size (); -+ -+ if (total_frame_size) -+ { -+ -+ if (TOO_BIG_OFFSET (total_frame_size)) -+ { -+ /* cfa_temp and cfa_store_reg are the same register, -+ cfa_store_reg overwrites cfa_temp */ -+ cfa_store_reg = gen_rtx_REG (SImode, TEMP_REG_NUM); -+ insn = emit_insn (gen_rtx_SET (SImode, -+ cfa_store_reg, -+ GEN_INT (total_frame_size))); -+ -+ RTX_FRAME_RELATED_P (insn) = 1; -+ -+ -+ insn = gen_rtx_SET (SImode, -+ stack_pointer_rtx, -+ gen_rtx_MINUS (SImode, -+ stack_pointer_rtx, -+ cfa_store_reg)); -+ -+ insn = emit_insn (insn); -+ RTX_FRAME_RELATED_P (insn) = 1; -+ -+ -+ /* if there are no registers to save, I don't need to -+ create a cfa_store */ -+ if (cfun->machine->frame.save_reg_size) -+ { -+ insn = gen_rtx_SET (SImode, -+ cfa_store_reg, -+ gen_rtx_PLUS (SImode, -+ cfa_store_reg, -+ stack_pointer_rtx)); -+ -+ insn = emit_insn (insn); -+ RTX_FRAME_RELATED_P (insn) = 1; -+ } -+ -+ cfa_store_offset -+ = total_frame_size -+ - (cfun->machine->frame.save_regs_offset -+ + cfun->machine->frame.save_reg_rounded); -+ } -+ else -+ { -+ insn = gen_rtx_SET (SImode, -+ stack_pointer_rtx, -+ gen_rtx_PLUS (SImode, -+ stack_pointer_rtx, -+ GEN_INT (-total_frame_size))); -+ insn = emit_insn (insn); -+ RTX_FRAME_RELATED_P (insn) = 1; -+ -+ cfa_store_reg = stack_pointer_rtx; -+ cfa_store_offset -+ = cfun->machine->frame.save_regs_offset -+ + cfun->machine->frame.save_reg_rounded; -+ } -+ } -+ -+ if (MUST_SAVE_REGISTER (RA_REGNO)) -+ { -+ cfa_store_offset -= 4; -+ save_reg (RA_REGNO, cfa_store_offset, cfa_store_reg); -+ } -+ if (MUST_SAVE_REGISTER (FP_REGNO)) -+ { -+ cfa_store_offset -= 4; -+ save_reg (FP_REGNO, cfa_store_offset, cfa_store_reg); -+ } -+ -+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) -+ { -+ if (MUST_SAVE_REGISTER (i) && i != FP_REGNO && i != RA_REGNO) -+ { -+ cfa_store_offset -= 4; -+ save_reg (i, cfa_store_offset, cfa_store_reg); -+ } -+ } -+ -+ if (frame_pointer_needed) -+ { -+ insn = emit_insn (gen_rtx_SET (SImode, -+ gen_rtx_REG (SImode, FP_REGNO), -+ gen_rtx_REG (SImode, SP_REGNO))); -+ -+ RTX_FRAME_RELATED_P (insn) = 1; -+ } -+ -+ /* If we are profiling, make sure no instructions are scheduled before -+ the call to mcount. */ -+ if (current_function_profile) -+ emit_insn (gen_blockage ()); -+} -+ -+void -+expand_epilogue (bool sibcall_p) -+{ -+ rtx insn; -+ int i; -+ HOST_WIDE_INT total_frame_size; -+ int register_store_offset; -+ -+ total_frame_size = compute_frame_size (); -+ -+ if (!sibcall_p && nios2_can_use_return_insn ()) -+ { -+ insn = emit_jump_insn (gen_return ()); -+ return; -+ } -+ -+ emit_insn (gen_blockage ()); -+ -+ register_store_offset = -+ cfun->machine->frame.save_regs_offset + -+ cfun->machine->frame.save_reg_rounded; -+ -+ if (MUST_SAVE_REGISTER (RA_REGNO)) -+ { -+ register_store_offset -= 4; -+ restore_reg (RA_REGNO, register_store_offset); -+ } -+ -+ if (MUST_SAVE_REGISTER (FP_REGNO)) -+ { -+ register_store_offset -= 4; -+ restore_reg (FP_REGNO, register_store_offset); -+ } -+ -+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) -+ { -+ if (MUST_SAVE_REGISTER (i) && i != FP_REGNO && i != RA_REGNO) -+ { -+ register_store_offset -= 4; -+ restore_reg (i, register_store_offset); -+ } -+ } -+ -+ if (total_frame_size) -+ { -+ rtx sp_adjust; -+ -+ if (TOO_BIG_OFFSET (total_frame_size)) -+ { -+ sp_adjust = gen_rtx_REG (SImode, TEMP_REG_NUM); -+ insn = emit_insn (gen_rtx_SET (SImode, -+ sp_adjust, -+ GEN_INT (total_frame_size))); -+ -+ } -+ else -+ { -+ sp_adjust = GEN_INT (total_frame_size); -+ } -+ -+ insn = gen_rtx_SET (SImode, -+ stack_pointer_rtx, -+ gen_rtx_PLUS (SImode, -+ stack_pointer_rtx, -+ sp_adjust)); -+ insn = emit_insn (insn); -+ } -+ -+ -+ if (!sibcall_p) -+ { -+ insn = emit_jump_insn (gen_return_from_epilogue (gen_rtx (REG, Pmode, -+ RA_REGNO))); -+ } -+} -+ -+ -+bool -+nios2_function_ok_for_sibcall (tree a ATTRIBUTE_UNUSED, tree b ATTRIBUTE_UNUSED) -+{ -+ return true; -+} -+ -+ -+ -+ -+ -+/* ----------------------- * -+ * Profiling -+ * ----------------------- */ -+ -+void -+function_profiler (FILE *file, int labelno) -+{ -+ fprintf (file, "\t%s mcount begin, label: .LP%d\n", -+ ASM_COMMENT_START, labelno); -+ fprintf (file, "\tnextpc\tr8\n"); -+ fprintf (file, "\tmov\tr9, ra\n"); -+ fprintf (file, "\tmovhi\tr10, %%hiadj(.LP%d)\n", labelno); -+ fprintf (file, "\taddi\tr10, r10, %%lo(.LP%d)\n", labelno); -+ fprintf (file, "\tcall\tmcount\n"); -+ fprintf (file, "\tmov\tra, r9\n"); -+ fprintf (file, "\t%s mcount end\n", ASM_COMMENT_START); -+} -+ -+ -+/*************************************** -+ * Stack Layout -+ ***************************************/ -+ -+ -+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->frame.total_size); -+ fprintf (file, "\t%s var_size = %ld\n", ASM_COMMENT_START, -+ cfun->machine->frame.var_size); -+ fprintf (file, "\t%s args_size = %ld\n", ASM_COMMENT_START, -+ cfun->machine->frame.args_size); -+ fprintf (file, "\t%s save_reg_size = %d\n", ASM_COMMENT_START, -+ cfun->machine->frame.save_reg_size); -+ fprintf (file, "\t%s save_reg_rounded = %d\n", ASM_COMMENT_START, -+ cfun->machine->frame.save_reg_rounded); -+ fprintf (file, "\t%s initialized = %d\n", ASM_COMMENT_START, -+ cfun->machine->frame.initialized); -+ fprintf (file, "\t%s num_regs = %d\n", ASM_COMMENT_START, -+ cfun->machine->frame.num_regs); -+ fprintf (file, "\t%s save_regs_offset = %ld\n", ASM_COMMENT_START, -+ cfun->machine->frame.save_regs_offset); -+ fprintf (file, "\t%s current_function_is_leaf = %d\n", ASM_COMMENT_START, -+ current_function_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, -+ current_function_pretend_args_size); -+ -+} -+ -+ -+/* Return the bytes needed to compute the frame pointer from the current -+ stack pointer. -+*/ -+ -+HOST_WIDE_INT -+compute_frame_size () -+{ -+ 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 save_reg_rounded; -+ /* # bytes needed to store callee save regs (rounded) */ -+ HOST_WIDE_INT out_args_size; /* # bytes needed for outgoing args */ -+ -+ save_reg_size = 0; -+ var_size = STACK_ALIGN (get_frame_size ()); -+ out_args_size = STACK_ALIGN (current_function_outgoing_args_size); -+ -+ total_size = var_size + out_args_size; -+ -+ /* Calculate space needed for gp registers. */ -+ for (regno = 0; regno <= FIRST_PSEUDO_REGISTER; regno++) -+ { -+ if (MUST_SAVE_REGISTER (regno)) -+ { -+ save_reg_size += 4; -+ } -+ } -+ -+ save_reg_rounded = STACK_ALIGN (save_reg_size); -+ total_size += save_reg_rounded; -+ -+ total_size += STACK_ALIGN (current_function_pretend_args_size); -+ -+ /* Save other computed information. */ -+ cfun->machine->frame.total_size = total_size; -+ cfun->machine->frame.var_size = var_size; -+ cfun->machine->frame.args_size = current_function_outgoing_args_size; -+ cfun->machine->frame.save_reg_size = save_reg_size; -+ cfun->machine->frame.save_reg_rounded = save_reg_rounded; -+ cfun->machine->frame.initialized = reload_completed; -+ cfun->machine->frame.num_regs = save_reg_size / UNITS_PER_WORD; -+ -+ cfun->machine->frame.save_regs_offset -+ = save_reg_rounded ? current_function_outgoing_args_size + var_size : 0; -+ -+ return total_size; -+} -+ -+ -+int -+nios2_initial_elimination_offset (int from, int to ATTRIBUTE_UNUSED) -+{ -+ int offset; -+ -+ /* Set OFFSET to the offset from the stack pointer. */ -+ switch (from) -+ { -+ case FRAME_POINTER_REGNUM: -+ offset = 0; -+ break; -+ -+ case ARG_POINTER_REGNUM: -+ compute_frame_size (); -+ offset = cfun->machine->frame.total_size; -+ offset -= current_function_pretend_args_size; -+ break; -+ -+ case RETURN_ADDRESS_POINTER_REGNUM: -+ compute_frame_size (); -+ /* since the return address is always the first of the -+ saved registers, return the offset to the beginning -+ of the saved registers block */ -+ offset = cfun->machine->frame.save_regs_offset; -+ break; -+ -+ default: -+ abort (); -+ } -+ -+ 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 () -+{ -+ if (!reload_completed) -+ return 0; -+ -+ if (regs_ever_live[RA_REGNO] || current_function_profile) -+ return 0; -+ -+ if (cfun->machine->frame.initialized) -+ return cfun->machine->frame.total_size == 0; -+ -+ return compute_frame_size () == 0; -+} -+ -+ -+ -+ -+ -+/*************************************** -+ * -+ ***************************************/ -+ -+const char *nios2_sys_nosys_string; /* for -msys=nosys */ -+const char *nios2_sys_lib_string; /* for -msys-lib= */ -+const char *nios2_sys_crt0_string; /* for -msys-crt0= */ -+ -+void -+override_options () -+{ -+ /* Function to allocate machine-dependent function status. */ -+ init_machine_status = &nios2_init_machine_status; -+ -+ nios2_section_threshold -+ = g_switch_set ? g_switch_value : NIOS2_DEFAULT_GVALUE; -+ -+ if (nios2_sys_nosys_string && *nios2_sys_nosys_string) -+ { -+ error ("invalid option '-msys=nosys%s'", nios2_sys_nosys_string); -+ } -+ -+ /* If we don't have mul, we don't have mulx either! */ -+ if (!TARGET_HAS_MUL && TARGET_HAS_MULX) -+ { -+ target_flags &= ~HAS_MULX_FLAG; -+ } -+ -+} -+ -+void -+optimization_options (int level, int size) -+{ -+ if (level || size) -+ { -+ target_flags |= INLINE_MEMCPY_FLAG; -+ } -+ -+ if (level >= 3 && !size) -+ { -+ target_flags |= FAST_SW_DIV_FLAG; -+ } -+} -+ -+/* Allocate a chunk of memory for per-function machine-dependent data. */ -+static struct machine_function * -+nios2_init_machine_status () -+{ -+ return ((struct machine_function *) -+ ggc_alloc_cleared (sizeof (struct machine_function))); -+} -+ -+ -+ -+/***************** -+ * Describing Relative Costs of Operations -+ *****************/ -+ -+/* 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 *total) -+{ -+ switch (code) -+ { -+ case CONST_INT: -+ if (INTVAL (x) == 0) -+ { -+ *total = COSTS_N_INSNS (0); -+ return true; -+ } -+ else if (SMALL_INT (INTVAL (x)) -+ || SMALL_INT_UNSIGNED (INTVAL (x)) -+ || UPPER16_INT (INTVAL (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 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; -+ } -+} -+ -+ -+/*************************************** -+ * INSTRUCTION SUPPORT -+ * -+ * These functions are used within the Machine Description to -+ * handle common or complicated output and expansions from -+ * instructions. -+ ***************************************/ -+ -+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)) -+ { -+ if (no_new_pseudos) -+ internal_error ("Trying to force_reg no_new_pseudos == 1"); -+ from = copy_to_mode_reg (mode, 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; -+ -+ /* it may look a little generic, but only SImode -+ is supported for now */ -+ if (mode != SImode) -+ abort (); -+ -+ libfunc = sdiv_optab->handlers[(int) SImode].libfunc; -+ -+ -+ -+ 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); -+ -+ convert_move (operands[0], -+ gen_rtx (MEM, QImode, -+ gen_rtx (PLUS, SImode, -+ lookup_value, -+ gen_rtx_SYMBOL_REF (SImode, "__divsi3_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; -+} -+ -+/* Branches/Compares */ -+ -+/* the way of handling branches/compares -+ in gcc is heavily borrowed from MIPS */ -+ -+enum internal_test -+{ -+ ITEST_EQ, -+ ITEST_NE, -+ ITEST_GT, -+ ITEST_GE, -+ ITEST_LT, -+ ITEST_LE, -+ ITEST_GTU, -+ ITEST_GEU, -+ ITEST_LTU, -+ ITEST_LEU, -+ ITEST_MAX -+}; -+ -+static enum internal_test map_test_to_internal_test (enum rtx_code); -+ -+/* Cached operands, and operator to compare for use in set/branch/trap -+ on condition codes. */ -+rtx branch_cmp[2]; -+enum cmp_type branch_type; -+ -+/* Make normal rtx_code into something we can index from an array */ -+ -+static enum internal_test -+map_test_to_internal_test (enum rtx_code test_code) -+{ -+ enum internal_test test = ITEST_MAX; -+ -+ switch (test_code) -+ { -+ case EQ: -+ test = ITEST_EQ; -+ break; -+ case NE: -+ test = ITEST_NE; -+ break; -+ case GT: -+ test = ITEST_GT; -+ break; -+ case GE: -+ test = ITEST_GE; -+ break; -+ case LT: -+ test = ITEST_LT; -+ break; -+ case LE: -+ test = ITEST_LE; -+ break; -+ case GTU: -+ test = ITEST_GTU; -+ break; -+ case GEU: -+ test = ITEST_GEU; -+ break; -+ case LTU: -+ test = ITEST_LTU; -+ break; -+ case LEU: -+ test = ITEST_LEU; -+ break; -+ default: -+ break; -+ } -+ -+ return test; -+} -+ -+/* Generate the code to compare (and possibly branch) two integer values -+ TEST_CODE is the comparison code we are trying to emulate -+ (or implement directly) -+ RESULT is where to store the result of the comparison, -+ or null to emit a branch -+ CMP0 CMP1 are the two comparison operands -+ DESTINATION is the destination of the branch, or null to only compare -+ */ -+ -+void -+gen_int_relational (enum rtx_code test_code, /* relational test (EQ, etc) */ -+ rtx result, /* result to store comp. or 0 if branch */ -+ rtx cmp0, /* first operand to compare */ -+ rtx cmp1, /* second operand to compare */ -+ rtx destination) /* destination of the branch, or 0 if compare */ -+{ -+ struct cmp_info -+ { -+ /* for register (or 0) compares */ -+ enum rtx_code test_code_reg; /* code to use in instruction (LT vs. LTU) */ -+ int reverse_regs; /* reverse registers in test */ -+ -+ /* for immediate compares */ -+ enum rtx_code test_code_const; -+ /* code to use in instruction (LT vs. LTU) */ -+ int const_low; /* low bound of constant we can accept */ -+ int const_high; /* high bound of constant we can accept */ -+ int const_add; /* constant to add */ -+ -+ /* generic info */ -+ int unsignedp; /* != 0 for unsigned comparisons. */ -+ }; -+ -+ static const struct cmp_info info[(int) ITEST_MAX] = { -+ -+ {EQ, 0, EQ, -32768, 32767, 0, 0}, /* EQ */ -+ {NE, 0, NE, -32768, 32767, 0, 0}, /* NE */ -+ -+ {LT, 1, GE, -32769, 32766, 1, 0}, /* GT */ -+ {GE, 0, GE, -32768, 32767, 0, 0}, /* GE */ -+ {LT, 0, LT, -32768, 32767, 0, 0}, /* LT */ -+ {GE, 1, LT, -32769, 32766, 1, 0}, /* LE */ -+ -+ {LTU, 1, GEU, 0, 65534, 1, 0}, /* GTU */ -+ {GEU, 0, GEU, 0, 65535, 0, 0}, /* GEU */ -+ {LTU, 0, LTU, 0, 65535, 0, 0}, /* LTU */ -+ {GEU, 1, LTU, 0, 65534, 1, 0}, /* LEU */ -+ }; -+ -+ enum internal_test test; -+ enum machine_mode mode; -+ const struct cmp_info *p_info; -+ int branch_p; -+ -+ -+ -+ -+ test = map_test_to_internal_test (test_code); -+ if (test == ITEST_MAX) -+ abort (); -+ -+ p_info = &info[(int) test]; -+ -+ mode = GET_MODE (cmp0); -+ if (mode == VOIDmode) -+ mode = GET_MODE (cmp1); -+ -+ branch_p = (destination != 0); -+ -+ /* We can't, under any circumstances, have const_ints in cmp0 -+ ??? Actually we could have const0 */ -+ if (GET_CODE (cmp0) == CONST_INT) -+ cmp0 = force_reg (mode, cmp0); -+ -+ /* if the comparison is against an int not in legal range -+ move it into a register */ -+ if (GET_CODE (cmp1) == CONST_INT) -+ { -+ HOST_WIDE_INT value = INTVAL (cmp1); -+ -+ if (value < p_info->const_low || value > p_info->const_high) -+ cmp1 = force_reg (mode, cmp1); -+ } -+ -+ /* Comparison to constants, may involve adding 1 to change a GT into GE. -+ Comparison between two registers, may involve switching operands. */ -+ if (GET_CODE (cmp1) == CONST_INT) -+ { -+ if (p_info->const_add != 0) -+ { -+ HOST_WIDE_INT new = INTVAL (cmp1) + p_info->const_add; -+ -+ /* If modification of cmp1 caused overflow, -+ we would get the wrong answer if we follow the usual path; -+ thus, x > 0xffffffffU would turn into x > 0U. */ -+ if ((p_info->unsignedp -+ ? (unsigned HOST_WIDE_INT) new > -+ (unsigned HOST_WIDE_INT) INTVAL (cmp1) -+ : new > INTVAL (cmp1)) != (p_info->const_add > 0)) -+ { -+ /* ??? This case can never happen with the current numbers, -+ but I am paranoid and would rather an abort than -+ a bug I will never find */ -+ abort (); -+ } -+ else -+ cmp1 = GEN_INT (new); -+ } -+ } -+ -+ else if (p_info->reverse_regs) -+ { -+ rtx temp = cmp0; -+ cmp0 = cmp1; -+ cmp1 = temp; -+ } -+ -+ -+ -+ if (branch_p) -+ { -+ if (register_operand (cmp0, mode) && register_operand (cmp1, mode)) -+ { -+ rtx insn; -+ rtx cond = gen_rtx (p_info->test_code_reg, mode, cmp0, cmp1); -+ rtx label = gen_rtx_LABEL_REF (VOIDmode, destination); -+ -+ insn = gen_rtx_SET (VOIDmode, pc_rtx, -+ gen_rtx_IF_THEN_ELSE (VOIDmode, -+ cond, label, pc_rtx)); -+ emit_jump_insn (insn); -+ } -+ else -+ { -+ rtx cond, label; -+ -+ result = gen_reg_rtx (mode); -+ -+ emit_move_insn (result, -+ gen_rtx (p_info->test_code_const, mode, cmp0, -+ cmp1)); -+ -+ cond = gen_rtx (NE, mode, result, const0_rtx); -+ label = gen_rtx_LABEL_REF (VOIDmode, destination); -+ -+ emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, -+ gen_rtx_IF_THEN_ELSE (VOIDmode, -+ cond, -+ label, pc_rtx))); -+ } -+ } -+ else -+ { -+ if (register_operand (cmp0, mode) && register_operand (cmp1, mode)) -+ { -+ emit_move_insn (result, -+ gen_rtx (p_info->test_code_reg, mode, cmp0, cmp1)); -+ } -+ else -+ { -+ emit_move_insn (result, -+ gen_rtx (p_info->test_code_const, mode, cmp0, -+ cmp1)); -+ } -+ } -+ -+} -+ -+ -+/* ??? For now conditional moves are only supported -+ when the mode of the operands being compared are -+ the same as the ones being moved */ -+ -+void -+gen_conditional_move (rtx *operands, enum machine_mode mode) -+{ -+ rtx insn, cond; -+ rtx cmp_reg = gen_reg_rtx (mode); -+ enum rtx_code cmp_code = GET_CODE (operands[1]); -+ enum rtx_code move_code = EQ; -+ -+ /* emit a comparison if it is not "simple". -+ Simple comparisons are X eq 0 and X ne 0 */ -+ if ((cmp_code == EQ || cmp_code == NE) && branch_cmp[1] == const0_rtx) -+ { -+ cmp_reg = branch_cmp[0]; -+ move_code = cmp_code; -+ } -+ else if ((cmp_code == EQ || cmp_code == NE) && branch_cmp[0] == const0_rtx) -+ { -+ cmp_reg = branch_cmp[1]; -+ move_code = cmp_code == EQ ? NE : EQ; -+ } -+ else -+ gen_int_relational (cmp_code, cmp_reg, branch_cmp[0], branch_cmp[1], -+ NULL_RTX); -+ -+ cond = gen_rtx (move_code, VOIDmode, cmp_reg, CONST0_RTX (mode)); -+ insn = gen_rtx_SET (mode, operands[0], -+ gen_rtx_IF_THEN_ELSE (mode, -+ cond, operands[2], operands[3])); -+ emit_insn (insn); -+} -+ -+/******************* -+ * Addressing Modes -+ *******************/ -+ -+int -+nios2_legitimate_address (rtx operand, enum machine_mode mode ATTRIBUTE_UNUSED, -+ int strict) -+{ -+ int ret_val = 0; -+ -+ switch (GET_CODE (operand)) -+ { -+ /* direct. */ -+ case SYMBOL_REF: -+ if (SYMBOL_REF_IN_NIOS2_SMALL_DATA_P (operand)) -+ { -+ ret_val = 1; -+ 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 = 0; -+ -+ break; -+ -+ /* Register indirect. */ -+ case REG: -+ ret_val = REG_OK_FOR_BASE_P2 (operand, strict); -+ break; -+ -+ /* Register indirect with displacement */ -+ case PLUS: -+ { -+ rtx op0 = XEXP (operand, 0); -+ rtx op1 = XEXP (operand, 1); -+ -+ if (REG_P (op0) && REG_P (op1)) -+ ret_val = 0; -+ else if (REG_P (op0) && CONSTANT_P (op1)) -+ ret_val = REG_OK_FOR_BASE_P2 (op0, strict) -+ && SMALL_INT (INTVAL (op1)); -+ else if (REG_P (op1) && CONSTANT_P (op0)) -+ ret_val = REG_OK_FOR_BASE_P2 (op1, strict) -+ && SMALL_INT (INTVAL (op0)); -+ else -+ ret_val = 0; -+ } -+ break; -+ -+ default: -+ ret_val = 0; -+ break; -+ } -+ -+ return ret_val; -+} -+ -+/* Return true if EXP should be placed in the small data section. */ -+ -+static bool -+nios2_in_small_data_p (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 && size <= nios2_section_threshold) -+ return true; -+ } -+ -+ return false; -+} -+ -+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; -+} -+ -+ -+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); -+ -+ /* ??? these string names need moving into an array in some header file */ -+ if (strcmp (name, ".sbss") == 0 -+ || strncmp (name, ".sbss.", 6) == 0 -+ || strcmp (name, ".sdata") == 0 -+ || strncmp (name, ".sdata.", 7) == 0) -+ flags |= SECTION_SMALL; -+ -+ return flags; -+} -+ -+ -+ -+ -+/***************************************** -+ * Defining the Output Assembler Language -+ *****************************************/ -+ -+/* -------------- * -+ * Output of Data -+ * -------------- */ -+ -+ -+/* -------------------------------- * -+ * Output of Assembler Instructions -+ * -------------------------------- */ -+ -+ -+/* 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 -+ */ -+ -+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_CACHE_VOLATILE) -+ || TARGET_BYPASS_CACHE)) -+ fprintf (file, "io"); -+ return; -+ -+ default: -+ break; -+ } -+ -+ if (comparison_operator (op, VOIDmode)) -+ { -+ if (letter == 0) -+ { -+ fprintf (file, "%s", GET_RTX_NAME (GET_CODE (op))); -+ return; -+ } -+ } -+ -+ -+ switch (GET_CODE (op)) -+ { -+ case REG: -+ if (letter == 0 || letter == 'z') -+ { -+ fprintf (file, "%s", reg_names[REGNO (op)]); -+ return; -+ } -+ -+ 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 (val); -+ 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; -+ } -+ -+ -+ case SUBREG: -+ case MEM: -+ if (letter == 0) -+ { -+ output_address (op); -+ return; -+ } -+ -+ case CODE_LABEL: -+ if (letter == 0) -+ { -+ output_addr_const (file, op); -+ return; -+ } -+ -+ default: -+ break; -+ } -+ -+ fprintf (stderr, "Missing way to print (%c) ", letter); -+ debug_rtx (op); -+ abort (); -+} -+ -+static int gprel_constant (rtx); -+ -+static int -+gprel_constant (rtx op) -+{ -+ if (GET_CODE (op) == SYMBOL_REF -+ && SYMBOL_REF_IN_NIOS2_SMALL_DATA_P (op)) -+ { -+ return 1; -+ } -+ else if (GET_CODE (op) == CONST -+ && GET_CODE (XEXP (op, 0)) == PLUS) -+ { -+ return gprel_constant (XEXP (XEXP (op, 0), 0)); -+ } -+ else -+ { -+ return 0; -+ } -+} -+ -+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 (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); -+ PRINT_OPERAND_ADDRESS (file, base); -+ return; -+ } -+ default: -+ break; -+ } -+ -+ fprintf (stderr, "Missing way to print address\n"); -+ debug_rtx (op); -+ abort (); -+} -+ -+ -+ -+ -+ -+/**************************** -+ * Predicates -+ ****************************/ -+ -+int -+arith_operand (rtx op, enum machine_mode mode) -+{ -+ if (GET_CODE (op) == CONST_INT && SMALL_INT (INTVAL (op))) -+ return 1; -+ -+ return register_operand (op, mode); -+} -+ -+int -+uns_arith_operand (rtx op, enum machine_mode mode) -+{ -+ if (GET_CODE (op) == CONST_INT && SMALL_INT_UNSIGNED (INTVAL (op))) -+ return 1; -+ -+ return register_operand (op, mode); -+} -+ -+int -+logical_operand (rtx op, enum machine_mode mode) -+{ -+ if (GET_CODE (op) == CONST_INT -+ && (SMALL_INT_UNSIGNED (INTVAL (op)) || UPPER16_INT (INTVAL (op)))) -+ return 1; -+ -+ return register_operand (op, mode); -+} -+ -+int -+shift_operand (rtx op, enum machine_mode mode) -+{ -+ if (GET_CODE (op) == CONST_INT && SHIFT_INT (INTVAL (op))) -+ return 1; -+ -+ return register_operand (op, mode); -+} -+ -+int -+rdwrctl_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -+{ -+ return GET_CODE (op) == CONST_INT && RDWRCTL_INT (INTVAL (op)); -+} -+ -+/* Return truth value of whether OP is a register or the constant 0. */ -+ -+int -+reg_or_0_operand (rtx op, enum machine_mode mode) -+{ -+ switch (GET_CODE (op)) -+ { -+ case CONST_INT: -+ return INTVAL (op) == 0; -+ -+ case CONST_DOUBLE: -+ return op == CONST0_RTX (mode); -+ -+ default: -+ break; -+ } -+ -+ return register_operand (op, mode); -+} -+ -+ -+int -+equality_op (rtx op, enum machine_mode mode) -+{ -+ if (mode != GET_MODE (op)) -+ return 0; -+ -+ return GET_CODE (op) == EQ || GET_CODE (op) == NE; -+} -+ -+int -+custom_insn_opcode (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -+{ -+ return GET_CODE (op) == CONST_INT && CUSTOM_INSN_OPCODE (INTVAL (op)); -+} -+ -+ -+ -+ -+ -+ -+ -+/***************************************************************************** -+** -+** instruction scheduler -+** -+*****************************************************************************/ -+static int -+nios2_use_dfa_pipeline_interface () -+{ -+ return 1; -+} -+ -+ -+static int -+nios2_issue_rate () -+{ -+#ifdef MAX_DFA_ISSUE_RATE -+ return MAX_DFA_ISSUE_RATE; -+#else -+ return 1; -+#endif -+} -+ -+ -+const char * -+asm_output_opcode (FILE *file ATTRIBUTE_UNUSED, -+ const char *ptr ATTRIBUTE_UNUSED) -+{ -+ const char *p; -+ -+ p = ptr; -+ return ptr; -+} -+ -+ -+ -+/***************************************************************************** -+** -+** function arguments -+** -+*****************************************************************************/ -+ -+void -+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; -+} -+ -+ -+/* Update the data in CUM to advance over an argument -+ of mode MODE and data type TYPE. -+ (TYPE is null for libcalls where that information may not be available.) */ -+ -+void -+function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, -+ tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED) -+{ -+ HOST_WIDE_INT param_size; -+ -+ if (mode == BLKmode) -+ { -+ param_size = int_size_in_bytes (type); -+ if (param_size < 0) -+ internal_error -+ ("Do not know how to handle large structs or variable length types"); -+ } -+ else -+ { -+ param_size = GET_MODE_SIZE (mode); -+ } -+ -+ /* convert to words (round up) */ -+ param_size = (3 + param_size) / 4; -+ -+ if (cum->regs_used + param_size > NUM_ARG_REGS) -+ { -+ cum->regs_used = NUM_ARG_REGS; -+ } -+ else -+ { -+ cum->regs_used += param_size; -+ } -+ -+ return; -+} -+ -+/* Define where to put the arguments to a function. Value is zero to -+ push the argument on the stack, or a hard register in which to -+ store the argument. -+ -+ 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). */ -+rtx -+function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode, -+ tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED) -+{ -+ 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; -+} -+ -+int -+function_arg_partial_nregs (const CUMULATIVE_ARGS *cum, -+ enum machine_mode mode, tree type, -+ int named ATTRIBUTE_UNUSED) -+{ -+ HOST_WIDE_INT param_size; -+ -+ if (mode == BLKmode) -+ { -+ param_size = int_size_in_bytes (type); -+ if (param_size < 0) -+ internal_error -+ ("Do not know how to handle large structs or variable length types"); -+ } -+ else -+ { -+ param_size = GET_MODE_SIZE (mode); -+ } -+ -+ /* convert to words (round up) */ -+ param_size = (3 + param_size) / 4; -+ -+ if (cum->regs_used < NUM_ARG_REGS -+ && cum->regs_used + param_size > NUM_ARG_REGS) -+ { -+ return NUM_ARG_REGS - cum->regs_used; -+ } -+ else -+ { -+ return 0; -+ } -+} -+ -+ -+int -+nios2_return_in_memory (tree type) -+{ -+ int res = ((int_size_in_bytes (type) > (2 * UNITS_PER_WORD)) -+ || (int_size_in_bytes (type) == -1)); -+ -+ return res; -+} -+ -+/* ??? It may be possible to eliminate the copyback and implement -+ my own va_arg type, but that is more work for now. */ -+int -+nios2_setup_incoming_varargs (const CUMULATIVE_ARGS *cum, -+ enum machine_mode mode, tree type, -+ int no_rtl) -+{ -+ CUMULATIVE_ARGS local_cum; -+ int regs_to_push; -+ -+ local_cum = *cum; -+ FUNCTION_ARG_ADVANCE (local_cum, mode, type, 1); -+ -+ regs_to_push = NUM_ARG_REGS - local_cum.regs_used; -+ -+ if (!no_rtl) -+ { -+ if (regs_to_push > 0) -+ { -+ rtx ptr, mem; -+ -+ ptr = virtual_incoming_args_rtx; -+ mem = gen_rtx_MEM (BLKmode, ptr); -+ -+ /* va_arg is an array access in this case, which causes -+ it to get MEM_IN_STRUCT_P set. We must set it here -+ so that the insn scheduler won't assume that these -+ stores can't possibly overlap with the va_arg loads. */ -+ MEM_SET_IN_STRUCT_P (mem, 1); -+ -+ emit_insn (gen_blockage ()); -+ move_block_from_reg (local_cum.regs_used + FIRST_ARG_REGNO, mem, -+ regs_to_push); -+ emit_insn (gen_blockage ()); -+ } -+ } -+ -+ return regs_to_push * UNITS_PER_WORD; -+ -+} -+ -+ -+ -+/***************************************************************************** -+** -+** builtins -+** -+** This method for handling builtins is from CSP where _many_ more types of -+** expanders have already been written. Check there first before writing -+** new ones. -+** -+*****************************************************************************/ -+ -+enum nios2_builtins -+{ -+ NIOS2_BUILTIN_LDBIO, -+ NIOS2_BUILTIN_LDBUIO, -+ NIOS2_BUILTIN_LDHIO, -+ NIOS2_BUILTIN_LDHUIO, -+ NIOS2_BUILTIN_LDWIO, -+ NIOS2_BUILTIN_STBIO, -+ NIOS2_BUILTIN_STHIO, -+ NIOS2_BUILTIN_STWIO, -+ NIOS2_BUILTIN_SYNC, -+ NIOS2_BUILTIN_RDCTL, -+ NIOS2_BUILTIN_WRCTL, -+ -+ NIOS2_BUILTIN_CUSTOM_N, -+ NIOS2_BUILTIN_CUSTOM_NI, -+ NIOS2_BUILTIN_CUSTOM_NF, -+ NIOS2_BUILTIN_CUSTOM_NP, -+ NIOS2_BUILTIN_CUSTOM_NII, -+ NIOS2_BUILTIN_CUSTOM_NIF, -+ NIOS2_BUILTIN_CUSTOM_NIP, -+ NIOS2_BUILTIN_CUSTOM_NFI, -+ NIOS2_BUILTIN_CUSTOM_NFF, -+ NIOS2_BUILTIN_CUSTOM_NFP, -+ NIOS2_BUILTIN_CUSTOM_NPI, -+ NIOS2_BUILTIN_CUSTOM_NPF, -+ NIOS2_BUILTIN_CUSTOM_NPP, -+ NIOS2_BUILTIN_CUSTOM_IN, -+ NIOS2_BUILTIN_CUSTOM_INI, -+ NIOS2_BUILTIN_CUSTOM_INF, -+ NIOS2_BUILTIN_CUSTOM_INP, -+ NIOS2_BUILTIN_CUSTOM_INII, -+ NIOS2_BUILTIN_CUSTOM_INIF, -+ NIOS2_BUILTIN_CUSTOM_INIP, -+ NIOS2_BUILTIN_CUSTOM_INFI, -+ NIOS2_BUILTIN_CUSTOM_INFF, -+ NIOS2_BUILTIN_CUSTOM_INFP, -+ NIOS2_BUILTIN_CUSTOM_INPI, -+ NIOS2_BUILTIN_CUSTOM_INPF, -+ NIOS2_BUILTIN_CUSTOM_INPP, -+ NIOS2_BUILTIN_CUSTOM_FN, -+ NIOS2_BUILTIN_CUSTOM_FNI, -+ NIOS2_BUILTIN_CUSTOM_FNF, -+ NIOS2_BUILTIN_CUSTOM_FNP, -+ NIOS2_BUILTIN_CUSTOM_FNII, -+ NIOS2_BUILTIN_CUSTOM_FNIF, -+ NIOS2_BUILTIN_CUSTOM_FNIP, -+ NIOS2_BUILTIN_CUSTOM_FNFI, -+ NIOS2_BUILTIN_CUSTOM_FNFF, -+ NIOS2_BUILTIN_CUSTOM_FNFP, -+ NIOS2_BUILTIN_CUSTOM_FNPI, -+ NIOS2_BUILTIN_CUSTOM_FNPF, -+ NIOS2_BUILTIN_CUSTOM_FNPP, -+ NIOS2_BUILTIN_CUSTOM_PN, -+ NIOS2_BUILTIN_CUSTOM_PNI, -+ NIOS2_BUILTIN_CUSTOM_PNF, -+ NIOS2_BUILTIN_CUSTOM_PNP, -+ NIOS2_BUILTIN_CUSTOM_PNII, -+ NIOS2_BUILTIN_CUSTOM_PNIF, -+ NIOS2_BUILTIN_CUSTOM_PNIP, -+ NIOS2_BUILTIN_CUSTOM_PNFI, -+ NIOS2_BUILTIN_CUSTOM_PNFF, -+ NIOS2_BUILTIN_CUSTOM_PNFP, -+ NIOS2_BUILTIN_CUSTOM_PNPI, -+ NIOS2_BUILTIN_CUSTOM_PNPF, -+ NIOS2_BUILTIN_CUSTOM_PNPP, -+ -+ -+ LIM_NIOS2_BUILTINS -+}; -+ -+struct builtin_description -+{ -+ const enum insn_code icode; -+ const char *const name; -+ const enum nios2_builtins code; -+ const tree *type; -+ rtx (* expander) PARAMS ((const struct builtin_description *, -+ tree, rtx, rtx, enum machine_mode, int)); -+}; -+ -+static rtx nios2_expand_STXIO (const struct builtin_description *, -+ tree, rtx, rtx, enum machine_mode, int); -+static rtx nios2_expand_LDXIO (const struct builtin_description *, -+ tree, rtx, rtx, enum machine_mode, int); -+static rtx nios2_expand_sync (const struct builtin_description *, -+ tree, rtx, rtx, enum machine_mode, int); -+static rtx nios2_expand_rdctl (const struct builtin_description *, -+ tree, rtx, rtx, enum machine_mode, int); -+static rtx nios2_expand_wrctl (const struct builtin_description *, -+ tree, rtx, rtx, enum machine_mode, int); -+ -+static rtx nios2_expand_custom_n (const struct builtin_description *, -+ tree, rtx, rtx, enum machine_mode, int); -+static rtx nios2_expand_custom_Xn (const struct builtin_description *, -+ tree, rtx, rtx, enum machine_mode, int); -+static rtx nios2_expand_custom_nX (const struct builtin_description *, -+ tree, rtx, rtx, enum machine_mode, int); -+static rtx nios2_expand_custom_XnX (const struct builtin_description *, -+ tree, rtx, rtx, enum machine_mode, int); -+static rtx nios2_expand_custom_nXX (const struct builtin_description *, -+ tree, rtx, rtx, enum machine_mode, int); -+static rtx nios2_expand_custom_XnXX (const struct builtin_description *, -+ tree, rtx, rtx, enum machine_mode, int); -+ -+static tree endlink; -+ -+/* int fn (volatile const void *) -+ */ -+static tree int_ftype_volatile_const_void_p; -+ -+/* int fn (int) -+ */ -+static tree int_ftype_int; -+ -+/* void fn (int, int) -+ */ -+static tree void_ftype_int_int; -+ -+/* void fn (volatile void *, int) -+ */ -+static tree void_ftype_volatile_void_p_int; -+ -+/* void fn (void) -+ */ -+static tree void_ftype_void; -+ -+static tree custom_n; -+static tree custom_ni; -+static tree custom_nf; -+static tree custom_np; -+static tree custom_nii; -+static tree custom_nif; -+static tree custom_nip; -+static tree custom_nfi; -+static tree custom_nff; -+static tree custom_nfp; -+static tree custom_npi; -+static tree custom_npf; -+static tree custom_npp; -+static tree custom_in; -+static tree custom_ini; -+static tree custom_inf; -+static tree custom_inp; -+static tree custom_inii; -+static tree custom_inif; -+static tree custom_inip; -+static tree custom_infi; -+static tree custom_inff; -+static tree custom_infp; -+static tree custom_inpi; -+static tree custom_inpf; -+static tree custom_inpp; -+static tree custom_fn; -+static tree custom_fni; -+static tree custom_fnf; -+static tree custom_fnp; -+static tree custom_fnii; -+static tree custom_fnif; -+static tree custom_fnip; -+static tree custom_fnfi; -+static tree custom_fnff; -+static tree custom_fnfp; -+static tree custom_fnpi; -+static tree custom_fnpf; -+static tree custom_fnpp; -+static tree custom_pn; -+static tree custom_pni; -+static tree custom_pnf; -+static tree custom_pnp; -+static tree custom_pnii; -+static tree custom_pnif; -+static tree custom_pnip; -+static tree custom_pnfi; -+static tree custom_pnff; -+static tree custom_pnfp; -+static tree custom_pnpi; -+static tree custom_pnpf; -+static tree custom_pnpp; -+ -+ -+static const struct builtin_description bdesc[] = { -+ {CODE_FOR_ldbio, "__builtin_ldbio", NIOS2_BUILTIN_LDBIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO}, -+ {CODE_FOR_ldbuio, "__builtin_ldbuio", NIOS2_BUILTIN_LDBUIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO}, -+ {CODE_FOR_ldhio, "__builtin_ldhio", NIOS2_BUILTIN_LDHIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO}, -+ {CODE_FOR_ldhuio, "__builtin_ldhuio", NIOS2_BUILTIN_LDHUIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO}, -+ {CODE_FOR_ldwio, "__builtin_ldwio", NIOS2_BUILTIN_LDWIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO}, -+ -+ {CODE_FOR_stbio, "__builtin_stbio", NIOS2_BUILTIN_STBIO, &void_ftype_volatile_void_p_int, nios2_expand_STXIO}, -+ {CODE_FOR_sthio, "__builtin_sthio", NIOS2_BUILTIN_STHIO, &void_ftype_volatile_void_p_int, nios2_expand_STXIO}, -+ {CODE_FOR_stwio, "__builtin_stwio", NIOS2_BUILTIN_STWIO, &void_ftype_volatile_void_p_int, nios2_expand_STXIO}, -+ -+ {CODE_FOR_sync, "__builtin_sync", NIOS2_BUILTIN_SYNC, &void_ftype_void, nios2_expand_sync}, -+ {CODE_FOR_rdctl, "__builtin_rdctl", NIOS2_BUILTIN_RDCTL, &int_ftype_int, nios2_expand_rdctl}, -+ {CODE_FOR_wrctl, "__builtin_wrctl", NIOS2_BUILTIN_WRCTL, &void_ftype_int_int, nios2_expand_wrctl}, -+ -+ {CODE_FOR_custom_n, "__builtin_custom_n", NIOS2_BUILTIN_CUSTOM_N, &custom_n, nios2_expand_custom_n}, -+ {CODE_FOR_custom_ni, "__builtin_custom_ni", NIOS2_BUILTIN_CUSTOM_NI, &custom_ni, nios2_expand_custom_nX}, -+ {CODE_FOR_custom_nf, "__builtin_custom_nf", NIOS2_BUILTIN_CUSTOM_NF, &custom_nf, nios2_expand_custom_nX}, -+ {CODE_FOR_custom_np, "__builtin_custom_np", NIOS2_BUILTIN_CUSTOM_NP, &custom_np, nios2_expand_custom_nX}, -+ {CODE_FOR_custom_nii, "__builtin_custom_nii", NIOS2_BUILTIN_CUSTOM_NII, &custom_nii, nios2_expand_custom_nXX}, -+ {CODE_FOR_custom_nif, "__builtin_custom_nif", NIOS2_BUILTIN_CUSTOM_NIF, &custom_nif, nios2_expand_custom_nXX}, -+ {CODE_FOR_custom_nip, "__builtin_custom_nip", NIOS2_BUILTIN_CUSTOM_NIP, &custom_nip, nios2_expand_custom_nXX}, -+ {CODE_FOR_custom_nfi, "__builtin_custom_nfi", NIOS2_BUILTIN_CUSTOM_NFI, &custom_nfi, nios2_expand_custom_nXX}, -+ {CODE_FOR_custom_nff, "__builtin_custom_nff", NIOS2_BUILTIN_CUSTOM_NFF, &custom_nff, nios2_expand_custom_nXX}, -+ {CODE_FOR_custom_nfp, "__builtin_custom_nfp", NIOS2_BUILTIN_CUSTOM_NFP, &custom_nfp, nios2_expand_custom_nXX}, -+ {CODE_FOR_custom_npi, "__builtin_custom_npi", NIOS2_BUILTIN_CUSTOM_NPI, &custom_npi, nios2_expand_custom_nXX}, -+ {CODE_FOR_custom_npf, "__builtin_custom_npf", NIOS2_BUILTIN_CUSTOM_NPF, &custom_npf, nios2_expand_custom_nXX}, -+ {CODE_FOR_custom_npp, "__builtin_custom_npp", NIOS2_BUILTIN_CUSTOM_NPP, &custom_npp, nios2_expand_custom_nXX}, -+ {CODE_FOR_custom_in, "__builtin_custom_in", NIOS2_BUILTIN_CUSTOM_IN, &custom_in, nios2_expand_custom_Xn}, -+ {CODE_FOR_custom_ini, "__builtin_custom_ini", NIOS2_BUILTIN_CUSTOM_INI, &custom_ini, nios2_expand_custom_XnX}, -+ {CODE_FOR_custom_inf, "__builtin_custom_inf", NIOS2_BUILTIN_CUSTOM_INF, &custom_inf, nios2_expand_custom_XnX}, -+ {CODE_FOR_custom_inp, "__builtin_custom_inp", NIOS2_BUILTIN_CUSTOM_INP, &custom_inp, nios2_expand_custom_XnX}, -+ {CODE_FOR_custom_inii, "__builtin_custom_inii", NIOS2_BUILTIN_CUSTOM_INII, &custom_inii, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_inif, "__builtin_custom_inif", NIOS2_BUILTIN_CUSTOM_INIF, &custom_inif, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_inip, "__builtin_custom_inip", NIOS2_BUILTIN_CUSTOM_INIP, &custom_inip, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_infi, "__builtin_custom_infi", NIOS2_BUILTIN_CUSTOM_INFI, &custom_infi, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_inff, "__builtin_custom_inff", NIOS2_BUILTIN_CUSTOM_INFF, &custom_inff, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_infp, "__builtin_custom_infp", NIOS2_BUILTIN_CUSTOM_INFP, &custom_infp, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_inpi, "__builtin_custom_inpi", NIOS2_BUILTIN_CUSTOM_INPI, &custom_inpi, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_inpf, "__builtin_custom_inpf", NIOS2_BUILTIN_CUSTOM_INPF, &custom_inpf, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_inpp, "__builtin_custom_inpp", NIOS2_BUILTIN_CUSTOM_INPP, &custom_inpp, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_fn, "__builtin_custom_fn", NIOS2_BUILTIN_CUSTOM_FN, &custom_fn, nios2_expand_custom_Xn}, -+ {CODE_FOR_custom_fni, "__builtin_custom_fni", NIOS2_BUILTIN_CUSTOM_FNI, &custom_fni, nios2_expand_custom_XnX}, -+ {CODE_FOR_custom_fnf, "__builtin_custom_fnf", NIOS2_BUILTIN_CUSTOM_FNF, &custom_fnf, nios2_expand_custom_XnX}, -+ {CODE_FOR_custom_fnp, "__builtin_custom_fnp", NIOS2_BUILTIN_CUSTOM_FNP, &custom_fnp, nios2_expand_custom_XnX}, -+ {CODE_FOR_custom_fnii, "__builtin_custom_fnii", NIOS2_BUILTIN_CUSTOM_FNII, &custom_fnii, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_fnif, "__builtin_custom_fnif", NIOS2_BUILTIN_CUSTOM_FNIF, &custom_fnif, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_fnip, "__builtin_custom_fnip", NIOS2_BUILTIN_CUSTOM_FNIP, &custom_fnip, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_fnfi, "__builtin_custom_fnfi", NIOS2_BUILTIN_CUSTOM_FNFI, &custom_fnfi, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_fnff, "__builtin_custom_fnff", NIOS2_BUILTIN_CUSTOM_FNFF, &custom_fnff, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_fnfp, "__builtin_custom_fnfp", NIOS2_BUILTIN_CUSTOM_FNFP, &custom_fnfp, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_fnpi, "__builtin_custom_fnpi", NIOS2_BUILTIN_CUSTOM_FNPI, &custom_fnpi, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_fnpf, "__builtin_custom_fnpf", NIOS2_BUILTIN_CUSTOM_FNPF, &custom_fnpf, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_fnpp, "__builtin_custom_fnpp", NIOS2_BUILTIN_CUSTOM_FNPP, &custom_fnpp, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_pn, "__builtin_custom_pn", NIOS2_BUILTIN_CUSTOM_PN, &custom_pn, nios2_expand_custom_Xn}, -+ {CODE_FOR_custom_pni, "__builtin_custom_pni", NIOS2_BUILTIN_CUSTOM_PNI, &custom_pni, nios2_expand_custom_XnX}, -+ {CODE_FOR_custom_pnf, "__builtin_custom_pnf", NIOS2_BUILTIN_CUSTOM_PNF, &custom_pnf, nios2_expand_custom_XnX}, -+ {CODE_FOR_custom_pnp, "__builtin_custom_pnp", NIOS2_BUILTIN_CUSTOM_PNP, &custom_pnp, nios2_expand_custom_XnX}, -+ {CODE_FOR_custom_pnii, "__builtin_custom_pnii", NIOS2_BUILTIN_CUSTOM_PNII, &custom_pnii, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_pnif, "__builtin_custom_pnif", NIOS2_BUILTIN_CUSTOM_PNIF, &custom_pnif, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_pnip, "__builtin_custom_pnip", NIOS2_BUILTIN_CUSTOM_PNIP, &custom_pnip, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_pnfi, "__builtin_custom_pnfi", NIOS2_BUILTIN_CUSTOM_PNFI, &custom_pnfi, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_pnff, "__builtin_custom_pnff", NIOS2_BUILTIN_CUSTOM_PNFF, &custom_pnff, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_pnfp, "__builtin_custom_pnfp", NIOS2_BUILTIN_CUSTOM_PNFP, &custom_pnfp, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_pnpi, "__builtin_custom_pnpi", NIOS2_BUILTIN_CUSTOM_PNPI, &custom_pnpi, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_pnpf, "__builtin_custom_pnpf", NIOS2_BUILTIN_CUSTOM_PNPF, &custom_pnpf, nios2_expand_custom_XnXX}, -+ {CODE_FOR_custom_pnpp, "__builtin_custom_pnpp", NIOS2_BUILTIN_CUSTOM_PNPP, &custom_pnpp, nios2_expand_custom_XnXX}, -+ -+ -+ {0, 0, 0, 0, 0}, -+}; -+ -+/* This does not have a closing bracket on purpose (see use) */ -+#define def_param(TYPE) \ -+ tree_cons (NULL_TREE, TYPE, -+ -+static void -+nios2_init_builtins () -+{ -+ const struct builtin_description *d; -+ -+ -+ endlink = void_list_node; -+ -+ /* Special indenting here because one of the brackets is in def_param */ -+ /* *INDENT-OFF* */ -+ -+ /* int fn (volatile const void *) -+ */ -+ int_ftype_volatile_const_void_p -+ = build_function_type (integer_type_node, -+ def_param (build_qualified_type (ptr_type_node, -+ TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)) -+ endlink)); -+ -+ -+ /* void fn (volatile void *, int) -+ */ -+ void_ftype_volatile_void_p_int -+ = build_function_type (void_type_node, -+ def_param (build_qualified_type (ptr_type_node, -+ TYPE_QUAL_VOLATILE)) -+ def_param (integer_type_node) -+ endlink))); -+ -+ /* void fn (void) -+ */ -+ void_ftype_void -+ = build_function_type (void_type_node, -+ endlink); -+ -+ /* int fn (int) -+ */ -+ int_ftype_int -+ = build_function_type (integer_type_node, -+ def_param (integer_type_node) -+ endlink)); -+ -+ /* void fn (int, int) -+ */ -+ void_ftype_int_int -+ = build_function_type (void_type_node, -+ def_param (integer_type_node) -+ def_param (integer_type_node) -+ endlink))); -+ -+ -+#define CUSTOM_NUM def_param (integer_type_node) -+ -+ custom_n -+ = build_function_type (void_type_node, -+ CUSTOM_NUM -+ endlink)); -+ custom_ni -+ = build_function_type (void_type_node, -+ CUSTOM_NUM -+ def_param (integer_type_node) -+ endlink))); -+ custom_nf -+ = build_function_type (void_type_node, -+ CUSTOM_NUM -+ def_param (float_type_node) -+ endlink))); -+ custom_np -+ = build_function_type (void_type_node, -+ CUSTOM_NUM -+ def_param (ptr_type_node) -+ endlink))); -+ custom_nii -+ = build_function_type (void_type_node, -+ CUSTOM_NUM -+ def_param (integer_type_node) -+ def_param (integer_type_node) -+ endlink)))); -+ custom_nif -+ = build_function_type (void_type_node, -+ CUSTOM_NUM -+ def_param (integer_type_node) -+ def_param (float_type_node) -+ endlink)))); -+ custom_nip -+ = build_function_type (void_type_node, -+ CUSTOM_NUM -+ def_param (integer_type_node) -+ def_param (ptr_type_node) -+ endlink)))); -+ custom_nfi -+ = build_function_type (void_type_node, -+ CUSTOM_NUM -+ def_param (float_type_node) -+ def_param (integer_type_node) -+ endlink)))); -+ custom_nff -+ = build_function_type (void_type_node, -+ CUSTOM_NUM -+ def_param (float_type_node) -+ def_param (float_type_node) -+ endlink)))); -+ custom_nfp -+ = build_function_type (void_type_node, -+ CUSTOM_NUM -+ def_param (float_type_node) -+ def_param (ptr_type_node) -+ endlink)))); -+ custom_npi -+ = build_function_type (void_type_node, -+ CUSTOM_NUM -+ def_param (ptr_type_node) -+ def_param (integer_type_node) -+ endlink)))); -+ custom_npf -+ = build_function_type (void_type_node, -+ CUSTOM_NUM -+ def_param (ptr_type_node) -+ def_param (float_type_node) -+ endlink)))); -+ custom_npp -+ = build_function_type (void_type_node, -+ CUSTOM_NUM -+ def_param (ptr_type_node) -+ def_param (ptr_type_node) -+ endlink)))); -+ -+ custom_in -+ = build_function_type (integer_type_node, -+ CUSTOM_NUM -+ endlink)); -+ custom_ini -+ = build_function_type (integer_type_node, -+ CUSTOM_NUM -+ def_param (integer_type_node) -+ endlink))); -+ custom_inf -+ = build_function_type (integer_type_node, -+ CUSTOM_NUM -+ def_param (float_type_node) -+ endlink))); -+ custom_inp -+ = build_function_type (integer_type_node, -+ CUSTOM_NUM -+ def_param (ptr_type_node) -+ endlink))); -+ custom_inii -+ = build_function_type (integer_type_node, -+ CUSTOM_NUM -+ def_param (integer_type_node) -+ def_param (integer_type_node) -+ endlink)))); -+ custom_inif -+ = build_function_type (integer_type_node, -+ CUSTOM_NUM -+ def_param (integer_type_node) -+ def_param (float_type_node) -+ endlink)))); -+ custom_inip -+ = build_function_type (integer_type_node, -+ CUSTOM_NUM -+ def_param (integer_type_node) -+ def_param (ptr_type_node) -+ endlink)))); -+ custom_infi -+ = build_function_type (integer_type_node, -+ CUSTOM_NUM -+ def_param (float_type_node) -+ def_param (integer_type_node) -+ endlink)))); -+ custom_inff -+ = build_function_type (integer_type_node, -+ CUSTOM_NUM -+ def_param (float_type_node) -+ def_param (float_type_node) -+ endlink)))); -+ custom_infp -+ = build_function_type (integer_type_node, -+ CUSTOM_NUM -+ def_param (float_type_node) -+ def_param (ptr_type_node) -+ endlink)))); -+ custom_inpi -+ = build_function_type (integer_type_node, -+ CUSTOM_NUM -+ def_param (ptr_type_node) -+ def_param (integer_type_node) -+ endlink)))); -+ custom_inpf -+ = build_function_type (integer_type_node, -+ CUSTOM_NUM -+ def_param (ptr_type_node) -+ def_param (float_type_node) -+ endlink)))); -+ custom_inpp -+ = build_function_type (integer_type_node, -+ CUSTOM_NUM -+ def_param (ptr_type_node) -+ def_param (ptr_type_node) -+ endlink)))); -+ -+ custom_fn -+ = build_function_type (float_type_node, -+ CUSTOM_NUM -+ endlink)); -+ custom_fni -+ = build_function_type (float_type_node, -+ CUSTOM_NUM -+ def_param (integer_type_node) -+ endlink))); -+ custom_fnf -+ = build_function_type (float_type_node, -+ CUSTOM_NUM -+ def_param (float_type_node) -+ endlink))); -+ custom_fnp -+ = build_function_type (float_type_node, -+ CUSTOM_NUM -+ def_param (ptr_type_node) -+ endlink))); -+ custom_fnii -+ = build_function_type (float_type_node, -+ CUSTOM_NUM -+ def_param (integer_type_node) -+ def_param (integer_type_node) -+ endlink)))); -+ custom_fnif -+ = build_function_type (float_type_node, -+ CUSTOM_NUM -+ def_param (integer_type_node) -+ def_param (float_type_node) -+ endlink)))); -+ custom_fnip -+ = build_function_type (float_type_node, -+ CUSTOM_NUM -+ def_param (integer_type_node) -+ def_param (ptr_type_node) -+ endlink)))); -+ custom_fnfi -+ = build_function_type (float_type_node, -+ CUSTOM_NUM -+ def_param (float_type_node) -+ def_param (integer_type_node) -+ endlink)))); -+ custom_fnff -+ = build_function_type (float_type_node, -+ CUSTOM_NUM -+ def_param (float_type_node) -+ def_param (float_type_node) -+ endlink)))); -+ custom_fnfp -+ = build_function_type (float_type_node, -+ CUSTOM_NUM -+ def_param (float_type_node) -+ def_param (ptr_type_node) -+ endlink)))); -+ custom_fnpi -+ = build_function_type (float_type_node, -+ CUSTOM_NUM -+ def_param (ptr_type_node) -+ def_param (integer_type_node) -+ endlink)))); -+ custom_fnpf -+ = build_function_type (float_type_node, -+ CUSTOM_NUM -+ def_param (ptr_type_node) -+ def_param (float_type_node) -+ endlink)))); -+ custom_fnpp -+ = build_function_type (float_type_node, -+ CUSTOM_NUM -+ def_param (ptr_type_node) -+ def_param (ptr_type_node) -+ endlink)))); -+ -+ -+ custom_pn -+ = build_function_type (ptr_type_node, -+ CUSTOM_NUM -+ endlink)); -+ custom_pni -+ = build_function_type (ptr_type_node, -+ CUSTOM_NUM -+ def_param (integer_type_node) -+ endlink))); -+ custom_pnf -+ = build_function_type (ptr_type_node, -+ CUSTOM_NUM -+ def_param (float_type_node) -+ endlink))); -+ custom_pnp -+ = build_function_type (ptr_type_node, -+ CUSTOM_NUM -+ def_param (ptr_type_node) -+ endlink))); -+ custom_pnii -+ = build_function_type (ptr_type_node, -+ CUSTOM_NUM -+ def_param (integer_type_node) -+ def_param (integer_type_node) -+ endlink)))); -+ custom_pnif -+ = build_function_type (ptr_type_node, -+ CUSTOM_NUM -+ def_param (integer_type_node) -+ def_param (float_type_node) -+ endlink)))); -+ custom_pnip -+ = build_function_type (ptr_type_node, -+ CUSTOM_NUM -+ def_param (integer_type_node) -+ def_param (ptr_type_node) -+ endlink)))); -+ custom_pnfi -+ = build_function_type (ptr_type_node, -+ CUSTOM_NUM -+ def_param (float_type_node) -+ def_param (integer_type_node) -+ endlink)))); -+ custom_pnff -+ = build_function_type (ptr_type_node, -+ CUSTOM_NUM -+ def_param (float_type_node) -+ def_param (float_type_node) -+ endlink)))); -+ custom_pnfp -+ = build_function_type (ptr_type_node, -+ CUSTOM_NUM -+ def_param (float_type_node) -+ def_param (ptr_type_node) -+ endlink)))); -+ custom_pnpi -+ = build_function_type (ptr_type_node, -+ CUSTOM_NUM -+ def_param (ptr_type_node) -+ def_param (integer_type_node) -+ endlink)))); -+ custom_pnpf -+ = build_function_type (ptr_type_node, -+ CUSTOM_NUM -+ def_param (ptr_type_node) -+ def_param (float_type_node) -+ endlink)))); -+ custom_pnpp -+ = build_function_type (ptr_type_node, -+ CUSTOM_NUM -+ def_param (ptr_type_node) -+ def_param (ptr_type_node) -+ endlink)))); -+ -+ -+ -+ /* *INDENT-ON* */ -+ -+ -+ for (d = bdesc; d->name; d++) -+ { -+ builtin_function (d->name, *d->type, d->code, -+ BUILT_IN_MD, NULL, NULL); -+ } -+} -+ -+/* 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, -+ enum machine_mode mode, int ignore) -+{ -+ const struct builtin_description *d; -+ tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); -+ unsigned int fcode = DECL_FUNCTION_CODE (fndecl); -+ -+ for (d = bdesc; d->name; d++) -+ if (d->code == fcode) -+ return (d->expander) (d, exp, target, subtarget, mode, ignore); -+ -+ /* we should have seen one of the functins we registered */ -+ abort (); -+} -+ -+static rtx nios2_create_target (const struct builtin_description *, rtx); -+ -+ -+static rtx -+nios2_create_target (const struct builtin_description *d, rtx target) -+{ -+ if (!target -+ || !(*insn_data[d->icode].operand[0].predicate) (target, -+ insn_data[d->icode].operand[0].mode)) -+ { -+ target = gen_reg_rtx (insn_data[d->icode].operand[0].mode); -+ } -+ -+ return target; -+} -+ -+ -+static rtx nios2_extract_opcode (const struct builtin_description *, int, tree); -+static rtx nios2_extract_operand (const struct builtin_description *, int, int, tree); -+ -+static rtx -+nios2_extract_opcode (const struct builtin_description *d, int op, tree arglist) -+{ -+ enum machine_mode mode = insn_data[d->icode].operand[op].mode; -+ tree arg = TREE_VALUE (arglist); -+ rtx opcode = expand_expr (arg, NULL_RTX, mode, 0); -+ opcode = protect_from_queue (opcode, 0); -+ -+ if (!(*insn_data[d->icode].operand[op].predicate) (opcode, mode)) -+ error ("Custom instruction opcode must be compile time constant in the range 0-255 for %s", d->name); -+ -+ return opcode; -+} -+ -+static rtx -+nios2_extract_operand (const struct builtin_description *d, int op, int argnum, tree arglist) -+{ -+ enum machine_mode mode = insn_data[d->icode].operand[op].mode; -+ tree arg = TREE_VALUE (arglist); -+ rtx operand = expand_expr (arg, NULL_RTX, mode, 0); -+ operand = protect_from_queue (operand, 0); -+ -+ if (!(*insn_data[d->icode].operand[op].predicate) (operand, mode)) -+ operand = copy_to_mode_reg (mode, operand); -+ -+ /* ??? Better errors would be nice */ -+ if (!(*insn_data[d->icode].operand[op].predicate) (operand, mode)) -+ error ("Invalid argument %d to %s", argnum, d->name); -+ -+ return operand; -+} -+ -+ -+static rtx -+nios2_expand_custom_n (const struct builtin_description *d, tree exp, -+ rtx target ATTRIBUTE_UNUSED, rtx subtarget ATTRIBUTE_UNUSED, -+ enum machine_mode mode ATTRIBUTE_UNUSED, int ignore ATTRIBUTE_UNUSED) -+{ -+ tree arglist = TREE_OPERAND (exp, 1); -+ rtx pat; -+ rtx opcode; -+ -+ /* custom_n should have exactly one operand */ -+ if (insn_data[d->icode].n_operands != 1) -+ abort (); -+ -+ opcode = nios2_extract_opcode (d, 0, arglist); -+ -+ pat = GEN_FCN (d->icode) (opcode); -+ if (!pat) -+ return 0; -+ emit_insn (pat); -+ return 0; -+} -+ -+static rtx -+nios2_expand_custom_Xn (const struct builtin_description *d, tree exp, -+ rtx target, rtx subtarget ATTRIBUTE_UNUSED, -+ enum machine_mode mode ATTRIBUTE_UNUSED, -+ int ignore ATTRIBUTE_UNUSED) -+{ -+ tree arglist = TREE_OPERAND (exp, 1); -+ rtx pat; -+ rtx opcode; -+ -+ /* custom_Xn should have exactly two operands */ -+ if (insn_data[d->icode].n_operands != 2) -+ abort (); -+ -+ target = nios2_create_target (d, target); -+ opcode = nios2_extract_opcode (d, 1, arglist); -+ -+ pat = GEN_FCN (d->icode) (target, opcode); -+ if (!pat) -+ return 0; -+ emit_insn (pat); -+ return target; -+} -+ -+static rtx -+nios2_expand_custom_nX (const struct builtin_description *d, tree exp, -+ rtx target ATTRIBUTE_UNUSED, rtx subtarget ATTRIBUTE_UNUSED, -+ enum machine_mode mode ATTRIBUTE_UNUSED, int ignore ATTRIBUTE_UNUSED) -+{ -+ tree arglist = TREE_OPERAND (exp, 1); -+ rtx pat; -+ rtx opcode; -+ rtx operands[1]; -+ int i; -+ -+ -+ /* custom_nX should have exactly two operands */ -+ if (insn_data[d->icode].n_operands != 2) -+ abort (); -+ -+ opcode = nios2_extract_opcode (d, 0, arglist); -+ for (i = 0; i < 1; i++) -+ { -+ arglist = TREE_CHAIN (arglist); -+ operands[i] = nios2_extract_operand (d, i + 1, i + 1, arglist); -+ } -+ -+ pat = GEN_FCN (d->icode) (opcode, operands[0]); -+ if (!pat) -+ return 0; -+ emit_insn (pat); -+ return 0; -+} -+ -+static rtx -+nios2_expand_custom_XnX (const struct builtin_description *d, tree exp, rtx target, -+ rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED, -+ int ignore ATTRIBUTE_UNUSED) -+{ -+ tree arglist = TREE_OPERAND (exp, 1); -+ rtx pat; -+ rtx opcode; -+ rtx operands[1]; -+ int i; -+ -+ /* custom_Xn should have exactly three operands */ -+ if (insn_data[d->icode].n_operands != 3) -+ abort (); -+ -+ target = nios2_create_target (d, target); -+ opcode = nios2_extract_opcode (d, 1, arglist); -+ -+ for (i = 0; i < 1; i++) -+ { -+ arglist = TREE_CHAIN (arglist); -+ operands[i] = nios2_extract_operand (d, i + 2, i + 1, arglist); -+ } -+ -+ pat = GEN_FCN (d->icode) (target, opcode, operands[0]); -+ -+ if (!pat) -+ return 0; -+ emit_insn (pat); -+ return target; -+} -+ -+static rtx -+nios2_expand_custom_nXX (const struct builtin_description *d, tree exp, rtx target ATTRIBUTE_UNUSED, -+ rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED, -+ int ignore ATTRIBUTE_UNUSED) -+{ -+ tree arglist = TREE_OPERAND (exp, 1); -+ rtx pat; -+ rtx opcode; -+ rtx operands[2]; -+ int i; -+ -+ -+ /* custom_nX should have exactly three operands */ -+ if (insn_data[d->icode].n_operands != 3) -+ abort (); -+ -+ opcode = nios2_extract_opcode (d, 0, arglist); -+ for (i = 0; i < 2; i++) -+ { -+ arglist = TREE_CHAIN (arglist); -+ operands[i] = nios2_extract_operand (d, i + 1, i + 1, arglist); -+ } -+ -+ pat = GEN_FCN (d->icode) (opcode, operands[0], operands[1]); -+ if (!pat) -+ return 0; -+ emit_insn (pat); -+ return 0; -+} -+ -+static rtx -+nios2_expand_custom_XnXX (const struct builtin_description *d, tree exp, rtx target, -+ rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED, -+ int ignore ATTRIBUTE_UNUSED) -+{ -+ tree arglist = TREE_OPERAND (exp, 1); -+ rtx pat; -+ rtx opcode; -+ rtx operands[2]; -+ int i; -+ -+ -+ /* custom_XnX should have exactly four operands */ -+ if (insn_data[d->icode].n_operands != 4) -+ abort (); -+ -+ target = nios2_create_target (d, target); -+ opcode = nios2_extract_opcode (d, 1, arglist); -+ for (i = 0; i < 2; i++) -+ { -+ arglist = TREE_CHAIN (arglist); -+ operands[i] = nios2_extract_operand (d, i + 2, i + 1, arglist); -+ } -+ -+ pat = GEN_FCN (d->icode) (target, opcode, operands[0], operands[1]); -+ -+ if (!pat) -+ return 0; -+ emit_insn (pat); -+ return target; -+} -+ -+ -+ -+static rtx -+nios2_expand_STXIO (const struct builtin_description *d, tree exp, rtx target ATTRIBUTE_UNUSED, -+ rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED, -+ int ignore ATTRIBUTE_UNUSED) -+{ -+ tree arglist = TREE_OPERAND (exp, 1); -+ rtx pat; -+ rtx store_dest, store_val; -+ enum insn_code icode = d->icode; -+ -+ /* stores should have exactly two operands */ -+ if (insn_data[icode].n_operands != 2) -+ abort (); -+ -+ /* process the destination of the store */ -+ { -+ enum machine_mode mode = insn_data[icode].operand[0].mode; -+ tree arg = TREE_VALUE (arglist); -+ store_dest = expand_expr (arg, NULL_RTX, VOIDmode, 0); -+ store_dest = protect_from_queue (store_dest, 0); -+ -+ store_dest = gen_rtx_MEM (mode, copy_to_mode_reg (Pmode, store_dest)); -+ -+ /* ??? Better errors would be nice */ -+ if (!(*insn_data[icode].operand[0].predicate) (store_dest, mode)) -+ error ("Invalid argument 1 to %s", d->name); -+ } -+ -+ -+ /* process the value to store */ -+ { -+ enum machine_mode mode = insn_data[icode].operand[1].mode; -+ tree arg = TREE_VALUE (TREE_CHAIN (arglist)); -+ store_val = expand_expr (arg, NULL_RTX, mode, 0); -+ store_val = protect_from_queue (store_val, 0); -+ -+ if (!(*insn_data[icode].operand[1].predicate) (store_val, mode)) -+ store_val = copy_to_mode_reg (mode, store_val); -+ -+ /* ??? Better errors would be nice */ -+ if (!(*insn_data[icode].operand[1].predicate) (store_val, mode)) -+ error ("Invalid argument 2 to %s", d->name); -+ } -+ -+ pat = GEN_FCN (d->icode) (store_dest, store_val); -+ if (!pat) -+ return 0; -+ emit_insn (pat); -+ return 0; -+} -+ -+ -+static rtx -+nios2_expand_LDXIO (const struct builtin_description * d, tree exp, rtx target, -+ rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED, -+ int ignore ATTRIBUTE_UNUSED) -+{ -+ tree arglist = TREE_OPERAND (exp, 1); -+ rtx pat; -+ rtx ld_src; -+ enum insn_code icode = d->icode; -+ -+ /* loads should have exactly two operands */ -+ if (insn_data[icode].n_operands != 2) -+ abort (); -+ -+ target = nios2_create_target (d, target); -+ -+ { -+ enum machine_mode mode = insn_data[icode].operand[1].mode; -+ tree arg = TREE_VALUE (arglist); -+ ld_src = expand_expr (arg, NULL_RTX, VOIDmode, 0); -+ ld_src = protect_from_queue (ld_src, 0); -+ -+ ld_src = gen_rtx_MEM (mode, copy_to_mode_reg (Pmode, ld_src)); -+ -+ /* ??? Better errors would be nice */ -+ if (!(*insn_data[icode].operand[1].predicate) (ld_src, mode)) -+ { -+ error ("Invalid argument 1 to %s", d->name); -+ } -+ } -+ -+ pat = GEN_FCN (d->icode) (target, ld_src); -+ if (!pat) -+ return 0; -+ emit_insn (pat); -+ return target; -+} -+ -+ -+static rtx -+nios2_expand_sync (const struct builtin_description * d ATTRIBUTE_UNUSED, -+ tree exp ATTRIBUTE_UNUSED, rtx target ATTRIBUTE_UNUSED, -+ rtx subtarget ATTRIBUTE_UNUSED, -+ enum machine_mode mode ATTRIBUTE_UNUSED, -+ int ignore ATTRIBUTE_UNUSED) -+{ -+ emit_insn (gen_sync ()); -+ return 0; -+} -+ -+static rtx -+nios2_expand_rdctl (const struct builtin_description * d ATTRIBUTE_UNUSED, -+ tree exp ATTRIBUTE_UNUSED, rtx target ATTRIBUTE_UNUSED, -+ rtx subtarget ATTRIBUTE_UNUSED, -+ enum machine_mode mode ATTRIBUTE_UNUSED, -+ int ignore ATTRIBUTE_UNUSED) -+{ -+ tree arglist = TREE_OPERAND (exp, 1); -+ rtx pat; -+ rtx rdctl_reg; -+ enum insn_code icode = d->icode; -+ -+ /* rdctl should have exactly two operands */ -+ if (insn_data[icode].n_operands != 2) -+ abort (); -+ -+ target = nios2_create_target (d, target); -+ -+ { -+ enum machine_mode mode = insn_data[icode].operand[1].mode; -+ tree arg = TREE_VALUE (arglist); -+ rdctl_reg = expand_expr (arg, NULL_RTX, VOIDmode, 0); -+ rdctl_reg = protect_from_queue (rdctl_reg, 0); -+ -+ if (!(*insn_data[icode].operand[1].predicate) (rdctl_reg, mode)) -+ { -+ error ("Control register number must be in range 0-31 for %s", d->name); -+ } -+ } -+ -+ pat = GEN_FCN (d->icode) (target, rdctl_reg); -+ if (!pat) -+ return 0; -+ emit_insn (pat); -+ return target; -+} -+ -+static rtx -+nios2_expand_wrctl (const struct builtin_description * d ATTRIBUTE_UNUSED, -+ tree exp ATTRIBUTE_UNUSED, rtx target ATTRIBUTE_UNUSED, -+ rtx subtarget ATTRIBUTE_UNUSED, -+ enum machine_mode mode ATTRIBUTE_UNUSED, -+ int ignore ATTRIBUTE_UNUSED) -+{ -+ tree arglist = TREE_OPERAND (exp, 1); -+ rtx pat; -+ rtx wrctl_reg, store_val; -+ enum insn_code icode = d->icode; -+ -+ /* stores should have exactly two operands */ -+ if (insn_data[icode].n_operands != 2) -+ abort (); -+ -+ /* process the destination of the store */ -+ { -+ enum machine_mode mode = insn_data[icode].operand[0].mode; -+ tree arg = TREE_VALUE (arglist); -+ wrctl_reg = expand_expr (arg, NULL_RTX, VOIDmode, 0); -+ wrctl_reg = protect_from_queue (wrctl_reg, 0); -+ -+ if (!(*insn_data[icode].operand[0].predicate) (wrctl_reg, mode)) -+ error ("Control register number must be in range 0-31 for %s", d->name); -+ } -+ -+ -+ /* process the value to store */ -+ { -+ enum machine_mode mode = insn_data[icode].operand[1].mode; -+ tree arg = TREE_VALUE (TREE_CHAIN (arglist)); -+ store_val = expand_expr (arg, NULL_RTX, mode, 0); -+ store_val = protect_from_queue (store_val, 0); -+ -+ if (!(*insn_data[icode].operand[1].predicate) (store_val, mode)) -+ store_val = copy_to_mode_reg (mode, store_val); -+ -+ /* ??? Better errors would be nice */ -+ if (!(*insn_data[icode].operand[1].predicate) (store_val, mode)) -+ error ("Invalid argument 2 to %s", d->name); -+ } -+ -+ pat = GEN_FCN (d->icode) (wrctl_reg, store_val); -+ if (!pat) -+ return 0; -+ emit_insn (pat); -+ return 0; -+} -+ -+ -+#include "gt-nios2.h" -+ ---- gcc-3.4.3/gcc/config/nios2/nios2.h -+++ gcc-3.4.3-nios2/gcc/config/nios2/nios2.h -@@ -0,0 +1,824 @@ -+/* Definitions of target machine for Altera NIOS 2G NIOS2 version. -+ Copyright (C) 2003 Altera -+ Contributed by Jonah Graham (jgraham@altera.com). -+ -+This file is part of GNU CC. -+ -+GNU CC is free software; you can redistribute it and/or modify -+it under the terms of the GNU General Public License as published by -+the Free Software Foundation; either version 2, or (at your option) -+any later version. -+ -+GNU CC is distributed in the hope that it will be useful, -+but WITHOUT ANY WARRANTY; without even the implied warranty of -+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+GNU General Public License for more details. -+ -+You should have received a copy of the GNU General Public License -+along with GNU CC; see the file COPYING. If not, write to -+the Free Software Foundation, 59 Temple Place - Suite 330, -+Boston, MA 02111-1307, USA. */ -+ -+ -+ -+#define TARGET_CPU_CPP_BUILTINS() \ -+ do \ -+ { \ -+ builtin_define_std ("NIOS2"); \ -+ builtin_define_std ("nios2"); \ -+ builtin_define ("_GNU_SOURCE"); \ -+ } \ -+ while (0) -+#define TARGET_VERSION fprintf (stderr, " (Altera Nios II)") -+ -+ -+ -+ -+ -+/********************************* -+ * Run-time Target Specification -+ *********************************/ -+ -+#define HAS_DIV_FLAG 0x0001 -+#define HAS_MUL_FLAG 0x0002 -+#define HAS_MULX_FLAG 0x0004 -+#define FAST_SW_DIV_FLAG 0x0008 -+#define INLINE_MEMCPY_FLAG 0x00010 -+#define CACHE_VOLATILE_FLAG 0x0020 -+#define BYPASS_CACHE_FLAG 0x0040 -+ -+extern int target_flags; -+#define TARGET_HAS_DIV (target_flags & HAS_DIV_FLAG) -+#define TARGET_HAS_MUL (target_flags & HAS_MUL_FLAG) -+#define TARGET_HAS_MULX (target_flags & HAS_MULX_FLAG) -+#define TARGET_FAST_SW_DIV (target_flags & FAST_SW_DIV_FLAG) -+#define TARGET_INLINE_MEMCPY (target_flags & INLINE_MEMCPY_FLAG) -+#define TARGET_CACHE_VOLATILE (target_flags & CACHE_VOLATILE_FLAG) -+#define TARGET_BYPASS_CACHE (target_flags & BYPASS_CACHE_FLAG) -+ -+#define TARGET_SWITCHES \ -+{ \ -+ { "hw-div", HAS_DIV_FLAG, \ -+ N_("Enable DIV, DIVU") }, \ -+ { "no-hw-div", -HAS_DIV_FLAG, \ -+ N_("Disable DIV, DIVU (default)") }, \ -+ { "hw-mul", HAS_MUL_FLAG, \ -+ N_("Enable MUL instructions (default)") }, \ -+ { "hw-mulx", HAS_MULX_FLAG, \ -+ N_("Enable MULX instructions, assume fast shifter") }, \ -+ { "no-hw-mul", -HAS_MUL_FLAG, \ -+ N_("Disable MUL instructions") }, \ -+ { "no-hw-mulx", -HAS_MULX_FLAG, \ -+ N_("Disable MULX instructions, assume slow shifter (default and implied by -mno-hw-mul)") }, \ -+ { "fast-sw-div", FAST_SW_DIV_FLAG, \ -+ N_("Use table based fast divide (default at -O3)") }, \ -+ { "no-fast-sw-div", -FAST_SW_DIV_FLAG, \ -+ N_("Don't use table based fast divide ever") }, \ -+ { "inline-memcpy", INLINE_MEMCPY_FLAG, \ -+ N_("Inline small memcpy (default when optimizing)") }, \ -+ { "no-inline-memcpy", -INLINE_MEMCPY_FLAG, \ -+ N_("Don't Inline small memcpy") }, \ -+ { "cache-volatile", CACHE_VOLATILE_FLAG, \ -+ N_("Volatile accesses use non-io variants of instructions (default)") }, \ -+ { "no-cache-volatile", -CACHE_VOLATILE_FLAG, \ -+ N_("Volatile accesses use io variants of instructions") }, \ -+ { "bypass-cache", BYPASS_CACHE_FLAG, \ -+ N_("All ld/st instructins use io variants") }, \ -+ { "no-bypass-cache", -BYPASS_CACHE_FLAG, \ -+ N_("All ld/st instructins do not use io variants (default)") }, \ -+ { "smallc", 0, \ -+ N_("Link with a limited version of the C library") }, \ -+ { "ctors-in-init", 0, \ -+ "" /* undocumented: N_("Link with static constructors and destructors in init") */ }, \ -+ { "", TARGET_DEFAULT, 0 } \ -+} -+ -+ -+extern const char *nios2_sys_nosys_string; /* for -msys=nosys */ -+extern const char *nios2_sys_lib_string; /* for -msys-lib= */ -+extern const char *nios2_sys_crt0_string; /* for -msys-crt0= */ -+ -+#define TARGET_OPTIONS \ -+{ \ -+ { "sys=nosys", &nios2_sys_nosys_string, \ -+ N_("Use stub versions of OS library calls (default)"), 0}, \ -+ { "sys-lib=", &nios2_sys_lib_string, \ -+ N_("Name of System Library to link against. (Converted to a -l option)"), 0}, \ -+ { "sys-crt0=", &nios2_sys_crt0_string, \ -+ N_("Name of the startfile. (default is a crt0 for the ISS only)"), 0}, \ -+} -+ -+ -+/* Default target_flags if no switches specified. */ -+#ifndef TARGET_DEFAULT -+# define TARGET_DEFAULT (HAS_MUL_FLAG | CACHE_VOLATILE_FLAG) -+#endif -+ -+/* Switch Recognition by gcc.c. Add -G xx support */ -+#undef SWITCH_TAKES_ARG -+#define SWITCH_TAKES_ARG(CHAR) \ -+ (DEFAULT_SWITCH_TAKES_ARG (CHAR) || (CHAR) == 'G') -+ -+#define OVERRIDE_OPTIONS override_options () -+#define OPTIMIZATION_OPTIONS(LEVEL, SIZE) optimization_options (LEVEL, SIZE) -+#define CAN_DEBUG_WITHOUT_FP -+ -+#define CC1_SPEC "\ -+%{G*}" -+ -+#undef LIB_SPEC -+#define LIB_SPEC \ -+"--start-group %{msmallc: -lsmallc} %{!msmallc: -lc} -lgcc \ -+ %{msys-lib=*: -l%*} \ -+ %{!msys-lib=*: -lc } \ -+ --end-group \ -+ %{msys-lib=: %eYou need a library name for -msys-lib=} \ -+" -+ -+ -+#undef STARTFILE_SPEC -+#define STARTFILE_SPEC \ -+"%{msys-crt0=*: %*} %{!msys-crt0=*: crt1%O%s} \ -+ %{msys-crt0=: %eYou need a C startup file for -msys-crt0=} \ -+ %{mctors-in-init: crti%O%s crtbegin%O%s} \ -+" -+ -+#undef ENDFILE_SPEC -+#define ENDFILE_SPEC \ -+ "%{mctors-in-init: crtend%O%s crtn%O%s}" -+ -+ -+/*********************** -+ * Storage Layout -+ ***********************/ -+ -+#define DEFAULT_SIGNED_CHAR 1 -+#define BITS_BIG_ENDIAN 0 -+#define BYTES_BIG_ENDIAN 0 -+#define WORDS_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 -+ -+ -+/************************* -+ * Condition Code Status -+ ************************/ -+ -+/* comparison type */ -+/* ??? currently only CMP_SI is used */ -+enum cmp_type { -+ CMP_SI, /* compare four byte integers */ -+ CMP_DI, /* compare eight byte integers */ -+ CMP_SF, /* compare single precision floats */ -+ CMP_DF, /* compare double precision floats */ -+ CMP_MAX /* max comparison type */ -+}; -+ -+extern GTY(()) rtx branch_cmp[2]; /* operands for compare */ -+extern enum cmp_type branch_type; /* what type of branch to use */ -+ -+/********************** -+ * Register Usage -+ **********************/ -+ -+/* ---------------------------------- * -+ * 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 -+23 r23 sc Static Chain (Callee Saved) -+ ??? Does $sc want to be caller or callee -+ saved. If caller, 15, else 23. -+24 r24 Exception Temporary -+25 r25 Breakpoint Temporary -+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 rap Return address pointer, this does not -+ actually exist and will be eliminated -+ -+39 fake_fp Fake Frame Pointer which will always be eliminated. -+40 fake_ap Fake Argument Pointer which will always be eliminated. -+ -+41 First Pseudo Register -+ -+ -+The definitions for all the hard register numbers -+are located in nios2.md. -+*/ -+ -+#define FIRST_PSEUDO_REGISTER 41 -+#define NUM_ARG_REGS (LAST_ARG_REGNO - FIRST_ARG_REGNO + 1) -+ -+ -+ -+/* also see CONDITIONAL_REGISTER_USAGE */ -+#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, 0, 0, 1, 1, 1, 1, 0, 1, \ -+/* 30 */ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, \ -+/* 40 */ 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, 0, 0, 1, 1, 1, 1, 0, 1, \ -+/* 30 */ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, \ -+/* 40 */ 1, \ -+ } -+ -+#define HARD_REGNO_NREGS(REGNO, MODE) \ -+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \ -+ / UNITS_PER_WORD) -+ -+/* --------------------------- * -+ * How Values Fit in Registers -+ * --------------------------- */ -+ -+#define HARD_REGNO_MODE_OK(REGNO, MODE) 1 -+ -+#define MODES_TIEABLE_P(MODE1, MODE2) 1 -+ -+ -+/************************* -+ * Register Classes -+ *************************/ -+ -+enum reg_class -+{ -+ NO_REGS, -+ ALL_REGS, -+ LIM_REG_CLASSES -+}; -+ -+#define N_REG_CLASSES (int) LIM_REG_CLASSES -+ -+#define REG_CLASS_NAMES \ -+ {"NO_REGS", \ -+ "ALL_REGS"} -+ -+#define GENERAL_REGS ALL_REGS -+ -+#define REG_CLASS_CONTENTS \ -+/* NO_REGS */ {{ 0, 0}, \ -+/* ALL_REGS */ {~0,~0}} \ -+ -+#define REGNO_REG_CLASS(REGNO) ALL_REGS -+ -+#define BASE_REG_CLASS ALL_REGS -+#define INDEX_REG_CLASS ALL_REGS -+ -+/* only one reg class, 'r', is handled automatically */ -+#define REG_CLASS_FROM_LETTER(CHAR) NO_REGS -+ -+#define REGNO_OK_FOR_BASE_P2(REGNO, STRICT) \ -+ ((STRICT) \ -+ ? (REGNO) < FIRST_PSEUDO_REGISTER \ -+ : (REGNO) < FIRST_PSEUDO_REGISTER || (reg_renumber && reg_renumber[REGNO] < FIRST_PSEUDO_REGISTER)) -+ -+#define REGNO_OK_FOR_INDEX_P2(REGNO, STRICT) \ -+ (REGNO_OK_FOR_BASE_P2 (REGNO, STRICT)) -+ -+#define REGNO_OK_FOR_BASE_P(REGNO) \ -+ (REGNO_OK_FOR_BASE_P2 (REGNO, 1)) -+ -+#define REGNO_OK_FOR_INDEX_P(REGNO) \ -+ (REGNO_OK_FOR_INDEX_P2 (REGNO, 1)) -+ -+#define REG_OK_FOR_BASE_P2(X, STRICT) \ -+ (STRICT \ -+ ? REGNO_OK_FOR_BASE_P2 (REGNO (X), 1) \ -+ : REGNO_OK_FOR_BASE_P2 (REGNO (X), 1) || REGNO(X) >= FIRST_PSEUDO_REGISTER) -+ -+#define REG_OK_FOR_INDEX_P2(X, STRICT) \ -+ (STRICT \ -+ ? REGNO_OK_FOR_INDEX_P2 (REGNO (X), 1) \ -+ : REGNO_OK_FOR_INDEX_P2 (REGNO (X), 1) || REGNO(X) >= FIRST_PSEUDO_REGISTER) -+ -+#define CLASS_MAX_NREGS(CLASS, MODE) \ -+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \ -+ / UNITS_PER_WORD) -+ -+ -+#define SMALL_INT(X) ((unsigned HOST_WIDE_INT) ((X) + 0x8000) < 0x10000) -+#define SMALL_INT_UNSIGNED(X) ((unsigned HOST_WIDE_INT) (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) -+ -+#define CONST_OK_FOR_LETTER_P(VALUE, C) \ -+ ( \ -+ (C) == 'I' ? SMALL_INT (VALUE) : \ -+ (C) == 'J' ? SMALL_INT_UNSIGNED (VALUE) : \ -+ (C) == 'K' ? UPPER16_INT (VALUE) : \ -+ (C) == 'L' ? SHIFT_INT (VALUE) : \ -+ (C) == 'M' ? (VALUE) == 0 : \ -+ (C) == 'N' ? CUSTOM_INSN_OPCODE (VALUE) : \ -+ (C) == 'O' ? RDWRCTL_INT (VALUE) : \ -+ 0) -+ -+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 0 -+ -+#define PREFERRED_RELOAD_CLASS(X, CLASS) \ -+ ((CLASS) == NO_REGS ? GENERAL_REGS : (CLASS)) -+ -+/* 'S' matches immediates which are in small data -+ and therefore can be added to gp to create a -+ 32-bit value. */ -+#define EXTRA_CONSTRAINT(VALUE, C) \ -+ ((C) == 'S' \ -+ && (GET_CODE (VALUE) == SYMBOL_REF) \ -+ && SYMBOL_REF_IN_NIOS2_SMALL_DATA_P (VALUE)) -+ -+ -+ -+ -+/* 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) -+ -+ -+#define DEFAULT_MAIN_RETURN c_expand_return (integer_zero_node) -+ -+/********************************** -+ * Trampolines for Nested Functions -+ ***********************************/ -+ -+#define TRAMPOLINE_TEMPLATE(FILE) \ -+ error ("trampolines not yet implemented") -+#define TRAMPOLINE_SIZE 20 -+#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ -+ error ("trampolines not yet implemented") -+ -+/*************************** -+ * Stack Layout and Calling Conventions -+ ***************************/ -+ -+/* ------------------ * -+ * Basic Stack Layout -+ * ------------------ */ -+ -+/* 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 current_function_outgoing_args_size -+#define FIRST_PARM_OFFSET(FUNDECL) 0 -+ -+/* Before the prologue, RA lives in r31. */ -+#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (VOIDmode, RA_REGNO) -+ -+/* -------------------------------------- * -+ * 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 -+#define RETURN_ADDRESS_POINTER_REGNUM RAP_REGNO -+/* the argumnet pointer needs to always be eliminated -+ so it is set to a fake hard register. */ -+#define ARG_POINTER_REGNUM FAKE_AP_REGNO -+ -+/* ----------------------------------------- * -+ * Eliminating Frame Pointer and Arg Pointer -+ * ----------------------------------------- */ -+ -+#define FRAME_POINTER_REQUIRED 0 -+ -+#define ELIMINABLE_REGS \ -+{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ -+ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \ -+ { RETURN_ADDRESS_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ -+ { RETURN_ADDRESS_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \ -+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ -+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}} -+ -+#define CAN_ELIMINATE(FROM, TO) 1 -+ -+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ -+ (OFFSET) = nios2_initial_elimination_offset ((FROM), (TO)) -+ -+#define MUST_SAVE_REGISTER(regno) \ -+ ((regs_ever_live[regno] && !call_used_regs[regno]) \ -+ || (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed) \ -+ || (regno == RA_REGNO && regs_ever_live[RA_REGNO])) -+ -+/* 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)) -+ -+ -+/* ------------------------------ * -+ * Passing Arguments in Registers -+ * ------------------------------ */ -+ -+/* see nios2.c */ -+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ -+ (function_arg (&CUM, MODE, TYPE, NAMED)) -+ -+#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \ -+ (function_arg_partial_nregs (&CUM, MODE, TYPE, NAMED)) -+ -+#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) 0 -+ -+#define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) 0 -+ -+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) \ -+ (init_cumulative_args (&CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS)) -+ -+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ -+ (function_arg_advance (&CUM, MODE, TYPE, NAMED)) -+ -+#define FUNCTION_ARG_REGNO_P(REGNO) \ -+ ((REGNO) >= FIRST_ARG_REGNO && (REGNO) <= LAST_ARG_REGNO) -+ -+#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \ -+ { \ -+ int pret_size = nios2_setup_incoming_varargs (&(CUM), (MODE), \ -+ (TYPE), (NO_RTL)); \ -+ if (pret_size) \ -+ (PRETEND_SIZE) = pret_size; \ -+ } -+ -+/* ----------------------------- * -+ * Generating Code for Profiling -+ * ----------------------------- */ -+ -+#define PROFILE_BEFORE_PROLOGUE -+ -+#define FUNCTION_PROFILER(FILE, LABELNO) \ -+ function_profiler ((FILE), (LABELNO)) -+ -+/* --------------------------------------- * -+ * Passing Function Arguments on the Stack -+ * --------------------------------------- */ -+ -+#define PROMOTE_PROTOTYPES 1 -+ -+#define PUSH_ARGS 0 -+#define ACCUMULATE_OUTGOING_ARGS 1 -+ -+#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACKSIZE) 0 -+ -+/* --------------------------------------- * -+ * How Scalar Function Values Are Returned -+ * --------------------------------------- */ -+ -+#define FUNCTION_VALUE(VALTYPE, FUNC) \ -+ gen_rtx(REG, TYPE_MODE(VALTYPE), FIRST_RETVAL_REGNO) -+ -+#define LIBCALL_VALUE(MODE) \ -+ gen_rtx(REG, MODE, FIRST_RETVAL_REGNO) -+ -+#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == FIRST_RETVAL_REGNO) -+ -+/* ----------------------------- * -+ * How Large Values Are Returned -+ * ----------------------------- */ -+ -+ -+#define RETURN_IN_MEMORY(TYPE) \ -+ nios2_return_in_memory (TYPE) -+ -+ -+#define STRUCT_VALUE 0 -+ -+#define DEFAULT_PCC_STRUCT_RETURN 0 -+ -+/******************* -+ * Addressing Modes -+ *******************/ -+ -+ -+#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) -+ -+#define CONSTANT_ADDRESS_P(X) (CONSTANT_P (X)) -+ -+#define MAX_REGS_PER_ADDRESS 1 -+ -+/* Go to ADDR if X is a valid address. */ -+#ifndef REG_OK_STRICT -+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -+ { \ -+ if (nios2_legitimate_address ((X), (MODE), 0)) \ -+ goto ADDR; \ -+ } -+#else -+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -+ { \ -+ if (nios2_legitimate_address ((X), (MODE), 1)) \ -+ goto ADDR; \ -+ } -+#endif -+ -+#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 -+ -+#define LEGITIMATE_CONSTANT_P(X) 1 -+ -+/* Nios II has no mode dependent addresses. */ -+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) -+ -+/* 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 */ -+#define SYMBOL_REF_IN_NIOS2_SMALL_DATA_P(RTX) \ -+ (SYMBOL_REF_SMALL_P(RTX) && !SYMBOL_REF_WEAK_DECL_P(RTX)) -+ -+/***************** -+ * Describing Relative Costs of Operations -+ *****************/ -+ -+#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 -+#define NO_RECURSIVE_FUNCTION_CSE -+ -+ -+ -+/***************************************** -+ * Defining the Output Assembler Language -+ *****************************************/ -+ -+/* ------------------------------------------ * -+ * The Overall Framework of an Assembler File -+ * ------------------------------------------ */ -+ -+#define ASM_APP_ON "#APP\n" -+#define ASM_APP_OFF "#NO_APP\n" -+ -+#define ASM_COMMENT_START "# " -+ -+/* ------------------------------- * -+ * Output and Generation of Labels -+ * ------------------------------- */ -+ -+#define GLOBAL_ASM_OP "\t.global\t" -+ -+ -+/* -------------- * -+ * Output of Data -+ * -------------- */ -+ -+#define DWARF2_UNWIND_INFO 0 -+ -+ -+/* -------------------------------- * -+ * Assembler Commands for Alignment -+ * -------------------------------- */ -+ -+#define ASM_OUTPUT_ALIGN(FILE, LOG) \ -+ do { \ -+ fprintf ((FILE), "%s%d\n", ALIGN_ASM_OP, (LOG)); \ -+ } while (0) -+ -+ -+/* -------------------------------- * -+ * Output of Assembler Instructions -+ * -------------------------------- */ -+ -+#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", \ -+ "r24", \ -+ "r25", \ -+ "gp", \ -+ "sp", \ -+ "fp", \ -+ "ta", \ -+ "ba", \ -+ "ra", \ -+ "status", \ -+ "estatus", \ -+ "bstatus", \ -+ "ipri", \ -+ "ecause", \ -+ "pc", \ -+ "rap", \ -+ "fake_fp", \ -+ "fake_ap", \ -+} -+ -+#define ASM_OUTPUT_OPCODE(STREAM, PTR)\ -+ (PTR) = asm_output_opcode (STREAM, PTR) -+ -+#define PRINT_OPERAND(STREAM, X, CODE) \ -+ nios2_print_operand (STREAM, X, CODE) -+ -+#define PRINT_OPERAND_ADDRESS(STREAM, X) \ -+ nios2_print_operand_address (STREAM, X) -+ -+#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) -+ -+ -+/* ------------ * -+ * Label Output -+ * ------------ */ -+ -+ -+/* ---------------------------------------------------- * -+ * Dividing the Output into Sections (Texts, Data, ...) -+ * ---------------------------------------------------- */ -+ -+/* 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") -+ -+ -+/* Default the definition of "small data" to 8 bytes. */ -+/* ??? How come I can't use HOST_WIDE_INT here? */ -+extern unsigned long nios2_section_threshold; -+#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" -+ -+#undef ASM_OUTPUT_ALIGNED_COMMON -+#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \ -+do \ -+{ \ -+ if ((SIZE) <= nios2_section_threshold) \ -+ { \ -+ named_section (0, ".sbss", 0); \ -+ (*targetm.asm_out.globalize_label) (FILE, NAME); \ -+ 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); \ -+ } \ -+ else \ -+ { \ -+ 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) \ -+ named_section (0, ".sbss", 0); \ -+ else \ -+ named_section (0, ".bss", 0); \ -+ 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) -+ -+ -+ -+/*************************** -+ * Miscellaneous Parameters -+ ***************************/ -+ -+#define MOVE_MAX 4 -+ -+#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 ---- gcc-3.4.3/gcc/config/nios2/nios2.md -+++ gcc-3.4.3-nios2/gcc/config/nios2/nios2.md -@@ -0,0 +1,2078 @@ -+;; Machine Description for Altera NIOS 2G NIOS2 version. -+;; Copyright (C) 2003 Altera -+;; Contributed by Jonah Graham (jgraham@altera.com). -+;; -+;; This file is part of GNU CC. -+;; -+;; GNU CC is free software; you can redistribute it and/or modify -+;; it under the terms of the GNU General Public License as published by -+;; the Free Software Foundation; either version 2, or (at your option) -+;; any later version. -+;; -+;; GNU CC is distributed in the hope that it will be useful, -+;; but WITHOUT ANY WARRANTY; without even the implied warranty of -+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+;; GNU General Public License for more details. -+;; -+;; You should have received a copy of the GNU General Public License -+;; along with GNU CC; see the file COPYING. If not, write to -+;; the Free Software Foundation, 59 Temple Place - Suite 330, -+;; Boston, MA 02111-1307, USA. */ -+ -+ -+ -+;***************************************************************************** -+;* -+;* constants -+;* -+;***************************************************************************** -+(define_constants [ -+ (GP_REGNO 26) -+ (SP_REGNO 27) -+ (FP_REGNO 28) -+ (RA_REGNO 31) -+ (RAP_REGNO 38) -+ (FIRST_RETVAL_REGNO 2) -+ (LAST_RETVAL_REGNO 3) -+ (FIRST_ARG_REGNO 4) -+ (LAST_ARG_REGNO 7) -+ (SC_REGNO 23) -+ (PC_REGNO 37) -+ (FAKE_FP_REGNO 39) -+ (FAKE_AP_REGNO 40) -+ -+ -+ (UNSPEC_BLOCKAGE 0) -+ (UNSPEC_LDBIO 1) -+ (UNSPEC_LDBUIO 2) -+ (UNSPEC_LDHIO 3) -+ (UNSPEC_LDHUIO 4) -+ (UNSPEC_LDWIO 5) -+ (UNSPEC_STBIO 6) -+ (UNSPEC_STHIO 7) -+ (UNSPEC_STWIO 8) -+ (UNSPEC_SYNC 9) -+ (UNSPEC_WRCTL 10) -+ (UNSPEC_RDCTL 11) -+ -+]) -+ -+ -+ -+;***************************************************************************** -+;* -+;* 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") -+ -+ -+;***************************************************************************** -+;* -+;* MOV Instructions -+;* -+;***************************************************************************** -+ -+(define_expand "movqi" -+ [(set (match_operand:QI 0 "nonimmediate_operand" "") -+ (match_operand:QI 1 "general_operand" ""))] -+ "" -+{ -+ if (nios2_emit_move_sequence (operands, QImode)) -+ 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) -+ || register_operand (operands[1], QImode) -+ || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" -+ "@ -+ 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 "ldbio" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(const_int 0)] UNSPEC_LDBIO)) -+ (use (match_operand:SI 1 "memory_operand" "m"))] -+ "" -+ "ldbio\\t%0, %1" -+ [(set_attr "type" "ld")]) -+ -+(define_insn "ldbuio" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(const_int 0)] UNSPEC_LDBUIO)) -+ (use (match_operand:SI 1 "memory_operand" "m"))] -+ "" -+ "ldbuio\\t%0, %1" -+ [(set_attr "type" "ld")]) -+ -+(define_insn "stbio" -+ [(set (match_operand:SI 0 "memory_operand" "=m") -+ (match_operand:SI 1 "register_operand" "r")) -+ (unspec_volatile:SI [(const_int 0)] UNSPEC_STBIO)] -+ "" -+ "stbio\\t%z1, %0" -+ [(set_attr "type" "st")]) -+ -+ -+(define_expand "movhi" -+ [(set (match_operand:HI 0 "nonimmediate_operand" "") -+ (match_operand:HI 1 "general_operand" ""))] -+ "" -+{ -+ if (nios2_emit_move_sequence (operands, HImode)) -+ DONE; -+}) -+ -+(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) -+ || register_operand (operands[1], HImode) -+ || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" -+ "@ -+ 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 "ldhio" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(const_int 0)] UNSPEC_LDHIO)) -+ (use (match_operand:SI 1 "memory_operand" "m"))] -+ "" -+ "ldhio\\t%0, %1" -+ [(set_attr "type" "ld")]) -+ -+(define_insn "ldhuio" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(const_int 0)] UNSPEC_LDHUIO)) -+ (use (match_operand:SI 1 "memory_operand" "m"))] -+ "" -+ "ldhuio\\t%0, %1" -+ [(set_attr "type" "ld")]) -+ -+(define_insn "sthio" -+ [(set (match_operand:SI 0 "memory_operand" "=m") -+ (match_operand:SI 1 "register_operand" "r")) -+ (unspec_volatile:SI [(const_int 0)] UNSPEC_STHIO)] -+ "" -+ "sthio\\t%z1, %0" -+ [(set_attr "type" "st")]) -+ -+(define_expand "movsi" -+ [(set (match_operand:SI 0 "nonimmediate_operand" "") -+ (match_operand:SI 1 "general_operand" ""))] -+ "" -+{ -+ if (nios2_emit_move_sequence (operands, SImode)) -+ DONE; -+}) -+ -+(define_insn "movsi_internal" -+ [(set (match_operand:SI 0 "nonimmediate_operand" "=m, r,r, r,r,r,r") -+ (match_operand:SI 1 "general_operand" "rM,m,rM,I,J,S,i"))] -+ "(register_operand (operands[0], SImode) -+ || register_operand (operands[1], SImode) -+ || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" -+ "@ -+ stw%o0\\t%z1, %0 -+ ldw%o1\\t%0, %1 -+ mov\\t%0, %z1 -+ movi\\t%0, %1 -+ movui\\t%0, %1 -+ 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")]) -+ -+(define_insn "ldwio" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(const_int 0)] UNSPEC_LDWIO)) -+ (use (match_operand:SI 1 "memory_operand" "m"))] -+ "" -+ "ldwio\\t%0, %1" -+ [(set_attr "type" "ld")]) -+ -+(define_insn "stwio" -+ [(set (match_operand:SI 0 "memory_operand" "=m") -+ (match_operand:SI 1 "register_operand" "r")) -+ (unspec_volatile:SI [(const_int 0)] UNSPEC_STWIO)] -+ "" -+ "stwio\\t%z1, %0" -+ [(set_attr "type" "st")]) -+ -+ -+ -+;***************************************************************************** -+;* -+;* zero extension -+;* -+;***************************************************************************** -+ -+ -+(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_extendqihi2" -+ [(set (match_operand:HI 0 "register_operand" "=r,r") -+ (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] -+ "" -+ "@ -+ andi\\t%0, %1, 0xff -+ ldbu%o1\\t%0, %1" -+ [(set_attr "type" "alu,ld")]) -+ -+(define_insn "zero_extendqisi2" -+ [(set (match_operand:SI 0 "register_operand" "=r,r") -+ (zero_extend:SI (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 -+;* -+;***************************************************************************** -+ -+(define_expand "extendhisi2" -+ [(set (match_operand:SI 0 "register_operand" "") -+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] -+ "" -+{ -+ if (optimize && GET_CODE (operands[1]) == MEM) -+ operands[1] = force_not_mem (operands[1]); -+ -+ if (GET_CODE (operands[1]) != MEM) -+ { -+ rtx op1 = gen_lowpart (SImode, operands[1]); -+ rtx temp = gen_reg_rtx (SImode); -+ rtx shift = GEN_INT (16); -+ -+ emit_insn (gen_ashlsi3 (temp, op1, shift)); -+ emit_insn (gen_ashrsi3 (operands[0], temp, shift)); -+ DONE; -+ } -+}) -+ -+(define_insn "extendhisi2_internal" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))] -+ "" -+ "ldh%o1\\t%0, %1" -+ [(set_attr "type" "ld")]) -+ -+(define_expand "extendqihi2" -+ [(set (match_operand:HI 0 "register_operand" "") -+ (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))] -+ "" -+{ -+ if (optimize && GET_CODE (operands[1]) == MEM) -+ operands[1] = force_not_mem (operands[1]); -+ -+ if (GET_CODE (operands[1]) != MEM) -+ { -+ rtx op0 = gen_lowpart (SImode, operands[0]); -+ rtx op1 = gen_lowpart (SImode, operands[1]); -+ rtx temp = gen_reg_rtx (SImode); -+ rtx shift = GEN_INT (24); -+ -+ emit_insn (gen_ashlsi3 (temp, op1, shift)); -+ emit_insn (gen_ashrsi3 (op0, temp, shift)); -+ DONE; -+ } -+}) -+ -+(define_insn "extendqihi2_internal" -+ [(set (match_operand:HI 0 "register_operand" "=r") -+ (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))] -+ "" -+ "ldb%o1\\t%0, %1" -+ [(set_attr "type" "ld")]) -+ -+ -+(define_expand "extendqisi2" -+ [(set (match_operand:SI 0 "register_operand" "") -+ (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] -+ "" -+{ -+ if (optimize && GET_CODE (operands[1]) == MEM) -+ operands[1] = force_not_mem (operands[1]); -+ -+ if (GET_CODE (operands[1]) != MEM) -+ { -+ rtx op1 = gen_lowpart (SImode, operands[1]); -+ rtx temp = gen_reg_rtx (SImode); -+ rtx shift = GEN_INT (24); -+ -+ emit_insn (gen_ashlsi3 (temp, op1, shift)); -+ emit_insn (gen_ashrsi3 (operands[0], temp, shift)); -+ DONE; -+ } -+}) -+ -+(define_insn "extendqisi2_insn" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))] -+ "" -+ "ldb%o1\\t%0, %1" -+ [(set_attr "type" "ld")]) -+ -+ -+ -+;***************************************************************************** -+;* -+;* Arithmetic Operations -+;* -+;***************************************************************************** -+ -+(define_insn "addsi3" -+ [(set (match_operand:SI 0 "register_operand" "=r,r") -+ (plus:SI (match_operand:SI 1 "register_operand" "%r,r") -+ (match_operand:SI 2 "arith_operand" "r,I")))] -+ "" -+ "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,r") -+ (mult:SI (match_operand:SI 1 "register_operand" "r,r") -+ (match_operand:SI 2 "arith_operand" "r,I")))] -+ "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_insn "smulsi3_highpart" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (truncate:SI -+ (lshiftrt:DI -+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r")) -+ (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))) -+ (const_int 32))))] -+ "TARGET_HAS_MULX" -+ "mulxss\\t%0, %1, %2" -+ [(set_attr "type" "mul")]) -+ -+(define_insn "umulsi3_highpart" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (truncate:SI -+ (lshiftrt:DI -+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) -+ (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))) -+ (const_int 32))))] -+ "TARGET_HAS_MULX" -+ "mulxuu\\t%0, %1, %2" -+ [(set_attr "type" "mul")]) -+ -+ -+(define_expand "mulsidi3" -+ [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 0) -+ (mult:SI (match_operand:SI 1 "register_operand" "") -+ (match_operand:SI 2 "register_operand" ""))) -+ (set (subreg:SI (match_dup 0) 4) -+ (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1)) -+ (sign_extend:DI (match_dup 2))) -+ (const_int 32))))] -+ "TARGET_HAS_MULX" -+ "") -+ -+(define_expand "umulsidi3" -+ [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 0) -+ (mult:SI (match_operand:SI 1 "register_operand" "") -+ (match_operand:SI 2 "register_operand" ""))) -+ (set (subreg:SI (match_dup 0) 4) -+ (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1)) -+ (zero_extend:DI (match_dup 2))) -+ (const_int 32))))] -+ "TARGET_HAS_MULX" -+ "") -+ -+ -+ -+;***************************************************************************** -+;* -+;* Negate and ones complement -+;* -+;***************************************************************************** -+ -+(define_insn "negsi2" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (neg:SI (match_operand:SI 1 "register_operand" "r")))] -+ "" -+{ -+ operands[2] = const0_rtx; -+ return "sub\\t%0, %z2, %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")))] -+ "" -+{ -+ operands[2] = const0_rtx; -+ return "nor\\t%0, %z2, %1"; -+} -+ [(set_attr "type" "alu")]) -+ -+ -+ -+; Logical Operantions -+ -+(define_insn "andsi3" -+ [(set (match_operand:SI 0 "register_operand" "=r, r,r") -+ (and:SI (match_operand:SI 1 "register_operand" "%r, r,r") -+ (match_operand:SI 2 "logical_operand" "rM,J,K")))] -+ "" -+ "@ -+ and\\t%0, %1, %z2 -+ and%i2\\t%0, %1, %2 -+ andh%i2\\t%0, %1, %U2" -+ [(set_attr "type" "alu")]) -+ -+(define_insn "iorsi3" -+ [(set (match_operand:SI 0 "register_operand" "=r, r,r") -+ (ior:SI (match_operand:SI 1 "register_operand" "%r, r,r") -+ (match_operand:SI 2 "logical_operand" "rM,J,K")))] -+ "" -+ "@ -+ or\\t%0, %1, %z2 -+ or%i2\\t%0, %1, %2 -+ orh%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")]) -+ -+(define_insn "xorsi3" -+ [(set (match_operand:SI 0 "register_operand" "=r, r,r") -+ (xor:SI (match_operand:SI 1 "register_operand" "%r, r,r") -+ (match_operand:SI 2 "logical_operand" "rM,J,K")))] -+ "" -+ "@ -+ xor\\t%0, %1, %z2 -+ xor%i2\\t%0, %1, %2 -+ xorh%i2\\t%0, %1, %U2" -+ [(set_attr "type" "alu")]) -+ -+ -+ -+;***************************************************************************** -+;* -+;* Shifts -+;* -+;***************************************************************************** -+ -+(define_insn "ashlsi3" -+ [(set (match_operand:SI 0 "register_operand" "=r,r") -+ (ashift:SI (match_operand:SI 1 "register_operand" "r,r") -+ (match_operand:SI 2 "shift_operand" "r,L")))] -+ "" -+ "sll%i2\\t%0, %1, %z2" -+ [(set_attr "type" "shift")]) -+ -+(define_insn "ashrsi3" -+ [(set (match_operand:SI 0 "register_operand" "=r,r") -+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "r,r") -+ (match_operand:SI 2 "shift_operand" "r,L")))] -+ "" -+ "sra%i2\\t%0, %1, %z2" -+ [(set_attr "type" "shift")]) -+ -+(define_insn "lshrsi3" -+ [(set (match_operand:SI 0 "register_operand" "=r,r") -+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r") -+ (match_operand:SI 2 "shift_operand" "r,L")))] -+ "" -+ "srl%i2\\t%0, %1, %z2" -+ [(set_attr "type" "shift")]) -+ -+(define_insn "rotlsi3" -+ [(set (match_operand:SI 0 "register_operand" "=r,r") -+ (rotate:SI (match_operand:SI 1 "register_operand" "r,r") -+ (match_operand:SI 2 "shift_operand" "r,L")))] -+ "" -+ "rol%i2\\t%0, %1, %z2" -+ [(set_attr "type" "shift")]) -+ -+(define_insn "rotrsi3" -+ [(set (match_operand:SI 0 "register_operand" "=r,r") -+ (rotatert:SI (match_operand:SI 1 "register_operand" "r,r") -+ (match_operand:SI 2 "register_operand" "r,r")))] -+ "" -+ "ror\\t%0, %1, %2" -+ [(set_attr "type" "shift")]) -+ -+(define_insn "*shift_mul_constants" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ashift:SI (mult:SI (match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "const_int_operand" "I")) -+ (match_operand:SI 3 "const_int_operand" "I")))] -+ "TARGET_HAS_MUL && SMALL_INT (INTVAL (operands[2]) << INTVAL (operands[3]))" -+{ -+ HOST_WIDE_INT mul = INTVAL (operands[2]) << INTVAL (operands[3]); -+ rtx ops[3]; -+ -+ ops[0] = operands[0]; -+ ops[1] = operands[1]; -+ ops[2] = GEN_INT (mul); -+ -+ output_asm_insn ("muli\t%0, %1, %2", ops); -+ return ""; -+} -+ [(set_attr "type" "mul")]) -+ -+ -+ -+ -+;***************************************************************************** -+;* -+;* 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)] -+ "reload_completed && nios2_can_use_return_insn ()" -+ "ret\\t" -+) -+ -+(define_insn "return_from_epilogue" -+ [(use (match_operand 0 "pmode_register_operand" "")) -+ (return)] -+ "reload_completed" -+ "ret\\t" -+) -+ -+;; 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)] UNSPEC_BLOCKAGE)] -+ "" -+ "" -+ [(set_attr "type" "unknown") -+ (set_attr "length" "0")]) -+ -+ -+ -+;***************************************************************************** -+;* -+;* Jumps and Calls -+;* -+;***************************************************************************** -+ -+(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 "" "")))] -+ "" -+ "br\\t%0" -+ [(set_attr "type" "control")]) -+ -+ -+(define_insn "indirect_call" -+ [(call (mem:QI (match_operand:SI 0 "register_operand" "r")) -+ (match_operand 1 "" "")) -+ (clobber (reg:SI RA_REGNO))] -+ "" -+ "callr\\t%0" -+ [(set_attr "type" "control")]) -+ -+(define_insn "indirect_call_value" -+ [(set (match_operand 0 "" "") -+ (call (mem:QI (match_operand:SI 1 "register_operand" "r")) -+ (match_operand 2 "" ""))) -+ (clobber (reg:SI RA_REGNO))] -+ "" -+ "callr\\t%1" -+) -+ -+(define_expand "call" -+ [(parallel [(call (match_operand 0 "" "") -+ (match_operand 1 "" "")) -+ (clobber (reg:SI RA_REGNO))])] -+ "" -+ "") -+ -+(define_expand "call_value" -+ [(parallel [(set (match_operand 0 "" "") -+ (call (match_operand 1 "" "") -+ (match_operand 2 "" ""))) -+ (clobber (reg:SI RA_REGNO))])] -+ "" -+ "") -+ -+(define_insn "*call" -+ [(call (mem:QI (match_operand:SI 0 "immediate_operand" "i")) -+ (match_operand 1 "" "")) -+ (clobber (match_operand:SI 2 "register_operand" "=r"))] -+ "" -+ "call\\t%0" -+ [(set_attr "type" "control")]) -+ -+(define_insn "*call_value" -+ [(set (match_operand 0 "" "") -+ (call (mem:QI (match_operand:SI 1 "immediate_operand" "i")) -+ (match_operand 2 "" ""))) -+ (clobber (match_operand:SI 3 "register_operand" "=r"))] -+ "" -+ "call\\t%1" -+ [(set_attr "type" "control")]) -+ -+(define_expand "sibcall" -+ [(parallel [(call (match_operand 0 "" "") -+ (match_operand 1 "" "")) -+ (return) -+ (use (match_operand 2 "" ""))])] -+ "" -+ { -+ XEXP (operands[0], 0) = copy_to_mode_reg (SImode, XEXP (operands[0], 0)); -+ -+ if (operands[2] == NULL_RTX) -+ operands[2] = const0_rtx; -+ } -+) -+ -+(define_expand "sibcall_value" -+ [(parallel [(set (match_operand 0 "" "") -+ (call (match_operand 1 "" "") -+ (match_operand 2 "" ""))) -+ (return) -+ (use (match_operand 3 "" ""))])] -+ "" -+ { -+ XEXP (operands[1], 0) = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); -+ -+ if (operands[3] == NULL_RTX) -+ operands[3] = const0_rtx; -+ } -+) -+ -+(define_insn "sibcall_insn" -+ [(call (mem:QI (match_operand:SI 0 "register_operand" "r")) -+ (match_operand 1 "" "")) -+ (return) -+ (use (match_operand 2 "" ""))] -+ "" -+ "jmp\\t%0" -+) -+ -+(define_insn "sibcall_value_insn" -+ [(set (match_operand 0 "register_operand" "") -+ (call (mem:QI (match_operand:SI 1 "register_operand" "r")) -+ (match_operand 2 "" ""))) -+ (return) -+ (use (match_operand 3 "" ""))] -+ "" -+ "jmp\\t%1" -+) -+ -+ -+ -+ -+(define_expand "tablejump" -+ [(parallel [(set (pc) (match_operand 0 "register_operand" "r")) -+ (use (label_ref (match_operand 1 "" "")))])] -+ "" -+ "" -+) -+ -+(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")]) -+ -+ -+ -+;***************************************************************************** -+;* -+;* Comparisons -+;* -+;***************************************************************************** -+;; Flow here is rather complex (based on MIPS): -+;; -+;; 1) The cmp{si,di,sf,df} routine is called. It deposits the -+;; arguments into the branch_cmp array, and the type into -+;; branch_type. No RTL is generated. -+;; -+;; 2) The appropriate branch define_expand is called, which then -+;; creates the appropriate RTL for the comparison and branch. -+;; Different CC modes are used, based on what type of branch is -+;; done, so that we can constrain things appropriately. There -+;; are assumptions in the rest of GCC that break if we fold the -+;; operands into the branchs for integer operations, and use cc0 -+;; for floating point, so we use the fp status register instead. -+;; If needed, an appropriate temporary is created to hold the -+;; of the integer compare. -+ -+(define_expand "cmpsi" -+ [(set (cc0) -+ (compare:CC (match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "arith_operand" "")))] -+ "" -+{ -+ branch_cmp[0] = operands[0]; -+ branch_cmp[1] = operands[1]; -+ branch_type = CMP_SI; -+ DONE; -+}) -+ -+(define_expand "tstsi" -+ [(set (cc0) -+ (match_operand:SI 0 "register_operand" ""))] -+ "" -+{ -+ branch_cmp[0] = operands[0]; -+ branch_cmp[1] = const0_rtx; -+ branch_type = CMP_SI; -+ DONE; -+}) -+ -+ -+;***************************************************************************** -+;* -+;* setting a register from a comparison -+;* -+;***************************************************************************** -+ -+(define_expand "seq" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (eq:SI (match_dup 1) -+ (match_dup 2)))] -+ "" -+{ -+ if (branch_type != CMP_SI) -+ FAIL; -+ -+ /* set up operands from compare. */ -+ operands[1] = branch_cmp[0]; -+ operands[2] = branch_cmp[1]; -+ -+ gen_int_relational (EQ, operands[0], operands[1], operands[2], NULL_RTX); -+ DONE; -+}) -+ -+ -+(define_insn "*seq" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (eq:SI (match_operand:SI 1 "reg_or_0_operand" "%rM") -+ (match_operand:SI 2 "arith_operand" "rI")))] -+ "" -+ "cmpeq%i2\\t%0, %z1, %z2" -+ [(set_attr "type" "alu")]) -+ -+ -+(define_expand "sne" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ne:SI (match_dup 1) -+ (match_dup 2)))] -+ "" -+{ -+ if (branch_type != CMP_SI) -+ FAIL; -+ -+ /* set up operands from compare. */ -+ operands[1] = branch_cmp[0]; -+ operands[2] = branch_cmp[1]; -+ -+ gen_int_relational (NE, operands[0], operands[1], operands[2], NULL_RTX); -+ DONE; -+}) -+ -+ -+(define_insn "*sne" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ne:SI (match_operand:SI 1 "reg_or_0_operand" "%rM") -+ (match_operand:SI 2 "arith_operand" "rI")))] -+ "" -+ "cmpne%i2\\t%0, %z1, %z2" -+ [(set_attr "type" "alu")]) -+ -+ -+(define_expand "sgt" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (gt:SI (match_dup 1) -+ (match_dup 2)))] -+ "" -+{ -+ if (branch_type != CMP_SI) -+ FAIL; -+ -+ /* set up operands from compare. */ -+ operands[1] = branch_cmp[0]; -+ operands[2] = branch_cmp[1]; -+ -+ gen_int_relational (GT, operands[0], operands[1], operands[2], NULL_RTX); -+ DONE; -+}) -+ -+ -+(define_insn "*sgt" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (gt:SI (match_operand:SI 1 "reg_or_0_operand" "rM") -+ (match_operand:SI 2 "reg_or_0_operand" "rM")))] -+ "" -+ "cmplt\\t%0, %z2, %z1" -+ [(set_attr "type" "alu")]) -+ -+ -+(define_expand "sge" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ge:SI (match_dup 1) -+ (match_dup 2)))] -+ "" -+{ -+ if (branch_type != CMP_SI) -+ FAIL; -+ -+ /* set up operands from compare. */ -+ operands[1] = branch_cmp[0]; -+ operands[2] = branch_cmp[1]; -+ -+ gen_int_relational (GE, operands[0], operands[1], operands[2], NULL_RTX); -+ DONE; -+}) -+ -+ -+(define_insn "*sge" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ge:SI (match_operand:SI 1 "reg_or_0_operand" "rM") -+ (match_operand:SI 2 "arith_operand" "rI")))] -+ "" -+ "cmpge%i2\\t%0, %z1, %z2" -+ [(set_attr "type" "alu")]) -+ -+(define_expand "sle" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (le:SI (match_dup 1) -+ (match_dup 2)))] -+ "" -+{ -+ if (branch_type != CMP_SI) -+ FAIL; -+ -+ /* set up operands from compare. */ -+ operands[1] = branch_cmp[0]; -+ operands[2] = branch_cmp[1]; -+ -+ gen_int_relational (LE, operands[0], operands[1], operands[2], NULL_RTX); -+ DONE; -+}) -+ -+ -+(define_insn "*sle" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (le:SI (match_operand:SI 1 "reg_or_0_operand" "rM") -+ (match_operand:SI 2 "reg_or_0_operand" "rM")))] -+ "" -+ "cmpge\\t%0, %z2, %z1" -+ [(set_attr "type" "alu")]) -+ -+ -+(define_expand "slt" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (lt:SI (match_dup 1) -+ (match_dup 2)))] -+ "" -+{ -+ if (branch_type != CMP_SI) -+ FAIL; -+ -+ /* set up operands from compare. */ -+ operands[1] = branch_cmp[0]; -+ operands[2] = branch_cmp[1]; -+ -+ gen_int_relational (LT, operands[0], operands[1], operands[2], NULL_RTX); -+ DONE; -+}) -+ -+ -+(define_insn "*slt" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (lt:SI (match_operand:SI 1 "reg_or_0_operand" "rM") -+ (match_operand:SI 2 "arith_operand" "rI")))] -+ "" -+ "cmplt%i2\\t%0, %z1, %z2" -+ [(set_attr "type" "alu")]) -+ -+ -+(define_expand "sgtu" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (gtu:SI (match_dup 1) -+ (match_dup 2)))] -+ "" -+{ -+ if (branch_type != CMP_SI) -+ FAIL; -+ -+ /* set up operands from compare. */ -+ operands[1] = branch_cmp[0]; -+ operands[2] = branch_cmp[1]; -+ -+ gen_int_relational (GTU, operands[0], operands[1], operands[2], NULL_RTX); -+ DONE; -+}) -+ -+ -+(define_insn "*sgtu" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (gtu:SI (match_operand:SI 1 "reg_or_0_operand" "rM") -+ (match_operand:SI 2 "reg_or_0_operand" "rM")))] -+ "" -+ "cmpltu\\t%0, %z2, %z1" -+ [(set_attr "type" "alu")]) -+ -+ -+(define_expand "sgeu" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (geu:SI (match_dup 1) -+ (match_dup 2)))] -+ "" -+{ -+ if (branch_type != CMP_SI) -+ FAIL; -+ -+ /* set up operands from compare. */ -+ operands[1] = branch_cmp[0]; -+ operands[2] = branch_cmp[1]; -+ -+ gen_int_relational (GEU, operands[0], operands[1], operands[2], NULL_RTX); -+ DONE; -+}) -+ -+ -+(define_insn "*sgeu" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (geu:SI (match_operand:SI 1 "reg_or_0_operand" "rM") -+ (match_operand:SI 2 "uns_arith_operand" "rJ")))] -+ "" -+ "cmpgeu%i2\\t%0, %z1, %z2" -+ [(set_attr "type" "alu")]) -+ -+(define_expand "sleu" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (leu:SI (match_dup 1) -+ (match_dup 2)))] -+ "" -+{ -+ if (branch_type != CMP_SI) -+ FAIL; -+ -+ /* set up operands from compare. */ -+ operands[1] = branch_cmp[0]; -+ operands[2] = branch_cmp[1]; -+ -+ gen_int_relational (LEU, operands[0], operands[1], operands[2], NULL_RTX); -+ DONE; -+}) -+ -+ -+(define_insn "*sleu" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (leu:SI (match_operand:SI 1 "reg_or_0_operand" "rM") -+ (match_operand:SI 2 "reg_or_0_operand" "rM")))] -+ "" -+ "cmpgeu\\t%0, %z2, %z1" -+ [(set_attr "type" "alu")]) -+ -+ -+(define_expand "sltu" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ltu:SI (match_dup 1) -+ (match_dup 2)))] -+ "" -+{ -+ if (branch_type != CMP_SI) -+ FAIL; -+ -+ /* set up operands from compare. */ -+ operands[1] = branch_cmp[0]; -+ operands[2] = branch_cmp[1]; -+ -+ gen_int_relational (LTU, operands[0], operands[1], operands[2], NULL_RTX); -+ DONE; -+}) -+ -+ -+(define_insn "*sltu" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ltu:SI (match_operand:SI 1 "reg_or_0_operand" "rM") -+ (match_operand:SI 2 "uns_arith_operand" "rJ")))] -+ "" -+ "cmpltu%i2\\t%0, %z1, %z2" -+ [(set_attr "type" "alu")]) -+ -+ -+ -+ -+;***************************************************************************** -+;* -+;* branches -+;* -+;***************************************************************************** -+ -+(define_insn "*cbranch" -+ [(set (pc) -+ (if_then_else -+ (match_operator:SI 0 "comparison_operator" -+ [(match_operand:SI 2 "reg_or_0_operand" "rM") -+ (match_operand:SI 3 "reg_or_0_operand" "rM")]) -+ (label_ref (match_operand 1 "" "")) -+ (pc)))] -+ "" -+ "b%0\\t%z2, %z3, %l1" -+ [(set_attr "type" "control")]) -+ -+ -+(define_expand "beq" -+ [(set (pc) -+ (if_then_else (eq:CC (cc0) -+ (const_int 0)) -+ (label_ref (match_operand 0 "" "")) -+ (pc)))] -+ "" -+{ -+ gen_int_relational (EQ, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]); -+ DONE; -+}) -+ -+ -+(define_expand "bne" -+ [(set (pc) -+ (if_then_else (ne:CC (cc0) -+ (const_int 0)) -+ (label_ref (match_operand 0 "" "")) -+ (pc)))] -+ "" -+{ -+ gen_int_relational (NE, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]); -+ DONE; -+}) -+ -+ -+(define_expand "bgt" -+ [(set (pc) -+ (if_then_else (gt:CC (cc0) -+ (const_int 0)) -+ (label_ref (match_operand 0 "" "")) -+ (pc)))] -+ "" -+{ -+ gen_int_relational (GT, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]); -+ DONE; -+}) -+ -+(define_expand "bge" -+ [(set (pc) -+ (if_then_else (ge:CC (cc0) -+ (const_int 0)) -+ (label_ref (match_operand 0 "" "")) -+ (pc)))] -+ "" -+{ -+ gen_int_relational (GE, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]); -+ DONE; -+}) -+ -+(define_expand "ble" -+ [(set (pc) -+ (if_then_else (le:CC (cc0) -+ (const_int 0)) -+ (label_ref (match_operand 0 "" "")) -+ (pc)))] -+ "" -+{ -+ gen_int_relational (LE, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]); -+ DONE; -+}) -+ -+(define_expand "blt" -+ [(set (pc) -+ (if_then_else (lt:CC (cc0) -+ (const_int 0)) -+ (label_ref (match_operand 0 "" "")) -+ (pc)))] -+ "" -+{ -+ gen_int_relational (LT, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]); -+ DONE; -+}) -+ -+ -+(define_expand "bgtu" -+ [(set (pc) -+ (if_then_else (gtu:CC (cc0) -+ (const_int 0)) -+ (label_ref (match_operand 0 "" "")) -+ (pc)))] -+ "" -+{ -+ gen_int_relational (GTU, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]); -+ DONE; -+}) -+ -+(define_expand "bgeu" -+ [(set (pc) -+ (if_then_else (geu:CC (cc0) -+ (const_int 0)) -+ (label_ref (match_operand 0 "" "")) -+ (pc)))] -+ "" -+{ -+ gen_int_relational (GEU, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]); -+ DONE; -+}) -+ -+(define_expand "bleu" -+ [(set (pc) -+ (if_then_else (leu:CC (cc0) -+ (const_int 0)) -+ (label_ref (match_operand 0 "" "")) -+ (pc)))] -+ "" -+{ -+ gen_int_relational (LEU, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]); -+ DONE; -+}) -+ -+(define_expand "bltu" -+ [(set (pc) -+ (if_then_else (ltu:CC (cc0) -+ (const_int 0)) -+ (label_ref (match_operand 0 "" "")) -+ (pc)))] -+ "" -+{ -+ gen_int_relational (LTU, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]); -+ DONE; -+}) -+ -+ -+;***************************************************************************** -+;* -+;* String and Block Operations -+;* -+;***************************************************************************** -+ -+; ??? This is all really a hack to get Dhrystone to work as fast as possible -+; things to be fixed: -+; * let the compiler core handle all of this, for that to work the extra -+; aliasing needs to be addressed. -+; * we use three temporary registers for loading and storing to ensure no -+; ld use stalls, this is excessive, because after the first ld/st only -+; two are needed. Only two would be needed all the way through if -+; we could schedule with other code. Consider: -+; 1 ld $1, 0($src) -+; 2 ld $2, 4($src) -+; 3 ld $3, 8($src) -+; 4 st $1, 0($dest) -+; 5 ld $1, 12($src) -+; 6 st $2, 4($src) -+; 7 etc. -+; The first store has to wait until 4. If it does not there will be one -+; cycle of stalling. However, if any other instruction could be placed -+; between 1 and 4, $3 would not be needed. -+; * In small we probably don't want to ever do this ourself because there -+; is no ld use stall. -+ -+(define_expand "movstrsi" -+ [(parallel [(set (match_operand:BLK 0 "general_operand" "") -+ (match_operand:BLK 1 "general_operand" "")) -+ (use (match_operand:SI 2 "const_int_operand" "")) -+ (use (match_operand:SI 3 "const_int_operand" "")) -+ (clobber (match_scratch:SI 4 "=&r")) -+ (clobber (match_scratch:SI 5 "=&r")) -+ (clobber (match_scratch:SI 6 "=&r"))])] -+ "TARGET_INLINE_MEMCPY" -+{ -+ rtx ld_addr_reg, st_addr_reg; -+ -+ /* If the predicate for op2 fails in expr.c:emit_block_move_via_movstr -+ it trys to copy to a register, but does not re-try the predicate. -+ ??? Intead of fixing expr.c, I fix it here. */ -+ if (!const_int_operand (operands[2], SImode)) -+ FAIL; -+ -+ /* ??? there are some magic numbers which need to be sorted out here. -+ the basis for them is not increasing code size hugely or going -+ out of range of offset addressing */ -+ if (INTVAL (operands[3]) < 4) -+ FAIL; -+ if (!optimize -+ || (optimize_size && INTVAL (operands[2]) > 12) -+ || (optimize < 3 && INTVAL (operands[2]) > 100) -+ || INTVAL (operands[2]) > 200) -+ FAIL; -+ -+ st_addr_reg -+ = replace_equiv_address (operands[0], -+ copy_to_mode_reg (Pmode, XEXP (operands[0], 0))); -+ ld_addr_reg -+ = replace_equiv_address (operands[1], -+ copy_to_mode_reg (Pmode, XEXP (operands[1], 0))); -+ emit_insn (gen_movstrsi_internal (st_addr_reg, ld_addr_reg, -+ operands[2], operands[3])); -+ -+ DONE; -+}) -+ -+ -+(define_insn "movstrsi_internal" -+ [(set (match_operand:BLK 0 "memory_operand" "=o") -+ (match_operand:BLK 1 "memory_operand" "o")) -+ (use (match_operand:SI 2 "const_int_operand" "i")) -+ (use (match_operand:SI 3 "const_int_operand" "i")) -+ (clobber (match_scratch:SI 4 "=&r")) -+ (clobber (match_scratch:SI 5 "=&r")) -+ (clobber (match_scratch:SI 6 "=&r"))] -+ "TARGET_INLINE_MEMCPY" -+{ -+ int ld_offset = INTVAL (operands[2]); -+ int ld_len = INTVAL (operands[2]); -+ int ld_reg = 0; -+ rtx ld_addr_reg = XEXP (operands[1], 0); -+ int st_offset = INTVAL (operands[2]); -+ int st_len = INTVAL (operands[2]); -+ int st_reg = 0; -+ rtx st_addr_reg = XEXP (operands[0], 0); -+ int delay_count = 0; -+ -+ /* ops[0] is the address used by the insn -+ ops[1] is the register being loaded or stored */ -+ rtx ops[2]; -+ -+ if (INTVAL (operands[3]) < 4) -+ abort (); -+ -+ while (ld_offset >= 4) -+ { -+ /* if the load use delay has been met, I can start -+ storing */ -+ if (delay_count >= 3) -+ { -+ ops[0] = gen_rtx (MEM, SImode, -+ plus_constant (st_addr_reg, st_len - st_offset)); -+ ops[1] = operands[st_reg + 4]; -+ output_asm_insn ("stw\t%1, %0", ops); -+ -+ st_reg = (st_reg + 1) % 3; -+ st_offset -= 4; -+ } -+ -+ ops[0] = gen_rtx (MEM, SImode, -+ plus_constant (ld_addr_reg, ld_len - ld_offset)); -+ ops[1] = operands[ld_reg + 4]; -+ output_asm_insn ("ldw\t%1, %0", ops); -+ -+ ld_reg = (ld_reg + 1) % 3; -+ ld_offset -= 4; -+ delay_count++; -+ } -+ -+ if (ld_offset >= 2) -+ { -+ /* if the load use delay has been met, I can start -+ storing */ -+ if (delay_count >= 3) -+ { -+ ops[0] = gen_rtx (MEM, SImode, -+ plus_constant (st_addr_reg, st_len - st_offset)); -+ ops[1] = operands[st_reg + 4]; -+ output_asm_insn ("stw\t%1, %0", ops); -+ -+ st_reg = (st_reg + 1) % 3; -+ st_offset -= 4; -+ } -+ -+ ops[0] = gen_rtx (MEM, HImode, -+ plus_constant (ld_addr_reg, ld_len - ld_offset)); -+ ops[1] = operands[ld_reg + 4]; -+ output_asm_insn ("ldh\t%1, %0", ops); -+ -+ ld_reg = (ld_reg + 1) % 3; -+ ld_offset -= 2; -+ delay_count++; -+ } -+ -+ if (ld_offset >= 1) -+ { -+ /* if the load use delay has been met, I can start -+ storing */ -+ if (delay_count >= 3) -+ { -+ ops[0] = gen_rtx (MEM, SImode, -+ plus_constant (st_addr_reg, st_len - st_offset)); -+ ops[1] = operands[st_reg + 4]; -+ output_asm_insn ("stw\t%1, %0", ops); -+ -+ st_reg = (st_reg + 1) % 3; -+ st_offset -= 4; -+ } -+ -+ ops[0] = gen_rtx (MEM, QImode, -+ plus_constant (ld_addr_reg, ld_len - ld_offset)); -+ ops[1] = operands[ld_reg + 4]; -+ output_asm_insn ("ldb\t%1, %0", ops); -+ -+ ld_reg = (ld_reg + 1) % 3; -+ ld_offset -= 1; -+ delay_count++; -+ } -+ -+ while (st_offset >= 4) -+ { -+ ops[0] = gen_rtx (MEM, SImode, -+ plus_constant (st_addr_reg, st_len - st_offset)); -+ ops[1] = operands[st_reg + 4]; -+ output_asm_insn ("stw\t%1, %0", ops); -+ -+ st_reg = (st_reg + 1) % 3; -+ st_offset -= 4; -+ } -+ -+ while (st_offset >= 2) -+ { -+ ops[0] = gen_rtx (MEM, HImode, -+ plus_constant (st_addr_reg, st_len - st_offset)); -+ ops[1] = operands[st_reg + 4]; -+ output_asm_insn ("sth\t%1, %0", ops); -+ -+ st_reg = (st_reg + 1) % 3; -+ st_offset -= 2; -+ } -+ -+ while (st_offset >= 1) -+ { -+ ops[0] = gen_rtx (MEM, QImode, -+ plus_constant (st_addr_reg, st_len - st_offset)); -+ ops[1] = operands[st_reg + 4]; -+ output_asm_insn ("stb\t%1, %0", ops); -+ -+ st_reg = (st_reg + 1) % 3; -+ st_offset -= 1; -+ } -+ -+ return ""; -+} -+; ??? lengths are not being used yet, but I will probably forget -+; to update this once I am using lengths, so set it to something -+; definetely big enough to cover it. 400 allows for 200 bytes -+; of motion. -+ [(set_attr "length" "400")]) -+ -+ -+ -+;***************************************************************************** -+;* -+;* Custom instructions -+;* -+;***************************************************************************** -+ -+(define_constants [ -+ (CUSTOM_N 100) -+ (CUSTOM_NI 101) -+ (CUSTOM_NF 102) -+ (CUSTOM_NP 103) -+ (CUSTOM_NII 104) -+ (CUSTOM_NIF 105) -+ (CUSTOM_NIP 106) -+ (CUSTOM_NFI 107) -+ (CUSTOM_NFF 108) -+ (CUSTOM_NFP 109) -+ (CUSTOM_NPI 110) -+ (CUSTOM_NPF 111) -+ (CUSTOM_NPP 112) -+ (CUSTOM_IN 113) -+ (CUSTOM_INI 114) -+ (CUSTOM_INF 115) -+ (CUSTOM_INP 116) -+ (CUSTOM_INII 117) -+ (CUSTOM_INIF 118) -+ (CUSTOM_INIP 119) -+ (CUSTOM_INFI 120) -+ (CUSTOM_INFF 121) -+ (CUSTOM_INFP 122) -+ (CUSTOM_INPI 123) -+ (CUSTOM_INPF 124) -+ (CUSTOM_INPP 125) -+ (CUSTOM_FN 126) -+ (CUSTOM_FNI 127) -+ (CUSTOM_FNF 128) -+ (CUSTOM_FNP 129) -+ (CUSTOM_FNII 130) -+ (CUSTOM_FNIF 131) -+ (CUSTOM_FNIP 132) -+ (CUSTOM_FNFI 133) -+ (CUSTOM_FNFF 134) -+ (CUSTOM_FNFP 135) -+ (CUSTOM_FNPI 136) -+ (CUSTOM_FNPF 137) -+ (CUSTOM_FNPP 138) -+ (CUSTOM_PN 139) -+ (CUSTOM_PNI 140) -+ (CUSTOM_PNF 141) -+ (CUSTOM_PNP 142) -+ (CUSTOM_PNII 143) -+ (CUSTOM_PNIF 144) -+ (CUSTOM_PNIP 145) -+ (CUSTOM_PNFI 146) -+ (CUSTOM_PNFF 147) -+ (CUSTOM_PNFP 148) -+ (CUSTOM_PNPI 149) -+ (CUSTOM_PNPF 150) -+ (CUSTOM_PNPP 151) -+]) -+ -+ -+(define_insn "custom_n" -+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")] CUSTOM_N)] -+ "" -+ "custom\\t%0, zero, zero, zero" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_ni" -+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N") -+ (match_operand:SI 1 "register_operand" "r")] CUSTOM_NI)] -+ "" -+ "custom\\t%0, zero, %1, zero" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_nf" -+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N") -+ (match_operand:SF 1 "register_operand" "r")] CUSTOM_NF)] -+ "" -+ "custom\\t%0, zero, %1, zero" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_np" -+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N") -+ (match_operand:SI 1 "register_operand" "r")] CUSTOM_NP)] -+ "" -+ "custom\\t%0, zero, %1, zero" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_nii" -+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N") -+ (match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r")] CUSTOM_NII)] -+ "" -+ "custom\\t%0, zero, %1, %2" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_nif" -+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N") -+ (match_operand:SI 1 "register_operand" "r") -+ (match_operand:SF 2 "register_operand" "r")] CUSTOM_NIF)] -+ "" -+ "custom\\t%0, zero, %1, %2" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_nip" -+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N") -+ (match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r")] CUSTOM_NIP)] -+ "" -+ "custom\\t%0, zero, %1, %2" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_nfi" -+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N") -+ (match_operand:SF 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r")] CUSTOM_NFI)] -+ "" -+ "custom\\t%0, zero, %1, %2" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_nff" -+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N") -+ (match_operand:SF 1 "register_operand" "r") -+ (match_operand:SF 2 "register_operand" "r")] CUSTOM_NFF)] -+ "" -+ "custom\\t%0, zero, %1, %2" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_nfp" -+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N") -+ (match_operand:SF 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r")] CUSTOM_NFP)] -+ "" -+ "custom\\t%0, zero, %1, %2" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_npi" -+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N") -+ (match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r")] CUSTOM_NPI)] -+ "" -+ "custom\\t%0, zero, %1, %2" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_npf" -+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N") -+ (match_operand:SI 1 "register_operand" "r") -+ (match_operand:SF 2 "register_operand" "r")] CUSTOM_NPF)] -+ "" -+ "custom\\t%0, zero, %1, %2" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_npp" -+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N") -+ (match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r")] CUSTOM_NPP)] -+ "" -+ "custom\\t%0, zero, %1, %2" -+ [(set_attr "type" "custom")]) -+ -+ -+ -+(define_insn "custom_in" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")] CUSTOM_IN))] -+ "" -+ "custom\\t%1, %0, zero, zero" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_ini" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r")] CUSTOM_INI))] -+ "" -+ "custom\\t%1, %0, %2, zero" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_inf" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SF 2 "register_operand" "r")] CUSTOM_INF))] -+ "" -+ "custom\\t%1, %0, %2, zero" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_inp" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r")] CUSTOM_INP))] -+ "" -+ "custom\\t%1, %0, %2, zero" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_inii" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r") -+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_INII))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_inif" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r") -+ (match_operand:SF 3 "register_operand" "r")] CUSTOM_INIF))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_inip" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r") -+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_INIP))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_infi" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SF 2 "register_operand" "r") -+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_INFI))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_inff" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SF 2 "register_operand" "r") -+ (match_operand:SF 3 "register_operand" "r")] CUSTOM_INFF))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_infp" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SF 2 "register_operand" "r") -+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_INFP))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_inpi" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r") -+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_INPI))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_inpf" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r") -+ (match_operand:SF 3 "register_operand" "r")] CUSTOM_INPF))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_inpp" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r") -+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_INPP))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+ -+ -+ -+ -+(define_insn "custom_fn" -+ [(set (match_operand:SF 0 "register_operand" "=r") -+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")] CUSTOM_FN))] -+ "" -+ "custom\\t%1, %0, zero, zero" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_fni" -+ [(set (match_operand:SF 0 "register_operand" "=r") -+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r")] CUSTOM_FNI))] -+ "" -+ "custom\\t%1, %0, %2, zero" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_fnf" -+ [(set (match_operand:SF 0 "register_operand" "=r") -+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SF 2 "register_operand" "r")] CUSTOM_FNF))] -+ "" -+ "custom\\t%1, %0, %2, zero" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_fnp" -+ [(set (match_operand:SF 0 "register_operand" "=r") -+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r")] CUSTOM_FNP))] -+ "" -+ "custom\\t%1, %0, %2, zero" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_fnii" -+ [(set (match_operand:SF 0 "register_operand" "=r") -+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r") -+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_FNII))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_fnif" -+ [(set (match_operand:SF 0 "register_operand" "=r") -+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r") -+ (match_operand:SF 3 "register_operand" "r")] CUSTOM_FNIF))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_fnip" -+ [(set (match_operand:SF 0 "register_operand" "=r") -+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r") -+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_FNIP))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_fnfi" -+ [(set (match_operand:SF 0 "register_operand" "=r") -+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SF 2 "register_operand" "r") -+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_FNFI))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_fnff" -+ [(set (match_operand:SF 0 "register_operand" "=r") -+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SF 2 "register_operand" "r") -+ (match_operand:SF 3 "register_operand" "r")] CUSTOM_FNFF))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_fnfp" -+ [(set (match_operand:SF 0 "register_operand" "=r") -+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SF 2 "register_operand" "r") -+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_FNFP))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_fnpi" -+ [(set (match_operand:SF 0 "register_operand" "=r") -+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r") -+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_FNPI))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_fnpf" -+ [(set (match_operand:SF 0 "register_operand" "=r") -+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r") -+ (match_operand:SF 3 "register_operand" "r")] CUSTOM_FNPF))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_fnpp" -+ [(set (match_operand:SF 0 "register_operand" "=r") -+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r") -+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_FNPP))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+ -+ -+(define_insn "custom_pn" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")] CUSTOM_PN))] -+ "" -+ "custom\\t%1, %0, zero, zero" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_pni" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r")] CUSTOM_PNI))] -+ "" -+ "custom\\t%1, %0, %2, zero" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_pnf" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SF 2 "register_operand" "r")] CUSTOM_PNF))] -+ "" -+ "custom\\t%1, %0, %2, zero" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_pnp" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r")] CUSTOM_PNP))] -+ "" -+ "custom\\t%1, %0, %2, zero" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_pnii" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r") -+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNII))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_pnif" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r") -+ (match_operand:SF 3 "register_operand" "r")] CUSTOM_PNIF))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_pnip" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r") -+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNIP))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_pnfi" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SF 2 "register_operand" "r") -+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNFI))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_pnff" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SF 2 "register_operand" "r") -+ (match_operand:SF 3 "register_operand" "r")] CUSTOM_PNFF))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_pnfp" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SF 2 "register_operand" "r") -+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNFP))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_pnpi" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r") -+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNPI))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_pnpf" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r") -+ (match_operand:SF 3 "register_operand" "r")] CUSTOM_PNPF))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+(define_insn "custom_pnpp" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N") -+ (match_operand:SI 2 "register_operand" "r") -+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNPP))] -+ "" -+ "custom\\t%1, %0, %2, %3" -+ [(set_attr "type" "custom")]) -+ -+ -+ -+ -+ -+ -+;***************************************************************************** -+;* -+;* Misc -+;* -+;***************************************************************************** -+ -+(define_insn "nop" -+ [(const_int 0)] -+ "" -+ "nop\\t" -+ [(set_attr "type" "alu")]) -+ -+(define_insn "sync" -+ [(unspec_volatile [(const_int 0)] UNSPEC_SYNC)] -+ "" -+ "sync\\t" -+ [(set_attr "type" "control")]) -+ -+ -+(define_insn "rdctl" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O")] UNSPEC_RDCTL))] -+ "" -+ "rdctl\\t%0, ctl%1" -+ [(set_attr "type" "control")]) -+ -+(define_insn "wrctl" -+ [(unspec_volatile:SI [(match_operand:SI 0 "rdwrctl_operand" "O") -+ (match_operand:SI 1 "register_operand" "r")] UNSPEC_WRCTL)] -+ "" -+ "wrctl\\tctl%0, %1" -+ [(set_attr "type" "control")]) -+ -+ -+ -+;***************************************************************************** -+;* -+;* Peepholes -+;* -+;***************************************************************************** -+ -+ ---- gcc-3.4.3/gcc/config/nios2/t-nios2 -+++ gcc-3.4.3-nios2/gcc/config/nios2/t-nios2 -@@ -0,0 +1,123 @@ -+## -+## Compiler flags to use when compiling libgcc2.c. -+## -+## LIB2FUNCS_EXTRA -+## A list of source file names to be compiled or assembled and inserted into libgcc.a. -+ -+LIB2FUNCS_EXTRA=$(srcdir)/config/nios2/lib2-divmod.c \ -+ $(srcdir)/config/nios2/lib2-divmod-hi.c \ -+ $(srcdir)/config/nios2/lib2-divtable.c \ -+ $(srcdir)/config/nios2/lib2-mul.c -+ -+## -+## Floating Point Emulation -+## To have GCC include software floating point libraries in libgcc.a define FPBIT -+## and DPBIT along with a few rules as follows: -+## -+## # We want fine grained libraries, so use the new code -+## # to build the floating point emulation libraries. -+FPBIT=$(srcdir)/config/nios2/nios2-fp-bit.c -+DPBIT=$(srcdir)/config/nios2/nios2-dp-bit.c -+ -+TARGET_LIBGCC2_CFLAGS = -O2 -+ -+# FLOAT_ONLY - no doubles -+# SMALL_MACHINE - QI/HI is faster than SI -+# Actually SMALL_MACHINE uses chars and shorts instead of ints -+# since ints (16-bit ones as they are today) are at least as fast -+# as chars and shorts, don't define SMALL_MACHINE -+# CMPtype - type returned by FP compare, i.e. INT (hard coded in fp-bit - see code ) -+ -+$(FPBIT): $(srcdir)/config/fp-bit.c Makefile -+ echo '#define FLOAT' > ${FPBIT} -+ cat $(srcdir)/config/fp-bit.c >> ${FPBIT} -+ -+$(DPBIT): $(srcdir)/config/fp-bit.c Makefile -+ echo '' > ${DPBIT} -+ cat $(srcdir)/config/fp-bit.c >> ${DPBIT} -+ -+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o -+ -+# Assemble startup files. -+$(T)crti.o: $(srcdir)/config/nios2/crti.asm $(GCC_PASSES) -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \ -+ -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/nios2/crti.asm -+ -+$(T)crtn.o: $(srcdir)/config/nios2/crtn.asm $(GCC_PASSES) -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \ -+ -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/nios2/crtn.asm -+ -+ -+## You may need to provide additional #defines at the beginning of -+## fp-bit.c and dp-bit.c to control target endianness and other options -+## -+## CRTSTUFF_T_CFLAGS -+## Special flags used when compiling crtstuff.c. See Initialization. -+## -+## CRTSTUFF_T_CFLAGS_S -+## Special flags used when compiling crtstuff.c for shared linking. Used -+## if you use crtbeginS.o and crtendS.o in EXTRA-PARTS. See Initialization. -+## -+## MULTILIB_OPTIONS -+## For some targets, invoking GCC in different ways produces objects that -+## can not be linked together. For example, for some targets GCC produces -+## both big and little endian code. For these targets, you must arrange -+## for multiple versions of libgcc.a to be compiled, one for each set of -+## incompatible options. When GCC invokes the linker, it arranges to link -+## in the right version of libgcc.a, based on the command line options -+## used. -+## The MULTILIB_OPTIONS macro lists the set of options for which special -+## versions of libgcc.a must be built. Write options that are mutually -+## incompatible side by side, separated by a slash. Write options that may -+## be used together separated by a space. The build procedure will build -+## all combinations of compatible options. -+## -+## For example, if you set MULTILIB_OPTIONS to m68000/m68020 msoft-float, -+## Makefile will build special versions of libgcc.a using the following -+## sets of options: -m68000, -m68020, -msoft-float, -m68000 -msoft-float, -+## and -m68020 -msoft-float. -+ -+MULTILIB_OPTIONS = mno-hw-mul mhw-mulx -+ -+## MULTILIB_DIRNAMES -+## If MULTILIB_OPTIONS is used, this variable specifies the directory names -+## that should be used to hold the various libraries. Write one element in -+## MULTILIB_DIRNAMES for each element in MULTILIB_OPTIONS. If -+## MULTILIB_DIRNAMES is not used, the default value will be -+## MULTILIB_OPTIONS, with all slashes treated as spaces. -+## For example, if MULTILIB_OPTIONS is set to m68000/m68020 msoft-float, -+## then the default value of MULTILIB_DIRNAMES is m68000 m68020 -+## msoft-float. You may specify a different value if you desire a -+## different set of directory names. -+ -+# MULTILIB_DIRNAMES = -+ -+## MULTILIB_MATCHES -+## Sometimes the same option may be written in two different ways. If an -+## option is listed in MULTILIB_OPTIONS, GCC needs to know about any -+## synonyms. In that case, set MULTILIB_MATCHES to a list of items of the -+## form option=option to describe all relevant synonyms. For example, -+## m68000=mc68000 m68020=mc68020. -+## -+## MULTILIB_EXCEPTIONS -+## Sometimes when there are multiple sets of MULTILIB_OPTIONS being -+## specified, there are combinations that should not be built. In that -+## case, set MULTILIB_EXCEPTIONS to be all of the switch exceptions in -+## shell case syntax that should not be built. -+## For example, in the PowerPC embedded ABI support, it is not desirable to -+## build libraries compiled with the -mcall-aix option and either of the -+## -fleading-underscore or -mlittle options at the same time. Therefore -+## MULTILIB_EXCEPTIONS is set to -+## -+## *mcall-aix/*fleading-underscore* *mlittle/*mcall-aix* -+## -+ -+MULTILIB_EXCEPTIONS = *mno-hw-mul/*mhw-mulx* -+ -+## -+## MULTILIB_EXTRA_OPTS Sometimes it is desirable that when building -+## multiple versions of libgcc.a certain options should always be passed on -+## to the compiler. In that case, set MULTILIB_EXTRA_OPTS to be the list -+## of options to be used for all builds. -+## -+ ---- gcc-3.4.3/gcc/config.gcc -+++ gcc-3.4.3-nios2/gcc/config.gcc -@@ -1321,6 +1321,10 @@ m32rle-*-linux*) - thread_file='posix' - fi - ;; -+# JBG -+nios2-*-* | nios2-*-*) -+ tm_file="elfos.h ${tm_file}" -+ ;; - # m68hc11 and m68hc12 share the same machine description. - m68hc11-*-*|m6811-*-*) - tm_file="dbxelf.h elfos.h m68hc11/m68hc11.h" ---- gcc-3.4.3/gcc/cse.c -+++ gcc-3.4.3-nios2/gcc/cse.c -@@ -3134,6 +3134,10 @@ find_comparison_args (enum rtx_code code - #ifdef FLOAT_STORE_FLAG_VALUE - REAL_VALUE_TYPE fsfv; - #endif -+#ifdef __nios2__ -+ if (p->is_const) -+ break; -+#endif - - /* If the entry isn't valid, skip it. */ - if (! exp_equiv_p (p->exp, p->exp, 1, 0)) ---- gcc-3.4.3/gcc/doc/extend.texi -+++ gcc-3.4.3-nios2/gcc/doc/extend.texi -@@ -5636,12 +5636,118 @@ to those machines. Generally these gene - instructions, but allow the compiler to schedule those calls. - - @menu -+* Altera Nios II Built-in Functions:: - * Alpha Built-in Functions:: - * ARM Built-in Functions:: - * X86 Built-in Functions:: - * PowerPC AltiVec Built-in Functions:: - @end menu - -+@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 Alpha Built-in Functions - @subsection Alpha Built-in Functions - ---- gcc-3.4.3/gcc/doc/invoke.texi -+++ gcc-3.4.3-nios2/gcc/doc/invoke.texi -@@ -337,6 +337,14 @@ in the following sections. - @item Machine Dependent Options - @xref{Submodel Options,,Hardware Models and Configurations}. - -+@emph{Altera Nios II Options} -+@gccoptlist{-msmallc -mno-bypass-cache -mbypass-cache @gol -+-mno-cache-volatile -mcache-volatile -mno-inline-memcpy @gol -+-minline-memcpy -mno-fast-sw-div -mfast-sw-div @gol -+-mhw-mul -mno-hw-mul -mhw-mulx -mno-hw-mulx @gol -+-mno-hw-div -mhw-div @gol -+-msys-crt0= -msys-lib= -msys=nosys } -+ - @emph{M680x0 Options} - @gccoptlist{-m68000 -m68020 -m68020-40 -m68020-60 -m68030 -m68040 @gol - -m68060 -mcpu32 -m5200 -m68881 -mbitfield -mc68000 -mc68020 @gol -@@ -5836,6 +5844,7 @@ machine description. The default for th - that macro, which enables you to change the defaults. - - @menu -+* Altera Nios II Options:: - * M680x0 Options:: - * M68hc1x Options:: - * VAX Options:: -@@ -5871,6 +5880,103 @@ that macro, which enables you to change - * FRV Options:: - @end menu - -+ -+@node Altera Nios II Options -+@subsection Altera Nios II Options -+@cindex Altera Nios II options -+ -+These are the @samp{-m} options defined for the Altera Nios II -+processor. -+ -+@table @gcctabopt -+ -+@item -msmallc -+@opindex msmallc -+ -+Link with a limited version of the C library, -lsmallc. For more -+information see the C Library Documentation. -+ -+ -+@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 io variants of the instructions. The default is to not -+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 io variants of -+the ld and st instructions. The default is to cache volatile -+accesses. -+ -+-mno-cache-volatile is deprecated and will be deleted in a -+future GCC release. -+ -+ -+@item -mno-inline-memcpy -+@itemx -minline-memcpy -+@opindex mno-inline-memcpy -+@opindex minline-memcpy -+ -+Do not inline memcpy. The default is to inline when -O is on. -+ -+ -+@item -mno-fast-sw-div -+@itemx -mfast-sw-div -+@opindex mno-fast-sw-div -+@opindex mfast-sw-div -+ -+Do no use table based fast divide for small numbers. The default -+is to use the fast divide at -O3 and above. -+ -+ -+@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}. -+ -+The different combinations of @code{mul} and @code{mulx} instructions -+generate a different multilib options. -+ -+ -+@item -msys-crt0=@var{startfile} -+@opindex msys-crt0 -+ -+@var{startfile} is the file name of the startfile (crt0) to use -+when linking. The default is crt0.o that comes with libgloss -+and is only suitable for use with the instruction set -+simulator. -+ -+@item -msys-lib=@var{systemlib} -+@itemx -msys-lib=nosys -+@opindex msys-lib -+ -+@var{systemlib} is the library name of the library which provides -+the system calls required by the C library, e.g. @code{read}, @code{write} -+etc. The default is to use nosys, this library provides -+stub implementations of the calls and is part of libgloss. -+ -+@end table -+ -+ - @node M680x0 Options - @subsection M680x0 Options - @cindex M680x0 options ---- gcc-3.4.3/gcc/doc/md.texi -+++ gcc-3.4.3-nios2/gcc/doc/md.texi -@@ -1335,6 +1335,49 @@ However, here is a summary of the machin - available on some particular machines. - - @table @emph -+ -+@item Altera Nios II family---@file{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. -+ -+@end table -+ -+ - @item ARM family---@file{arm.h} - @table @code - @item f |