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