diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/config/picflag.m4 gcc-4.8.2-or1k-rtems/config/picflag.m4
--- gcc-4.8.2/config/picflag.m4 2012-01-23 08:25:28.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/config/picflag.m4 2014-03-17 04:22:39.605043272 +0200
@@ -39,6 +39,9 @@
mips-sgi-irix6*)
# PIC is the default.
;;
+ or1k-*-*)
+ $1=-fPIC
+ ;;
rs6000-ibm-aix* | powerpc-ibm-aix*)
# All AIX code is PIC.
;;
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/config.guess gcc-4.8.2-or1k-rtems/config.guess
--- gcc-4.8.2/config.guess 2013-01-09 00:46:38.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/config.guess 2014-03-17 09:14:15.665104892 +0200
@@ -957,8 +957,11 @@
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
;;
- or32:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ or1k:Linux:*:*)
+ echo or1k-unknown-linux-gnu
+ exit ;;
+ or1knd:Linux:*:*)
+ echo or1knd-unknown-linux-gnu
exit ;;
padre:Linux:*:*)
echo sparc-unknown-linux-gnu
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/config.sub gcc-4.8.2-or1k-rtems/config.sub
--- gcc-4.8.2/config.sub 2013-01-11 15:02:58.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/config.sub 2014-03-17 09:09:36.721103909 +0200
@@ -300,7 +300,7 @@
| nios | nios2 \
| ns16k | ns32k \
| open8 \
- | or32 \
+ | or1k | or1knd \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \
@@ -922,9 +922,12 @@
basic_machine=hppa1.1-oki
os=-proelf
;;
- openrisc | openrisc-*)
- basic_machine=or32-unknown
+ or1k | or1k-*)
+ basic_machine=or1k-unknown
;;
+ or1knd | or1knd-*)
+ basic_machine=or1knd-unknown
+ ;;
os400)
basic_machine=powerpc-ibm
os=-os400
@@ -1593,7 +1596,10 @@
mips*-*)
os=-elf
;;
- or32-*)
+ or1k-*)
+ os=-coff
+ ;;
+ or1knd-*)
os=-coff
;;
*-tti) # must be before sparc entry or we get the wrong os.
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/common/config/or1k/or1k-common.c gcc-4.8.2-or1k-rtems/gcc/common/config/or1k/or1k-common.c
--- gcc-4.8.2/gcc/common/config/or1k/or1k-common.c 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/common/config/or1k/or1k-common.c 2014-03-14 07:27:49.000000000 +0200
@@ -0,0 +1,61 @@
+/* Common hooks for OR1K.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ . */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "common/common-target.h"
+#include "common/common-target-def.h"
+#include "opts.h"
+#include "flags.h"
+
+/* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */
+static const struct default_options or1k_option_optimization_table[] =
+ {
+ { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
+ { OPT_LEVELS_NONE, 0, NULL, 0 }
+ };
+
+/* Implement TARGET_EXCEPT_UNWIND_INFO. */
+static enum unwind_info_type
+or1k_except_unwind_info (struct gcc_options *opts)
+{
+ /* Honor the --enable-sjlj-exceptions configure switch. */
+#ifdef CONFIG_SJLJ_EXCEPTIONS
+ if (CONFIG_SJLJ_EXCEPTIONS)
+ return UI_SJLJ;
+#endif
+
+ if (DWARF2_UNWIND_INFO)
+ return UI_DWARF2;
+
+ return UI_SJLJ;
+}
+
+#undef TARGET_EXCEPT_UNWIND_INFO
+#define TARGET_EXCEPT_UNWIND_INFO or1k_except_unwind_info
+
+#undef TARGET_OPTION_OPTIMIZATION_TABLE
+#define TARGET_OPTION_OPTIMIZATION_TABLE or1k_option_optimization_table
+
+#undef TARGET_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS (MASK_HARD_MUL)
+
+struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/constraints.md gcc-4.8.2-or1k-rtems/gcc/config/or1k/constraints.md
--- gcc-4.8.2/gcc/config/or1k/constraints.md 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/constraints.md 2014-03-14 07:27:49.000000000 +0200
@@ -0,0 +1,59 @@
+;; Copyright (C) 2010 Embecosm Limited
+;;
+;; Contributed by Joern Rennecke in 2010
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3. If not see
+;; .
+
+(define_constraint "I"
+ ""
+ (and (match_code "const_int")
+ (match_test "ival >= -32768 && ival <= 32767")))
+
+(define_constraint "J"
+ ""
+ (and (match_code "const_int")
+ (match_test "ival == 0")))
+
+(define_constraint "K"
+ ""
+ (and (match_code "const_int")
+ (match_test "ival >= 0 && ival <= 65535")))
+
+(define_constraint "L"
+ ""
+ (and (match_code "const_int")
+ (match_test "ival >= 0 && ival <= 31")))
+
+(define_constraint "M"
+ ""
+ (and (match_code "const_int")
+ (match_test "(ival & 0xffff) == 0")))
+
+(define_constraint "N"
+ ""
+ (and (match_code "const_int")
+ (match_test "ival >= -33554432 && ival <= 33554431")))
+
+(define_constraint "O"
+ ""
+ (and (match_code "const_int")
+ (match_test "ival == 0")))
+
+(define_constraint "C"
+ ""
+ (match_code "const_double"))
+
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/elf.h gcc-4.8.2-or1k-rtems/gcc/config/or1k/elf.h
--- gcc-4.8.2/gcc/config/or1k/elf.h 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/elf.h 2014-04-28 18:11:06.181280553 +0200
@@ -0,0 +1,31 @@
+/* Definitions for rtems targeting an OpenRisc OR1K using COFF
+ ??? this is for OR1K, but the rest of the above seems bogus.
+ Copyright (C) 1996, 1997, 2005 Free Software Foundation, Inc.
+ Contributed by Joel Sherrill (joel@OARcorp.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Use ELF */
+#undef OBJECT_FORMAT_ELF
+#define OBJECT_FORMAT_ELF
+
+/* or1k debug info support is controlled by tm.h header files we include:
+ dbxelf.h enables optional stabs debug info.
+ elfos.h sets PREFERRED_DEBUGGING_TYPE to DWARF2_DEBUG . */
+
+#define DRIVER_SELF_SPECS "%{!mno-newlib:-mnewlib}"
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/elf.h.rej gcc-4.8.2-or1k-rtems/gcc/config/or1k/elf.h.rej
--- gcc-4.8.2/gcc/config/or1k/elf.h.rej 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/elf.h.rej 2014-04-28 18:10:09.429312182 +0200
@@ -0,0 +1,34 @@
+--- gcc/config/or1k/elf.h 2014-04-28 10:45:18.320114849 -0500
++++ gcc/config/or1k/elf.h 1969-12-31 18:00:00.000000000 -0600
+@@ -1,31 +0,0 @@
+-/* Definitions for rtems targeting an OpenRisc OR1K using COFF
+- ??? this is for OR1K, but the rest of the above seems bogus.
+- Copyright (C) 1996, 1997, 2005 Free Software Foundation, Inc.
+- Contributed by Joel Sherrill (joel@OARcorp.com).
+-
+-This file is part of GNU CC.
+-
+-GNU CC is free software; you can redistribute it and/or modify
+-it under the terms of the GNU General Public License as published by
+-the Free Software Foundation; either version 2, or (at your option)
+-any later version.
+-
+-GNU CC is distributed in the hope that it will be useful,
+-but WITHOUT ANY WARRANTY; without even the implied warranty of
+-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-GNU General Public License for more details.
+-
+-You should have received a copy of the GNU General Public License
+-along with GNU CC; see the file COPYING. If not, write to
+-the Free Software Foundation, 59 Temple Place - Suite 330,
+-Boston, MA 02111-1307, USA. */
+-
+-/* Use ELF */
+-#undef OBJECT_FORMAT_ELF
+-#define OBJECT_FORMAT_ELF
+-
+-/* or1k debug info support is controlled by tm.h header files we include:
+- dbxelf.h enables optional stabs debug info.
+- elfos.h sets PREFERRED_DEBUGGING_TYPE to DWARF2_DEBUG . */
+-
+-#define DRIVER_SELF_SPECS "%{!mno-newlib:-mnewlib}"
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/linux-elf.h gcc-4.8.2-or1k-rtems/gcc/config/or1k/linux-elf.h
--- gcc-4.8.2/gcc/config/or1k/linux-elf.h 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/linux-elf.h 2014-03-14 07:27:49.000000000 +0200
@@ -0,0 +1,97 @@
+/* Definitions for or1k running Linux-based GNU systems using ELF
+ Copyright (C) 2002, 2005
+ Free Software Foundation, Inc.
+ Contributed by Marko Mlinar
+
+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 this program; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* elfos.h should have already been included. Now just override
+ any conflicting definitions and add any extras. */
+
+/* Do not assume anything about header files. */
+#define NO_IMPLICIT_EXTERN_C
+
+/* This is how we tell the assembler that two symbols have the same value. */
+#define ASM_OUTPUT_DEF(FILE, NAME1, NAME2) \
+ do \
+ { \
+ assemble_name (FILE, NAME1); \
+ fputs (" = ", FILE); \
+ assemble_name (FILE, NAME2); \
+ fputc ('\n', FILE); \
+ } \
+ while (0)
+
+
+#if 0
+/* Node: Label Output */
+
+#define SET_ASM_OP "\t.set\t"
+
+#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \
+ (*targetm.asm_out.globalize_label) (FILE, XSTR (FUN, 0))
+
+#define ASM_WEAKEN_LABEL(FILE, NAME) \
+ do \
+ { \
+ fputs ("\t.weak\t", (FILE)); \
+ assemble_name ((FILE), (NAME)); \
+ fputc ('\n', (FILE)); \
+ } \
+ while (0)
+
+#endif
+
+/* The GNU C++ standard library requires that these macros be defined. */
+#undef CPLUSPLUS_CPP_SPEC
+#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
+
+#undef DRIVER_SELF_SPECS
+#define DRIVER_SELF_SPECS ""
+
+#define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1"
+
+/* Define a set of Linux builtins. This is copied from linux.h. We can't
+ include the whole file for now, because that causes configure to require ld
+ to support --eh-frame-header, which it currently doesn't */
+#define LINUX_TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define ("__gnu_linux__"); \
+ builtin_define_std ("linux"); \
+ builtin_define_std ("unix"); \
+ builtin_assert ("system=linux"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=posix"); \
+ } while (0)
+
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ LINUX_TARGET_OS_CPP_BUILTINS(); \
+ if (OPTION_UCLIBC) \
+ builtin_define ("__UCLIBC__"); \
+ /* The GNU C++ standard library requires this. */ \
+ if (c_dialect_cxx ()) \
+ builtin_define ("_GNU_SOURCE"); \
+ } while (0)
+
+#undef LINK_SPEC
+#define LINK_SPEC "%{mnewlib:-entry 0x100} \
+ -dynamic-linker " GNU_USER_DYNAMIC_LINKER " \
+ %{static:-static} \
+ %{shared:-shared}"
+
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/linux-gas.h gcc-4.8.2-or1k-rtems/gcc/config/or1k/linux-gas.h
--- gcc-4.8.2/gcc/config/or1k/linux-gas.h 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/linux-gas.h 2014-03-14 07:27:49.000000000 +0200
@@ -0,0 +1,37 @@
+/* Definitions of target machine for GNU compiler.
+ Or32 Linux-based GNU systems version.
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+ Contributed by Marko Mlinar
+
+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 this program; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Unsigned chars produces much better code than signed. */
+#undef DEFAULT_SIGNED_CHAR
+#define DEFAULT_SIGNED_CHAR 1
+
+/* Make gcc agree with */
+
+#define SIZE_TYPE "unsigned int"
+#define PTRDIFF_TYPE "int"
+#define WCHAR_TYPE "unsigned int"
+#define WCHAR_TYPE_SIZE 32
+
+
+/* Clear the instruction cache from `beg' to `end'. This makes an
+ inline system call to SYS_cacheflush. */
+#define CLEAR_INSN_CACHE(BEG, END) /* Do something here !!! */
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/or1k.c gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k.c
--- gcc-4.8.2/gcc/config/or1k/or1k.c 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k.c 2014-03-14 07:27:49.000000000 +0200
@@ -0,0 +1,2263 @@
+/* Subroutines for insn-output.c for GNU compiler. OpenRISC 1000 version.
+ Copyright (C) 1987, 1992, 1997, 1999, 2000, 2001, 2002, 2003, 2004,
+ 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc
+ Copyright (C) 2010 Embecosm Limited
+
+ Contributed by Damjan Lampret in 1999.
+ Major optimizations by Matjaz Breskvar in 2005.
+ Updated for GCC 4.5 by Jeremy Bennett
+ and Joern Rennecke in 2010.
+
+ This file is part of GNU CC.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see . */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "tree.h"
+#include "obstack.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "real.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "output.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "reload.h"
+#include "function.h"
+#include "expr.h"
+#include "toplev.h"
+#include "recog.h"
+#include "ggc.h"
+#include "except.h"
+#include "tm_p.h"
+#include "target.h"
+#include "target-def.h"
+#include "debug.h"
+#include "langhooks.h"
+#include "df.h"
+#include "dwarf2.h"
+#include "ansidecl.h"
+
+/* ========================================================================== */
+/* Local macros */
+
+/* Construct a l.movhi instruction for the given reg and value */
+#define OR1K_MOVHI(rd, k) \
+ ((0x6 << 26) | ((rd) << 21) | (k))
+
+/* Construct a l.ori instruction for the given two regs and value */
+#define OR1K_ORI(rd, ra, k) \
+ ((0x2a << 26) | ((rd) << 21) | ((ra) << 16) | (k))
+
+/* Construct a l.lwz instruction for the given two registers and offset */
+#define OR1K_LWZ(rd, ra, i) \
+ ((0x21 << 26) | ((rd) << 21) | ((ra) << 16) | (i))
+
+/* Construct a l.jr instruction for the given register */
+#define OR1K_JR(rb) \
+ ((0x11 << 26) | ((rb) << 11))
+
+#define OR1K_NOP \
+ (0x15 << 24)
+
+/* ========================================================================== */
+/* Static variables (i.e. global to this file only. */
+
+
+/*!Stack layout we use for pushing and poping saved registers */
+static struct
+{
+ bool save_lr_p;
+ int lr_save_offset;
+ bool save_fp_p;
+ int fp_save_offset;
+ int gpr_size;
+ int gpr_offset;
+ int total_size;
+ int vars_size;
+ int args_size;
+ int gpr_frame;
+ int late_frame;
+ HOST_WIDE_INT mask;
+} frame_info;
+
+
+/* ========================================================================== */
+/* Local (i.e. static) utility functions */
+
+/* -------------------------------------------------------------------------- */
+/*!Must the current function save a register?
+
+ @param[in] regno The register to consider.
+
+ @return Non-zero (TRUE) if current function must save "regno", zero
+ (FALSE) otherwise. */
+/* -------------------------------------------------------------------------- */
+static bool
+or1k_save_reg_p (int regno)
+{
+ /* No need to save the faked cc0 register. */
+ if (regno == OR1K_FLAGS_REG)
+ return false;
+
+ /* Check call-saved registers. */
+ if (df_regs_ever_live_p(regno) && !call_used_regs[regno])
+ return true;
+
+ /* We need to save the old frame pointer before setting up a new
+ one. */
+ if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
+ return true;
+
+ /* Save the stack pointer for DWARF2 for now.
+ * AFAIK, DWARF should be able to unwind using only the current stack
+ * register and the CFA offset, but I never got that to work. */
+ if (regno == STACK_POINTER_REGNUM && !frame_pointer_needed)
+ return true;
+
+ /* We need to save the incoming return address if it is ever clobbered
+ within the function. */
+ if (regno == LINK_REGNUM
+ && (df_regs_ever_live_p(regno) || crtl->uses_pic_offset_table
+ || cfun->machine->force_lr_save))
+ return true;
+
+ if(crtl->calls_eh_return)
+ {
+ unsigned int i;
+ for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM; i++)
+ {
+ if ((unsigned int)regno == EH_RETURN_DATA_REGNO (i))
+ return true;
+ }
+ }
+
+ return false;
+
+} /* or1k_save_reg_p () */
+
+bool
+or1k_save_reg_p_cached (int regno)
+{
+ return (frame_info.mask & ((HOST_WIDE_INT) 1 << regno)) != 0;
+}
+
+/* N.B. contrary to the ISA documentation, the stack includes the outgoing
+ arguments. */
+/* -------------------------------------------------------------------------- */
+/*!Compute full frame size and layout.
+
+ Store information in "frame_info".
+
+ @param[in] size The size of the function's local variables.
+
+ @return Total size of stack frame. */
+/* -------------------------------------------------------------------------- */
+static HOST_WIDE_INT
+or1k_compute_frame_size (HOST_WIDE_INT size)
+{
+ HOST_WIDE_INT args_size;
+ HOST_WIDE_INT vars_size;
+ HOST_WIDE_INT stack_offset;
+ HOST_WIDE_INT save_size;
+ bool interrupt_p = false;
+ int regno;
+
+ args_size = crtl->outgoing_args_size;
+ vars_size = OR1K_ALIGN (size, 4);
+
+ frame_info.args_size = args_size;
+ frame_info.vars_size = vars_size;
+ frame_info.gpr_frame = interrupt_p ? or1k_redzone : 0;
+
+ /* If the function has local variables, we're committed to
+ allocating it anyway. Otherwise reclaim it here. */
+ /* FIXME: Verify this. Got if from the MIPS port. */
+ if (vars_size == 0 && crtl->is_leaf)
+ args_size = 0;
+
+ stack_offset = 0;
+
+ /* Save link register right at the bottom. */
+ if (or1k_save_reg_p (LINK_REGNUM))
+ {
+ stack_offset = stack_offset - UNITS_PER_WORD;
+ frame_info.lr_save_offset = stack_offset;
+ frame_info.save_lr_p = true;
+ }
+ else
+ frame_info.save_lr_p = false;
+
+ /* HACK: In PIC mode we need to save the PIC reg and the link reg in
+ in case the function is doing references through the got or plt,
+ but this information is not necessarily available when the initial
+ elimination offset is calculated, so we always reserve the space even
+ if it is not used... */
+ if (!frame_info.save_lr_p && flag_pic)
+ stack_offset = stack_offset - UNITS_PER_WORD;
+
+ /* Save frame pointer right after possible link register. */
+ if (frame_pointer_needed)
+ {
+ stack_offset = stack_offset - UNITS_PER_WORD;
+ frame_info.fp_save_offset = stack_offset;
+ frame_info.save_fp_p = true;
+ }
+ else
+ frame_info.save_fp_p = false;
+
+ frame_info.gpr_size = 0;
+ frame_info.mask = 0;
+
+ for (regno = 0; regno <= OR1K_LAST_ACTUAL_REG; regno++)
+ {
+ if (regno == LINK_REGNUM
+ || (frame_pointer_needed && regno == HARD_FRAME_POINTER_REGNUM))
+ /* These have already been saved if so needed. */
+ continue;
+
+ if (or1k_save_reg_p (regno))
+ {
+ frame_info.gpr_size += UNITS_PER_WORD;
+ frame_info.mask |= ((HOST_WIDE_INT) 1 << regno);
+ }
+ }
+
+ if (!or1k_save_reg_p (PIC_OFFSET_TABLE_REGNUM)
+ && (crtl->uses_pic_offset_table || (flag_pic && frame_info.save_lr_p)))
+ {
+ frame_info.gpr_size += UNITS_PER_WORD;
+ frame_info.mask |= ((HOST_WIDE_INT) 1 << PIC_OFFSET_TABLE_REGNUM);
+ }
+ else if (flag_pic && !or1k_save_reg_p (PIC_OFFSET_TABLE_REGNUM))
+ frame_info.gpr_size += UNITS_PER_WORD;
+
+ save_size = (frame_info.gpr_size
+ + (frame_info.save_fp_p ? UNITS_PER_WORD : 0)
+ + (frame_info.save_lr_p || flag_pic ? UNITS_PER_WORD : 0));
+ frame_info.total_size = save_size + vars_size + args_size;
+ gcc_assert (PROLOGUE_TMP != STATIC_CHAIN_REGNUM);
+ if (frame_info.total_size > 32767 && interrupt_p)
+ {
+ int n_extra
+ = (!!(~frame_info.mask && 1 << PROLOGUE_TMP)
+ + !!(~frame_info.mask & 1 << EPILOGUE_TMP)) * UNITS_PER_WORD;
+
+ save_size += n_extra;
+ frame_info.gpr_size += n_extra;
+ frame_info.total_size += n_extra;
+ frame_info.mask |= (1 << PROLOGUE_TMP) | (1 << EPILOGUE_TMP);
+ }
+
+ stack_offset -= frame_info.gpr_size;
+ frame_info.gpr_offset = stack_offset;
+ frame_info.late_frame = frame_info.total_size;
+
+ if (save_size > or1k_redzone
+ || (frame_info.gpr_frame
+ && (frame_info.gpr_frame + frame_info.late_frame <= 32767)))
+ {
+ if (frame_info.gpr_frame + frame_info.late_frame <= 32767)
+ save_size = frame_info.total_size;
+ frame_info.gpr_frame += save_size;
+ frame_info.lr_save_offset += save_size;
+ frame_info.fp_save_offset += save_size;
+ frame_info.gpr_offset += save_size;
+ frame_info.late_frame -= save_size;
+ /* FIXME: check in TARGET_OVERRIDE_OPTIONS for invalid or1k_redzone. */
+ gcc_assert (frame_info.gpr_frame <= 32767);
+ gcc_assert ((frame_info.gpr_frame & 3) == 0);
+ }
+
+ return frame_info.total_size;
+
+} /* or1k_compute_frame_size () */
+
+
+/* -------------------------------------------------------------------------- */
+/*!Emit a frame related insn.
+
+ Same as emit_insn, but sets RTX_FRAME_RELATED_P to one. Getting this right
+ will matter for DWARF 2 output, if prologues are handled via the "prologue"
+ pattern rather than target hooks.
+
+ @param[in] insn The insn to emit.
+
+ @return The RTX for the emitted insn. */
+/* -------------------------------------------------------------------------- */
+static rtx
+emit_frame_insn (rtx insn)
+{
+ insn = emit_insn (insn);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ return (insn);
+
+} /* emit_frame_insn () */
+
+
+/* -------------------------------------------------------------------------- */
+/* Generate a RTX for the indexed memory address based on stack_pointer_rtx
+ and a displacement
+
+ @param[in] disp The displacement
+
+ @return The RTX for the generated address. */
+/* -------------------------------------------------------------------------- */
+static rtx
+stack_disp_mem (HOST_WIDE_INT disp)
+{
+ return gen_frame_mem (Pmode, plus_constant (Pmode, stack_pointer_rtx, disp));
+}
+
+enum machine_mode
+or1k_select_cc_mode (enum rtx_code op)
+{
+ switch (op) {
+ case EQ: return CCEQmode;
+ case NE: return CCNEmode;
+ case GEU: return CCGEUmode;
+ case GTU: return CCGTUmode;
+ case LTU: return CCLTUmode;
+ case LEU: return CCLEUmode;
+ case GE: return CCGEmode;
+ case LT: return CCLTmode;
+ case GT: return CCGTmode;
+ case LE: return CCLEmode;
+ default: gcc_unreachable ();
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+/*!Generate insn patterns to do an integer compare of operands.
+
+ @param[in] code RTX for the condition code.
+ @param[in] op0 RTX for the first operand.
+ @param[in] op1 RTX for the second operand.
+
+ @return RTX for the comparison. */
+/* -------------------------------------------------------------------------- */
+static rtx
+or1k_expand_int_compare (enum rtx_code code,
+ rtx op0,
+ rtx op1)
+{
+ enum machine_mode cmpmode;
+ rtx tmp, flags;
+
+ cmpmode = or1k_select_cc_mode (code);
+ flags = gen_rtx_REG (cmpmode, OR1K_FLAGS_REG);
+
+ /* This is very simple, but making the interface the same as in the
+ FP case makes the rest of the code easier. */
+ tmp = gen_rtx_COMPARE (cmpmode, op0, op1);
+ emit_insn (gen_rtx_SET (VOIDmode, flags, tmp));
+
+ /* Return the test that should be put into the flags user, i.e.
+ the bcc, scc, or cmov instruction. */
+ return gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx);
+
+} /* or1k_expand_int_compare () */
+
+
+/* -------------------------------------------------------------------------- */
+/*!Generate insn patterns to do an integer compare of operands.
+
+ We only deal with the case where the comparison is an integer
+ comparison. This wrapper function potentially allows reuse for non-integer
+ comparison in the future.
+
+ @param[in] code RTX for the condition code.
+ @param[in] op0 RTX for the first operand.
+ @param[in] op1 RTX for the second operand.
+
+ @return RTX for the comparison. */
+/* -------------------------------------------------------------------------- */
+static rtx
+or1k_expand_compare (enum rtx_code code, rtx op0, rtx op1)
+{
+ return or1k_expand_int_compare (code, op0, op1);
+
+} /* or1k_expand_compare () */
+
+
+/* -------------------------------------------------------------------------- */
+/*!Emit insns to use the l.cmov instruction
+
+ Emit a compare and then cmov. Only works for integer first operand.
+
+ @param[in] dest RTX for the destination operand.
+ @param[in] op RTX for the comparison operation
+ @param[in] true_cond RTX to move to dest if condition is TRUE.
+ @param[in] false_cond RTX to move to dest if condition is FALSE.
+
+ @return Non-zero (TRUE) if insns were emitted, zero (FALSE) otherwise. */
+/* -------------------------------------------------------------------------- */
+static int
+or1k_emit_int_cmove (rtx dest,
+ rtx op,
+ rtx true_cond,
+ rtx false_cond)
+{
+ rtx condition_rtx, cr;
+ rtx op0 = XEXP (op, 0);
+ rtx op1 = XEXP (op, 1);
+
+ if ((GET_MODE (op0) != SImode) &&
+ (GET_MODE (op0) != HImode) &&
+ (GET_MODE (op0) != QImode))
+ {
+ return 0;
+ }
+
+ /* We still have to do the compare, because cmov doesn't do a compare, it
+ just looks at the FLAG bit set by a previous compare instruction. */
+ condition_rtx = or1k_expand_compare (GET_CODE (op), op0, op1);
+
+ cr = XEXP (condition_rtx, 0);
+
+ emit_insn (gen_cmov (dest, condition_rtx, true_cond, false_cond, cr));
+
+ return 1;
+
+} /* or1k_emit_int_cmove () */
+
+
+static void
+or1k_print_operand_address (FILE *stream, rtx addr)
+{
+ rtx offset;
+
+ switch (GET_CODE (addr))
+ {
+ case MEM:
+ if (GET_CODE (XEXP (addr, 0)) == REG)
+ fprintf (stream, "%s", reg_names[REGNO (addr)]);
+ else
+ abort ();
+ break;
+
+ case REG:
+ fprintf (stream, "0(%s)", reg_names[REGNO (addr)]);
+ break;
+
+ case PLUS:
+ offset = 0;
+
+ if (GET_CODE (XEXP (addr, 0)) == REG)
+ {
+ offset = XEXP (addr, 1);
+ addr = XEXP (addr, 0);
+ }
+ else if (GET_CODE (XEXP (addr, 1)) == REG)
+ {
+ offset = XEXP (addr, 0);
+ addr = XEXP (addr, 1);
+ }
+ output_address (offset);
+ fprintf (stream, "(%s)", reg_names[REGNO (addr)]);
+ break;
+
+ case SYMBOL_REF:
+ if (SYMBOL_REF_DECL (addr))
+ assemble_external (SYMBOL_REF_DECL (addr));
+
+ if (XSTR (addr, 0)[0] == '*')
+ fputs (&XSTR (addr, 0)[1], stream);
+ else
+ {
+ asm_fprintf (stream, "%U%s", XSTR (addr, 0));
+ }
+ break;
+
+ default:
+ output_addr_const (stream, addr);
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+/*!Is this a value suitable for an OR1K address displacement?
+
+ Must be an integer (signed) which fits into 16-bits. If the result is a
+ double word, we had better also check that we can also get at the second
+ word.
+
+ @param[in] mode Mode of the result for which this displacement will be
+ used.
+ @param[in] x RTX for an expression.
+
+ @return Non-zero (TRUE) if this is a valid 16-bit offset, zero (FALSE)
+ otherwise. */
+/* -------------------------------------------------------------------------- */
+static int
+or1k_legitimate_displacement_p (enum machine_mode mode,
+ rtx x)
+{
+ if (CONST_INT == GET_CODE(x))
+ {
+ HOST_WIDE_INT disp = INTVAL (x);
+
+ /* Allow for a second access 4 bytes further on if double. */
+ if ((DFmode == mode) || (DImode == mode))
+ {
+ return (-32768 < disp) && (disp <= 32763);
+ }
+ else
+ {
+ return (-32768 < disp) && (disp <= 32767);
+ }
+ }
+ else
+ {
+ return 0;
+ }
+} /* or1k_legitimate_displacement_p () */
+
+
+/* -------------------------------------------------------------------------- */
+/*!Can this register be used as a base register?
+
+ We need a strict version, for which the register must either be a hard
+ register, or already renumbered to a hard register.
+
+ For the non-strict version, any register (other than the flag register will
+ do).
+
+ @todo The code from the old port does not allow r0 as a base when strict,
+ and does when non-strict. Surely it is always a valid register?
+
+ @param[in] regno The register to test
+ @param[in] strict Non-zero (TRUE) if this is a strict check, zero (FALSE)
+ otherwise.
+
+ @return Non-zero (TRUE) if this register can be used as a base register,
+ zero (FALSE) otherwise. */
+/* -------------------------------------------------------------------------- */
+static bool
+or1k_regnum_ok_for_base_p (HOST_WIDE_INT num,
+ bool strict)
+{
+ if (strict)
+ {
+ return (num < FIRST_PSEUDO_REGISTER)
+ ? (num > 0) && (num <= OR1K_LAST_INT_REG)
+ : (reg_renumber[num] > 0) && (reg_renumber[num] <= OR1K_LAST_INT_REG);
+ }
+ else
+ {
+ return (num <= OR1K_LAST_INT_REG) || (num >= FIRST_PSEUDO_REGISTER);
+ }
+} /* or1k_regnum_ok_for_base_p () */
+
+int
+or1k_legitimate_pic_operand_p (rtx x)
+{
+ if (GET_CODE (x) == CONST
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && ((GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
+ && (!SYMBOL_REF_LOCAL_P (XEXP (XEXP (x, 0), 0))
+ || SYMBOL_REF_WEAK (XEXP (XEXP (x, 0), 0))))
+ || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF)
+ && CONST_INT_P (XEXP (XEXP (x, 0), 1)))
+ return or1k_legitimate_displacement_p (SImode, XEXP (XEXP (x, 0), 1));
+
+ return 1;
+}
+
+static bool
+or1k_expand_pic_symbol_ref (enum machine_mode mode ATTRIBUTE_UNUSED,
+ rtx operands[])
+{
+ if (GET_CODE (operands[1]) == LABEL_REF
+ || (GET_CODE (operands[1]) == SYMBOL_REF
+ && SYMBOL_REF_LOCAL_P (operands[1])
+ && !SYMBOL_REF_WEAK (operands[1])))
+ {
+ crtl->uses_pic_offset_table = 1;
+ emit_insn (gen_movsi_gotoffhi (operands[0], operands[1]));
+ emit_insn (gen_movsi_gotofflo (operands[0], operands[0],
+ operands[1]));
+ emit_insn (gen_add3_insn(operands[0], operands[0],
+ pic_offset_table_rtx));
+ return true;
+ }
+ else if (GET_CODE (operands[1]) == SYMBOL_REF)
+ {
+ crtl->uses_pic_offset_table = 1;
+ emit_insn (gen_movsi_got (operands[0], operands[1]));
+ return true;
+ }
+ else if (GET_CODE (operands[1]) == CONST
+ && GET_CODE (XEXP (operands[1], 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF
+ && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT)
+ {
+ rtx symbolref = XEXP (XEXP (operands[1], 0), 0);
+ crtl->uses_pic_offset_table = 1;
+
+ if (SYMBOL_REF_LOCAL_P (symbolref)
+ && !SYMBOL_REF_WEAK (symbolref))
+ {
+ emit_insn (gen_movsi_gotoffhi (operands[0], operands[1]));
+ emit_insn (gen_movsi_gotofflo (operands[0], operands[0],
+ operands[1]));
+ emit_insn (gen_add3_insn(operands[0], operands[0],
+ pic_offset_table_rtx));
+ }
+ else
+ {
+ rtx const_int = XEXP (XEXP (operands[1], 0), 1);
+
+ /* Expand the constant into a register if it doesn't
+ fit directly as an 16-bit immediate in the add below.
+ Note that the reg allocation is allowed here since
+ we are guarded by LEGITIMATE_PIC_OPERAND_P. */
+ if (!or1k_legitimate_displacement_p (mode, const_int))
+ {
+ rtx scratch = gen_reg_rtx (mode);
+
+ or1k_emit_set_const32 (scratch, const_int);
+ const_int = scratch;
+ }
+
+ emit_insn (gen_movsi_got (operands[0], symbolref));
+ emit_insn (gen_add3_insn(operands[0], operands[0], const_int));
+ }
+ return true;
+ }
+ return false;
+}
+
+/* Return the TLS type for TLS symbols, 0 otherwise. */
+enum tls_model
+or1k_tls_symbolic_operand (rtx op)
+{
+ if (GET_CODE (op) == CONST)
+ {
+ rtx sym, addend;
+ split_const (op, &sym, &addend);
+ if (GET_CODE (sym) == SYMBOL_REF)
+ return SYMBOL_REF_TLS_MODEL (sym);
+ }
+ else if (GET_CODE (op) == SYMBOL_REF)
+ return SYMBOL_REF_TLS_MODEL (op);
+
+ return TLS_MODEL_NONE;
+}
+
+static GTY(()) rtx gen_tls_tga;
+
+/* Get reference to the '__tls_get_addr' symbol */
+static rtx
+gen_tls_get_addr (void)
+{
+ if (!gen_tls_tga)
+ gen_tls_tga = init_one_libfunc ("__tls_get_addr");
+ return gen_tls_tga;
+}
+
+/* Emit call to '__tls_get_addr' */
+static void
+or1k_tls_call (rtx arg)
+{
+ emit_library_call_value (gen_tls_get_addr(), arg,
+ LCT_CONST, Pmode, 1, arg, Pmode);
+}
+
+bool
+or1k_expand_symbol_ref(enum machine_mode mode, rtx operands[])
+{
+ if (mode == Pmode)
+ {
+ rtx op0, op1;
+ enum tls_model tls_kind;
+
+ op0 = operands[0];
+ op1 = operands[1];
+
+ if ((tls_kind = or1k_tls_symbolic_operand (op1)) != TLS_MODEL_NONE)
+ {
+ rtx tp;
+ tp = gen_rtx_REG(Pmode, THREAD_PTR_REGNUM);
+ switch (tls_kind)
+ {
+ case TLS_MODEL_GLOBAL_DYNAMIC:
+ case TLS_MODEL_LOCAL_DYNAMIC:
+ /* TODO: For now, treat LD as GD */
+ crtl->uses_pic_offset_table = 1;
+ emit_insn (gen_movsi_tlsgdhi (op0, op1));
+ emit_insn (gen_movsi_tlsgdlo (op0, op0, op1));
+ emit_insn (gen_add3_insn (op0, op0, pic_offset_table_rtx));
+ or1k_tls_call (op0);
+ break;
+
+ case TLS_MODEL_INITIAL_EXEC:
+ crtl->uses_pic_offset_table = 1;
+ emit_insn (gen_movsi_gottpoffhi (op0, op1));
+ emit_insn (gen_movsi_gottpofflo (op0, op0, op1));
+ emit_insn (gen_add3_insn (op0, op0, pic_offset_table_rtx));
+ emit_insn (gen_load_gottpoff (op0, op0));
+ emit_insn (gen_add3_insn (op0, op0, tp));
+ break;
+
+ case TLS_MODEL_LOCAL_EXEC:
+ emit_insn (gen_movsi_tpoffhi (op0, op1));
+ emit_insn (gen_movsi_tpofflo (op0, op0, op1));
+ emit_insn (gen_add3_insn (op0, op0, tp));
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ return true;
+ }
+ }
+
+ if (flag_pic && or1k_expand_pic_symbol_ref(mode, operands))
+ return true;
+
+ return false;
+}
+
+bool
+or1k_expand_move (enum machine_mode mode, rtx operands[])
+{
+ if (can_create_pseudo_p ())
+ {
+ if (GET_CODE (operands[0]) == MEM
+ || (GET_CODE (operands[0]) == SUBREG
+ && GET_CODE (SUBREG_REG (operands[0])) == MEM))
+ {
+ /* Source operand for store must be in a register. */
+ operands[1] = force_reg (SImode, operands[1]);
+ }
+ }
+
+ if (or1k_expand_symbol_ref (mode, operands))
+ return true;
+
+ /* Working with CONST_INTs is easier, so convert
+ a double if needed. */
+
+ if (GET_CODE (operands[1]) == CONST_DOUBLE) {
+ operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
+ }
+
+ /* Handle sets of MEM first. */
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ if (register_operand(operands[1], SImode)
+ || (operands[1] == const0_rtx))
+ goto movsi_is_ok;
+
+ if (! reload_in_progress)
+ {
+ operands[0] = validize_mem (operands[0]);
+ operands[1] = force_reg (SImode, operands[1]);
+ }
+ }
+
+ /* This makes sure we will not get rematched due to splittage. */
+ if (! CONSTANT_P (operands[1]) || input_operand (operands[1], SImode))
+ ;
+ else if (CONSTANT_P (operands[1])
+ && GET_CODE (operands[1]) != HIGH
+ && GET_CODE (operands[1]) != LO_SUM)
+ {
+ or1k_emit_set_const32 (operands[0], operands[1]);
+ return true;
+ }
+ movsi_is_ok:
+ ;
+
+ return false;
+}
+
+/* -------------------------------------------------------------------------- */
+/*!Emit a move from SRC to DEST.
+
+ Assume that the move expanders can handle all moves if !can_create_pseudo_p
+ (). The distinction is important because, unlike emit_move_insn, the move
+ expanders know how to force Pmode objects into the constant pool even when
+ the constant pool address is not itself legitimate.
+
+ @param[in] dest Destination of the move.
+ @param[in] src Source for the move.
+
+ @return RTX for the move. */
+/* -------------------------------------------------------------------------- */
+static rtx
+or1k_emit_move (rtx dest, rtx src)
+{
+ return (can_create_pseudo_p ()
+ ? emit_move_insn (dest, src)
+ : emit_move_insn_1 (dest, src));
+
+} /* or1k_emit_move () */
+
+
+/* -------------------------------------------------------------------------- */
+/*!Emit an instruction of the form (set TARGET (CODE OP0 OP1)).
+
+ @param[in] code The code for the operation.
+ @param[in] target Destination for the set operation.
+ @param[in] op0 First operand.
+ @param[in] op1 Second operand. */
+/* -------------------------------------------------------------------------- */
+static void
+or1k_emit_binary (enum rtx_code code,
+ rtx target,
+ rtx op0,
+ rtx op1)
+{
+ emit_insn (gen_rtx_SET (VOIDmode, target,
+ gen_rtx_fmt_ee (code, GET_MODE (target), op0, op1)));
+
+} /* or1k_emit_binary () */
+
+
+/* -------------------------------------------------------------------------- */
+/*!Compute the result of an operation into a new register.
+
+ Compute ("code" "op0" "op1") and store the result in a new register of mode
+ "mode".
+
+ @param[in] mode Mode of the result
+ @parma[in] code RTX for the operation to perform
+ @param[in] op0 RTX for the first operand
+ @param[in] op1 RTX for the second operand
+
+ @return The RTX for the new register. */
+/* -------------------------------------------------------------------------- */
+static rtx
+or1k_force_binary (enum machine_mode mode,
+ enum rtx_code code,
+ rtx op0,
+ rtx op1)
+{
+ rtx reg;
+
+ reg = gen_reg_rtx (mode);
+ or1k_emit_binary (code, reg, op0, op1);
+
+ return reg;
+
+} /* or1k_force_binary () */
+
+
+/* ========================================================================== */
+/* Global support functions */
+
+static int
+or1k_trampoline_code_words (void)
+{
+ int words = 5;
+
+ /* need one more word in TARGET_DELAY_COMPAT mode to hold l.nop in delay slot */
+ if (TARGET_DELAY_COMPAT)
+ words++;
+
+ return words;
+}
+
+/* -------------------------------------------------------------------------- */
+/* Return the size in bytes of the trampoline code.
+
+ Padded to TRAMPOLINE_ALIGNMENT bits. The code sequence is documented in
+ or1k_trampoline_init ().
+
+ This is just the code size. the static chain pointer and target function
+ address immediately follow.
+
+ @return The size of the trampoline code in bytes. */
+/* -------------------------------------------------------------------------- */
+int
+or1k_trampoline_code_size (void)
+{
+ const int TRAMP_BYTE_ALIGN = TRAMPOLINE_ALIGNMENT / 8;
+
+ return (or1k_trampoline_code_words() * 4 + TRAMP_BYTE_ALIGN - 1) / TRAMP_BYTE_ALIGN * TRAMP_BYTE_ALIGN;
+
+} /* or1k_trampoline_code_size () */
+
+
+/* ========================================================================== */
+/* Functions to support the Machine Description */
+
+
+/* -------------------------------------------------------------------------- */
+/*!Expand a prologue pattern.
+
+ Called after register allocation to add any instructions needed for the
+ prologue. Using a prologue insn is favored compared to putting all of the
+ instructions in output_function_prologue(), since it allows the scheduler
+ to intermix instructions with the saves of the caller saved registers. In
+ some cases, it might be necessary to emit a barrier instruction as the last
+ insn to prevent such scheduling. */
+/* -------------------------------------------------------------------------- */
+void
+or1k_expand_prologue (void)
+{
+ int total_size = or1k_compute_frame_size (get_frame_size ());
+ rtx insn;
+
+ if (!total_size)
+ /* No frame needed. */
+ return;
+
+ gcc_assert (!frame_info.save_lr_p || !frame_info.save_fp_p
+ || frame_info.lr_save_offset != frame_info.fp_save_offset);
+
+ if (frame_info.gpr_frame)
+ emit_frame_insn (gen_add2_insn (stack_pointer_rtx,
+ GEN_INT (-frame_info.gpr_frame)));
+ if (frame_info.save_fp_p)
+ {
+ emit_frame_insn (gen_rtx_SET (Pmode,
+ stack_disp_mem (frame_info.fp_save_offset),
+ hard_frame_pointer_rtx));
+
+ emit_frame_insn
+ (gen_add3_insn (hard_frame_pointer_rtx, stack_pointer_rtx, const0_rtx));
+ }
+ if (frame_info.save_lr_p)
+ {
+ emit_frame_insn
+ (gen_rtx_SET (Pmode, stack_disp_mem (frame_info.lr_save_offset),
+ gen_rtx_REG (Pmode, LINK_REGNUM)));
+ }
+ if (frame_info.gpr_size)
+ {
+ int offset = 0;
+ int regno;
+
+ for (regno = 0; regno <= OR1K_LAST_ACTUAL_REG; regno++)
+ {
+ if (!(frame_info.mask & ((HOST_WIDE_INT) 1 << regno)))
+ continue;
+
+ /* Check that the offsets aren't stepping on lr/fp slots */
+ gcc_assert (!frame_info.save_lr_p
+ || ((frame_info.gpr_offset + offset)
+ != frame_info.lr_save_offset));
+ gcc_assert (!frame_info.save_fp_p
+ || ((frame_info.gpr_offset + offset)
+ != frame_info.fp_save_offset));
+
+ emit_frame_insn
+ (gen_rtx_SET (Pmode,
+ stack_disp_mem (frame_info.gpr_offset + offset),
+ gen_rtx_REG (Pmode, regno)));
+ offset = offset + UNITS_PER_WORD;
+ }
+ }
+
+ /* Update the stack pointer to reflect frame size. */
+ total_size = frame_info.late_frame;
+ insn = gen_add2_insn (stack_pointer_rtx, GEN_INT (-total_size));
+ if (total_size > 32768)
+ {
+ rtx note = insn;
+ rtx value_rtx = gen_rtx_REG (Pmode, PROLOGUE_TMP);
+
+ or1k_emit_set_const32 (value_rtx, GEN_INT (-total_size));
+ if (frame_info.save_fp_p)
+ insn = gen_frame_alloc_fp (value_rtx);
+ else
+ insn = gen_add2_insn (stack_pointer_rtx, value_rtx);
+ insn = emit_frame_insn (insn);
+ add_reg_note (insn, REG_FRAME_RELATED_EXPR, note);
+ }
+ else if (total_size)
+ {
+ if (frame_info.save_fp_p)
+ emit_frame_insn (gen_frame_alloc_fp (GEN_INT (-total_size)));
+ else
+ emit_frame_insn (insn);
+ }
+ /* Emit got pointer acquiring if there are any got references or
+ this function has calls */
+ if (crtl->uses_pic_offset_table || (flag_pic && frame_info.save_lr_p))
+ {
+ SET_REGNO (pic_offset_table_rtx, PIC_OFFSET_TABLE_REGNUM);
+ emit_insn (gen_set_got (pic_offset_table_rtx));
+ }
+
+} /* or1k_expand_prologue () */
+
+
+/* -------------------------------------------------------------------------- */
+/*!Expand an epilogue pattern.
+
+ Called after register allocation to add any instructions needed for the
+ epilogue. Using an epilogue insn is favored compared to putting all of the
+ instructions in output_function_epilogue(), since it allows the scheduler
+ to intermix instructions with the restores of the caller saved registers.
+ In some cases, it might be necessary to emit a barrier instruction as the
+ first insn to prevent such scheduling. */
+/* -------------------------------------------------------------------------- */
+void
+or1k_expand_epilogue (void)
+{
+ int total_size = or1k_compute_frame_size (get_frame_size ());
+
+ if (frame_info.save_fp_p)
+ {
+ emit_insn (gen_frame_dealloc_fp ());
+ emit_insn
+ (gen_rtx_SET (Pmode, hard_frame_pointer_rtx,
+ stack_disp_mem (frame_info.fp_save_offset)));
+ }
+ else
+ {
+ rtx value_rtx;
+
+ total_size = frame_info.late_frame;
+ if (total_size > 32767)
+ {
+ value_rtx = gen_rtx_REG (Pmode, EPILOGUE_TMP);
+ or1k_emit_set_const32 (value_rtx, GEN_INT (total_size));
+ }
+ else if (frame_info.late_frame)
+ value_rtx = GEN_INT (total_size);
+ if (total_size)
+ emit_insn (gen_frame_dealloc_sp (value_rtx));
+ }
+
+ /* eh_return sets the LR, do not overwrite it */
+ if (frame_info.save_lr_p && !crtl->calls_eh_return)
+ {
+ emit_insn
+ (gen_rtx_SET (Pmode, gen_rtx_REG (Pmode, LINK_REGNUM),
+ stack_disp_mem (frame_info.lr_save_offset)));
+ }
+
+ if (frame_info.gpr_size)
+ {
+ int offset = 0;
+ int regno;
+
+ for (regno = 0; regno <= OR1K_LAST_ACTUAL_REG; regno++)
+ {
+ if (!(frame_info.mask & ((HOST_WIDE_INT) 1 << regno)))
+ continue;
+
+ if (regno != FIRST_PSEUDO_REGISTER)
+ emit_insn
+ (gen_rtx_SET (Pmode, gen_rtx_REG (Pmode, regno),
+ stack_disp_mem (frame_info.gpr_offset + offset)));
+ offset = offset + UNITS_PER_WORD;
+ }
+ }
+
+ if (crtl->calls_eh_return)
+ emit_insn (gen_add2_insn (stack_pointer_rtx, EH_RETURN_STACKADJ_RTX));
+
+ if (frame_info.gpr_frame)
+ emit_insn (gen_add2_insn (stack_pointer_rtx,
+ GEN_INT (frame_info.gpr_frame)));
+ emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, 9)));
+
+} /* or1k_expand_epilogue () */
+
+
+
+/* -------------------------------------------------------------------------- */
+/*!Generate assembler code for a movdi/movdf pattern
+
+ @param[in] operands Operands to the movdx pattern.
+
+ @return The assembler string to output (always "", since we've done the
+ output here). */
+/* -------------------------------------------------------------------------- */
+const char *
+or1k_output_move_double (rtx *operands)
+{
+ rtx xoperands[3];
+
+ switch (GET_CODE (operands[0]))
+ {
+ case REG:
+ if (GET_CODE (operands[1]) == REG)
+ {
+ if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
+ {
+ output_asm_insn ("\tl.or \t%H0, %H1, r0", operands);
+ output_asm_insn ("\tl.or \t%0, %1, r0", operands);
+ return "";
+ }
+ else
+ {
+ output_asm_insn ("\tl.or \t%0, %1, r0", operands);
+ output_asm_insn ("\tl.or \t%H0, %H1, r0", operands);
+ return "";
+ }
+ }
+ else if (GET_CODE (operands[1]) == MEM)
+ {
+ xoperands[1] = XEXP (operands[1], 0);
+ if (GET_CODE (xoperands[1]) == REG)
+ {
+ xoperands[0] = operands[0];
+ if (REGNO (xoperands[0]) == REGNO (xoperands[1]))
+ {
+ output_asm_insn ("\tl.lwz \t%H0, 4(%1)", xoperands);
+ output_asm_insn ("\tl.lwz \t%0, 0(%1)", xoperands);
+ return "";
+ }
+ else
+ {
+ output_asm_insn ("\tl.lwz \t%0, 0(%1)", xoperands);
+ output_asm_insn ("\tl.lwz \t%H0, 4(%1)", xoperands);
+ return "";
+ }
+ }
+ else if (GET_CODE (xoperands[1]) == PLUS)
+ {
+ if (GET_CODE (xoperands[2] = XEXP (xoperands[1], 1)) == REG)
+ {
+ xoperands[0] = operands[0];
+ xoperands[1] = XEXP (xoperands[1], 0);
+ if (REGNO (xoperands[0]) == REGNO (xoperands[2]))
+ {
+ output_asm_insn ("\tl.lwz \t%H0, %1+4(%2)",
+ xoperands);
+ output_asm_insn ("\tl.lwz \t%0, %1(%2)", xoperands);
+ return "";
+ }
+ else
+ {
+ output_asm_insn ("\tl.lwz \t%0, %1(%2)", xoperands);
+ output_asm_insn ("\tl.lwz \t%H0, %1+4(%2)",
+ xoperands);
+ return "";
+ }
+ }
+ else if (GET_CODE (xoperands[2] = XEXP (xoperands[1], 0)) ==
+ REG)
+ {
+ xoperands[0] = operands[0];
+ xoperands[1] = XEXP (xoperands[1], 1);
+ if (REGNO (xoperands[0]) == REGNO (xoperands[2]))
+ {
+ output_asm_insn ("\tl.lwz \t%H0, %1+4(%2)",
+ xoperands);
+ output_asm_insn ("\tl.lwz \t%0, %1(%2)", xoperands);
+ return "";
+ }
+ else
+ {
+ output_asm_insn ("\tl.lwz \t%0, %1(%2)", xoperands);
+ output_asm_insn ("\tl.lwz \t%H0, %1+4(%2)",
+ xoperands);
+ return "";
+ }
+ }
+ else
+ abort ();
+ }
+ else
+ abort ();
+ }
+ else
+ abort ();
+ case MEM:
+ xoperands[0] = XEXP (operands[0], 0);
+ if (GET_CODE (xoperands[0]) == REG)
+ {
+ xoperands[1] = operands[1];
+ output_asm_insn ("\tl.sw \t0(%0), %1", xoperands);
+ output_asm_insn ("\tl.sw \t4(%0), %H1", xoperands);
+ return "";
+ }
+ else if (GET_CODE (xoperands[0]) == PLUS)
+ {
+ if (GET_CODE (xoperands[1] = XEXP (xoperands[0], 1)) == REG)
+ {
+ xoperands[0] = XEXP (xoperands[0], 0);
+ xoperands[2] = operands[1];
+ output_asm_insn ("\tl.sw \t%0(%1), %2", xoperands);
+ output_asm_insn ("\tl.sw \t%0+4(%1), %H2", xoperands);
+ return "";
+ }
+ else if (GET_CODE (xoperands[1] = XEXP (xoperands[0], 0)) == REG)
+ {
+ xoperands[0] = XEXP (xoperands[0], 1);
+ xoperands[2] = operands[1];
+ output_asm_insn ("\tl.sw \t%0(%1), %2", xoperands);
+ output_asm_insn ("\tl.sw \t%0+4(%1), %H2", xoperands);
+ return "";
+ }
+ else
+ abort ();
+ }
+ else
+ {
+ fprintf (stderr, " O/p error %s\n",
+ GET_RTX_NAME (GET_CODE (xoperands[0])));
+ return "";
+ /* abort (); */
+ }
+ default:
+ abort ();
+ }
+} /* or1k_output_move_double () */
+
+
+/* -------------------------------------------------------------------------- */
+/*!Expand a conditional branch
+
+ @param[in] operands Operands to the branch.
+ @param[in] mode Mode of the comparison. */
+/* -------------------------------------------------------------------------- */
+void
+or1k_expand_conditional_branch (rtx *operands,
+ enum machine_mode mode)
+{
+ rtx tmp;
+ enum rtx_code test_code = GET_CODE(operands[0]);
+
+ switch (mode)
+ {
+ case SImode:
+ tmp = or1k_expand_compare (test_code, operands[1], operands[2]);
+ tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
+ tmp,
+ gen_rtx_LABEL_REF (VOIDmode, operands[3]),
+ pc_rtx);
+ emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
+ return;
+
+ case SFmode:
+ tmp = or1k_expand_compare (test_code, operands[1], operands[2]);
+ tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
+ tmp,
+ gen_rtx_LABEL_REF (VOIDmode, operands[3]),
+ pc_rtx);
+ emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
+ return;
+
+ default:
+ abort ();
+ }
+
+} /* or1k_expand_conditional_branch () */
+
+
+/* -------------------------------------------------------------------------- */
+/*!Emit a conditional move
+
+ move "true_cond" to "dest" if "op" of the operands of the last comparison
+ is nonzero/true, "false_cond" if it is zero/false.
+
+ @param[in] dest RTX for the destination operand.
+ @param[in] op RTX for the comparison operation
+ @param[in] true_cond RTX to move to dest if condition is TRUE.
+ @param[in] false_cond RTX to move to dest if condition is FALSE.
+
+ @return Non-zero (TRUE) if the hardware supports such an operation, zero
+ (FALSE) otherwise. */
+/* -------------------------------------------------------------------------- */
+int
+or1k_emit_cmove (rtx dest,
+ rtx op,
+ rtx true_cond,
+ rtx false_cond)
+{
+ enum machine_mode result_mode = GET_MODE (dest);
+
+ if (GET_MODE (true_cond) != result_mode)
+ return 0;
+
+ if (GET_MODE (false_cond) != result_mode)
+ return 0;
+
+ /* First, work out if the hardware can do this at all */
+ return or1k_emit_int_cmove (dest, op, true_cond, false_cond);
+
+} /* or1k_emit_cmove () */
+
+
+/* -------------------------------------------------------------------------- */
+/*!Output the assembler for a branch on flag instruction.
+
+ @param[in] operands Operands to the branch.
+
+ @return The assembler string to use. */
+/* -------------------------------------------------------------------------- */
+const char *
+or1k_output_bf (rtx * operands)
+{
+ enum rtx_code code;
+ enum machine_mode mode_calc, mode_got;
+
+ code = GET_CODE (operands[1]);
+ mode_calc = or1k_select_cc_mode (code);
+ mode_got = GET_MODE (operands[2]);
+
+ if (mode_calc != mode_got)
+ return "l.bnf\t%l0%(";
+ else
+ return "l.bf\t%l0%(";
+} /* or1k_output_bf () */
+
+
+/* -------------------------------------------------------------------------- */
+/*!Output the assembler for a conditional move instruction.
+
+ @param[in] operands Operands to the conditional move.
+
+ @return The assembler string to use. */
+/* -------------------------------------------------------------------------- */
+const char *
+or1k_output_cmov (rtx * operands)
+{
+ enum rtx_code code;
+ enum machine_mode mode_calc, mode_got;
+
+ code = GET_CODE (operands[1]);
+ mode_calc = or1k_select_cc_mode (code);
+ mode_got = GET_MODE (operands[4]);
+
+ if (mode_calc != mode_got)
+ return "l.cmov\t%0,%3,%2"; /* reversed */
+ else
+ return "l.cmov\t%0,%2,%3";
+
+} /* or1k_output_cmov () */
+
+/* -------------------------------------------------------------------------- */
+/*!Load a 32-bit constant.
+
+ We know it can't be done in one insn when we get here, the movsi expander
+ guarantees this.
+
+ @param[in] op0 RTX for the destination.
+ @param[in] op1 RTX for the (constant) source. */
+/* -------------------------------------------------------------------------- */
+void
+or1k_emit_set_const32 (rtx op0,
+ rtx op1)
+{
+ enum machine_mode mode = GET_MODE (op0);
+ rtx temp;
+
+ /* Sanity check that we really can't do it in one instruction. I.e that we
+ don't have a 16-bit constant. */
+ if (GET_CODE (op1) == CONST_INT)
+ {
+ HOST_WIDE_INT val = INTVAL (op1) & GET_MODE_MASK (mode);
+
+ if ((-32768 <= val) && (val <= 32767))
+ {
+ abort ();
+ }
+ }
+
+ /* Full 2-insn decomposition is needed. */
+ if (reload_in_progress || reload_completed)
+ temp = op0;
+ else
+ temp = gen_reg_rtx (mode);
+
+ if (GET_CODE (op1) == CONST_INT)
+ {
+ /* Emit them as real moves instead of a HIGH/LO_SUM,
+ this way CSE can see everything and reuse intermediate
+ values if it wants. */
+ emit_insn (gen_rtx_SET (VOIDmode, temp,
+ GEN_INT (INTVAL (op1)
+ & ~(HOST_WIDE_INT) 0xffff)));
+
+ emit_insn (gen_rtx_SET (VOIDmode,
+ op0,
+ gen_rtx_IOR (mode, temp,
+ GEN_INT (INTVAL (op1) & 0xffff))));
+ }
+ else
+ {
+ /* since or1k bfd can not deal with relocs that are not of type
+ OR1K_CONSTH_RELOC + OR1K_CONST_RELOC (ie move high must be
+ followed by exactly one lo_sum)
+ */
+ emit_insn (gen_movsi_insn_big (op0, op1));
+ }
+} /* or1k_emit_set_const32 () */
+
+
+/* ========================================================================== */
+/* Target hook functions.
+
+ These are initialized at the end of this file, to avoid having to
+ predeclare all the functions. They are only needed here, so are static. */
+
+
+
+
+/* -------------------------------------------------------------------------- */
+/*!Define where a function returns values.
+
+ Define this to return an RTX representing the place where a function
+ returns or receives a value of data type ret type, a tree node representing
+ a data type. "func" is a tree node representing FUNCTION_DECL or
+ FUNCTION_TYPE of a function being called. If "outgoing" is false, the hook
+ should compute the register in which the caller will see the return
+ value. Otherwise, the hook should return an RTX representing the place
+ where a function returns a value.
+
+ On many machines, only TYPE_MODE ("ret_type") is relevant. (Actually, on
+ most machines, scalar values are returned in the same place regardless of
+ mode.) The value of the expression is usually a reg RTX for the hard
+ register where the return value is stored. The value can also be a parallel
+ RTX, if the return value is in multiple places. See FUNCTION_ARG for an
+ explanation of the parallel form. Note that the callee will populate every
+ location specified in the parallel, but if the first element of the
+ parallel contains the whole return value, callers will use that element as
+ the canonical location and ignore the others. The m68k port uses this type
+ of parallel to return pointers in both ‘%a0’ (the canonical location) and
+ ‘%d0’.
+
+ If TARGET_PROMOTE_FUNCTION_RETURN returns true, you must apply the same
+ promotion rules specified in PROMOTE_MODE if valtype is a scalar type.
+
+ If the precise function being called is known, "func" is a tree node
+ (FUNCTION_DECL) for it; otherwise, "func" is a null pointer. This makes it
+ possible to use a different value-returning convention for specific
+ functions when all their calls are known.
+
+ Some target machines have "register windows" so that the register in which
+ a function returns its value is not the same as the one in which the caller
+ sees the value. For such machines, you should return different RTX
+ depending on outgoing.
+
+ TARGET_FUNCTION_VALUE is not used for return values with aggregate data
+ types, because these are returned in another way. See
+ TARGET_STRUCT_VALUE_RTX and related macros.
+
+ For the OR1K, we can just use the result of LIBCALL_VALUE, since all
+ functions return their result in the same place (register rv = r11).
+
+ JPB 30-Aug-10: What about 64-bit scalar returns (long long int, double),
+ which also use rvh (=r12)?
+
+ @param[in] ret_type The return type of the function.
+ @param[in] func Tree representing function being called.
+ @param[in] outgoing Non-zero (TRUE) if the result represents where the
+ function places the results, zero (FALSE) if the
+ result represents where the caller sees the result.
+
+ @return A RTX representing where the result can be found. */
+/* -------------------------------------------------------------------------- */
+static rtx
+or1k_function_value (const_tree ret_type,
+ const_tree func ATTRIBUTE_UNUSED,
+ bool outgoing ATTRIBUTE_UNUSED)
+{
+ return LIBCALL_VALUE (TYPE_MODE(ret_type));
+
+} /* or1k_function_value () */
+
+
+/* -------------------------------------------------------------------------- */
+/*!Check if a function is suitable for tail call optimization.
+
+ True if it is OK to do sibling call optimization for the specified call
+ expression "exp". "decl" will be the called function, or NULL if this is an
+ indirect call.
+
+ It is not uncommon for limitations of calling conventions to prevent tail
+ calls to functions outside the current unit of translation, or during PIC
+ compilation. The hook is used to enforce these restrictions, as the sibcall
+ md pattern can not fail, or fall over to a “normal” call. The criteria for
+ successful sibling call optimization may vary greatly between different
+ architectures.
+
+ For the OR1K, we currently don't allow sibcalls.
+
+ @param[in] decl The function for which we may optimize
+ @param[in] exp The call expression which is candidate for optimization.
+
+ @return Non-zero (TRUE) if sibcall optimization is permitted, zero (FALSE)
+ otherwise. */
+/* -------------------------------------------------------------------------- */
+static bool
+or1k_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
+ tree exp ATTRIBUTE_UNUSED)
+{
+ return 0;
+} /* or1k_function_ok_for_sibcall () */
+
+
+/* -------------------------------------------------------------------------- */
+/*!Should an argument be passed by reference.
+
+ This target hook should return true if an argument at the position
+ indicated by "cum" should be passed by reference. This predicate is queried
+ after target independent reasons for being passed by reference, such as
+ TREE_ADDRESSABLE ("type").
+
+ If the hook returns TRUE, a copy of that argument is made in memory and a
+ pointer to the argument is passed instead of the argument itself. The
+ pointer is passed in whatever way is appropriate for passing a pointer to
+ that type.
+
+ For the OR1K, all aggregates and arguments greater than 8 bytes are passed
+ this way.
+
+ @param[in] cum Position of argument under consideration.
+ @param[in[ mode Not sure what this relates to.
+ @param[in] type Type of the argument.
+ @param[in] named Not sure what this relates to.
+
+ @return Non-zero (TRUE) if the argument should be passed by reference,
+ zero (FALSE) otherwise. */
+/* -------------------------------------------------------------------------- */
+static bool
+or1k_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ const_tree type,
+ bool named ATTRIBUTE_UNUSED)
+{
+ return (type && (AGGREGATE_TYPE_P (type) || int_size_in_bytes (type) > 8));
+
+} /* or1k_pass_by_reference () */
+
+
+int
+or1k_initial_elimination_offset(int from, int to)
+{
+ or1k_compute_frame_size (get_frame_size ());
+ return ((from == FRAME_POINTER_REGNUM
+ ? frame_info.gpr_offset : frame_info.gpr_frame)
+ + (to == STACK_POINTER_REGNUM ? frame_info.late_frame : 0));
+}
+
+
+/* -------------------------------------------------------------------------- */
+/*!How many bytes at the beginning of an argument must be put into registers.
+
+ This target hook returns the number of bytes at the beginning of an
+ argument that must be put in registers. The value must be zero for
+ arguments that are passed entirely in registers or that are entirely pushed
+ on the stack.
+
+ On some machines, certain arguments must be passed partially in registers
+ and partially in memory. On these machines, typically the first few words
+ of arguments a re passed in registers, and the rest on the stack. If a
+ multi-word argument (a double or a structure) crosses that boundary, its
+ first few words must be passed in registers and the rest must be
+ pushed. This macro tells the compiler when this occurs, and how many bytes
+ should go in registers.
+
+ FUNCTION_ARG for these arguments should return the first register to be
+ used by the caller for this argument; likewise FUNCTION_INCOMING_ARG, for
+ the called function.
+
+ On the OR1K we never split argumetns between registers and memory.
+
+ JPB 30-Aug-10: Is this correct? Surely we should allow this. The ABI spec
+ is incomplete on this point.
+
+ @param[in] cum Position of argument under consideration.
+ @param[in[ mode Not sure what this relates to.
+ @param[in] type Type of the argument.
+ @param[in] named Not sure what this relates to.
+
+ @return The number of bytes of the argument to go into registers */
+/* -------------------------------------------------------------------------- */
+static int
+or1k_arg_partial_bytes (cumulative_args_t cum ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ tree type ATTRIBUTE_UNUSED,
+ bool named ATTRIBUTE_UNUSED)
+{
+ return 0;
+
+} /* or1k_arg_partial_bytes () */
+
+
+/* -------------------------------------------------------------------------- */
+/*!Promote the mode of a function's arguments/return value.
+
+ Like PROMOTE_MODE, but it is applied to outgoing function arguments or
+ function return values. The target hook should return the new mode and
+ possibly change "*punsignedp" if the promotion should change
+ signedness. This function is called only for scalar or pointer types.
+
+ "for_return" allows to distinguish the promotion of arguments and return
+ values. If it is 1, a return value is being promoted and
+ TARGET_FUNCTION_VALUE must perform the same promotions done here. If it is
+ 2, the returned mode should be that of the register in which an incoming
+ parameter is copied, or the outgoing result is computed; then the hook
+ should return the same mode as PROMOTE_MODE, though the signedness may be
+ different.
+
+ The default is to not promote arguments and return values. You can also
+ define the hook to "default_promote_function_mode_always_promote" if you
+ would like to apply the same rules given by PROMOTE_MODE.
+
+ For the OR1K, if the size of the mode is integral and less than 4, we
+ promote to SImode, otherwise we return the mode we are supplied.
+
+ @param[in] type Not sure. Type of the argument?
+ @param[in] mode The mode of argument/return value to consider.
+ @param[out] punsignedp Signedness of the value.
+ @param[in] fntype Not sure. Type of the function?
+ @param[in] for_return 1 if a return value, 2 if an incoming value.
+
+ @return The new mode. */
+/* -------------------------------------------------------------------------- */
+static enum machine_mode
+or1k_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
+ enum machine_mode mode,
+ int *punsignedp ATTRIBUTE_UNUSED,
+ const_tree fntype ATTRIBUTE_UNUSED,
+ int for_return ATTRIBUTE_UNUSED)
+{
+ return ( (GET_MODE_CLASS (mode) == MODE_INT)
+ && (GET_MODE_SIZE (mode) < 4)) ? SImode : mode;
+
+} /* or1k_promote_function_mode () */
+
+
+/* -------------------------------------------------------------------------- */
+/*!Is this a legitimate address?
+
+ A function that returns whether x (an RTX) is a legitimate memory address on
+ the target machine for a memory operand of mode mode.
+
+ Legitimate addresses are defined in two variants: a strict variant and a
+ non-strict one. The strict parameter chooses which variant is desired by
+ the caller.
+
+ The strict variant is used in the reload pass. It must be defined so that
+ any pseudo- register that has not been allocated a hard register is
+ considered a memory reference. This is because in contexts where some kind
+ of register is required, a pseudo-register with no hard register must be
+ rejected. For non-hard registers, the strict variant should look up the
+ reg_renumber array; it should then proceed using the hard register number in
+ the array, or treat the pseudo as a memory reference if the array holds -1.
+
+ The non-strict variant is used in other passes. It must be defined to accept
+ all pseudo-registers in every context where some kind of register is
+ required.
+
+ Normally, constant addresses which are the sum of a symbol_ref and an
+ integer are stored inside a const RTX to mark them as constant. Therefore,
+ there is no need to recognize such sums specifically as legitimate
+ addresses. Normally you would simply recognize any const as legitimate.
+
+ Usually PRINT_OPERAND_ADDRESS is not prepared to handle constant sums that
+ are not marked with const. It assumes that a naked plus indicates
+ indexing. If so, then you must reject such naked constant sums as
+ illegitimate addresses, so that none of them will be given to
+ PRINT_OPERAND_ADDRESS.
+
+ On some machines, whether a symbolic address is legitimate depends on the
+ section that the address refers to. On these machines, define the target
+ hook TARGET_ENCODE_ SECTION_INFO to store the information into the
+ symbol_ref, and then check for it here. When you see a const, you will have
+ to look inside it to find the symbol_ref in order to determine the
+ section. See the internals manual section on "Assembler Format" for more
+ info.
+
+ Some ports are still using a deprecated legacy substitute for this hook, the
+ GO_IF_LEGITIMATE_ADDRESS macro. This macro has this syntax:
+
+ #define GO_IF_LEGITIMATE_ADDRESS (mode, x, label )
+
+ and should goto label if the address x is a valid address on the target
+ machine for a memory operand of mode mode. Whether the strict or non-strict
+ variants are desired is defined by the REG_OK_STRICT macro introduced
+ earlier in this section. Using the hook is usually simpler because it limits
+ the number of files that are recompiled when changes are made.
+
+ The OR1K only has a single addressing mode, which is a base register with
+ 16-bit displacement. We can accept just 16-bit constants as addresses (they
+ can use r0 as base address, and we can accept plain registers as addresses
+ (they can use a displacement of zero).
+
+ @param[in] mode The mode of the address
+ @param[in] x The address (RTX)
+ @param[in] strict Non-zero (TRUE) if we are in "strict" mode, zero (FALSE)
+ otherwise.
+
+ @return Non-zero (TRUE) if this is a legitimate address, zero (FALSE)
+ otherwise. */
+/* -------------------------------------------------------------------------- */
+static bool
+or1k_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+ rtx x,
+ bool strict)
+{
+ /* You might think 16-bit constants are suitable. They can be built into
+ addresses using r0 as the base. However this seems to lead to defective
+ code. So for now this is a placeholder, and this code is not used.
+
+ if (or1k_legitimate_displacement_p (mode, x))
+ {
+ return 1;
+ }
+ */
+ /* Addresses consisting of a register and 16-bit displacement are also
+ suitable. We need the mode, since for double words, we had better be
+ able to address the full 8 bytes. */
+ if (GET_CODE(x) == PLUS)
+ {
+ rtx reg = XEXP(x,0);
+
+ /* If valid register... */
+ if ((GET_CODE(reg) == REG)
+ && or1k_regnum_ok_for_base_p (REGNO (reg), strict))
+ {
+ rtx offset = XEXP(x,1);
+
+ /* ...and valid offset */
+ if (or1k_legitimate_displacement_p (mode, offset))
+ {
+ return 1;
+ }
+ }
+ }
+
+ /* Addresses consisting of just a register are OK. They can be built into
+ addresses using an offset of zero (and an offset of four if double
+ word). */
+ if (GET_CODE(x) == REG
+ && or1k_regnum_ok_for_base_p(REGNO(x),strict)) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/* -------------------------------------------------------------------------- */
+/*!Initialize a trampoline for nested functions.
+
+ A nested function is defined by *two* pieces of information, the address of
+ the function (like any other function) and a pointer to the frame of the
+ enclosing function. The latter is required to allow the nested function to
+ access local variables in the enclosing function's frame.
+
+ This represents a problem, since a function in C is represented as an
+ address that can be held in a single variable as a pointer. Requiring two
+ pointers will not fit.
+
+ The solution is documented in "Lexical Closures for C++" by Thomas
+ M. Breuel (USENIX C++ Conference Proceedings, October 17-21, 1988). The
+ nested function is represented by a small block of code and data on the
+ enclosing function's stack frame, which sets up a pointer to the enclosing
+ function's stack frame (the static chain pointer) in a register defined by
+ the ABI, and then jumps to the code of the function proper.
+
+ The function can be represented as a single pointer to this block of code,
+ known as a trampoline, which when called generates both pointers
+ needed. The nested function (which knows it is a nested function at compile
+ time) can then generate code to access the enclosing frame via the static
+ chain register.
+
+ There is a catch that the trampoline is set up as data, but executed as
+ instructions. The former will be via the data cache, the latter via the
+ instruction cache. There is a risk that a later trampoline will not be seen
+ by the instruction cache, so the wrong code will be executed. So the
+ instruction cache should be flushed for the trampoline address range.
+
+ This hook is called to initialize a trampoline. "m_tramp" is an RTX for the
+ memory block for the trampoline; "fndecl" is the FUNCTION_DECL for the
+ nested function; "static_chain" is an RTX for the static chain value that
+ should be passed to the function when it is called.
+
+ If the target defines TARGET_ASM_TRAMPOLINE_TEMPLATE, then the first thing
+ this hook should do is emit a block move into "m_tramp" from the memory
+ block returned by assemble_trampoline_template. Note that the block move
+ need only cover the constant parts of the trampoline. If the target
+ isolates the variable parts of the trampoline to the end, not all
+ TRAMPOLINE_SIZE bytes need be copied.
+
+ If the target requires any other actions, such as flushing caches or
+ enabling stack execution, these actions should be performed after
+ initializing the trampoline proper.
+
+ For the OR1K, no static chain register is used. We choose to use the return
+ value (rv) register. The code is based on that for MIPS.
+ The trampoline code is:
+
+ l.movhi r11,hi(end_addr)
+ l.ori r11,lo(end_addr)
+ l.lwz r13,4(r11)
+ l.jr r13
+ l.lwz r11,0(r11)
+ end_addr:
+ .word
+ .word
+
+ @note For the OR1K we need to flush the instruction cache, which is a
+ privileged operation. Needs fixing.
+
+ @param[in] m_tramp The lowest address of the trampoline on the stack.
+ @param[in] fndecl Declaration of the enclosing function.
+ @param[in] chain_value Static chain pointer to pass to the nested
+ function. */
+/* -------------------------------------------------------------------------- */
+static void
+or1k_trampoline_init (rtx m_tramp,
+ tree fndecl,
+ rtx chain_value)
+{
+ rtx addr; /* Start address of the trampoline */
+ rtx end_addr; /* End address of the code block */
+
+ rtx high; /* RTX for the high part of end_addr */
+ rtx low; /* RTX for the low part of end_addr */
+ rtx opcode; /* RTX for generated opcodes */
+ rtx mem; /* RTX for trampoline memory */
+
+ rtx *trampoline; /* The trampoline code */
+
+ unsigned int i; /* Index into trampoline */
+ unsigned int j; /* General counter */
+
+ HOST_WIDE_INT end_addr_offset; /* Offset to end of code */
+ HOST_WIDE_INT static_chain_offset; /* Offset to stack chain word */
+ HOST_WIDE_INT target_function_offset; /* Offset to func address word */
+
+ /* Work out the offsets of the pointers from the start of the trampoline
+ code. */
+ trampoline = (rtx*) alloca (or1k_trampoline_code_words() * sizeof(rtx));
+ end_addr_offset = or1k_trampoline_code_size ();
+ static_chain_offset = end_addr_offset;
+ target_function_offset = static_chain_offset + GET_MODE_SIZE (ptr_mode);
+
+ /* Get pointers in registers to the beginning and end of the code block. */
+ addr = force_reg (Pmode, XEXP (m_tramp, 0));
+ end_addr = or1k_force_binary (Pmode, PLUS, addr, GEN_INT (end_addr_offset));
+
+ /* Build up the code in TRAMPOLINE.
+
+ l.movhi r11,hi(end_addr)
+ l.ori r11,lo(end_addr)
+ l.lwz r13,4(r11)
+ l.jr r13
+ l.lwz r11,0(r11)
+ end_addr:
+ */
+
+ i = 0;
+
+ /* Break out the high and low parts of the end_addr */
+ high = expand_simple_binop (SImode, LSHIFTRT, end_addr, GEN_INT (16),
+ NULL, false, OPTAB_WIDEN);
+ low = convert_to_mode (SImode, gen_lowpart (HImode, end_addr), true);
+
+ /* Emit the l.movhi, adding an operation to OR in the high bits from the
+ RTX. */
+ opcode = gen_int_mode (OR1K_MOVHI (11, 0), SImode);
+ trampoline[i++] = expand_simple_binop (SImode, IOR, opcode, high, NULL,
+ false, OPTAB_WIDEN);
+
+ /* Emit the l.ori, adding an operations to OR in the low bits from the
+ RTX. */
+ opcode = gen_int_mode (OR1K_ORI (11, 11, 0), SImode);
+ trampoline[i++] = expand_simple_binop (SImode, IOR, opcode, low, NULL,
+ false, OPTAB_WIDEN);
+
+ /* Emit the l.lwz of the function address. No bits to OR in here, so we can
+ do the opcode directly. */
+ trampoline[i++] =
+ gen_int_mode (OR1K_LWZ (13, 11, target_function_offset - end_addr_offset),
+ SImode);
+
+ if (TARGET_DELAY_ON) {
+ /* Emit the l.jr of the function. No bits to OR in here, so we can do the
+ opcode directly. */
+ trampoline[i++] = gen_int_mode (OR1K_JR (13), SImode);
+
+ /* Emit the l.lwz of the static chain. No bits to OR in here, so we can
+ do the opcode directly. */
+ trampoline[i++] =
+ gen_int_mode (OR1K_LWZ (STATIC_CHAIN_REGNUM, 11,
+ static_chain_offset - end_addr_offset), SImode);
+ } else {
+ trampoline[i++] =
+ gen_int_mode (OR1K_LWZ (STATIC_CHAIN_REGNUM, 11,
+ static_chain_offset - end_addr_offset), SImode);
+ trampoline[i++] = gen_int_mode (OR1K_JR (13), SImode);
+ if (TARGET_DELAY_COMPAT)
+ trampoline[i++] = gen_int_mode (OR1K_NOP, SImode);
+ }
+
+ /* Copy the trampoline code. Leave any padding uninitialized. */
+ for (j = 0; j < i; j++)
+ {
+ mem = adjust_address (m_tramp, SImode, j * GET_MODE_SIZE (SImode));
+ or1k_emit_move (mem, trampoline[j]);
+ }
+
+ /* Set up the static chain pointer field. */
+ mem = adjust_address (m_tramp, ptr_mode, static_chain_offset);
+ or1k_emit_move (mem, chain_value);
+
+ /* Set up the target function field. */
+ mem = adjust_address (m_tramp, ptr_mode, target_function_offset);
+ or1k_emit_move (mem, XEXP (DECL_RTL (fndecl), 0));
+
+ /* Flushing the trampoline from the instruction cache needs to be done
+ here. */
+
+} /* or1k_trampoline_init () */
+
+
+/* -------------------------------------------------------------------------- */
+/*!Provide support for DW_AT_calling_convention
+
+ Define this to enable the dwarf attribute DW_AT_calling_convention to be
+ emitted for each function. Instead of an integer return the enum value for
+ the DW_CC_ tag.
+
+ To support optional call frame debugging information, you must also define
+ INCOMING_RETURN_ADDR_RTX and either set RTX_FRAME_RELATED_P on the prologue
+ insns if you use RTL for the prologue, or call "dwarf2out_def_cfa" and
+ "dwarf2out_reg_save" as appropriate from TARGET_ASM_FUNCTION_PROLOGUE if
+ you don’t.
+
+ For the OR1K, it should be sufficient to return DW_CC_normal in all cases.
+
+ @param[in] function The function requiring debug information
+
+ @return The enum of the DW_CC tag. */
+/* -------------------------------------------------------------------------- */
+static int
+or1k_dwarf_calling_convention (const_tree function ATTRIBUTE_UNUSED)
+{
+ return DW_CC_normal;
+
+} /* or1k_dwarf_calling_convention () */
+
+/* ========================================================================== */
+/* Target hook initialization.
+
+ In most cases these use the static functions declared above. They have
+ defaults, so must be undefined first, before being redefined.
+
+ The description of what they do is found with the function above, unless it
+ is a standard function or a constant, in which case it is defined here (as
+ with TARGET_ASM_NAMED_SECTION).
+
+ The final declaration is of the global "targetm" structure. */
+
+/* Output assembly directives to switch to section name. The section should
+ have attributes as specified by flags, which is a bit mask of the SECTION_*
+ flags defined in ‘output.h’. If decl is non-NULL, it is the VAR_DECL or
+ FUNCTION_DECL with which this section is associated.
+
+ For OR1K, we use the default ELF sectioning. */
+#undef TARGET_ASM_NAMED_SECTION
+#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section
+
+#undef TARGET_FUNCTION_VALUE
+#define TARGET_FUNCTION_VALUE or1k_function_value
+
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL or1k_function_ok_for_sibcall
+
+#undef TARGET_PASS_BY_REFERENCE
+#define TARGET_PASS_BY_REFERENCE or1k_pass_by_reference
+
+#undef TARGET_ARG_PARTIAL_BYTES
+#define TARGET_ARG_PARTIAL_BYTES or1k_arg_partial_bytes
+
+#undef TARGET_OPTION_OVERRIDE
+#define TARGET_OPTION_OVERRIDE or1k_option_override
+
+#undef TARGET_ASM_FILE_START
+#define TARGET_ASM_FILE_START or1k_asm_file_start
+
+/* This target hook returns TRUE if an argument declared in a prototype as an
+ integral type smaller than int should actually be passed as an int. In
+ addition to avoiding errors in certain cases of mismatch, it also makes for
+ better code on certain machines.
+
+ The default is to not promote prototypes.
+
+ For the OR1K we do require this, so use a utility hook, which always
+ returns TRUE. */
+#undef TARGET_PROMOTE_PROTOTYPES
+#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
+
+#undef TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE or1k_promote_function_mode
+
+#undef TARGET_LEGITIMATE_ADDRESS_P
+#define TARGET_LEGITIMATE_ADDRESS_P or1k_legitimate_address_p
+
+#undef TARGET_TRAMPOLINE_INIT
+#define TARGET_TRAMPOLINE_INIT or1k_trampoline_init
+
+#undef TARGET_DWARF_CALLING_CONVENTION
+#define TARGET_DWARF_CALLING_CONVENTION or1k_dwarf_calling_convention
+
+/* uClibc has some instances where (non-coforming to ISO C) a non-varargs
+ prototype is in scope when calling that function which is implemented
+ as varargs. We want this to work at least where none of the anonymous
+ arguments are used. I.e. we want the last named argument to be known
+ as named so it can be passed in a register, varars funtion or not. */
+#undef TARGET_STRICT_ARGUMENT_NAMING
+#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
+
+/* Is this suitable for an immediate operand.
+
+ JPB 1-Sep-10: Is this correct. We can only do 16-bit immediates directly. */
+static bool
+or1k_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+{
+ return GET_CODE(x) != CONST_DOUBLE || (GET_MODE (x) == VOIDmode && !flag_pic);
+}
+#undef TARGET_LEGITIMATE_CONSTANT_P
+#define TARGET_LEGITIMATE_CONSTANT_P or1k_legitimate_constant_p
+
+/* On the OR1K, no functions pop their arguments.
+ JPB 29-Aug-10: Is this really correct? */
+static int
+or1k_return_pops_args (tree ARG_UNUSED(fundecl), tree ARG_UNUSED(funtype), int ARG_UNUSED(size))
+{
+ return 0;
+}
+#undef TARGET_RETURN_POPS_ARGS
+#define TARGET_RETURN_POPS_ARGS or1k_return_pops_args
+
+/* Determine where to put an argument to a function. Value is zero to push
+ the argument on the stack, or a hard register in which to store the
+ argument.
+
+ "mode" is the argument's machine mode.
+
+ "type" is the data type of the argument (as a tree). This is null for
+ libcalls where that information may not be available.
+
+ "cum" is a variable of type CUMULATIVE_ARGS which gives info about the
+ preceding args and about the function being called.
+
+ "named" is nonzero if this argument is a named parameter (otherwise it is
+ an extra parameter matching an ellipsis).
+
+ On the ARC the first MAX_ARC_PARM_REGS args are normally in registers and
+ the rest are pushed. */
+static rtx
+or1k_function_arg (cumulative_args_t cum, enum machine_mode mode,
+ const_tree type, bool named)
+{
+ CUMULATIVE_ARGS *cum_pnt = get_cumulative_args (cum);
+
+ if (OR1K_PASS_IN_REG_P (*cum_pnt, mode, type, named))
+ return gen_rtx_REG (mode, OR1K_ROUND_ADVANCE_CUM (*cum_pnt, mode, type)
+ + GP_ARG_MIN_REG);
+ else
+ return 0;
+}
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG or1k_function_arg
+/* Update the data in "cum" to advance over an argument of mode "mode" and
+ data type "type". ("type" is null for libcalls where that information may
+ not be available.) */
+static void
+or1k_function_arg_advance (cumulative_args_t cum, enum machine_mode mode,
+ const_tree type, bool ARG_UNUSED(named))
+{
+ CUMULATIVE_ARGS *cum_pnt = get_cumulative_args (cum);
+
+ *cum_pnt = OR1K_ROUND_ADVANCE_CUM (*cum_pnt, mode, type)
+ + OR1K_ROUND_ADVANCE_ARG (mode, type);
+}
+
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE or1k_function_arg_advance
+
+#undef TARGET_PRINT_OPERAND_ADDRESS
+#define TARGET_PRINT_OPERAND_ADDRESS or1k_print_operand_address
+
+/* Trampoline stubs are yet to be written. */
+/* #define TARGET_ASM_TRAMPOLINE_TEMPLATE */
+/* #define TARGET_TRAMPOLINE_INIT */
+
+/* Lay out structs with increased alignment so that they can be accessed
+ more efficiently. But don't increase the size of one or two byte
+ structs. */
+int
+or1k_struct_alignment (tree t)
+{
+ unsigned HOST_WIDE_INT total = 0;
+ int default_align_fields = 0;
+ int special_align_fields = 0;
+ tree field;
+ unsigned max_align
+ = maximum_field_alignment ? maximum_field_alignment : BIGGEST_ALIGNMENT;
+ bool struct_p;
+
+ switch (TREE_CODE (t))
+ {
+ case RECORD_TYPE:
+ struct_p = true; break;
+ case UNION_TYPE: case QUAL_UNION_TYPE:
+ struct_p = false; break;
+ default: gcc_unreachable ();
+ }
+ /* Skip all non field decls */
+ for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
+ {
+ unsigned HOST_WIDE_INT field_size;
+
+ if (TREE_CODE (field) != FIELD_DECL ||
+ TREE_TYPE (field) == error_mark_node)
+ continue;
+ /* If this is a field in a non-qualified union, or the sole field in
+ a struct, and the alignment was set by the user, don't change the
+ alignment.
+ If the field is a struct/union in a non-qualified union, we already
+ had sufficient opportunity to pad it - if we didn't, that'd be
+ because the alignment was set as above.
+ Likewise if the field is a struct/union and the sole field in a
+ struct. */
+ if (DECL_USER_ALIGN (field)
+ || TYPE_USER_ALIGN (TREE_TYPE (field))
+ || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE
+ || TREE_CODE (TREE_TYPE (field)) == QUAL_UNION_TYPE
+ || TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
+ {
+ if (TREE_CODE (t) == UNION_TYPE)
+ return 0;
+ special_align_fields++;
+ }
+ else if (DECL_PACKED (field))
+ special_align_fields++;
+ else
+ default_align_fields++;
+ if (!host_integerp (DECL_SIZE (field), 1))
+ field_size = max_align;
+ else
+ field_size = tree_low_cst (DECL_SIZE (field), 1);
+ if (field_size >= BIGGEST_ALIGNMENT)
+ total = max_align;
+ if (struct_p)
+ total += field_size;
+ else
+ total = MAX (total, field_size);
+ }
+
+ if (!default_align_fields
+ && (TREE_CODE (t) != RECORD_TYPE || special_align_fields <= 1))
+ return 0;
+ return total < max_align ? (1U << ceil_log2 (total)) : max_align;
+}
+
+/* Increase the alignment of objects so that they are easier to copy.
+ Note that this can cause more struct copies to be inlined, so code
+ size might increase, but so should perfromance. */
+int
+or1k_data_alignment (tree t, int align)
+{
+ if (align < FASTEST_ALIGNMENT && TREE_CODE (t) == ARRAY_TYPE)
+ {
+ int size = int_size_in_bytes (t);
+
+ return (size > 0 && size < FASTEST_ALIGNMENT / BITS_PER_UNIT
+ ? (1 << floor_log2 (size)) * BITS_PER_UNIT
+ : FASTEST_ALIGNMENT);
+ }
+ return align;
+}
+
+static void
+or1k_option_override (void)
+{
+ if (!TARGET_DELAY_ON)
+ flag_delayed_branch = FALSE;
+}
+
+static void
+or1k_asm_file_start(void)
+{
+ default_file_start();
+
+ if (TARGET_DELAY_OFF) {
+ fprintf(asm_out_file, "\t.nodelay\n");
+ }
+}
+
+/* Implement EH_RETURN_HANDLER_RTX.
+ * Make eh_return use the link register. Epilogue LR restore
+ * is suppressed for eh_return. */
+rtx
+or1k_eh_return_handler_rtx (void)
+{
+ return INCOMING_RETURN_ADDR_RTX;
+}
+
+/* Implement RETURN_ADDR_RTX.
+ * We do not support moving back to a previous frame. */
+rtx
+or1k_return_addr_rtx (int count, rtx frame ATTRIBUTE_UNUSED)
+{
+ if (count != 0)
+ return const0_rtx;
+
+ /* We don't know if LR is going to be saved or if we're going to
+ * be clobbering it with the GOT instruction.
+ * Therefore the safest bet is to force a save of LR and use that.
+ * Assume it's going to be first in the stack. */
+
+ cfun->machine->force_lr_save = true;
+ return gen_rtx_MEM (Pmode, plus_constant (Pmode, arg_pointer_rtx,
+ -UNITS_PER_WORD));
+}
+
+/* Implement TARGET_FRAME_POINTER_REQUIRED.
+ * We want frame pointer in eh_return and when alloca is used */
+static bool
+or1k_frame_pointer_required (void)
+{
+ return crtl->calls_eh_return || cfun->calls_alloca;
+}
+
+/* Functions to save and restore machine-specific function data. */
+static struct machine_function *
+or1k_init_machine_status (void)
+{
+ return ggc_alloc_cleared_machine_function ();
+}
+
+void
+or1k_init_expanders (void)
+{
+ /* Arrange to initialize and mark the machine per-function
+ * status. */
+ init_machine_status = or1k_init_machine_status;
+
+ if (cfun && cfun->machine)
+ {
+ cfun->machine->force_lr_save = false;
+ }
+}
+
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED or1k_frame_pointer_required
+
+/* Initialize the GCC target structure. */
+struct gcc_target targetm = TARGET_INITIALIZER;
+
+#include "gt-or1k.h"
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/or1k.h gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k.h
--- gcc-4.8.2/gcc/config/or1k/or1k.h 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k.h 2014-03-14 07:27:49.000000000 +0200
@@ -0,0 +1,1210 @@
+/* Definitions of target machine for GNU compiler. OpenRISC 1000 version.
+ Copyright (C) 1987, 1988, 1992, 1995, 1996, 1999, 2000, 2001, 2002,
+ 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2010 Embecosm Limited
+ Contributed by Damjan Lampret in 1999.
+ Major optimizations by Matjaz Breskvar in 2005.
+
+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 1, 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. */
+
+#ifndef _OR1K_H_
+#define _OR1K_H_
+
+#include "config/or1k/or1k-opts.h"
+
+/* Target CPU builtins */
+#define TARGET_CPU_CPP_BUILTINS() \
+ do \
+ { \
+ if (TARGET_DELAY_OFF) { \
+ builtin_define ("__OR1KND__"); \
+ builtin_define ("__or1knd__"); \
+ builtin_assert ("cpu=or1knd"); \
+ builtin_assert ("machine=or1knd"); \
+ } else { \
+ builtin_define ("__OR1K__"); \
+ builtin_define ("__or1k__"); \
+ builtin_assert ("cpu=or1k"); \
+ builtin_assert ("machine=or1k"); \
+ } \
+ if (TARGET_DELAY_ON) { \
+ builtin_define ("__OR1K_DELAY__"); \
+ } else if (TARGET_DELAY_OFF) { \
+ builtin_define ("__OR1K_NODELAY__"); \
+ } else if (TARGET_DELAY_COMPAT) { \
+ builtin_define ("__OR1K_DELAY_COMPAT__"); \
+ } \
+ } \
+ while (0)
+
+#undef CPP_SPEC
+#define CPP_SPEC \
+ "%{!mnewlib:%{pthread:-D_XOPEN_SOURCE=700}}"
+
+/* Make sure we pick up the crti.o, crtbegin.o, crtend.o and crtn.o files. */
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ "%{!shared:%{pie:Scrt0.o%s;:crt0.o%s}} crti.o%s \
+ %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s}"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "%{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s"
+
+#undef LINK_SPEC
+#define LINK_SPEC "%{mnewlib:-entry 0x100} %{static:-static} %{shared:-shared}"
+
+/* Override previous definitions (linux.h). Newlib doesn't have a profiling
+ version of the library, but it does have a debugging version (libg.a) */
+#undef LIB_SPEC
+#define LIB_SPEC "%{!mnewlib:%{pthread:-lpthread} \
+ %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}" \
+ "%{mnewlib:%{!g:-lc} %{g:-lg} -lor1k \
+ %{mboard=*:-lboard-%*} %{!mboard=*:-lboard-or1ksim} \
+ %{!g:-lc} %{g:-lg} \
+ }"
+
+/* Target machine storage layout */
+
+/* Define this if most significant bit is lowest numbered
+ in instructions that operate on numbered bit-fields.
+ This is not true on the or1k. */
+#define BITS_BIG_ENDIAN 0
+
+/* Define this if most significant byte of a word is the lowest numbered. */
+#define BYTES_BIG_ENDIAN 1
+
+/* Define this if most significant word of a multiword number is numbered. */
+#define WORDS_BIG_ENDIAN 1
+
+/* Number of bits in an addressable storage unit */
+#define BITS_PER_UNIT 8
+
+#define BITS_PER_WORD 32
+#define SHORT_TYPE_SIZE 16
+#define INT_TYPE_SIZE 32
+#define LONG_TYPE_SIZE 32
+#define LONG_LONG_TYPE_SIZE 64
+#define FLOAT_TYPE_SIZE 32
+#define DOUBLE_TYPE_SIZE 64
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+/* Width of a word, in units (bytes). */
+#define UNITS_PER_WORD 4
+
+/* Width in bits of a pointer.
+ See also the macro `Pmode' defined below. */
+#define POINTER_SIZE 32
+
+/* Allocation boundary (in *bits*) for storing pointers in memory. */
+#define POINTER_BOUNDARY 32
+
+/* Allocation boundary (in *bits*) for storing arguments in argument list. */
+#define PARM_BOUNDARY 32
+
+/* Boundary (in *bits*) on which stack pointer should be aligned. */
+#define STACK_BOUNDARY 32
+
+/* Allocation boundary (in *bits*) for the code of a function. */
+#define FUNCTION_BOUNDARY 32
+
+/* Alignment of field after `int : 0' in a structure. */
+#define EMPTY_FIELD_BOUNDARY 8
+
+/* Every structure's size must be a multiple of this. */
+#define STRUCTURE_SIZE_BOUNDARY (TARGET_PADSTRUCT ? 32 : 8)
+
+/* A bitfield declared as `int' forces `int' alignment for the struct. */
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* No data type wants to be aligned rounder than this. */
+#define BIGGEST_ALIGNMENT 32
+
+/* The best alignment to use in cases where we have a choice. */
+#define FASTEST_ALIGNMENT 32
+
+#define ROUND_TYPE_ALIGN(STRUCT, COMPUTED, SPECIFIED) \
+ ((TREE_CODE (STRUCT) == RECORD_TYPE \
+ || TREE_CODE (STRUCT) == UNION_TYPE \
+ || TREE_CODE (STRUCT) == QUAL_UNION_TYPE) \
+ && !TYPE_PACKED (STRUCT) \
+ && TYPE_FIELDS (STRUCT) != 0 \
+ ? MAX (MAX ((COMPUTED), (SPECIFIED)), or1k_struct_alignment (STRUCT)) \
+ : MAX ((COMPUTED), (SPECIFIED))) \
+
+/* Make strings word-aligned so strcpy from constants will be faster. */
+/*
+#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
+ ((TREE_CODE (EXP) == STRING_CST || TREE_CODE (EXP) == CONSTRUCTOR) \
+ && (ALIGN) < FASTEST_ALIGNMENT \
+ ? FASTEST_ALIGNMENT : (ALIGN))
+*/
+
+/* One use of this macro is to increase alignment of medium-size
+ data to make it all fit in fewer cache lines. Another is to
+ cause character arrays to be word-aligned so that `strcpy' calls
+ that copy constants to character arrays can be done inline. */
+/*
+#define DATA_ALIGNMENT(TYPE, ALIGN) \
+ ((((ALIGN) < FASTEST_ALIGNMENT) \
+ && (TREE_CODE (TYPE) == ARRAY_TYPE \
+ || TREE_CODE (TYPE) == UNION_TYPE \
+ || TREE_CODE (TYPE) == RECORD_TYPE)) ? FASTEST_ALIGNMENT : (ALIGN))
+*/ /* CHECK - btw code gets bigger with this one */
+#define DATA_ALIGNMENT(TYPE, ALIGN) \
+ ((ALIGN) < FASTEST_ALIGNMENT \
+ ? or1k_data_alignment ((TYPE), (ALIGN)) : (ALIGN))
+
+#define LOCAL_ALIGNMENT(TYPE, ALIGN) \
+ ((ALIGN) < FASTEST_ALIGNMENT \
+ ? or1k_data_alignment ((TYPE), (ALIGN)) : (ALIGN))
+
+/* Define this if move instructions will actually fail to work
+ when given unaligned data. */
+#define STRICT_ALIGNMENT 1 /* CHECK */
+
+/* Align an address */
+#define OR1K_ALIGN(n,a) (((n) + (a) - 1) & ~((a) - 1))
+
+/* Define if operations between registers always perform the operation
+ on the full register even if a narrower mode is specified. */
+#define WORD_REGISTER_OPERATIONS /* CHECK */
+
+
+/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD
+ will either zero-extend or sign-extend. The value of this macro should
+ be the code that says which one of the two operations is implicitly
+ done, NIL if none. */
+#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
+
+/* Define this macro if it is advisable to hold scalars in registers
+ in a wider mode than that declared by the program. In such cases,
+ the value is constrained to be within the bounds of the declared
+ type, but kept valid in the wider mode. The signedness of the
+ extension may differ from that of the type. */
+#define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \
+ if (GET_MODE_CLASS (MODE) == MODE_INT \
+ && GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \
+ (MODE) = SImode;
+ /* CHECK */
+
+
+/*
+ * brings 0.4% improvment in static size for linux
+ *
+#define PROMOTE_FOR_CALL_ONLY
+*/
+
+/* Define this macro if it is as good or better to call a constant
+ function address than to call an address kept in a register. */
+#define NO_FUNCTION_CSE 1 /* check */
+
+/* Standard register usage. */
+
+/* Number of actual hardware registers.
+ The hardware registers are assigned numbers for the compiler
+ from 0 to just below FIRST_PSEUDO_REGISTER.
+ All registers that the compiler knows about must be given numbers,
+ even those that are not normally considered general registers. */
+
+#define OR1K_LAST_ACTUAL_REG 31
+#define ARG_POINTER_REGNUM (OR1K_LAST_ACTUAL_REG + 1)
+#define FRAME_POINTER_REGNUM (ARG_POINTER_REGNUM + 1)
+#define OR1K_LAST_INT_REG FRAME_POINTER_REGNUM
+#define OR1K_FLAGS_REG (OR1K_LAST_INT_REG + 1)
+#define FIRST_PSEUDO_REGISTER (OR1K_FLAGS_REG + 1)
+
+/* 1 for registers that have pervasive standard uses
+ and are not available for the register allocator.
+ On the or1k, these are r1 as stack pointer and
+ r2 as frame/arg pointer. r9 is link register, r0
+ is zero, r10 is linux thread and r16 is got pointer */
+#define FIXED_REGISTERS { \
+ 1, 1, 0, 0, 0, 0, 0, 0, \
+ 0, 1, 1, 0, 0, 0, 0, 0, \
+ 1, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1 }
+/* 1 for registers not available across function calls.
+ These must include the FIXED_REGISTERS and also any
+ registers that can be used without being saved.
+ The latter must include the registers where values are returned
+ and the register where structure-value addresses are passed.
+ Aside from that, you can include as many other registers as you like. */
+#define CALL_USED_REGISTERS { \
+ 1, 1, 0, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 0, 1, \
+ 1, 1, 0, 1, 0, 1, 0, 1, \
+ 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1}
+
+/* stack pointer: must be FIXED and CALL_USED */
+/* hard frame pointer: must be call saved. */
+/* soft frame pointer / arg pointer: must be FIXED and CALL_USED */
+
+/* Return number of consecutive hard regs needed starting at reg REGNO
+ to hold something of mode MODE.
+ This is ordinarily the length in words of a value of mode MODE
+ but can be less for certain modes in special long registers.
+ On the or1k, all registers are one word long. */
+#define HARD_REGNO_NREGS(REGNO, MODE) \
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */
+#define HARD_REGNO_MODE_OK(REGNO, MODE) 1
+
+/* Value is 1 if it is a good idea to tie two pseudo registers
+ when one has mode MODE1 and one has mode MODE2.
+ If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
+ for any hard reg, then this must be 0 for correct output. */
+#define MODES_TIEABLE_P(MODE1, MODE2) 1
+
+/* A C expression for the cost of moving data of mode mode from a register in
+ class "from" to one in class "to". The classes are expressed using the
+ enumeration values such as GENERAL_REGS. A value of 2 is the default; other
+ values are interpreted relative to that.
+
+ It is not required that the cost always equal 2 when "from" is the same as
+ "to"; on some machines it is expensive to move between registers if they are
+ not general registers.
+
+ If reload sees an insn consisting of a single set between two hard
+ registers, and if REGISTER_MOVE_COST applied to their classes returns a
+ value of 2, reload does not check to ensure that the constraints of the
+ insn are met. Setting a cost of other than 2 will allow reload to verify
+ that the constraints are met. You should do this if the "movm" pattern's
+ constraints do not allow such copying.
+
+ JPB 31-Aug-10: This is just the default. */
+#define REGISTER_MOVE_COST(mode, from, to) 2
+
+/* A C expression for the cost of moving data of mode mode between a register
+ of class "class" and memory; "in" is zero if the value is to be written to
+ memory, nonzero if it is to be read in. This cost is relative to those in
+ REGISTER_MOVE_COST. If moving between registers and memory is more
+ expensive than between two registers, you should define this macro to
+ express the relative cost.
+
+ If you do not define this macro, GCC uses a default cost of 4 plus the cost
+ of copying via a secondary reload register, if one is needed. If your
+ machine requires a secondary reload register to copy between memory and a
+ register of class but the reload mechanism is more complex than copying via
+ an intermediate, define this macro to reflect the actual cost of the move.
+
+ GCC defines the function "memory_move_secondary_cost" if secondary reloads
+ are needed. It computes the costs due to copying via a secondary
+ register. If your machine copies from memory using a secondary register in
+ the conventional way but the default base value of 4 is not correct for
+ your machine, define this macro to add some other value to the result of
+ that function. The arguments to that function are the same as to this
+ macro.
+
+ JPB 31-Aug-10. Is this really correct? I suppose the OR1K only takes one
+ cycle, notionally, to access memory, but surely that will
+ often stall the pipeline. Needs more investigation. */
+#define MEMORY_MOVE_COST(mode, class, in) 2
+
+/* A C expression for the cost of a branch instruction. A value of 1 is the
+ default; other values are interpreted relative to that. Parameter "speed_p"
+ is TRUE when the branch in question should be optimized for speed. When it
+ is FALSE, BRANCH_COST should be returning value optimal for code size
+ rather then performance considerations. "predictable_p" is true for well
+ predictable branches. On many architectures the BRANCH_COST can be reduced
+ then.
+
+ JPB 31-Aug-10. The original code had the comment that "... this should
+ specify the cost of a branch insn; roughly the number of
+ extra insns that should be added to avoid a branch.
+
+ Set this to 3 on the or1k since that is roughly the average
+ cost of an unscheduled conditional branch.
+
+ Cost of 2 and 3 give equal and ~0.7% bigger binaries
+ respectively."
+
+ This seems ad-hoc. Probably we need some experiments. */
+#define BRANCH_COST(speed_p, predictable_p) 2
+
+/* Specify the registers used for certain standard purposes.
+ The values of these macros are register numbers. */
+
+/* Register to use for pushing function arguments. */
+#define STACK_POINTER_REGNUM 1
+
+/* Base register for access to local variables of the function. */
+#define HARD_FRAME_POINTER_REGNUM 2
+
+/* Link register. */
+#define LINK_REGNUM 9
+
+/* Register in which static-chain is passed to a function. */
+
+#define STATIC_CHAIN_REGNUM 11
+
+#define PROLOGUE_TMP 13
+#define EPILOGUE_TMP 3
+
+/* Register in which address to store a structure value
+ is passed to a function. */
+/*#define STRUCT_VALUE_REGNUM 0*/
+
+/* Pass address of result struct to callee as "invisible" first argument */
+#define STRUCT_VALUE 0
+
+/* -----------------------[ PHX start ]-------------------------------- */
+
+/* Define the classes of registers for register constraints in the
+ machine description. Also define ranges of constants.
+
+ One of the classes must always be named ALL_REGS and include all hard regs.
+ If there is more than one class, another class must be named NO_REGS
+ and contain no registers.
+
+ The name GENERAL_REGS must be the name of a class (or an alias for
+ another name such as ALL_REGS). This is the class of registers
+ that is allowed by "g" or "r" in a register constraint.
+ Also, registers outside this class are allocated only when
+ instructions express preferences for them.
+
+ GENERAL_REGS and BASE_REGS classess are the same on or1k.
+
+ The classes must be numbered in nondecreasing order; that is,
+ a larger-numbered class must never be contained completely
+ in a smaller-numbered class.
+
+ For any two classes, it is very desirable that there be another
+ class that represents their union. */
+
+/* The or1k has only one kind of registers, so NO_REGS, GENERAL_REGS
+ and ALL_REGS are the only classes. */
+/* JPB 26-Aug-10: Based on note from Mikhael (mirekez@gmail.com), we don't
+ need CR_REGS and it is in the wrong place for later things! */
+enum reg_class
+{
+ NO_REGS,
+ GENERAL_REGS,
+ ALL_REGS,
+ LIM_REG_CLASSES
+};
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+/* Give names of register classes as strings for dump file. */
+#define REG_CLASS_NAMES \
+{ \
+ "NO_REGS", \
+ "GENERAL_REGS", \
+ "ALL_REGS" \
+}
+
+/* Define which registers fit in which classes. This is an initializer for a
+ vector of HARD_REG_SET of length N_REG_CLASSES.
+
+ An initializer containing the contents of the register classes, as integers
+ which are bit masks. The Nth integer specifies the contents of class N.
+ The way the integer MASK is interpreted is that register R is in the class
+ if `MASK & (1 << R)' is 1.
+
+ When the machine has more than 32 registers, an integer does not suffice.
+ Then the integers are replaced by sub-initializers, braced groupings
+ containing several integers. Each sub-initializer must be suitable as an
+ initializer for the type `HARD_REG_SET' which is defined in
+ `hard-reg-set.h'.
+
+ For the OR1K we have the minimal set. GENERAL_REGS is all except r0, which
+ it permanently zero. */
+#define REG_CLASS_CONTENTS \
+ { \
+ { 0x00000000, 0x00000000 }, /* NO_REGS */ \
+ { 0xffffffff, 0x00000003 }, /* GENERAL_REGS */ \
+ { 0xffffffff, 0x00000007 } /* ALL_REGS */ \
+ }
+
+/* The same information, inverted:
+
+ Return the class number of the smallest class containing reg number REGNO.
+ This could be a conditional expression or could index an array.
+
+ ??? 0 is not really a register, but a constant. */
+#define REGNO_REG_CLASS(regno) \
+ ((0 == regno) ? ALL_REGS : ((1 <= regno) && (regno <= OR1K_LAST_INT_REG)) \
+ ? GENERAL_REGS : NO_REGS)
+
+/* The class value for index registers, and the one for base regs. */
+#define INDEX_REG_CLASS GENERAL_REGS
+#define BASE_REG_CLASS GENERAL_REGS
+
+/* Given an rtx X being reloaded into a reg required to be in class CLASS,
+ return the class of reg to actually use. In general this is just CLASS;
+ but on some machines in some cases it is preferable to use a more
+ restrictive class. */
+#define PREFERRED_RELOAD_CLASS(X,CLASS) (CLASS)
+
+/* Return the maximum number of consecutive registers needed to represent mode
+ MODE in a register of class CLASS.
+
+ On the or1k, this is always the size of MODE in words, since all registers
+ are the same size. */
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+
+/* -------------------------------------------------------------------------- */
+/* Stack layout; function entry, exit and calling. */
+
+/* Define this if pushing a word on the stack makes the stack pointer a
+ smaller address. */
+#define STACK_GROWS_DOWNWARD 1
+
+/* Define this if the nominal address of the stack frame is at the
+ high-address end of the local variables; that is, each additional local
+ variable allocated goes at a more negative offset in the frame. */
+#define FRAME_GROWS_DOWNWARD 1
+
+/* Offset within stack frame to start allocating local variables at. If
+ FRAME_GROWS_DOWNWARD, this is the offset to the END of the first local
+ allocated. Otherwise, it is the offset to the BEGINNING of the first local
+ allocated. */
+#define STARTING_FRAME_OFFSET 0
+
+/* Offset of first parameter from the argument pointer register value. */
+#define FIRST_PARM_OFFSET(FNDECL) 0
+
+/* Define this if stack space is still allocated for a parameter passed
+ in a register. The value is the number of bytes allocated to this
+ area.
+
+ No such allocation for OR1K. */
+/* #define REG_PARM_STACK_SPACE(FNDECL) (UNITS_PER_WORD * GP_ARG_NUM_REG) */
+
+/* Define this if the above stack space is to be considered part of the
+ space allocated by the caller.
+
+ N/a for OR1K. */
+/* #define OUTGOING_REG_PARM_STACK_SPACE */
+
+/* Define this macro if `REG_PARM_STACK_SPACE' is defined, but the
+ stack parameters don't skip the area specified by it.
+
+ N/a for OR1K. */
+/* #define STACK_PARMS_IN_REG_PARM_AREA */
+
+/* If nonzero, the maximum amount of space required for outgoing arguments
+ will be computed and placed into the variable
+ current_function_outgoing_args_size. No space will be pushed onto the stack
+ for each call; instead, the function prologue should increase the stack
+ frame size by this amount.
+
+ Setting both PUSH_ARGS and ACCUMULATE_OUTGOING_ARGS is not proper.
+
+ This is the approached used by OR1K. */
+#define ACCUMULATE_OUTGOING_ARGS 1
+
+#define ELIMINABLE_REGS \
+{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
+
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
+ (OFFSET) = or1k_initial_elimination_offset ((FROM), (TO))
+
+/* Minimum and maximum general purpose registers used to hold arguments. */
+#define GP_ARG_MIN_REG 3
+#define GP_ARG_MAX_REG 8
+#define GP_ARG_NUM_REG (GP_ARG_MAX_REG - GP_ARG_MIN_REG + 1)
+
+/* Return register */
+#define GP_ARG_RETURN 11
+#define GP_ARG_RETURNH 12
+
+/* TLS thread pointer register */
+#define THREAD_PTR_REGNUM 10
+
+/* Position Independent Code. */
+
+#define PIC_OFFSET_TABLE_REGNUM 16
+
+/* A C expression that is nonzero if X is a legitimate immediate
+ operand on the target machine when generating position independent code.
+ You can assume that X satisfies CONSTANT_P, so you need not
+ check this. You can also assume `flag_pic' is true, so you need not
+ check it either. You need not define this macro if all constants
+ (including SYMBOL_REF) can be immediate operands when generating
+ position independent code. */
+#define LEGITIMATE_PIC_OPERAND_P(X) or1k_legitimate_pic_operand_p (X)
+
+/* A C expression to create an RTX representing the place where a library
+ function returns a value of mode mode.
+
+ Note that “library function” in this context means a compiler support
+ routine, used to perform arithmetic, whose name is known specially by the
+ compiler and was not mentioned in the C code being compiled.
+
+ For the OR1K, return value is in R11 (GP_ARG_RETURN). */
+#define LIBCALL_VALUE(mode) \
+ gen_rtx_REG( \
+ ((GET_MODE_CLASS (mode) != MODE_INT \
+ || GET_MODE_SIZE (mode) >= 4) \
+ ? (mode) \
+ : SImode), \
+ GP_ARG_RETURN)
+
+/* Define this if PCC uses the nonreentrant convention for returning
+ structure and union values.
+
+ Not needed for OR1K. */
+/*#define PCC_STATIC_STRUCT_RETURN */
+
+/* A C expression that is nonzero if regno is the number of a hard register in
+ which the values of called function may come back.
+
+ A register whose use for returning values is limited to serving as the
+ second of a pair (for a value of type double, say) need not be recognized
+ by this macro. So for most machines, this definition suffices:
+
+ #define FUNCTION_VALUE_REGNO_P(N) ((N) == 0)
+
+ If the machine has register windows, so that the caller and the called
+ function use different registers for the return value, this macro should
+ recognize only the caller's register numbers.
+
+ For OR1K, we must check if we have the return register.
+
+ From GCC 4.6, this will be replaced by TARGET_FUNCION_VALUE_REGNO_P target
+ hook function. */
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == GP_ARG_RETURN)
+
+/* 1 if N is a possible register number for function argument passing. */
+#define FUNCTION_ARG_REGNO_P(N) \
+ ((N) >= GP_ARG_MIN_REG && (N) <= GP_ARG_MAX_REG)
+
+/* A code distinguishing the floating point format of the target
+ machine. There are three defined values: IEEE_FLOAT_FORMAT,
+ VAX_FLOAT_FORMAT, and UNKNOWN_FLOAT_FORMAT. */
+#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
+#define FLOAT_WORDS_BIG_ENDIAN 1
+
+/* A C type for declaring a variable that is used as the first argument of
+ FUNCTION_ARG and other related values. For some target machines, the type
+ int suffices and can hold the number of bytes of argument so far.
+
+ There is no need to record in CUMULATIVE_ARGS anything about the arguments
+ that have been passed on the stack. The compiler has other variables to
+ keep track of that. For target machines on which all arguments are passed
+ on the stack, there is no need to store anything in CUMULATIVE_ARGS;
+ however, the data structure must exist and should not be empty, so use
+ int. */
+#define CUMULATIVE_ARGS int
+
+/* A C statement (sans semicolon) for initializing the variable "cum" for the
+ state at the beginning of the argument list. The variable has type
+ CUMULATIVE_ARGS. The value of "fntype" is the tree node for the data type
+ of the function which will receive the args, or 0 if the args are to a
+ compiler support library function. For direct calls that are not libcalls,
+ "fndecl" contain the declaration node of the function. "fndecl" is also set
+ when INIT_CUMULATIVE_ARGS is used to find arguments for the function being
+ compiled. "n_named_args" is set to the number of named arguments,
+ including a structure return address if it is passed as a parameter, when
+ making a call. When processing incoming arguments, "n_named_args" is set to
+ −1.
+
+ When processing a call to a compiler support library function, "libname"
+ identifies which one. It is a symbol_ref rtx which contains the name of the
+ function, as a string. "libname" is 0 when an ordinary C function call is
+ being processed. Thus, each time this macro is called, either "libname" or
+ "fntype" is nonzero, but never both of them at once.
+
+ For the OR1K, we set "cum" to zero each time.
+ JPB 29-Aug-10: Is this correct? */
+#define INIT_CUMULATIVE_ARGS(cum, fntype, libname, fndecl, n_named_args) \
+ (cum = 0)
+
+/* -------------------------------------------------------------------------- */
+/* Define intermediate macro to compute the size (in registers) of an argument
+ for the or1k.
+
+ The OR1K_ROUND_ADVANCE* macros are local to this file. */
+
+/* Round "size" up to a word boundary. */
+#define OR1K_ROUND_ADVANCE(size) \
+ (((size) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* Round arg "mode"/"type" up to the next word boundary. */
+#define OR1K_ROUND_ADVANCE_ARG(mode, type) \
+ ((mode) == BLKmode \
+ ? OR1K_ROUND_ADVANCE (int_size_in_bytes (type)) \
+ : OR1K_ROUND_ADVANCE (GET_MODE_SIZE (mode)))
+
+/* The ABI says that no rounding to even or odd words takes place. */
+#define OR1K_ROUND_ADVANCE_CUM(cum, mode, type) (cum)
+
+/* Return boolean indicating if arg of type "type" and mode "mode" will be
+ passed in a reg. This includes arguments that have to be passed by
+ reference as the pointer to them is passed in a reg if one is available
+ (and that is what we're given).
+
+ When passing arguments "named" is always 1. When receiving arguments
+ "named" is 1 for each argument except the last in a stdarg/varargs
+ function. In a stdarg function we want to treat the last named arg as
+ named. In a varargs function we want to treat the last named arg (which is
+ `__builtin_va_alist') as unnamed.
+
+ This macro is only used in this file. */
+#define OR1K_PASS_IN_REG_P(cum, mode, type, named) \
+ ((named) \
+ && ((OR1K_ROUND_ADVANCE_CUM ((cum), (mode), (type)) \
+ + OR1K_ROUND_ADVANCE_ARG ((mode), (type)) \
+ <= GP_ARG_NUM_REG)))
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry. */
+#define FUNCTION_PROFILER(FILE, LABELNO)
+
+/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, the
+ stack pointer does not matter. The value is tested only in functions that
+ have frame pointers. No definition is equivalent to always zero.
+
+ The default suffices for OR1K. */
+#define EXIT_IGNORE_STACK 0
+
+/* A C expression whose value is RTL representing the location of the
+ incoming return address at the beginning of any function, before the
+ prologue. This RTL is either a REG, indicating that the return
+ value is saved in REG, or a MEM representing a location in
+ the stack. */
+#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, LINK_REGNUM)
+
+#define RETURN_ADDR_RTX or1k_return_addr_rtx
+
+/* Addressing modes, and classification of registers for them. */
+
+/* #define HAVE_POST_INCREMENT */
+/* #define HAVE_POST_DECREMENT */
+
+/* #define HAVE_PRE_DECREMENT */
+/* #define HAVE_PRE_INCREMENT */
+
+/* Macros to check register numbers against specific register classes. */
+#define MAX_REGS_PER_ADDRESS 1
+
+/* True if X is an rtx for a constant that is a valid address.
+
+ JPB 29-Aug-10: Why is the default implementation not OK? */
+#define CONSTANT_ADDRESS_P(X) \
+ (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
+ || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \
+ || GET_CODE (X) == HIGH)
+
+/* A C expression which is nonzero if register number num is suitable for use
+ as a base register in operand addresses. Like TARGET_LEGITIMATE_ADDRESS_P,
+ this macro should also define a strict and a non-strict variant. Both
+ variants behave the same for hard register; for pseudos, the strict variant
+ will pass only those that have been allocated to a valid hard registers,
+ while the non-strict variant will pass all pseudos.
+
+ Compiler source files that want to use the strict variant of this and other
+ macros define the macro REG_OK_STRICT. You should use an #ifdef
+ REG_OK_STRICT conditional to define the strict variant in that case and the
+ non-strict variant otherwise.
+
+ JPB 29-Aug-10: This has been conflated with the old REG_OK_FOR_BASE_P
+ function, which is no longer part of GCC.
+
+ I'm not sure this is right. r0 can be a base register, just
+ it can't get set by the user. */
+#ifdef REG_OK_STRICT
+#define REGNO_OK_FOR_BASE_P(num) \
+ ( ((0 < (num)) && ((num) <= OR1K_LAST_INT_REG)) \
+ || ((0 < reg_renumber[num]) && (reg_renumber[num] <= OR1K_LAST_INT_REG)))
+
+#else
+/* Accept an int register or a pseudo reg.
+
+ JPB 1-Sep-10: Should this allow r0, if the strict version does not? */
+#define REGNO_OK_FOR_BASE_P(num) ((num) <= OR1K_LAST_INT_REG || \
+ (num) >= FIRST_PSEUDO_REGISTER)
+#endif
+
+/* OR1K doesn't have any indexed addressing. */
+#define REG_OK_FOR_INDEX_P(X) 0
+#define REGNO_OK_FOR_INDEX_P(X) 0
+
+
+/* Specify the machine mode that this machine uses for the index in the
+ tablejump instruction. */
+#define CASE_VECTOR_MODE SImode
+
+/* Define as C expression which evaluates to nonzero if the tablejump
+ instruction expects the table to contain offsets from the address of the
+ table.
+
+ Do not define this if the table should contain absolute addresses. */
+/* #define CASE_VECTOR_PC_RELATIVE 1 */
+
+/* Define this as 1 if `char' should by default be signed; else as 0. */
+#define DEFAULT_SIGNED_CHAR 1
+
+/* The maximum number of bytes that a single instruction can move quickly
+ between memory and registers or between two memory locations. */
+#define MOVE_MAX 4
+
+/* Define this if zero-extension is slow (more than one real instruction). */
+/* #define SLOW_ZERO_EXTEND */
+
+/* Nonzero if access to memory by bytes is slow and undesirable.
+ For RISC chips, it means that access to memory by bytes is no
+ better than access by words when possible, so grab a whole word
+ and maybe make use of that. */
+#define SLOW_BYTE_ACCESS 1
+
+/* Define if shifts truncate the shift count
+ which implies one can omit a sign-extension or zero-extension
+ of a shift count. */
+/* #define SHIFT_COUNT_TRUNCATED */
+
+/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
+ is done just by pretending it is already truncated. */
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+
+/* Specify the machine mode that pointers have.
+ After generation of rtl, the compiler makes no further distinction
+ between pointers and any other objects of this machine mode. */
+#define Pmode SImode
+
+/* A function address in a call instruction
+ is a byte address (for indexing purposes)
+ so give the MEM rtx a byte's mode. */
+#define FUNCTION_MODE SImode
+
+
+/* -------------------------------------------------------------------------- */
+/* Condition code stuff */
+
+/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
+ return the mode to be used for the comparison. */
+#define SELECT_CC_MODE(op, x, y) or1k_select_cc_mode(op)
+
+/* Can the condition code MODE be safely reversed? This is safe in
+ all cases on this port, because at present it doesn't use the
+ trapping FP comparisons (fcmpo). */
+#define REVERSIBLE_CC_MODE(mode) 1
+
+/* Given a condition code and a mode, return the inverse condition.
+
+ JPB 31-Aug-10: This seems like the default. Do we even need this? */
+#define REVERSE_CONDITION(code, mode) reverse_condition (code)
+
+
+/* -------------------------------------------------------------------------- */
+/* Control the assembler format that we output. */
+
+/* A C string constant describing how to begin a comment in the target
+ assembler language. The compiler assumes that the comment will end at
+ the end of the line. */
+#define ASM_COMMENT_START "#"
+
+/* Output to assembler file text saying following lines may contain character
+ constants, extra white space, comments, etc.
+
+ JPB 29-Aug-10: Default would seem to be OK here. */
+#define ASM_APP_ON "#APP\n"
+
+/* Output to assembler file text saying following lines no longer contain
+ unusual constructs.
+
+ JPB 29-Aug-10: Default would seem to be OK here. */
+#define ASM_APP_OFF "#NO_APP\n"
+
+/* Switch to the text or data segment. */
+
+/* Output before read-only data. */
+#define TEXT_SECTION_ASM_OP "\t.section .text"
+
+/* Output before writable data. */
+#define DATA_SECTION_ASM_OP "\t.section .data"
+
+/* Output before uninitialized data. */
+#define BSS_SECTION_ASM_OP "\t.section .bss"
+
+/* How to refer to registers in assembler output. This sequence is indexed by
+ compiler's hard-register-number (see above). */
+#define REGISTER_NAMES \
+ {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", \
+ "argp", "frame", "cc-flag"}
+
+
+/* -------------------------------------------------------------------------- */
+/* Debug things for DBX (STABS) */
+/* */
+/* Note. Our config.gcc includes dbxelf.h, which sets up appropriate */
+/* defaults. Choice of which debug format to use is in our elf.h */
+/* -------------------------------------------------------------------------- */
+
+/* Don't try to use the type-cross-reference character in DBX data.
+ Also has the consequence of putting each struct, union or enum
+ into a separate .stabs, containing only cross-refs to the others. */
+/* JPB 24-Aug-10: Is this really correct. Can't GDB use this info? */
+#define DBX_NO_XREFS
+
+/* -------------------------------------------------------------------------- */
+/* Debug things for DWARF2 */
+/* */
+/* Note. Choice of which debug format to use is in our elf.h */
+/* -------------------------------------------------------------------------- */
+
+/* We support frame unwind info including for exceptions handling. This needs
+ INCOMING_RETURN_ADDR_RTX to be set and OBJECT_FORMAT_ELF to be defined (in
+ elfos.h). Override any default value. */
+#undef DWARF2_UNWIND_INFO
+#define DWARF2_UNWIND_INFO 1
+
+/* We want frame info produced. Note that this is superfluous if
+ DWARF2_UNWIND_INFO is non-zero, but we set so this so, we can produce frame
+ info even when it is zero. Override any default value. */
+#undef DWARF2_FRAME_INFO
+#define DWARF2_FRAME_INFO 1
+
+/* Macro specifying which register holds the return address */
+#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (LINK_REGNUM)
+
+/* Where is the start of our stack frame in relation to the end of the
+ previous stack frame at the start of a function, before the prologue */
+#define INCOMING_FRAME_SP_OFFSET 0
+
+/* Use compact debug tables. Generates .file/.loc directives. */
+#undef DWARF2_ASM_LINE_DEBUG_INFO
+#define DWARF2_ASM_LINE_DEBUG_INFO 1
+
+/* We don't need an alternative return address for now. */
+/* DWARF_ALT_FRAME_RETURN_COLUMN */
+
+/* We always save registers in the prologue with word alignment, so don't
+ need this. */
+/* DWARF_CIE_DATA_ALIGNMENT */
+
+/* This specifies the maximum number of registers we can save in a frame. We
+ could note that only SP, FP, LR, arg regs and callee saved regs come into
+ this category. However this is only an efficiency thing, so for now we
+ don't use it. */
+/* DWARF_FRAME_REGISTERS */
+
+/* This specifies a mapping from register numbers in .dwarf_frame to
+ .eh_frame. However for us they are the same, so we don't need it. */
+/* DWARF_FRAME_REGNUM */
+
+/* Defined if the DWARF column numbers do not match register numbers. For us
+ they do, so this is not needed. */
+/* DWARF_REG_TO_UNWIND_COLUMN */
+
+/* Can be used to define a register guaranteed to be zero. Only useful if zero
+ is used to terminate backtraces, and not recommended for new ports, so we
+ don't use it. */
+/* DWARF_ZERO_REG */
+
+/* This is the inverse function for DWARF_FRAME_REGNUM. Again not needed. */
+/* DWARF2_FRAME_REG_OUT */
+
+
+/* -------------------------------------------------------------------------- */
+/* Node: Label Output */
+
+/* Globalizing directive for a label. */
+#define GLOBAL_ASM_OP "\t.global "
+
+#define SUPPORTS_WEAK 1
+
+/* This is how to output the definition of a user-level label named NAME,
+ such as the label on a static function or variable NAME. */
+#define ASM_OUTPUT_LABEL(FILE,NAME) \
+ { assemble_name (FILE, NAME); fputs (":\n", FILE); }
+
+/* We use -fleading-underscore to add it, when necessary.
+ JPB: No prefix for global symbols */
+#define USER_LABEL_PREFIX ""
+
+/* Remove any previous definition (elfos.h). */
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
+ sprintf (LABEL, "*%s%d", PREFIX, NUM)
+
+/* This is how to output an assembler line defining an int constant. */
+#define ASM_OUTPUT_INT(stream, value) \
+ { \
+ fprintf (stream, "\t.word\t"); \
+ output_addr_const (stream, (value)); \
+ fprintf (stream, "\n")}
+
+/* This is how to output an assembler line defining a float constant. */
+#define ASM_OUTPUT_FLOAT(stream, value) \
+ { long l; \
+ REAL_VALUE_TO_TARGET_SINGLE (value,l); \
+ fprintf(stream,"\t.word\t0x%08x\t\t# float %26.7e\n", l, value); }
+
+/* This is how to output an assembler line defining a double constant. */
+#define ASM_OUTPUT_DOUBLE(stream, value) \
+ { long l[2]; \
+ REAL_VALUE_TO_TARGET_DOUBLE (value,&l[0]); \
+ fprintf(stream,"\t.word\t0x%08x,0x%08x\t# float %26.16le\n", \
+ l[0],l[1],value); }
+
+/* This is how to output an assembler line defining a long double constant.
+
+ JPB 29-Aug-10: Do we really mean this. I thought long double on OR1K was
+ the same as double. */
+#define ASM_OUTPUT_LONG_DOUBLE(stream, value) \
+ { long l[4]; \
+ REAL_VALUE_TO_TARGET_DOUBLE (value,&l[0]); \
+ fprintf (stream, \
+ "\t.word\t0x%08x,0x%08x,0x%08x,0x%08x\t# float %26.18lle\n", \
+ l[0],l[1],l[2],l[3],value); }
+
+/* This is how to output an assembler line defining a short constant. */
+#define ASM_OUTPUT_SHORT(stream, value) \
+ { fprintf (stream, "\t.half\t"); \
+ output_addr_const (stream, (value)); \
+ fprintf (stream, "\n"); }
+
+/* This is how to output an assembler line defining a char constant. */
+#define ASM_OUTPUT_CHAR(stream, value) \
+ { fprintf (stream, "\t.byte\t"); \
+ output_addr_const (stream, (value)); \
+ fprintf (stream, "\n")}
+
+/* This is how to output an assembler line for a numeric constant byte. */
+#define ASM_OUTPUT_BYTE(stream, value) \
+ fprintf (stream, "\t.byte\t0x%02x\n", (value))
+
+/* This is how to output an insn to push a register on the stack.
+ It need not be very fast code.
+
+ JPB 29-Aug-10: This was using l.sub (since we don't have l.subi), so it
+ was potty code. Replaced by adding immediate -1. */
+#define ASM_OUTPUT_REG_PUSH(stream, regno) \
+ { fprintf (stream, "\tl.addi\tr1,r1,-4\n"); \
+ fprintf (stream, "\tl.sw\t0(r1),%s\n", reg_names[regno]); }
+
+/* This is how to output an insn to pop a register from the stack.
+ It need not be very fast code. */
+#define ASM_OUTPUT_REG_POP(stream,REGNO) \
+ { fprintf (stream, "\tl.lwz\t%s,0(r1)\n", reg_names[REGNO]); \
+ fprintf (stream, "\tl.addi\tr1,r1,4\n"); }
+
+/* This is how to output an element of a case-vector that is absolute.
+ (The Vax does not use such vectors,
+ but we must define this macro anyway.) */
+#define ASM_OUTPUT_ADDR_VEC_ELT(stream, value) \
+ fprintf (stream, "\t.word\t.L%d\n", value)
+
+/* This is how to output an element of a case-vector that is relative. */
+#define ASM_OUTPUT_ADDR_DIFF_ELT(stream, body, value, rel) \
+ fprintf (stream, "\t.word\t.L%d-.L%d\n", value, rel)
+
+#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic)
+/* ??? If we were serious about PIC, we should also use l.jal to get
+ the table start address. */
+
+/* This is how to output an assembler line that says to advance the location
+ counter to a multiple of 2**log bytes. */
+#define ASM_OUTPUT_ALIGN(stream, log) \
+ if ((log) != 0) \
+ { \
+ fprintf (stream, "\t.align\t%d\n", 1 << (log)); \
+ }
+
+/* This is how to output an assembler line that says to advance the location
+ counter by "size" bytes. */
+#define ASM_OUTPUT_SKIP(stream, size) \
+ fprintf (stream, "\t.space %d\n", (size))
+
+/* Need to split up .ascii directives to avoid breaking
+ the linker. */
+
+/* This is how to output a string. */
+#define ASM_OUTPUT_ASCII(stream, ptr, len) \
+ output_ascii_pseudo_op (stream, (const unsigned char *) (ptr), len)
+
+/* Invoked just before function output. */
+#define ASM_OUTPUT_FUNCTION_PREFIX(stream, fnname) \
+ { fputs (".proc\t", stream); assemble_name (stream, fnname); \
+ fputs ("\n", stream); }
+
+/* This says how to output an assembler line to define a global common
+ symbol. */
+#define ASM_OUTPUT_COMMON(stream,name,size,rounded) \
+ { data_section (); \
+ fputs ("\t.global\t", stream); \
+ assemble_name(stream, name); \
+ fputs ("\n", stream); \
+ assemble_name (stream, name); \
+ fputs (":\n", stream); \
+ fprintf (stream, "\t.space\t%d\n", rounded); }
+
+/* This says how to output an assembler line to define a local common
+ symbol.
+
+ JPB 29-Aug-10: I'm sure this doesn't work - we don't have a .bss directive
+ like this. */
+#define ASM_OUTPUT_LOCAL(stream, name, size, rounded) \
+ { fputs ("\t.bss\t", (stream)); \
+ assemble_name ((stream), (name)); \
+ fprintf ((stream), ",%d,%d\n", (size), (rounded)); }
+
+/* This says how to output an assembler line to define a global common symbol
+ with size "size" (in bytes) and alignment "align" (in bits). */
+#define ASM_OUTPUT_ALIGNED_COMMON(stream, name, size, align) \
+ { data_section(); \
+ if ((ALIGN) > 8) \
+ { \
+ fprintf(stream, "\t.align %d\n", ((align) / BITS_PER_UNIT)); \
+ } \
+ fputs("\t.global\t", stream); assemble_name(stream, name); \
+ fputs("\n", stream); \
+ assemble_name(stream, name); \
+ fputs (":\n", stream); \
+ fprintf(stream, "\t.space\t%d\n", size); }
+
+/* This says how to output an assembler line to define a local common symbol
+ with size "size" (in bytes) and alignment "align" (in bits). */
+#define ASM_OUTPUT_ALIGNED_LOCAL(stream, name, size, align) \
+ { data_section(); \
+ if ((align) > 8) \
+ { \
+ fprintf(stream, "\t.align %d\n", ((align) / BITS_PER_UNIT)); \
+ } \
+ assemble_name(stream, name); \
+ fputs (":\n", stream); \
+ fprintf(stream, "\t.space %d\n", size); }
+
+/* Store in "output" a string (made with alloca) containing an assembler-name
+ for a local static variable named "name". "labelno" is an integer which is
+ different for each call. */
+#define ASM_FORMAT_PRIVATE_NAME(output, name, labelno) \
+ { (output) = (char *) alloca (strlen ((name)) + 10); \
+ sprintf ((output), "%s.%lu", (name), (unsigned long int) (labelno)); }
+
+/* Macro for %code validation. Returns nonzero if valid.
+
+ The acceptance of '(' is an idea taken from SPARC; output nop for %( if not
+ optimizing or the slot is not filled. */
+#define PRINT_OPERAND_PUNCT_VALID_P(code) (('(' == code) || ('%' == code))
+
+/* Print an instruction operand "x" on file "stream". "code" is the code from
+ the %-spec that requested printing this operand; if `%z3' was used to print
+ operand 3, then CODE is 'z'. */
+#define PRINT_OPERAND(stream, x, code) \
+{ \
+ if (code == 'r' \
+ && GET_CODE (x) == MEM \
+ && GET_CODE (XEXP (x, 0)) == REG) \
+ { \
+ fprintf (stream, "%s", reg_names[REGNO (XEXP (x, 0))]); \
+ } \
+ else if (code == '(') \
+ { \
+ if (TARGET_DELAY_ON && dbr_sequence_length ()) \
+ fprintf (stream, "\t# delay slot filled"); \
+ else if (!TARGET_DELAY_OFF) \
+ fprintf (stream, "\n\tl.nop\t\t\t# nop delay slot"); \
+ } \
+ else if (code == 'C') \
+ { \
+ switch (GET_CODE (x)) \
+ { \
+ case EQ: \
+ fputs ("eq", stream); \
+ break; \
+ case NE: \
+ fputs ("ne", stream); \
+ break; \
+ case GT: \
+ fputs ("gts", stream); \
+ break; \
+ case GE: \
+ fputs ("ges", stream); \
+ break; \
+ case LT: \
+ fputs ("lts", stream); \
+ break; \
+ case LE: \
+ fputs ("les", stream); \
+ break; \
+ case GTU: \
+ fputs ("gtu", stream); \
+ break; \
+ case GEU: \
+ fputs ("geu", stream); \
+ break; \
+ case LTU: \
+ fputs ("ltu", stream); \
+ break; \
+ case LEU: \
+ fputs ("leu", stream); \
+ break; \
+ default: \
+ abort (); \
+ } \
+ } \
+ else if (code == 'H') \
+ { \
+ if (GET_CODE (x) == REG) \
+ fprintf (stream, "%s", reg_names[REGNO (x) + 1]); \
+ else \
+ abort (); \
+ } \
+ else if (GET_CODE (x) == REG) \
+ fprintf (stream, "%s", reg_names[REGNO (x)]); \
+ else if (GET_CODE (x) == MEM) \
+ output_address (XEXP (x, 0)); \
+ else \
+ output_addr_const (stream, x); \
+}
+
+/* The size of the trampoline in bytes. This is a block of code followed by
+ two words specifying the function address and static chain pointer. */
+#define TRAMPOLINE_SIZE \
+ (or1k_trampoline_code_size () + GET_MODE_SIZE (ptr_mode) * 2)
+
+/* Alignment required for trampolines, in bits.
+
+ For the OR1K, there is no need for anything other than word alignment. */
+#define TRAMPOLINE_ALIGNMENT 32
+
+/* Assume that if the assembler supports thread local storage
+ * the system supports it. */
+#if !defined(TARGET_HAVE_TLS) && defined(HAVE_AS_TLS)
+#define TARGET_HAVE_TLS true
+#endif
+
+/* Describe how we implement __builtin_eh_return. */
+#define EH_RETURN_REGNUM 23
+/* Use r25, r27, r29 and r31 (clobber regs) for exception data */
+#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (25 + ((N)<<1)) : INVALID_REGNUM)
+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, EH_RETURN_REGNUM)
+#define EH_RETURN_HANDLER_RTX or1k_eh_return_handler_rtx ()
+
+#define INIT_EXPANDERS or1k_init_expanders ()
+
+/* A C structure for machine-specific, per-function data. This is
+ * added to the cfun structure. */
+typedef struct GTY(()) machine_function
+{
+ /* Force stack save of LR. Used in RETURN_ADDR_RTX. */
+ int force_lr_save;
+} machine_function;
+
+#endif /* _OR1K_H_ */
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/or1k.md gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k.md
--- gcc-4.8.2/gcc/config/or1k/or1k.md 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k.md 2014-03-14 07:27:49.000000000 +0200
@@ -0,0 +1,1426 @@
+;; Machine description for GNU compiler, OpenRISC 1000 family, OR32 ISA
+;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+;; 2009, 2010 Free Software Foundation, Inc.
+;; Copyright (C) 2010 Embecosm Limited
+
+;; Contributed by Damjan Lampret in 1999.
+;; Major optimizations by Matjaz Breskvar in 2005.
+;; Floating point additions by Jungsook Yang
+;; Julius Baxter in 2010
+;; Updated for GCC 4.5 by Jeremy Bennett
+;; and Joern Rennecke in 2010
+
+;; This file is part of GNU CC.
+
+;; This program is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by the Free
+;; Software Foundation; either version 3 of the License, or (at your option)
+;; any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+;; more details.
+;;
+;; You should have received a copy of the GNU General Public License along
+;; with this program. If not, see . */
+
+(define_constants [
+ (SP_REG 1)
+ (FP_REG 2) ; hard frame pointer
+ (CC_REG 34)
+
+ ;; unspec values
+ (UNSPEC_FRAME 0)
+ (UNSPEC_GOT 1)
+ (UNSPEC_GOTOFFHI 2)
+ (UNSPEC_GOTOFFLO 3)
+ (UNSPEC_TPOFFLO 4)
+ (UNSPEC_TPOFFHI 5)
+ (UNSPEC_GOTTPOFFLO 6)
+ (UNSPEC_GOTTPOFFHI 7)
+ (UNSPEC_GOTTPOFFLD 8)
+ (UNSPEC_TLSGDLO 9)
+ (UNSPEC_TLSGDHI 10)
+ (UNSPEC_SET_GOT 101)
+])
+
+(include "predicates.md")
+
+(include "constraints.md")
+
+(define_attr "type"
+ "unknown,load,store,move,extend,logic,add,mul,shift,compare,branch,jump,fp,jump_restore"
+ (const_string "unknown"))
+
+;; Number of machine instructions required to implement an insn.
+(define_attr "length" "" (const_int 1))
+
+;; Single delay slot after branch or jump instructions, wich may contain any
+;; instruction but another branch or jump.
+;; If TARGET_DELAY_OFF is not true, then never use delay slots.
+;; If TARGET_DELAY_ON is not true, no instruction will be allowed to
+;; fill the slot, and so it will be filled by a nop instead.
+(define_delay (and (match_test "!TARGET_DELAY_OFF") (eq_attr "type" "branch,jump"))
+ [(and (match_test "TARGET_DELAY_ON")
+ (eq_attr "type" "!branch,jump")
+ (eq_attr "length" "1")) (nil) (nil)])
+
+;; ALU is modelled as a single functional unit, which is reserved for varying
+;; numbers of slots.
+;;
+;; I think this is all incorrect for the OR1K. The latency says when the
+;; result will be ready, not how long the pipeline takes to execute.
+(define_cpu_unit "or1k_alu")
+(define_insn_reservation "bit_unit" 3 (eq_attr "type" "shift") "or1k_alu")
+(define_insn_reservation "lsu_load" 3 (eq_attr "type" "load") "or1k_alu*3")
+(define_insn_reservation "lsu_store" 2 (eq_attr "type" "store") "or1k_alu")
+(define_insn_reservation "alu_unit" 2
+ (eq_attr "type" "add,logic,extend,move,compare")
+ "or1k_alu")
+(define_insn_reservation "mul_unit" 16 (eq_attr "type" "mul") "or1k_alu*16")
+
+
+;; Called after register allocation to add any instructions needed for the
+;; prologue. Using a prologue insn is favored compared to putting all of the
+;; instructions in output_function_prologue(), since it allows the scheduler
+;; to intermix instructions with the saves of the caller saved registers. In
+;; some cases, it might be necessary to emit a barrier instruction as the last
+;; insn to prevent such scheduling.
+
+(define_expand "prologue"
+ [(use (const_int 1))]
+ ""
+{
+ or1k_expand_prologue ();
+ DONE;
+})
+
+;; Called after register allocation to add any instructions needed for the
+;; epilogue. Using an epilogue insn is favored compared to putting all of the
+;; instructions in output_function_epilogue(), since it allows the scheduler
+;; to intermix instructions with the restores of the caller saved registers.
+;; In some cases, it might be necessary to emit a barrier instruction as the
+;; first insn to prevent such scheduling.
+(define_expand "epilogue"
+ [(use (const_int 2))]
+ ""
+{
+ or1k_expand_epilogue ();
+ DONE;
+})
+
+(define_insn "frame_alloc_fp"
+ [(set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
+ (match_operand:SI 0 "nonmemory_operand" "r,I")))
+ (clobber (mem:QI (plus:SI (reg:SI FP_REG)
+ (unspec:SI [(const_int FP_REG)] UNSPEC_FRAME))))]
+ ""
+ "@
+ l.add\tr1,r1,%0\t# allocate frame
+ l.addi\tr1,r1,%0\t# allocate frame"
+ [(set_attr "type" "add")
+ (set_attr "length" "1")])
+
+(define_insn "frame_dealloc_fp"
+ [(set (reg:SI SP_REG) (reg:SI FP_REG))
+ (clobber (mem:QI (plus:SI (reg:SI FP_REG)
+ (unspec:SI [(const_int FP_REG)] UNSPEC_FRAME))))]
+ ""
+ "l.ori\tr1,r2,0\t# deallocate frame"
+ [(set_attr "type" "logic")
+ (set_attr "length" "1")])
+
+(define_insn "frame_dealloc_sp"
+ [(set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
+ (match_operand:SI 0 "nonmemory_operand" "r,I")))
+ (clobber (mem:QI (plus:SI (reg:SI SP_REG)
+ (unspec:SI [(const_int SP_REG)] UNSPEC_FRAME))))]
+ ""
+ "@
+ l.add\tr1,r1,%0
+ l.addi\tr1,r1,%0"
+ [(set_attr "type" "add")
+ (set_attr "length" "1")])
+
+(define_insn "return_internal"
+ [(return)
+ (use (match_operand 0 "pmode_register_operand" ""))]
+ ""
+ "l.jr \t%0\t# return_internal%("
+ [(set_attr "type" "jump")
+ (set_attr "length" "1")])
+
+
+
+;;
+;; movQI
+;;
+
+(define_expand "movqi"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (match_operand:QI 1 "general_operand" ""))]
+ ""
+ "
+ if (can_create_pseudo_p())
+ {
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ rtx reg = gen_reg_rtx (SImode);
+
+ emit_insn (gen_movsi (reg, operands[1]));
+ operands[1] = gen_lowpart (QImode, reg);
+ }
+ if (GET_CODE (operands[1]) == MEM && optimize > 0)
+ {
+ rtx reg = gen_reg_rtx (SImode);
+
+ emit_insn (gen_rtx_SET (SImode, reg,
+ gen_rtx_ZERO_EXTEND (SImode,
+ operands[1])));
+
+ operands[1] = gen_lowpart (QImode, reg);
+ }
+ if (GET_CODE (operands[0]) != REG)
+ operands[1] = force_reg (QImode, operands[1]);
+ }
+")
+
+(define_insn "*movqi_internal"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=m,r,r,r,r")
+ (match_operand:QI 1 "general_operand" "r,r,I,K,m"))]
+ ""
+ "@
+ l.sb \t%0,%1\t # movqi
+ l.ori \t%0,%1,0\t # movqi: move reg to reg
+ l.addi \t%0,r0,%1\t # movqi: move immediate
+ l.ori \t%0,r0,%1\t # movqi: move immediate
+ l.lbz \t%0,%1\t # movqi"
+ [(set_attr "type" "store,add,add,logic,load")])
+
+
+;;
+;; movHI
+;;
+
+(define_expand "movhi"
+ [(set (match_operand:HI 0 "general_operand" "")
+ (match_operand:HI 1 "general_operand" ""))]
+ ""
+ "
+ if (can_create_pseudo_p())
+ {
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ rtx reg = gen_reg_rtx (SImode);
+
+ emit_insn (gen_movsi (reg, operands[1]));
+ operands[1] = gen_lowpart (HImode, reg);
+ }
+ else if (GET_CODE (operands[1]) == MEM && optimize > 0)
+ {
+ rtx reg = gen_reg_rtx (SImode);
+
+ emit_insn (gen_rtx_SET (SImode, reg,
+ gen_rtx_ZERO_EXTEND (SImode,
+ operands[1])));
+ operands[1] = gen_lowpart (HImode, reg);
+ }
+ if (GET_CODE (operands[0]) != REG)
+ operands[1] = force_reg (HImode, operands[1]);
+ }
+")
+
+(define_insn "*movhi_internal"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=m,r,r,r,r")
+ (match_operand:HI 1 "general_operand" "r,r,I,K,m"))]
+ ""
+ "@
+ l.sh \t%0,%1\t # movhi
+ l.ori \t%0,%1,0\t # movhi: move reg to reg
+ l.addi \t%0,r0,%1\t # movhi: move immediate
+ l.ori \t%0,r0,%1\t # movhi: move immediate
+ l.lhz \t%0,%1\t # movhi"
+ [(set_attr "type" "store,add,add,logic,load")])
+
+(define_expand "movsi"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (match_operand:SI 1 "general_operand" ""))]
+ ""
+{
+ if (or1k_expand_move (SImode, operands)) DONE;
+})
+
+;;
+;; movSI
+;;
+
+(define_insn "*movsi_insn"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,m")
+ (match_operand:SI 1 "input_operand" "I,K,M,r,m,r"))]
+ "(register_operand (operands[0], SImode)
+ || (register_operand (operands[1], SImode))
+ || (operands[1] == const0_rtx))"
+ "@
+ l.addi \t%0,r0,%1\t # move immediate I
+ l.ori \t%0,r0,%1\t # move immediate K
+ l.movhi \t%0,hi(%1)\t # move immediate M
+ l.ori \t%0,%1,0\t # move reg to reg
+ l.lwz \t%0,%1\t # SI load
+ l.sw \t%0,%1\t # SI store"
+ [(set_attr "type" "add,load,store,add,logic,move")
+ (set_attr "length" "1,1,1,1,1,1")])
+
+(define_insn "movsi_lo_sum"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "immediate_operand" "i")))]
+ ""
+ "l.ori \t%0,%1,lo(%2) # movsi_lo_sum"
+ [(set_attr "type" "logic")
+ (set_attr "length" "1")])
+
+(define_insn "movsi_high"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (high:SI (match_operand:SI 1 "immediate_operand" "i")))]
+ ""
+ "l.movhi \t%0,hi(%1) # movsi_high"
+[(set_attr "type" "move")
+ (set_attr "length" "1")])
+
+(define_insn "movsi_gotofflo"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand 2 "" ""))] UNSPEC_GOTOFFLO))]
+ "flag_pic"
+ "l.ori \t%0,%1,gotofflo(%2) # movsi_gotofflo"
+ [(set_attr "type" "logic")
+ (set_attr "length" "1")])
+
+(define_insn "movsi_gotoffhi"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand 1 "" "")] UNSPEC_GOTOFFHI))]
+ "flag_pic"
+ "l.movhi \t%0,gotoffhi(%1) # movsi_gotoffhi"
+ [(set_attr "type" "move")
+ (set_attr "length" "1")])
+
+(define_insn "movsi_got"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand 1 "" "")] UNSPEC_GOT))
+ (use (reg:SI 16))]
+ "flag_pic"
+ "l.lwz \t%0, got(%1)(r16)"
+ [(set_attr "type" "load")]
+)
+
+(define_insn "movsi_tlsgdlo"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "immediate_operand" "i"))] UNSPEC_TLSGDLO))]
+ ""
+ "l.ori \t%0,%1,tlsgdlo(%2) # movsi_tlsgdlo"
+ [(set_attr "type" "logic")
+ (set_attr "length" "1")])
+
+(define_insn "movsi_tlsgdhi"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_TLSGDHI))]
+ ""
+ "l.movhi \t%0,tlsgdhi(%1) # movsi_tlsgdhi"
+[(set_attr "type" "move")
+ (set_attr "length" "1")])
+
+(define_insn "movsi_gottpofflo"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "immediate_operand" "i"))] UNSPEC_GOTTPOFFLO))]
+ ""
+ "l.ori \t%0,%1,gottpofflo(%2) # movsi_gottpofflo"
+ [(set_attr "type" "logic")
+ (set_attr "length" "1")])
+
+(define_insn "movsi_gottpoffhi"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_GOTTPOFFHI))]
+ ""
+ "l.movhi \t%0,gottpoffhi(%1) # movsi_gottpoffhi"
+[(set_attr "type" "move")
+ (set_attr "length" "1")])
+
+(define_insn "load_gottpoff"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "r")] UNSPEC_GOTTPOFFLD))]
+ ""
+ "l.lwz \t%0,0(%1) # load_gottpoff"
+[(set_attr "type" "load")
+ (set_attr "length" "1")])
+
+(define_insn "movsi_tpofflo"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "immediate_operand" "i"))] UNSPEC_TPOFFLO))]
+ ""
+ "l.ori \t%0,%1,tpofflo(%2) # movsi_tpofflo"
+ [(set_attr "type" "logic")
+ (set_attr "length" "1")])
+
+(define_insn "movsi_tpoffhi"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_TPOFFHI))]
+ ""
+ "l.movhi \t%0,tpoffhi(%1) # movsi_tpoffhi"
+[(set_attr "type" "move")
+ (set_attr "length" "1")])
+
+
+(define_insn_and_split "movsi_insn_big"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "immediate_operand" "i"))]
+ "GET_CODE (operands[1]) != CONST_INT"
+ ;; the switch of or1k bfd to Rela allows us to schedule insns separately.
+ "l.movhi \t%0,hi(%1)\;l.ori \t%0,%0,lo(%1)"
+ "(GET_CODE (operands[1]) != CONST_INT
+ || ! (CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[1]), 'I', \"I\")
+ || CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[1]), 'K', \"K\")
+ || CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[1]), 'M', \"M\")))
+ && reload_completed
+ && GET_CODE (operands[1]) != HIGH && GET_CODE (operands[1]) != LO_SUM"
+ [(pc)]
+{
+ if (!or1k_expand_symbol_ref(SImode, operands))
+ {
+ emit_insn (gen_movsi_high (operands[0], operands[1]));
+ emit_insn (gen_movsi_lo_sum (operands[0], operands[0], operands[1]));
+ }
+ DONE;
+}
+ [(set_attr "type" "move")
+ (set_attr "length" "2")])
+
+
+;;
+;; Conditional Branches & Moves
+;;
+
+(define_expand "addsicc"
+ [(match_operand:SI 0 "register_operand" "")
+ (match_operand 1 "comparison_operator" "")
+ (match_operand:SI 2 "register_operand" "")
+ (match_operand:SI 3 "register_operand" "")]
+ ""
+ "FAIL;")
+
+(define_expand "addhicc"
+ [(match_operand:HI 0 "register_operand" "")
+ (match_operand 1 "comparison_operator" "")
+ (match_operand:HI 2 "register_operand" "")
+ (match_operand:HI 3 "register_operand" "")]
+ ""
+ "FAIL;")
+
+(define_expand "addqicc"
+ [(match_operand:QI 0 "register_operand" "")
+ (match_operand 1 "comparison_operator" "")
+ (match_operand:QI 2 "register_operand" "")
+ (match_operand:QI 3 "register_operand" "")]
+ ""
+ "FAIL;")
+
+
+;;
+;; conditional moves
+;;
+
+(define_expand "movsicc"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (if_then_else:SI (match_operand 1 "comparison_operator" "")
+ (match_operand:SI 2 "register_operand" "")
+ (match_operand:SI 3 "register_operand" "")))]
+ "TARGET_MASK_CMOV"
+ "
+{
+ if (or1k_emit_cmove (operands[0], operands[1], operands[2], operands[3]))
+ DONE;
+}")
+
+(define_expand "movhicc"
+ [(set (match_operand:HI 0 "register_operand" "")
+ (if_then_else:SI (match_operand 1 "comparison_operator" "")
+ (match_operand:HI 2 "register_operand" "")
+ (match_operand:HI 3 "register_operand" "")))]
+ ""
+ "
+{
+ FAIL;
+}")
+
+(define_expand "movqicc"
+ [(set (match_operand:QI 0 "register_operand" "")
+ (if_then_else:SI (match_operand 1 "comparison_operator" "")
+ (match_operand:QI 2 "register_operand" "")
+ (match_operand:QI 3 "register_operand" "")))]
+ ""
+ "
+{
+ FAIL;
+}")
+
+
+;; We use the BASE_REGS for the cmov input operands because, if rA is
+;; 0, the value of 0 is placed in rD upon truth. Similarly for rB
+;; because we may switch the operands and rB may end up being rA.
+
+(define_insn "cmov"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (if_then_else:SI
+ (match_operator 1 "comparison_operator"
+ [(match_operand 4 "cc_reg_operand" "")
+ (const_int 0)])
+ (match_operand:SI 2 "register_operand" "r")
+ (match_operand:SI 3 "register_operand" "r")))]
+ "TARGET_MASK_CMOV"
+ "*
+ return or1k_output_cmov(operands);
+ ")
+
+;;
+;; ....................
+;;
+;; COMPARISONS
+;;
+;; ....................
+
+;; Flow here is rather complex:
+;;
+;; 1) The cmp{si,di,sf,df} routine is called. It deposits the
+;; arguments into the branch_cmp array, and the type into
+;; branch_type. No RTL is generated.
+;;
+;; 2) The appropriate branch define_expand is called, which then
+;; creates the appropriate RTL for the comparison and branch.
+;; Different CC modes are used, based on what type of branch is
+;; done, so that we can constrain things appropriately. There
+;; are assumptions in the rest of GCC that break if we fold the
+;; operands into the branches for integer operations, and use cc0
+;; for floating point, so we use the fp status register instead.
+;; If needed, an appropriate temporary is created to hold the
+;; of the integer compare.
+
+;; Compare insns are next. Note that the RS/6000 has two types of compares,
+;; signed & unsigned, and one type of branch.
+;;
+;; Start with the DEFINE_EXPANDs to generate the rtl for compares, scc
+;; insns, and branches. We store the operands of compares until we see
+;; how it is used.
+
+;; JPB 31-Aug-10: cmpxx appears to be obsolete in GCC 4.5. Needs more
+;; investigation.
+
+;;(define_expand "cmpsi"
+;; [(set (reg:CC CC_REG)
+;; (compare:CC (match_operand:SI 0 "register_operand" "")
+;; (match_operand:SI 1 "nonmemory_operand" "")))]
+;; ""
+;; {
+;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+;; operands[0] = force_reg (SImode, operands[0]);
+;; or1k_compare_op0 = operands[0];
+;; or1k_compare_op1 = operands[1];
+;; DONE;
+;; })
+
+;; (define_expand "cmpsf"
+;; [(set (reg:CC CC_REG)
+;; (compare:CC (match_operand:SF 0 "register_operand" "")
+;; (match_operand:SF 1 "register_operand" "")))]
+;; "TARGET_HARD_FLOAT"
+;; {
+;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+;; operands[0] = force_reg (SFmode, operands[0]);
+;; or1k_compare_op0 = operands[0];
+;; or1k_compare_op1 = operands[1];
+;; DONE;
+;; })
+
+(define_expand "cbranchsi4"
+ [(match_operator 0 "comparison_operator"
+ [(match_operand:SI 1 "register_operand")
+ (match_operand:SI 2 "nonmemory_operand")])
+ (match_operand 3 "")]
+ ""
+ {
+ or1k_expand_conditional_branch (operands, SImode);
+ DONE;
+ })
+
+(define_expand "cbranchsf4"
+ [(match_operator 0 "comparison_operator"
+ [(match_operand:SF 1 "register_operand")
+ (match_operand:SF 2 "register_operand")])
+ (match_operand 3 "")]
+ "TARGET_HARD_FLOAT"
+ {
+ or1k_expand_conditional_branch (operands, SFmode);
+ DONE;
+ })
+
+;;
+;; Setting a CCxx registers from comparision
+;;
+
+
+
+;; Here are the actual compare insns.
+(define_insn "*cmpsi_eq"
+ [(set (reg:CCEQ CC_REG)
+ (compare:CCEQ (match_operand:SI 0 "register_operand" "r,r")
+ (match_operand:SI 1 "nonmemory_operand" "I,r")))]
+ ""
+ "@
+ l.sfeqi\t%0,%1 # cmpsi_eq
+ l.sfeq \t%0,%1 # cmpsi_eq"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
+
+(define_insn "*cmpsi_ne"
+ [(set (reg:CCNE CC_REG)
+ (compare:CCNE (match_operand:SI 0 "register_operand" "r,r")
+ (match_operand:SI 1 "nonmemory_operand" "I,r")))]
+ ""
+ "@
+ l.sfnei\t%0,%1 # cmpsi_ne
+ l.sfne \t%0,%1 # cmpsi_ne"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
+
+(define_insn "*cmpsi_gt"
+ [(set (reg:CCGT CC_REG)
+ (compare:CCGT (match_operand:SI 0 "register_operand" "r,r")
+ (match_operand:SI 1 "nonmemory_operand" "I,r")))]
+ ""
+ "@
+ l.sfgtsi\t%0,%1 # cmpsi_gt
+ l.sfgts \t%0,%1 # cmpsi_gt"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
+
+(define_insn "*cmpsi_gtu"
+ [(set (reg:CCGTU CC_REG)
+ (compare:CCGTU (match_operand:SI 0 "register_operand" "r,r")
+ (match_operand:SI 1 "nonmemory_operand" "I,r")))]
+ ""
+ "@
+ l.sfgtui\t%0,%1 # cmpsi_gtu
+ l.sfgtu \t%0,%1 # cmpsi_gtu"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
+
+(define_insn "*cmpsi_lt"
+ [(set (reg:CCLT CC_REG)
+ (compare:CCLT (match_operand:SI 0 "register_operand" "r,r")
+ (match_operand:SI 1 "nonmemory_operand" "I,r")))]
+ ""
+ "@
+ l.sfltsi\t%0,%1 # cmpsi_lt
+ l.sflts \t%0,%1 # cmpsi_lt"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
+
+(define_insn "*cmpsi_ltu"
+ [(set (reg:CCLTU CC_REG)
+ (compare:CCLTU (match_operand:SI 0 "register_operand" "r,r")
+ (match_operand:SI 1 "nonmemory_operand" "I,r")))]
+ ""
+ "@
+ l.sfltui\t%0,%1 # cmpsi_ltu
+ l.sfltu \t%0,%1 # cmpsi_ltu"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
+
+(define_insn "*cmpsi_ge"
+ [(set (reg:CCGE CC_REG)
+ (compare:CCGE (match_operand:SI 0 "register_operand" "r,r")
+ (match_operand:SI 1 "nonmemory_operand" "I,r")))]
+ ""
+ "@
+ l.sfgesi\t%0,%1 # cmpsi_ge
+ l.sfges \t%0,%1 # cmpsi_ge"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
+
+
+(define_insn "*cmpsi_geu"
+ [(set (reg:CCGEU CC_REG)
+ (compare:CCGEU (match_operand:SI 0 "register_operand" "r,r")
+ (match_operand:SI 1 "nonmemory_operand" "I,r")))]
+ ""
+ "@
+ l.sfgeui\t%0,%1 # cmpsi_geu
+ l.sfgeu \t%0,%1 # cmpsi_geu"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
+
+
+(define_insn "*cmpsi_le"
+ [(set (reg:CCLE CC_REG)
+ (compare:CCLE (match_operand:SI 0 "register_operand" "r,r")
+ (match_operand:SI 1 "nonmemory_operand" "I,r")))]
+ ""
+ "@
+ l.sflesi\t%0,%1 # cmpsi_le
+ l.sfles \t%0,%1 # cmpsi_le"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
+
+(define_insn "*cmpsi_leu"
+ [(set (reg:CCLEU CC_REG)
+ (compare:CCLEU (match_operand:SI 0 "register_operand" "r,r")
+ (match_operand:SI 1 "nonmemory_operand" "I,r")))]
+ ""
+ "@
+ l.sfleui\t%0,%1 # cmpsi_leu
+ l.sfleu \t%0,%1 # cmpsi_leu"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
+
+;; Single precision floating point evaluation instructions
+(define_insn "*cmpsf_eq"
+ [(set (reg:CCEQ CC_REG)
+ (compare:CCEQ (match_operand:SF 0 "register_operand" "r,r")
+ (match_operand:SF 1 "register_operand" "r,r")))]
+ "TARGET_HARD_FLOAT"
+ "lf.sfeq.s\t%0,%1 # cmpsf_eq"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
+
+(define_insn "*cmpsf_ne"
+ [(set (reg:CCNE CC_REG)
+ (compare:CCNE (match_operand:SF 0 "register_operand" "r,r")
+ (match_operand:SF 1 "register_operand" "r,r")))]
+ "TARGET_HARD_FLOAT"
+ "lf.sfne.s\t%0,%1 # cmpsf_ne"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
+
+
+(define_insn "*cmpsf_gt"
+ [(set (reg:CCGT CC_REG)
+ (compare:CCGT (match_operand:SF 0 "register_operand" "r,r")
+ (match_operand:SF 1 "register_operand" "r,r")))]
+ "TARGET_HARD_FLOAT"
+ "lf.sfgt.s\t%0,%1 # cmpsf_gt"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
+
+(define_insn "*cmpsf_ge"
+ [(set (reg:CCGE CC_REG)
+ (compare:CCGE (match_operand:SF 0 "register_operand" "r,r")
+ (match_operand:SF 1 "register_operand" "r,r")))]
+ "TARGET_HARD_FLOAT"
+ "lf.sfge.s\t%0,%1 # cmpsf_ge"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
+
+
+(define_insn "*cmpsf_lt"
+ [(set (reg:CCLT CC_REG)
+ (compare:CCLT (match_operand:SF 0 "register_operand" "r,r")
+ (match_operand:SF 1 "register_operand" "r,r")))]
+ "TARGET_HARD_FLOAT"
+ "lf.sflt.s\t%0,%1 # cmpsf_lt"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
+
+(define_insn "*cmpsf_le"
+ [(set (reg:CCLE CC_REG)
+ (compare:CCLE (match_operand:SF 0 "register_operand" "r,r")
+ (match_operand:SF 1 "register_operand" "r,r")))]
+ "TARGET_HARD_FLOAT"
+ "lf.sfle.s\t%0,%1 # cmpsf_le"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
+
+(define_insn "*bf"
+ [(set (pc)
+ (if_then_else (match_operator 1 "comparison_operator"
+ [(match_operand 2
+ "cc_reg_operand" "")
+ (const_int 0)])
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+ return or1k_output_bf(operands);
+ "
+ [(set_attr "type" "branch")
+ (set_attr "length" "1")])
+
+;;
+;;
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;
+(define_insn_and_split "movdi"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r, r, m, r")
+ (match_operand:DI 1 "general_operand" " r, m, r, n"))]
+ ""
+ "*
+ return or1k_output_move_double (operands);
+ "
+ "&& reload_completed && CONSTANT_P (operands[1])"
+ [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (match_dup 5))]
+ "operands[2] = operand_subword (operands[0], 0, 0, DImode);
+ operands[3] = operand_subword (operands[1], 0, 0, DImode);
+ operands[4] = operand_subword (operands[0], 1, 0, DImode);
+ operands[5] = operand_subword (operands[1], 1, 0, DImode);"
+ [(set_attr "length" "2,2,2,3")])
+
+;; Moving double and single precision floating point values
+
+
+(define_insn "movdf"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=r, r, m, r")
+ (match_operand:DF 1 "general_operand" " r, m, r, i"))]
+ ""
+ "*
+ return or1k_output_move_double (operands);
+ "
+ [(set_attr "length" "2,2,2,3")])
+
+
+(define_insn "movsf"
+ [(set (match_operand:SF 0 "general_operand" "=r,r,m")
+ (match_operand:SF 1 "general_operand" "r,m,r"))]
+ ""
+ "@
+ l.ori \t%0,%1,0\t # movsf
+ l.lwz \t%0,%1\t # movsf
+ l.sw \t%0,%1\t # movsf"
+ [(set_attr "type" "move,load,store")
+ (set_attr "length" "1,1,1")])
+
+
+;;
+;; extendqisi2
+;;
+
+(define_expand "extendqisi2"
+ [(use (match_operand:SI 0 "register_operand" ""))
+ (use (match_operand:QI 1 "nonimmediate_operand" ""))]
+ ""
+ "
+{
+ if (TARGET_MASK_SEXT)
+ emit_insn (gen_extendqisi2_sext(operands[0], operands[1]));
+ else {
+ if ( GET_CODE(operands[1]) == MEM ) {
+ emit_insn (gen_extendqisi2_no_sext_mem(operands[0], operands[1]));
+ }
+ else {
+ emit_insn (gen_extendqisi2_no_sext_reg(operands[0], operands[1]));
+ }
+ }
+ DONE;
+}")
+
+(define_insn "extendqisi2_sext"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
+ "TARGET_MASK_SEXT"
+ "@
+ l.extbs \t%0,%1\t # extendqisi2_has_signed_extend
+ l.lbs \t%0,%1\t # extendqisi2_has_signed_extend"
+ [(set_attr "length" "1,1")
+ (set_attr "type" "extend,load")])
+
+(define_insn "extendqisi2_no_sext_mem"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
+ "!TARGET_MASK_SEXT"
+ "l.lbs \t%0,%1\t # extendqisi2_no_sext_mem"
+ [(set_attr "length" "1")
+ (set_attr "type" "load")])
+
+(define_expand "extendqisi2_no_sext_reg"
+ [(set (match_dup 2)
+ (ashift:SI (match_operand:QI 1 "register_operand" "")
+ (const_int 24)))
+ (set (match_operand:SI 0 "register_operand" "")
+ (ashiftrt:SI (match_dup 2)
+ (const_int 24)))]
+ "!TARGET_MASK_SEXT"
+ "
+{
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ operands[2] = gen_reg_rtx (SImode); }")
+
+;;
+;; extendhisi2
+;;
+
+(define_expand "extendhisi2"
+ [(use (match_operand:SI 0 "register_operand" ""))
+ (use (match_operand:HI 1 "nonimmediate_operand" ""))]
+ ""
+ "
+{
+ if (TARGET_MASK_SEXT)
+ emit_insn (gen_extendhisi2_sext(operands[0], operands[1]));
+ else {
+ if ( GET_CODE(operands[1]) == MEM ) {
+ emit_insn (gen_extendhisi2_no_sext_mem(operands[0], operands[1]));
+ }
+ else {
+ emit_insn (gen_extendhisi2_no_sext_reg(operands[0], operands[1]));
+ }
+ }
+ DONE;
+}")
+
+(define_insn "extendhisi2_sext"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
+ "TARGET_MASK_SEXT"
+ "@
+ l.exths \t%0,%1\t # extendhisi2_has_signed_extend
+ l.lhs \t%0,%1\t # extendhisi2_has_signed_extend"
+ [(set_attr "length" "1,1")
+ (set_attr "type" "extend,load")])
+
+(define_insn "extendhisi2_no_sext_mem"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
+ "!TARGET_MASK_SEXT"
+ "l.lhs \t%0,%1\t # extendhisi2_no_sext_mem"
+ [(set_attr "length" "1")
+ (set_attr "type" "load")])
+
+(define_expand "extendhisi2_no_sext_reg"
+ [(set (match_dup 2)
+ (ashift:SI (match_operand:HI 1 "register_operand" "")
+ (const_int 16)))
+ (set (match_operand:SI 0 "register_operand" "")
+ (ashiftrt:SI (match_dup 2)
+ (const_int 16)))]
+ "!TARGET_MASK_SEXT"
+ "
+{
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ operands[2] = gen_reg_rtx (SImode); }")
+
+
+;;
+;; zero_extend2
+;;
+
+(define_insn "zero_extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
+ ""
+ "@
+ l.andi \t%0,%1,0xff\t # zero_extendqisi2
+ l.lbz \t%0,%1\t # zero_extendqisi2"
+ [(set_attr "type" "logic,load")
+ (set_attr "length" "1,1")])
+
+
+(define_insn "zero_extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
+ ""
+ "@
+ l.andi \t%0,%1,0xffff\t # zero_extendqisi2
+ l.lhz \t%0,%1\t # zero_extendqisi2"
+ [(set_attr "type" "logic,load")
+ (set_attr "length" "1,1")])
+
+;;
+;; Shift/rotate operations
+;;
+
+(define_insn "ashlsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (ashift:SI (match_operand:SI 1 "register_operand" "r,r")
+ (match_operand:SI 2 "nonmemory_operand" "r,L")))]
+ ""
+ "@
+ l.sll \t%0,%1,%2 # ashlsi3
+ l.slli \t%0,%1,%2 # ashlsi3"
+ [(set_attr "type" "shift,shift")
+ (set_attr "length" "1,1")])
+
+(define_insn "ashrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
+ (match_operand:SI 2 "nonmemory_operand" "r,L")))]
+ ""
+ "@
+ l.sra \t%0,%1,%2 # ashrsi3
+ l.srai \t%0,%1,%2 # ashrsi3"
+ [(set_attr "type" "shift,shift")
+ (set_attr "length" "1,1")])
+
+(define_insn "lshrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
+ (match_operand:SI 2 "nonmemory_operand" "r,L")))]
+ ""
+ "@
+ l.srl \t%0,%1,%2 # lshrsi3
+ l.srli \t%0,%1,%2 # lshrsi3"
+ [(set_attr "type" "shift,shift")
+ (set_attr "length" "1,1")])
+
+(define_insn "rotrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (rotatert:SI (match_operand:SI 1 "register_operand" "r,r")
+ (match_operand:SI 2 "nonmemory_operand" "r,L")))]
+ "TARGET_MASK_ROR"
+ "@
+ l.ror \t%0,%1,%2 # rotrsi3
+ l.rori \t%0,%1,%2 # rotrsi3"
+ [(set_attr "type" "shift,shift")
+ (set_attr "length" "1,1")])
+
+;;
+;; Logical bitwise operations
+;;
+
+(define_insn "andsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (and:SI (match_operand:SI 1 "register_operand" "%r,r")
+ (match_operand:SI 2 "nonmemory_operand" "r,K")))]
+ ""
+ "@
+ l.and \t%0,%1,%2 # andsi3
+ l.andi \t%0,%1,%2 # andsi3"
+ [(set_attr "type" "logic,logic")
+ (set_attr "length" "1,1")])
+
+(define_insn "iorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (ior:SI (match_operand:SI 1 "register_operand" "%r,r")
+ (match_operand:SI 2 "nonmemory_operand" "r,K")))]
+ ""
+ "@
+ l.or \t%0,%1,%2 # iorsi3
+ l.ori \t%0,%1,%2 # iorsi3"
+ [(set_attr "type" "logic,logic")
+ (set_attr "length" "1,1")])
+
+(define_insn "xorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (xor:SI (match_operand:SI 1 "register_operand" "%r,r")
+ (match_operand:SI 2 "nonmemory_operand" "r,I")))]
+ ""
+ "@
+ l.xor \t%0,%1,%2 # xorsi3
+ l.xori \t%0,%1,%2 # xorsi3"
+ [(set_attr "type" "logic,logic")
+ (set_attr "length" "1,1")])
+
+(define_insn "one_cmplqi2"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (not:QI (match_operand:QI 1 "register_operand" "r")))]
+ ""
+ "l.xori \t%0,%1,0x00ff # one_cmplqi2"
+ [(set_attr "type" "logic")
+ (set_attr "length" "1")])
+
+(define_insn "one_cmplsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (not:SI (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "l.xori \t%0,%1,0xffff # one_cmplsi2"
+ [(set_attr "type" "logic")
+ (set_attr "length" "1")])
+
+;;
+;; Arithmetic operations
+;;
+
+(define_insn "negsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (neg:SI (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "l.sub \t%0,r0,%1 # negsi2"
+ [(set_attr "type" "add")
+ (set_attr "length" "1")])
+
+(define_insn "addsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (plus:SI (match_operand:SI 1 "register_operand" "%r,r")
+ (match_operand:SI 2 "nonmemory_operand" "r,I")))]
+ ""
+ "@
+ l.add \t%0,%1,%2 # addsi3
+ l.addi \t%0,%1,%2 # addsi3"
+ [(set_attr "type" "add,add")
+ (set_attr "length" "1,1")])
+
+(define_insn "subsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (minus:SI (match_operand:SI 1 "register_operand" "r,r")
+ (match_operand:SI 2 "nonmemory_operand" "r,I")))]
+ ""
+ "@
+ l.sub \t%0,%1,%2 # subsi3
+ l.addi \t%0,%1,%n2 # subsi3"
+ [(set_attr "type" "add,add")]
+)
+
+;;
+;; mul and div
+;;
+
+(define_insn "mulsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mult:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r")))]
+ "TARGET_HARD_MUL"
+ "l.mul \t%0,%1,%2 # mulsi3"
+ [(set_attr "type" "mul")
+ (set_attr "length" "1")])
+
+(define_insn "divsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (div:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r")))]
+ "TARGET_HARD_DIV"
+ "l.div \t%0,%1,%2 # divsi3"
+ [(set_attr "type" "mul")
+ (set_attr "length" "1")])
+
+(define_insn "udivsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (udiv:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r")))]
+ "TARGET_HARD_DIV"
+ "l.divu \t%0,%1,%2 # udivsi3"
+ [(set_attr "type" "mul")
+ (set_attr "length" "1")])
+
+;;
+;; jumps
+;;
+
+;; jump
+
+(define_expand "jump"
+ [(set (pc)
+ (label_ref (match_operand 0 "" "")))]
+ ""
+ "
+{
+ emit_jump_insn (gen_jump_internal (operands[0]));
+ DONE;
+}")
+
+(define_insn "jump_internal"
+ [(set (pc)
+ (label_ref (match_operand 0 "" "")))]
+ ""
+ "l.j \t%l0 # jump_internal%("
+ [(set_attr "type" "jump")
+ (set_attr "length" "1")])
+
+;; indirect jump
+
+(define_expand "indirect_jump"
+ [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
+ ""
+ "
+{
+ emit_jump_insn (gen_indirect_jump_internal (operands[0]));
+ DONE;
+
+}")
+
+(define_insn "indirect_jump_internal"
+ [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
+ ""
+ "l.jr \t%0 # indirect_jump_internal%("
+ [(set_attr "type" "jump")
+ (set_attr "length" "1")])
+
+;;
+;; calls
+;;
+
+;; call
+
+(define_expand "call"
+ [(parallel [(call (match_operand:SI 0 "sym_ref_mem_operand" "")
+ (match_operand 1 "" "i"))
+ (clobber (reg:SI 9))
+ (use (reg:SI 16))])]
+ ""
+ "
+{
+ emit_call_insn (gen_call_internal (operands[0], operands[1]));
+ DONE;
+}")
+
+(define_insn "call_internal"
+[(parallel [(call (match_operand:SI 0 "sym_ref_mem_operand" "")
+ (match_operand 1 "" "i"))
+ (clobber (reg:SI 9))
+ (use (reg:SI 16))])]
+ ""
+ {
+ if (flag_pic)
+ {
+ crtl->uses_pic_offset_table = 1;
+ return "l.jal \tplt(%S0)# call_internal%(";
+ }
+
+ return "l.jal \t%S0# call_internal%(";
+ }
+ [(set_attr "type" "jump")
+ (set_attr "length" "1")])
+
+;; call value
+
+(define_expand "call_value"
+ [(parallel [(set (match_operand 0 "register_operand" "=r")
+ (call (match_operand:SI 1 "sym_ref_mem_operand" "")
+ (match_operand 2 "" "i")))
+ (clobber (reg:SI 9))
+ (use (reg:SI 16))])]
+ ""
+ "
+{
+ emit_call_insn (gen_call_value_internal (operands[0], operands[1], operands[2]));
+ DONE;
+}")
+
+(define_insn "call_value_internal"
+[(parallel [(set (match_operand 0 "register_operand" "=r")
+ (call (match_operand:SI 1 "sym_ref_mem_operand" "")
+ (match_operand 2 "" "i")))
+ (clobber (reg:SI 9))
+ (use (reg:SI 16))])]
+ ""
+ {
+ if (flag_pic)
+ {
+ crtl->uses_pic_offset_table = 1;
+ return "l.jal \tplt(%S1) # call_value_internal%(";
+ }
+ return "l.jal \t%S1 # call_value_internal%(";
+ }
+ [(set_attr "type" "jump")
+ (set_attr "length" "1")])
+
+;; indirect call value
+
+(define_expand "call_value_indirect"
+ [(parallel [(set (match_operand 0 "register_operand" "=r")
+ (call (mem:SI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand 2 "" "i")))
+ (clobber (reg:SI 9))
+ (use (reg:SI 16))])]
+ ""
+ "
+{
+ emit_call_insn (gen_call_value_indirect_internal (operands[0], operands[1], operands[2]));
+ DONE;
+}")
+
+(define_insn "call_value_indirect_internal"
+ [(parallel [(set (match_operand 0 "register_operand" "=r")
+ (call (mem:SI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand 2 "" "i")))
+ (clobber (reg:SI 9))
+ (use (reg:SI 16))])]
+ ""
+ "l.jalr \t%1 # call_value_indirect_internal%("
+ [(set_attr "type" "jump")
+ (set_attr "length" "1")])
+
+;; indirect call
+
+(define_expand "call_indirect"
+ [(parallel [(call (mem:SI (match_operand:SI 0 "register_operand" "r"))
+ (match_operand 1 "" "i"))
+ (clobber (reg:SI 9))
+ (use (reg:SI 16))])]
+ ""
+ "
+{
+ emit_call_insn (gen_call_indirect_internal (operands[0], operands[1]));
+ DONE;
+}")
+
+(define_insn "call_indirect_internal"
+[(parallel [(call (mem:SI (match_operand:SI 0 "register_operand" "r"))
+ (match_operand 1 "" "i"))
+ (clobber (reg:SI 9))
+ (use (reg:SI 16))])]
+ ""
+ "l.jalr \t%0 # call_indirect_internal%("
+ [(set_attr "type" "jump")
+ (set_attr "length" "1")])
+
+;; table jump
+
+(define_expand "tablejump"
+ [(set (pc) (match_operand:SI 0 "register_operand" "r"))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "
+{
+ if (CASE_VECTOR_PC_RELATIVE || flag_pic)
+ operands[0]
+ = force_reg (Pmode,
+ gen_rtx_PLUS (Pmode, operands[0],
+ gen_rtx_LABEL_REF (Pmode, operands[1])));
+ emit_jump_insn (gen_tablejump_internal (operands[0], operands[1]));
+ DONE;
+}")
+
+(define_insn "tablejump_internal"
+ [(set (pc) (match_operand:SI 0 "register_operand" "r"))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "l.jr \t%0 # tablejump_internal%("
+ [(set_attr "type" "jump")
+ (set_attr "length" "1")])
+
+
+;; no-op
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "l.nop"
+ [(set_attr "type" "logic")
+ (set_attr "length" "1")])
+
+;;
+;; floating point
+;;
+
+;; floating point arithmetic
+
+(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")))]
+ "TARGET_HARD_FLOAT"
+ "lf.add.s\t%0,%1,%2 # addsf3"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
+
+(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")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
+ "lf.add.d\t%0,%1,%2 # adddf3"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
+
+(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")))]
+ "TARGET_HARD_FLOAT"
+ "lf.sub.s\t%0,%1,%2 # subsf3"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
+
+(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")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
+ "lf.sub.d\t%0,%1,%2 # subdf3"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
+
+(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")))]
+ "TARGET_HARD_FLOAT"
+ "lf.mul.s\t%0,%1,%2 # mulsf3"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
+
+(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")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
+ "lf.mul.d\t%0,%1,%2 # muldf3"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
+
+(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")))]
+ "TARGET_HARD_FLOAT"
+ "lf.div.s\t%0,%1,%2 # divsf3"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
+
+(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")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
+ "lf.div.d\t%0,%1,%2 # divdf3"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
+
+;; Conversion between fixed point and floating point.
+
+
+(define_insn "floatsisf2"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (float:SF (match_operand:SI 1 "register_operand" "r")))]
+ "TARGET_HARD_FLOAT"
+ "lf.itof.s\t%0, %1 # floatsisf2"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
+
+;; not working
+(define_insn "fixunssfsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (fix:SI (match_operand:SF 1 "register_operand" "r")))]
+ "TARGET_HARD_FLOAT"
+ "lf.ftoi.s\t%0, %1 # fixunssfsi2"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
+
+;; The insn to set GOT.
+;; TODO: support for no-delay target
+(define_insn "set_got"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
+ (clobber (reg:SI 9))
+ (clobber (reg:SI 16))]
+ ""
+ "l.jal \t8
+ \tl.movhi \tr16,gotpchi(_GLOBAL_OFFSET_TABLE_-4)
+ \tl.ori \tr16,r16,gotpclo(_GLOBAL_OFFSET_TABLE_+0)
+ \tl.add \tr16,r16,r9"
+ [(set_attr "length" "16")])
+
+
+;; Local variables:
+;; mode:emacs-lisp
+;; comment-start: ";; "
+;; eval: (set-syntax-table (copy-sequence (syntax-table)))
+;; eval: (modify-syntax-entry ?[ "(]")
+;; eval: (modify-syntax-entry ?] ")[")
+;; eval: (modify-syntax-entry ?{ "(}")
+;; eval: (modify-syntax-entry ?} "){")
+;; eval: (setq indent-tabs-mode t)
+;; End:
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/or1k-modes.def gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k-modes.def
--- gcc-4.8.2/gcc/config/or1k/or1k-modes.def 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k-modes.def 2014-03-14 07:27:49.000000000 +0200
@@ -0,0 +1,38 @@
+/* Definitions of target machine for GNU compiler, for OR32.
+ Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA. */
+
+/* Add any extra modes needed to represent the condition code.
+ */
+
+CC_MODE (CCEQ);
+CC_MODE (CCNE);
+
+CC_MODE (CCLE);
+CC_MODE (CCGE);
+CC_MODE (CCLT);
+CC_MODE (CCGT);
+
+CC_MODE (CCLEU);
+CC_MODE (CCGEU);
+CC_MODE (CCLTU);
+CC_MODE (CCGTU);
+
+CC_MODE(CCFP);
+CC_MODE(CCUNS);
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/or1k.opt gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k.opt
--- gcc-4.8.2/gcc/config/or1k/or1k.opt 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k.opt 2014-03-14 07:27:49.000000000 +0200
@@ -0,0 +1,96 @@
+; Options for the OR1K port of the compiler
+; This file is part of GCC.
+;
+; Copyright (C) 2010 Embecosm Limited
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 3, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+; for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING3. If not see
+; .
+
+HeaderInclude
+config/or1k/or1k-opts.h
+
+Variable
+enum or1k_delay or1k_delay_selected = OR1K_DELAY_DEFAULT
+
+mdelay
+Target RejectNegative Negative(mno-delay) Var(or1k_delay_selected, OR1K_DELAY_ON)
+Assume branches and jumps have a delay slot
+
+mno-delay
+Target RejectNegative Negative(mcompat-delay) Var(or1k_delay_selected, OR1K_DELAY_OFF)
+Assume branches and jumps do not have a delay slot
+
+mcompat-delay
+Target RejectNegative Negative(mdelay) Var(or1k_delay_selected, OR1K_DELAY_COMPAT)
+Assume branches and jumps have a delay slot, but fill them with nops
+
+mhard-float
+Target RejectNegative Mask(HARD_FLOAT)
+Use hardware floating point
+
+msoft-float
+Target RejectNegative InverseMask(HARD_FLOAT)
+Do not use hardware floating point
+
+mdouble-float
+Target Report RejectNegative Mask(DOUBLE_FLOAT)
+Allow hardware floating-point instructions to cover both 32-bit and 64-bit operations
+
+mhard-div
+Target RejectNegative Mask(HARD_DIV)
+Use hardware division
+
+msoft-div
+Target RejectNegative InverseMask(HARD_DIV)
+Do not use hardware division
+
+mhard-mul
+Target RejectNegative Mask(HARD_MUL)
+Use hardware multiplication
+
+msoft-mul
+Target RejectNegative InverseMask(HARD_MUL)
+Do not use hardware multiplication
+
+msext
+Target Mask(MASK_SEXT)
+Use sign-extending instructions
+
+mcmov
+Target Mask(MASK_CMOV)
+Use conditional move instructions
+
+mror
+Target Mask(MASK_ROR)
+Emit ROR instructions
+
+mboard=
+Target RejectNegative Joined
+Link with libgloss configuration suitable for this board
+
+mnewlib
+Target Report RejectNegative
+Compile for the Linux/Gnu/newlib based toolchain
+
+;; provide struct padding as in previous releases.
+;; Note that this will only affect STRUCTURE_SIZE_BOUNDARY, in particular
+;; make 2 byte structs 4-byte alignned and sized.
+;; We still use ROUND_TYPE_ALIGN to increase alignment of larger structs.
+mpadstruct
+Target Report RejectNegative Mask(PADSTRUCT)
+Make structs a multiple of 4 bytes (warning: ABI altered)
+
+mredzone=
+Target RejectNegative Joined UInteger Var(or1k_redzone) Init(128)
+Set the size of the stack below sp that is assumed to be safe from interrupts.
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/or1k-opts.h gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k-opts.h
--- gcc-4.8.2/gcc/config/or1k/or1k-opts.h 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k-opts.h 2014-03-14 07:27:49.000000000 +0200
@@ -0,0 +1,14 @@
+#ifndef OR1K_OPTS_H
+#define OR1K_OPTS_H
+
+enum or1k_delay {
+ OR1K_DELAY_OFF = 0,
+ OR1K_DELAY_ON = 1,
+ OR1K_DELAY_COMPAT = 2
+};
+
+#define TARGET_DELAY_ON (or1k_delay_selected == OR1K_DELAY_ON)
+#define TARGET_DELAY_OFF (or1k_delay_selected == OR1K_DELAY_OFF)
+#define TARGET_DELAY_COMPAT (or1k_delay_selected == OR1K_DELAY_COMPAT)
+
+#endif
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/or1k-protos.h gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k-protos.h
--- gcc-4.8.2/gcc/config/or1k/or1k-protos.h 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k-protos.h 2014-03-14 07:27:49.000000000 +0200
@@ -0,0 +1,62 @@
+/* Definitions of target machine for GNU compiler, OR1K cpu.
+
+ Copyright (C) 2010 Embecosm Limited
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+. */
+
+#ifndef GCC_OR1K_PROTOS_H
+#define GCC_OR1K_PROTOS_H
+
+/* The following are for general support. */
+extern int or1k_trampoline_code_size (void);
+
+/* The following are only needed when handling the machine definition. */
+#ifdef RTX_CODE
+extern void or1k_init_expanders (void);
+extern void or1k_expand_prologue (void);
+extern void or1k_expand_epilogue (void);
+extern bool or1k_expand_move (enum machine_mode mode, rtx operands[]);
+extern const char *or1k_output_move_double (rtx *operands);
+extern void or1k_expand_conditional_branch (rtx *operands,
+ enum machine_mode mode);
+extern int or1k_emit_cmove (rtx dest,
+ rtx op,
+ rtx true_cond,
+ rtx false_cond);
+extern enum machine_mode or1k_select_cc_mode (enum rtx_code op);
+extern const char *or1k_output_bf (rtx * operands);
+extern const char *or1k_output_cmov (rtx * operands);
+extern void or1k_emit_set_const32 (rtx op0,
+ rtx op1);
+extern bool or1k_expand_symbol_ref (enum machine_mode mode,
+ rtx operands[]);
+#endif
+
+#endif
+extern int or1k_struct_alignment (tree);
+extern int or1k_data_alignment (tree, int);
+
+extern int or1k_initial_elimination_offset (int, int);
+extern bool or1k_save_reg_p_cached (int regno);
+extern void or1k_print_jump_restore (rtx jump_address);
+extern rtx or1k_eh_return_handler_rtx (void);
+extern rtx or1k_return_addr_rtx (int, rtx);
+
+extern int or1k_legitimate_pic_operand_p (rtx x);
+
+/* For RETURN_ADDR_RTX */
+extern rtx get_hard_reg_initial_val (enum machine_mode, unsigned int);
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/predicates.md gcc-4.8.2-or1k-rtems/gcc/config/or1k/predicates.md
--- gcc-4.8.2/gcc/config/or1k/predicates.md 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/predicates.md 2014-03-14 07:27:49.000000000 +0200
@@ -0,0 +1,74 @@
+;; Predicate definitions for OR32
+;;
+;; Copyright (C) 2010 Embecosm Limited
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3. If not see
+;; .
+
+(define_predicate "cc_reg_operand"
+ (match_code "subreg,reg")
+{
+ register_operand (op, mode);
+
+ if (GET_CODE (op) == REG && REGNO (op) == CC_REG)
+ return 1;
+
+ return 0;
+})
+
+(define_predicate "input_operand"
+ (match_code "subreg,reg,const_int,mem,const")
+{
+ /* If both modes are non-void they must be the same. */
+ if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
+ return 0;
+
+ /* Allow any one instruction integer constant, and all CONST_INT
+ variants when we are working in DImode and !arch64. */
+ if (GET_MODE_CLASS (mode) == MODE_INT
+ && ((GET_CODE (op) == CONST_INT)
+ && (satisfies_constraint_K (op)
+ || satisfies_constraint_M (op)
+ || satisfies_constraint_I (op))))
+ return 1;
+
+ if (register_operand (op, mode))
+ return 1;
+
+ /* If this is a SUBREG, look inside so that we handle
+ paradoxical ones. */
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+
+ /* Check for valid MEM forms. */
+ if (GET_CODE (op) == MEM)
+ return memory_address_p (mode, XEXP (op, 0));
+
+ return 0;
+})
+
+(define_predicate "sym_ref_mem_operand"
+ (match_code "mem")
+{
+ if (GET_CODE (op) == MEM)
+ {
+ rtx t1 = XEXP (op, 0);
+ if (GET_CODE (t1) == SYMBOL_REF)
+ return 1;
+ }
+ return 0;
+})
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/rtems.h gcc-4.8.2-or1k-rtems/gcc/config/or1k/rtems.h
--- gcc-4.8.2/gcc/config/or1k/rtems.h 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/rtems.h 2014-04-29 01:30:16.103239278 +0200
@@ -0,0 +1,43 @@
+/* Definitions for rtems targeting an OpenRisc OR1K using ELF
+
+ Copyright (C) 1996, 1997, 2005 Free Software Foundation, Inc.
+ Contributed by Joel Sherrill (joel@OARcorp.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Use ELF */
+#undef OBJECT_FORMAT_ELF
+#define OBJECT_FORMAT_ELF
+
+/* what does this comment go to?
+ or1k debug info support is controlled by tm.h header files we include:
+ dbxelf.h enables optional stabs debug info.
+ elfos.h sets PREFERRED_DEBUGGING_TYPE to DWARF2_DEBUG . */
+
+/* RTEMS always uses newlib */
+#undef DRIVER_SELF_SPECS
+
+/* Target OS builtins. */
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__rtems__"); \
+ builtin_assert ("system=rtems"); \
+ } \
+ while (0)
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/t-linux gcc-4.8.2-or1k-rtems/gcc/config/or1k/t-linux
--- gcc-4.8.2/gcc/config/or1k/t-linux 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/t-linux 2014-03-14 07:27:49.000000000 +0200
@@ -0,0 +1,12 @@
+MULTILIB_DIRNAMES =
+EXTRA_MULTILIB_PARTS = crti.o crtbegin.o crtend.o crtn.o
+
+# hack:
+# the non-shared uclibc-0.9.31/libc/misc/internals/__uClibc_main.c
+# already defines __dso_handle. To avoid a duplicate definition,
+# we rename the crtbegin one.
+# JPB 18-Nov-10: Commented out, since uClibc no longer defines.
+# amend gcc Makefile CLFAGS variable
+# $(T)crtbegin.o: CRTSTUFF_CFLAGS += '-D__dso_handle=__dso_handle_dummy'
+# amend libgcc Makefile CLFAGS variable
+# crtbegin$(objext): CRTSTUFF_T_CFLAGS += '-D__dso_handle=__dso_handle_dummy'
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/t-or1k gcc-4.8.2-or1k-rtems/gcc/config/or1k/t-or1k
--- gcc-4.8.2/gcc/config/or1k/t-or1k 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/t-or1k 2014-03-14 07:27:49.000000000 +0200
@@ -0,0 +1,28 @@
+# t-or1k is a Makefile fragment to be included when
+# building gcc for the or1k target
+
+# Copyright (C) 2010 Embecosm Limited
+
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# .
+
+# we don't support -g so don't use it
+LIBGCC2_DEBUG_CFLAGS =
+
+# Build the libraries for both hard and soft floating point
+MULTILIB_OPTIONS = mno-delay/mcompat-delay msoft-float
+MULTILIB_DIRNAMES = no-delay compat-delay soft-float
+MULTILIB_MATCHES =
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/t-or1knd gcc-4.8.2-or1k-rtems/gcc/config/or1k/t-or1knd
--- gcc-4.8.2/gcc/config/or1k/t-or1knd 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/t-or1knd 2014-03-14 07:27:49.000000000 +0200
@@ -0,0 +1,28 @@
+# t-or1knd is a Makefile fragment to be included when
+# building gcc for the or1k target
+
+# Copyright (C) 2010 Embecosm Limited
+
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# .
+
+# we don't support -g so don't use it
+LIBGCC2_DEBUG_CFLAGS =
+
+# Build the libraries for both hard and soft floating point
+MULTILIB_OPTIONS = mdelay/mcompat-delay msoft-float
+MULTILIB_DIRNAMES = delay compat-delay soft-float
+MULTILIB_MATCHES =
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/t-rtems gcc-4.8.2-or1k-rtems/gcc/config/or1k/t-rtems
--- gcc-4.8.2/gcc/config/or1k/t-rtems 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/t-rtems 2014-04-29 00:32:16.947998363 +0200
@@ -0,0 +1,2 @@
+# Custom multilibs for RTEMS
+
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config.gcc gcc-4.8.2-or1k-rtems/gcc/config.gcc
--- gcc-4.8.2/gcc/config.gcc 2013-10-03 02:47:24.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/config.gcc 2014-04-29 01:29:36.179658466 +0200
@@ -415,6 +415,12 @@
extra_headers="loongson.h"
extra_options="${extra_options} g.opt mips/mips-tables.opt"
;;
+or1k-*-*)
+ cpu_type=or1k
+ ;;
+or1knd-*-*)
+ cpu_type=or1k
+ ;;
picochip-*-*)
cpu_type=picochip
;;
@@ -1964,6 +1970,40 @@
use_collect2=no
use_gcc_stdint=wrap
;;
+or1k-*-elf*)
+ tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h ${cpu_type}/elf.h"
+ extra_parts="crti.o crtbegin.o crtend.o crtn.o"
+ tmake_file=or1k/t-or1k
+ tm_defines="${tm_defines} OR1K_DELAY_DEFAULT=OR1K_DELAY_ON"
+ ;;
+or1k-*-linux-*)
+ tm_file="${tm_file} dbxelf.h elfos.h or1k/elf.h gnu-user.h linux.h or1k/linux-gas.h or1k/linux-elf.h uclibc-stdint.h"
+ tmake_file="or1k/t-or1k or1k/t-linux ${tmake_file}"
+ tm_defines="${tm_defines} OR1K_DELAY_DEFAULT=OR1K_DELAY_ON"
+ ;;
+or1k-*-rtems*)
+ tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h rtems.h ${cpu_type}/elf.h or1k/rtems.h"
+ extra_parts="crti.o crtbegin.o crtend.o crtn.o"
+ tmake_file="or1k/t-or1k t-rtems or1k/t-rtems"
+ tm_defines="${tm_defines} OR1K_DELAY_DEFAULT=OR1K_DELAY_ON"
+ ;;
+or1knd-*-elf*)
+ tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h ${cpu_type}/elf.h"
+ extra_parts="crti.o crtbegin.o crtend.o crtn.o"
+ tmake_file=or1k/t-or1knd
+ tm_defines="${tm_defines} OR1K_DELAY_DEFAULT=OR1K_DELAY_OFF"
+ ;;
+or1knd-*-linux-*)
+ tm_file="${tm_file} dbxelf.h elfos.h or1k/elf.h linux.h or1k/linux-gas.h or1k/linux-elf.h uclibc-stdint.h"
+ tmake_file="or1k/t-or1knd or1k/t-linux ${tmake_file}"
+ tm_defines="${tm_defines} OR1K_DELAY_DEFAULT=OR1K_DELAY_OFF"
+ ;;
+or1knd-*-rtems*)
+ tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h rtems.h ${cpu_type}/elf.h or1k/rtems.h"
+ extra_parts="crti.o crtbegin.o crtend.o crtn.o"
+ tmake_file="or1k/t-or1k t-rtems or1k/t-rtems"
+ tm_defines="${tm_defines} OR1K_DELAY_DEFAULT=OR1K_DELAY_OFF"
+ ;;
pdp11-*-*)
tm_file="${tm_file} newlib-stdint.h"
use_gcc_stdint=wrap
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/configure.ac gcc-4.8.2-or1k-rtems/gcc/configure.ac
--- gcc-4.8.2/gcc/configure.ac 2013-06-19 03:18:38.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/configure.ac 2014-03-17 04:57:55.337050724 +0200
@@ -3026,6 +3026,20 @@
tls_first_minor=20
tls_as_opt='--fatal-warnings'
;;
+ or1k*-*-*)
+ conftest_s='
+ .section ".tdata","awT",%progbits
+foo: .long 25
+ .text
+ l.movhi r3,tlsgdhi(foo)
+ l.ori r3,r3,tlsgdlo(foo)
+
+ l.jal __tls_get_addr
+ l.nop'
+ tls_first_major=2
+ tls_first_minor=23
+ tls_as_opt='--fatal-warnings'
+ ;;
powerpc-ibm-aix*)
conftest_s='
.extern __get_tpointer
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/testsuite/gcc.c-torture/execute/20101011-1.c gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.c-torture/execute/20101011-1.c
--- gcc-4.8.2/gcc/testsuite/gcc.c-torture/execute/20101011-1.c 2013-02-08 18:02:47.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.c-torture/execute/20101011-1.c 2014-03-17 05:04:56.421052207 +0200
@@ -36,6 +36,12 @@
/* Epiphany does not have hardware division, and the software implementation
has truly undefined behaviour for division by 0. */
# define DO_TEST 0
+#elif defined (__or1k__)
+ /* There is no strict behavior requirement for integer divide by zero
+ on OpenRISC 1000. The bare metal implementation ignores it, so we
+ will disable this test for now.
+ */
+# define DO_TEST 0
#elif defined (__m68k__) && !defined(__linux__)
/* Attempting to trap division-by-zero in this way isn't likely to work on
bare-metal m68k systems. */
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/testsuite/gcc.dg/20020312-2.c gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/20020312-2.c
--- gcc-4.8.2/gcc/testsuite/gcc.dg/20020312-2.c 2013-02-16 21:32:15.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/20020312-2.c 2014-03-17 05:07:59.717052852 +0200
@@ -34,6 +34,8 @@
/* PIC register is r1, but is used even without -fpic. */
#elif defined(__lm32__)
/* No pic register. */
+#elif defined(__or1k__)
+/* No pic register. */
#elif defined(__M32R__)
/* No pic register. */
#elif defined(__m68k__)
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/testsuite/gcc.dg/builtin-apply2.c gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/builtin-apply2.c
--- gcc-4.8.2/gcc/testsuite/gcc.dg/builtin-apply2.c 2012-10-23 19:20:56.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/builtin-apply2.c 2014-03-17 05:08:43.741053007 +0200
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." { "aarch64*-*-* avr-*-* " } { "*" } { "" } } */
+/* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." { "aarch64*-*-* avr-*-* or1k-*-*" } { "*" } { "" } } */
/* { dg-skip-if "Variadic funcs use Base AAPCS. Normal funcs use VFP variant." { "arm*-*-*" } { "-mfloat-abi=hard" } { "" } } */
/* PR target/12503 */
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/testsuite/gcc.dg/builtin-stringop-chk-1.c gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/builtin-stringop-chk-1.c
--- gcc-4.8.2/gcc/testsuite/gcc.dg/builtin-stringop-chk-1.c 2012-05-03 10:48:22.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/builtin-stringop-chk-1.c 2014-03-17 05:09:20.449053137 +0200
@@ -104,8 +104,8 @@
S *s[3];
memset (s, 0, sizeof (S) * 3); /* { dg-warning "will always overflow" "memset" } */
- struct T { char a[8]; char b[4]; char c[10]; } t;
- stpcpy (t.c,"Testing..."); /* { dg-warning "will always overflow" "stpcpy" } */
+ struct T { char a[8]; char b[4]; char c[10]; } t; /* or1k pads this to 12 bytes, and __builtin_object_size (t.c, 0) gives the size of the full object. */
+ stpcpy (t.c,"Testing..."); /* { dg-warning "will always overflow" "stpcpy" { target { ! or1k-*-* } } } */
char b1[7];
char b2[4];
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/testsuite/gcc.dg/nop.h gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/nop.h
--- gcc-4.8.2/gcc/testsuite/gcc.dg/nop.h 2010-11-17 22:35:46.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/nop.h 2014-03-17 05:09:42.941053216 +0200
@@ -2,6 +2,8 @@
#define NOP "nop 0"
#elif defined (__MMIX__)
#define NOP "swym 0"
+#elif defined (__or1k__)
+#define NOP "l.nop 0"
#else
#define NOP "nop"
#endif
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/testsuite/gcc.dg/torture/pr37868.c gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/torture/pr37868.c
--- gcc-4.8.2/gcc/testsuite/gcc.dg/torture/pr37868.c 2011-07-15 11:43:05.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/torture/pr37868.c 2014-03-17 05:10:08.189053305 +0200
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-options "-fno-strict-aliasing" } */
/* { dg-skip-if "unaligned access" { sparc*-*-* sh*-*-* tic6x-*-* } "*" "" } */
+/* { dg-skip-if "alignment exception" { or1k*-*-* } "*" "" } */
extern void abort (void);
#if (__SIZEOF_INT__ <= 2)
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c
--- gcc-4.8.2/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c 2012-10-16 00:38:37.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c 2014-03-17 05:10:30.225053382 +0200
@@ -6,6 +6,7 @@
/* { dg-do run } */
+/* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." {"or1k-*-*"} { "*" } { "" } } */
/* { dg-skip-if "Variadic funcs use Base AAPCS. Normal funcs use VFP variant." { arm_hf_eabi } } */
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/testsuite/gcc.dg/tree-ssa/pr44258.c gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/tree-ssa/pr44258.c
--- gcc-4.8.2/gcc/testsuite/gcc.dg/tree-ssa/pr44258.c 2010-06-10 19:49:09.000000000 +0300
+++ gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/tree-ssa/pr44258.c 2014-03-17 05:11:18.057053551 +0200
@@ -15,7 +15,7 @@
struct val
{
char y;
- struct blah b2;
+ struct blah b2 __attribute__((packed)); /* { dg-warning "attribute ignored" "" { target { ! or1k-*-* } } } */
};
union U
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/testsuite/g++.dg/ext/strncpy-chk1.C gcc-4.8.2-or1k-rtems/gcc/testsuite/g++.dg/ext/strncpy-chk1.C
--- gcc-4.8.2/gcc/testsuite/g++.dg/ext/strncpy-chk1.C 2009-07-10 14:56:55.000000000 +0300
+++ gcc-4.8.2-or1k-rtems/gcc/testsuite/g++.dg/ext/strncpy-chk1.C 2014-03-17 05:04:02.377052016 +0200
@@ -2,7 +2,7 @@
// { dg-do compile }
// { dg-options "-O2" }
-struct A { char x[12], y[35]; };
+struct A { char x[12], y[35]; }; // change to y[32] to get warning on or1k
struct B { char z[50]; };
inline void
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/testsuite/lib/target-supports.exp gcc-4.8.2-or1k-rtems/gcc/testsuite/lib/target-supports.exp
--- gcc-4.8.2/gcc/testsuite/lib/target-supports.exp 2013-02-12 01:11:12.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/gcc/testsuite/lib/target-supports.exp 2014-03-17 05:12:15.121053752 +0200
@@ -386,7 +386,8 @@
# Some targets don't support gc-sections despite whatever's
# advertised by ld's options.
if { [istarget alpha*-*-*]
- || [istarget ia64-*-*] } {
+ || [istarget ia64-*-*]
+ || [istarget or1k-*-*] } {
set gc_sections_available_saved 0
return 0
}
@@ -529,6 +530,7 @@
|| [istarget mmix-*-*]
|| [istarget mn10300-*-elf*]
|| [istarget moxie-*-elf*]
+ || [istarget or1k-*-elf*]
|| [istarget picochip-*-*]
|| [istarget powerpc-*-eabi*]
|| [istarget powerpc-*-elf]
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/libgcc/config/or1k/crti.S gcc-4.8.2-or1k-rtems/libgcc/config/or1k/crti.S
--- gcc-4.8.2/libgcc/config/or1k/crti.S 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/libgcc/config/or1k/crti.S 2014-03-14 07:28:07.000000000 +0200
@@ -0,0 +1,36 @@
+# Start .init and .fini sections.
+# Copyright (C) 2010 Embecosm Limited
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# .
+
+#include "or1k-asm.h"
+
+ .section .init
+ .global _init
+ l.nop # So _init doesn't start at 0
+_init:
+ l.addi r1,r1,-4
+ l.sw 0(r1),r9
+
+ .section .fini
+ .global _fini
+_fini:
+ l.addi r1,r1,-4
+ l.sw 0(r1),r9
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/libgcc/config/or1k/crtn.S gcc-4.8.2-or1k-rtems/libgcc/config/or1k/crtn.S
--- gcc-4.8.2/libgcc/config/or1k/crtn.S 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/libgcc/config/or1k/crtn.S 2014-03-14 07:28:08.000000000 +0200
@@ -0,0 +1,37 @@
+# End .init and .fini sections.
+# Copyright (C) 2010 Embecosm Limited
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# .
+
+#include "or1k-asm.h"
+
+ .section .init
+ l.lwz r9,0(r1)
+ OR1K_DELAYED(
+ OR1K_INST(l.addi r1,r1,4),
+ OR1K_INST(l.jr r9)
+ )
+
+ .section .fini
+ l.lwz r9,0(r1)
+ OR1K_DELAYED(
+ OR1K_INST(l.addi r1,r1,4),
+ OR1K_INST(l.jr r9)
+ )
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/libgcc/config/or1k/lib2funcs.c gcc-4.8.2-or1k-rtems/libgcc/config/or1k/lib2funcs.c
--- gcc-4.8.2/libgcc/config/or1k/lib2funcs.c 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/libgcc/config/or1k/lib2funcs.c 2014-03-14 07:28:08.000000000 +0200
@@ -0,0 +1,40 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+. */
+
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+
+USItype
+__mulsi3 (USItype a, USItype b)
+{
+ USItype c = 0;
+
+ while (a != 0)
+ {
+ if (a & 1)
+ c += b;
+ a >>= 1;
+ b <<= 1;
+ }
+
+ return c;
+}
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/libgcc/config/or1k/linux-unwind.h gcc-4.8.2-or1k-rtems/libgcc/config/or1k/linux-unwind.h
--- gcc-4.8.2/libgcc/config/or1k/linux-unwind.h 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/libgcc/config/or1k/linux-unwind.h 2014-03-14 07:28:08.000000000 +0200
@@ -0,0 +1,77 @@
+/* DWARF2 EH unwinding support for OpenRISC.
+ Copyright (C) 2011, 2012
+ Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+. */
+
+#ifndef inhibit_libc
+
+#include
+#include
+#include
+
+#define MD_FALLBACK_FRAME_STATE_FOR or1k_fallback_frame_state
+
+static _Unwind_Reason_Code
+or1k_fallback_frame_state (struct _Unwind_Context *context,
+ _Unwind_FrameState *fs)
+{
+ struct rt_sigframe {
+ siginfo_t info;
+ struct ucontext uc;
+ } *frame = context->cfa;
+
+ struct sigcontext *sc;
+ unsigned char *pc = context->ra;
+ long new_cfa;
+ int i;
+
+ /*
+ * Note: These have to be the same as in the kernel.
+ * Please see arch/openrisc/kernel/signal.c
+ */
+ if (!(*(unsigned short *)(pc + 0) == 0xa960
+ && *(unsigned short *)(pc + 2) == __NR_rt_sigreturn
+ && *(unsigned long *)(pc + 4) == 0x20000001
+ && *(unsigned long *)(pc + 8) == 0x15000000))
+ return _URC_END_OF_STACK;
+
+ sc = (struct sigcontext *) &frame->uc.uc_mcontext;
+
+ new_cfa = sc->regs.gpr[1];
+ fs->regs.cfa_how = CFA_REG_OFFSET;
+ fs->regs.cfa_reg = STACK_POINTER_REGNUM;
+ fs->regs.cfa_offset = new_cfa - (long) context->cfa;
+
+ for (i = 0; i < 32; ++i)
+ {
+ fs->regs.reg[i].how = REG_SAVED_OFFSET;
+ fs->regs.reg[i].loc.offset = (long)&sc->regs.gpr[i] - new_cfa;
+ }
+
+ fs->retaddr_column = 9;
+ fs->signal_frame = 1;
+
+ return _URC_NO_REASON;
+}
+
+#endif /* ifdef inhibit_libc */
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/libgcc/config/or1k/or1k-asm.h gcc-4.8.2-or1k-rtems/libgcc/config/or1k/or1k-asm.h
--- gcc-4.8.2/libgcc/config/or1k/or1k-asm.h 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/libgcc/config/or1k/or1k-asm.h 2014-03-14 07:28:08.000000000 +0200
@@ -0,0 +1,20 @@
+#ifndef OR1K_ASM_H
+#define OR1K_ASM_H
+
+#define OR1K_INST(...) __VA_ARGS__
+
+#if defined(__OR1K_NODELAY__)
+#define OR1K_DELAYED(a, b) a; b
+#define OR1K_DELAYED_NOP(a) a
+.nodelay
+#elif defined(__OR1K_DELAY__)
+#define OR1K_DELAYED(a, b) b; a
+#define OR1K_DELAYED_NOP(a) a; l.nop
+#elif defined(__OR1K_DELAY_COMPAT__)
+#define OR1K_DELAYED(a, b) a; b; l.nop
+#define OR1K_DELAYED_NOP(a) a; l.nop
+#else
+#error One of __OR1K_NODELAY__, __OR1K_DELAY__, or __OR1K_DELAY_COMPAT__ must be defined
+#endif
+
+#endif
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/libgcc/config/or1k/or1k.S gcc-4.8.2-or1k-rtems/libgcc/config/or1k/or1k.S
--- gcc-4.8.2/libgcc/config/or1k/or1k.S 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/libgcc/config/or1k/or1k.S 2014-03-14 07:28:08.000000000 +0200
@@ -0,0 +1,182 @@
+/*
+ * Assembly functions for software multiplication and devision.
+ */
+
+#define ENTRY(symbol) \
+ .align 4 ;\
+ .global symbol ;\
+symbol:
+
+#ifdef L__mulsi3
+ENTRY(__mulsi3)
+ l.addi r11,r0,0x0
+ l.sfne r3,r11
+ l.bnf 3f
+ l.ori r5,r3,0x0
+ l.addi r6,r0,0x0
+1:
+ l.andi r3,r5,0x1
+ l.sfeq r3,r6
+ l.bf 2f
+ l.srli r5,r5,0x1
+ l.add r11,r11,r4
+2:
+ l.sfne r5,r6
+ l.bf 1b
+ l.slli r4,r4,0x1
+3:
+ l.jr r9
+ l.nop 0x0
+#endif
+
+#ifdef L__udivsi3
+ENTRY(__udivsi3)
+ l.addi r1,r1,-4
+ l.sw 0(r1),r9
+ l.addi r11,r0,0
+ l.addi r8,r4,0
+ l.addi r5,r3,0
+ l.sfne r8,r11
+ l.bnf 4f
+ l.addi r7,r0,0
+ l.sfgtu r8,r5
+ l.bf 5f
+ l.sfeq r8,r5
+ l.bf 6f
+ l.sfltu r11,r8
+ l.bnf 2f
+ l.addi r13,r0,32
+ l.movhi r9,hi(0x80000000)
+ l.addi r6,r0,-1
+1:
+ l.and r3,r5,r9
+ l.slli r4,r7,1
+ l.addi r15,r5,0
+ l.srli r3,r3,31
+ l.add r13,r13,r6
+ l.or r7,r4,r3
+ l.sfltu r7,r8
+ l.bf 1b
+ l.slli r5,r5,1
+2:
+ l.srli r7,r7,1
+ l.addi r13,r13,1
+ l.addi r9,r0,0
+ l.sfltu r9,r13
+ l.bnf 4f
+ l.addi r5,r15,0
+ l.movhi r15,hi(0x80000000)
+ l.addi r17,r0,0
+3:
+ l.and r3,r5,r15
+ l.slli r4,r7,1
+ l.srli r3,r3,31
+ l.or r7,r4,r3
+ l.sub r6,r7,r8
+ l.and r3,r6,r15
+ l.srli r3,r3,31
+ l.addi r4,r0,0
+ l.sfne r3,r4
+ l.bf 1f
+ l.slli r3,r11,1
+ l.addi r4,r0,1
+1:
+ l.slli r5,r5,1
+ l.sfne r4,r17
+ l.bnf 2f
+ l.or r11,r3,r4
+ l.addi r7,r6,0
+2:
+ l.addi r9,r9,1
+ l.sfltu r9,r13
+ l.bf 3b
+ l.nop 0
+ l.j 4f
+ l.nop 0
+6:
+ l.j 4f
+ l.addi r11,r0,1
+5:
+ l.addi r7,r5,0
+4:
+ l.lwz r9,0(r1)
+ l.jr r9
+ l.addi r1,r1,4
+#endif
+
+
+#ifdef L__divsi3
+ENTRY(__divsi3)
+ l.addi r1,r1,-8
+ l.sw 0(r1),r9
+ l.sw 4(r1),r14
+ l.addi r5,r3,0
+ l.addi r14,r0,0
+ l.sflts r5,r0
+ l.bnf 1f
+ l.addi r3,r0,0
+ l.addi r14,r0,1
+ l.sub r5,r0,r5
+1:
+ l.sflts r4,r0
+ l.bnf 1f
+ l.nop 0
+ l.addi r14,r14,1
+ l.sub r4,r0,r4
+1:
+ l.jal __udivsi3
+ l.addi r3,r5,0
+ l.sfeqi r14,1
+ l.bnf 1f
+ l.nop 0
+ l.sub r11,r0,r11
+1:
+ l.lwz r9,0(r1)
+ l.lwz r14,4(r1)
+ l.jr r9
+ l.addi r1,r1,8
+#endif
+
+
+#ifdef L__umodsi3
+ENTRY(__umodsi3)
+ l.addi r1,r1,-4
+ l.sw 0(r1),r9
+ l.jal __udivsi3
+ l.nop 0
+ l.addi r11,r7,0
+ l.lwz r9,0(r1)
+ l.jr r9
+ l.addi r1,r1,4
+#endif
+
+
+#ifdef L__modsi3
+ENTRY(__modsi3)
+ l.addi r1,r1,-8
+ l.sw 0(r1),r9
+ l.sw 4(r1),r14
+ l.addi r14,r0,0
+ l.sflts r3,r0
+ l.bnf 1f
+ l.nop 0
+ l.addi r14,r0,1
+ l.sub r3,r0,r3
+1:
+ l.sflts r4,r0
+ l.bnf 1f
+ l.nop 0
+ l.sub r4,r0,r4
+1:
+ l.jal __udivsi3
+ l.nop 0
+ l.sfeqi r14,1
+ l.bnf 1f
+ l.addi r11,r7,0
+ l.sub r11,r0,r11
+1:
+ l.lwz r9,0(r1)
+ l.lwz r14,4(r1)
+ l.jr r9
+ l.addi r1,r1,8
+#endif
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/libgcc/config/or1k/sfp-machine.h gcc-4.8.2-or1k-rtems/libgcc/config/or1k/sfp-machine.h
--- gcc-4.8.2/libgcc/config/or1k/sfp-machine.h 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/libgcc/config/or1k/sfp-machine.h 2014-03-14 07:28:08.000000000 +0200
@@ -0,0 +1,51 @@
+#define _FP_W_TYPE_SIZE 32
+#define _FP_W_TYPE unsigned long
+#define _FP_WS_TYPE signed long
+#define _FP_I_TYPE long
+
+#define _FP_MUL_MEAT_S(R,X,Y) \
+ _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_D(R,X,Y) \
+ _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y) \
+ _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_loop(S,R,X,Y)
+#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y)
+
+#define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1)
+#define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1), -1
+#define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
+#define _FP_NANSIGN_S 0
+#define _FP_NANSIGN_D 0
+#define _FP_NANSIGN_Q 0
+
+#define _FP_KEEPNANFRACP 1
+
+/* Someone please check this. */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \
+ do { \
+ if ((_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs) \
+ && !(_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs)) \
+ { \
+ R##_s = Y##_s; \
+ _FP_FRAC_COPY_##wc(R,Y); \
+ } \
+ else \
+ { \
+ R##_s = X##_s; \
+ _FP_FRAC_COPY_##wc(R,X); \
+ } \
+ R##_c = FP_CLS_NAN; \
+ } while (0)
+
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+
+#define __BYTE_ORDER __BIG_ENDIAN
+
+/* Define ALIASNAME as a strong alias for NAME. */
+# define strong_alias(name, aliasname) _strong_alias(name, aliasname)
+# define _strong_alias(name, aliasname) \
+ extern __typeof (name) aliasname __attribute__ ((alias (#name)));
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/libgcc/config/or1k/t-crtstuff gcc-4.8.2-or1k-rtems/libgcc/config/or1k/t-crtstuff
--- gcc-4.8.2/libgcc/config/or1k/t-crtstuff 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/libgcc/config/or1k/t-crtstuff 2014-03-14 07:28:08.000000000 +0200
@@ -0,0 +1,4 @@
+# This will prevent gcc from appending data to .eh_frame.
+# Other archs use fno-asynchronous-unwind-tables but we do not have that flag.
+CRTSTUFF_T_CFLAGS += -fno-dwarf2-cfi-asm
+CRTSTUFF_T_CFLAGS_S += -fno-dwarf2-cfi-asm
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/libgcc/config/or1k/t-linux gcc-4.8.2-or1k-rtems/libgcc/config/or1k/t-linux
--- gcc-4.8.2/libgcc/config/or1k/t-linux 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/libgcc/config/or1k/t-linux 2014-03-14 07:28:08.000000000 +0200
@@ -0,0 +1,12 @@
+MULTILIB_DIRNAMES = be
+EXTRA_MULTILIB_PARTS = crti.o crtbegin.o crtend.o crtn.o
+
+# hack:
+# the non-shared uclibc-0.9.31/libc/misc/internals/__uClibc_main.c
+# already defines __dso_handle. To avoid a duplicate definition,
+# we rename the crtbegin one.
+# JPB 18-Nov-10: Commented out, since uClibc no longer defines.
+# amend gcc Makefile CLFAGS variable
+# $(T)crtbegin.o: CRTSTUFF_CFLAGS += '-D__dso_handle=__dso_handle_dummy'
+# amend libgcc Makefile CLFAGS variable
+# crtbegin$(objext): CRTSTUFF_T_CFLAGS += '-D__dso_handle=__dso_handle_dummy'
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/libgcc/config/or1k/t-or1k gcc-4.8.2-or1k-rtems/libgcc/config/or1k/t-or1k
--- gcc-4.8.2/libgcc/config/or1k/t-or1k 1970-01-01 02:00:00.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/libgcc/config/or1k/t-or1k 2014-03-14 07:28:08.000000000 +0200
@@ -0,0 +1,30 @@
+# t-or1k is a Makefile fragment to be included when
+# building gcc for the or1k target
+
+# Copyright (C) 2010 Embecosm Limited
+
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# .
+
+# for now, don't use asm versions of these functions
+LIB2ADD = \
+ $(srcdir)/udivmod.c \
+ $(srcdir)/divmod.c \
+ $(srcdir)/udivmodsi4.c \
+ $(srcdir)/config/or1k/lib2funcs.c
+
+#LIB1ASMSRC = or1k/or1k.S
+#LIB1ASMFUNCS = __mulsi3 __udivsi3 __divsi3 __umodsi3 __modsi3
diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/libgcc/config.host gcc-4.8.2-or1k-rtems/libgcc/config.host
--- gcc-4.8.2/libgcc/config.host 2013-07-09 23:35:57.000000000 +0200
+++ gcc-4.8.2-or1k-rtems/libgcc/config.host 2014-04-28 20:14:29.949218502 +0200
@@ -137,6 +137,12 @@
cpu_type=mips
tmake_file=mips/t-mips
;;
+or1k-*-*)
+ cpu_type=or1k
+ ;;
+or1knd-*-*)
+ cpu_type=or1k
+ ;;
powerpc*-*-*)
cpu_type=rs6000
;;
@@ -797,6 +803,18 @@
# Don't use default.
extra_parts=
;;
+or1k*-*-linux* | or1k*-*-uclinux*)
+ tmake_file="$tmake_file or1k/t-or1k or1k/t-linux or1k/t-crtstuff t-softfp-sfdf t-softfp"
+ md_unwind_header=or1k/linux-unwind.h
+ ;;
+or1k*-*-rtems*)
+ tmake_file="$tmake_file or1k/t-or1k or1k/t-crtstuff t-softfp-sfdf t-softfp"
+ extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o crti.o crtn.o"
+ ;;
+or1k*-*-*)
+ tmake_file="$tmake_file or1k/t-or1k or1k/t-crtstuff t-softfp-sfdf t-softfp"
+ extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o crti.o crtn.o"
+ ;;
pdp11-*-*)
tmake_file="pdp11/t-pdp11 t-fdpbit"
;;