OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gcc/] [gcc-3.4.4/] [gcc-3.4.4-or32-unified.diff] - Rev 1765

Compare with Previous | Blame | View Log

diff -Nru gcc-3.4.4.orig/config.sub gcc-3.4.4-DONE/config.sub
--- gcc-3.4.4.orig/config.sub	2004-02-22 16:44:23.000000000 +0200
+++ gcc-3.4.4-DONE/config.sub	2005-12-13 17:38:35.000000000 +0200
@@ -256,7 +256,7 @@
 	| mn10200 | mn10300 \
 	| msp430 \
 	| ns16k | ns32k \
-	| openrisc | or32 \
+	| or32 \
 	| pdp10 | pdp11 | pj | pjl \
 	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
 	| pyramid \
@@ -750,9 +750,8 @@
 		basic_machine=hppa1.1-oki
 		os=-proelf
 		;;
-	or32 | or32-*)
-		basic_machine=or32-unknown
-		os=-coff
+ 	or32 | or32-*)
+		basic_machine=or32-`echo $basic_machine | sed 's/^[^-]*-//'`
 		;;
 	os400)
 		basic_machine=powerpc-ibm
@@ -1355,8 +1354,8 @@
 	mips*-*)
 		os=-elf
 		;;
-	or32-*)
-		os=-coff
+ 	or32-*)
+		os=-elf
 		;;
 	*-tti)	# must be before sparc entry or we get the wrong os.
 		os=-sysv3
diff -Nru gcc-3.4.4.orig/configure.in gcc-3.4.4-DONE/configure.in
--- gcc-3.4.4.orig/configure.in	2005-03-08 19:31:40.000000000 +0200
+++ gcc-3.4.4-DONE/configure.in	2005-12-13 17:38:35.000000000 +0200
@@ -608,6 +608,9 @@
   mn10300-*-*)
     noconfigdirs="$noconfigdirs ${libgcj}"
     ;;
+  or32-*-*)
+    noconfigdirs="$noconfigdirs target-libgloss ${libgcj}"
+    ;;
   powerpc-*-aix*)
     # copied from rs6000-*-* entry
     noconfigdirs="$noconfigdirs gprof target-libgloss ${libgcj}"
diff -Nru gcc-3.4.4.orig/gcc/config/or32/default.h gcc-3.4.4-DONE/gcc/config/or32/default.h
--- gcc-3.4.4.orig/gcc/config/or32/default.h	1970-01-01 02:00:00.000000000 +0200
+++ gcc-3.4.4-DONE/gcc/config/or32/default.h	2005-11-29 16:23:09.000000000 +0200
@@ -0,0 +1,74 @@
+/* Definitions of target machine for GNU compiler for OR1K running Linux.
+   (Actually OR1K is not yet running Linux but eventually it will).
+   Copyright (C) 1996, 1997, 1998, 2005 Free Software Foundation, Inc.
+   Contributed by Damjan Lampret <damjanl@bsemi.com> in 1999.
+   Based upon the rs6000 port.
+   
+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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES \
+ "-DOR1K -D__or1k__ -D__OR1K__ -D__ELF__ -Dunix -Dlinux -Dor1k -Asystem(unix) -Asystem(linux) -Acpu(or1k) -Amachine(or1k)"
+
+#undef	CPP_OS_DEFAULT_SPEC
+#define CPP_OS_DEFAULT_SPEC "%(cpp_os_linux)"
+
+#undef LINK_SPEC
+#define LINK_SPEC "-m elf32or32 %{G*} %{shared:-shared} \
+  %{!shared: \
+    %{!static: \
+      %{rdynamic:-export-dynamic} \
+      %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}} \
+    %{static:-static}}"
+
+#undef	LIB_DEFAULT_SPEC
+#define LIB_DEFAULT_SPEC "%(lib_linux)"
+
+#undef	STARTFILE_DEFAULT_SPEC
+#define STARTFILE_DEFAULT_SPEC "%(startfile_linux)"
+
+#undef	ENDFILE_DEFAULT_SPEC
+#define ENDFILE_DEFAULT_SPEC "%(endfile_linux)"
+
+#undef	LINK_START_DEFAULT_SPEC
+#define LINK_START_DEFAULT_SPEC "%(link_start_linux)"
+
+#undef	LINK_OS_DEFAULT_SPEC
+#define LINK_OS_DEFAULT_SPEC "%(link_os_linux)"
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (OpenRISC 1000 GNU/Linux)");
+
+/* Define this macro as a C expression for the initializer of an
+   array of string to tell the driver program which options are
+   defaults for this target and thus do not need to be handled
+   specially when using `MULTILIB_OPTIONS'.
+
+   Do not define this macro if `MULTILIB_OPTIONS' is not defined in
+   the target makefile fragment or if none of the options listed in
+   `MULTILIB_OPTIONS' are set by default.  *Note Target Fragment::.  */
+
+#undef	MULTILIB_DEFAULTS
+#define	MULTILIB_DEFAULTS { "mbig", "mcall-linux" }
+
+#undef DEFAULT_VTABLE_THUNKS
+#ifndef USE_GNULIBC_1
+#define DEFAULT_VTABLE_THUNKS 1
+#endif
+
+#undef JUMP_TABLES_IN_TEXT_SECTION
+#define JUMP_TABLES_IN_TEXT_SECTION 0
diff -Nru gcc-3.4.4.orig/gcc/config/or32/elf.h gcc-3.4.4-DONE/gcc/config/or32/elf.h
--- gcc-3.4.4.orig/gcc/config/or32/elf.h	1970-01-01 02:00:00.000000000 +0200
+++ gcc-3.4.4-DONE/gcc/config/or32/elf.h	2005-11-29 16:23:09.000000000 +0200
@@ -0,0 +1,45 @@
+/* Definitions for rtems targeting an OpenRisc OR32 using COFF
+   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.  */
+
+#undef  TARGET_VERSION
+#define TARGET_VERSION  fputs (" (OR32/ELF)", stderr);
+
+/* Use ELF */
+#undef  OBJECT_FORMAT_ELF
+#define OBJECT_FORMAT_ELF
+
+/* use SDB debugging info and make it default */
+#undef  DBX_DEBUGGING_INFO
+#define DBX_DEBUGGING_INFO
+
+#undef  PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+
+#undef  PUT_SDB_DEF
+#define PUT_SDB_DEF
+
+/* Generate calls to memcpy, memcmp and memset.  */
+#ifndef TARGET_MEM_FUNCTIONS
+#  define TARGET_MEM_FUNCTIONS
+#endif
+
+#undef  USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX "_"
diff -Nru gcc-3.4.4.orig/gcc/config/or32/linux-elf.h gcc-3.4.4-DONE/gcc/config/or32/linux-elf.h
--- gcc-3.4.4.orig/gcc/config/or32/linux-elf.h	1970-01-01 02:00:00.000000000 +0200
+++ gcc-3.4.4-DONE/gcc/config/or32/linux-elf.h	2005-11-29 16:23:09.000000000 +0200
@@ -0,0 +1,65 @@
+/* Definitions for or32 running Linux-based GNU systems using ELF
+   Copyright (C) 2002, 2005
+   Free Software Foundation, Inc.
+   Contributed by Marko Mlinar <markom@opencores.org>
+
+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.  */
+
+/* Run-time Target Specification.  */
+#undef  TARGET_VERSION
+#define TARGET_VERSION  fputs (" (OR32 GNU/Linux with ELF)", stderr);
+
+/* Do not assume anything about header files.  */
+#define NO_IMPLICIT_EXTERN_C
+
+#undef  USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX "_"
+
+
+/* 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
diff -Nru gcc-3.4.4.orig/gcc/config/or32/linux-gas.h gcc-3.4.4-DONE/gcc/config/or32/linux-gas.h
--- gcc-3.4.4.orig/gcc/config/or32/linux-gas.h	1970-01-01 02:00:00.000000000 +0200
+++ gcc-3.4.4-DONE/gcc/config/or32/linux-gas.h	2005-11-29 16:23:09.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 <markom@opencores.org>
+
+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 <machine/ansi.h> */
+
+#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 -Nru gcc-3.4.4.orig/gcc/config/or32/or32.c gcc-3.4.4-DONE/gcc/config/or32/or32.c
--- gcc-3.4.4.orig/gcc/config/or32/or32.c	1970-01-01 02:00:00.000000000 +0200
+++ gcc-3.4.4-DONE/gcc/config/or32/or32.c	2005-11-29 16:23:09.000000000 +0200
@@ -0,0 +1,1260 @@
+/* Subroutines for insn-output.c for GNU compiler.  OpenRISC 1000 version.
+   Copyright (C) 1987, 1992, 1997, 1999, 2000, 2001, 2002, 2003, 2004,
+   2005  Free Software Foundation, Inc
+   Contributed by Damjan Lampret <damjanl@bsemi.com> in 1999.
+   Major optimizations by Matjaz Breskvar <matjazb@bsemi.com> 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.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "real.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "tree.h"
+#include "expr.h"
+#include "except.h"
+#include "function.h"
+#include "toplev.h"
+#include "recog.h"
+#include "tm_p.h"
+#include "debug.h"
+#include "output.h"
+#include "target.h"
+#include "target-def.h"
+#include "ggc.h"
+#include "optabs.h"
+
+/* Set thist to nonzero if you want l.nop instruction in delay slot
+   of l.jr instruction in epilogue. */
+#define  NOP_DELAY_SLOT_FILL 0
+
+/* This is the pseudo register number that holds the comparison flags */
+
+#define FLAGS_REG 32
+
+/* Save information from a "cmpxx" operation until the branch or scc is
+   emitted.  */
+rtx or32_compare_op0, or32_compare_op1;
+
+/* used in function prologue/epilogue generation */
+extern int leaf_function;
+
+/* Local function prototypes */
+static void or32_output_function_prologue (FILE * file, HOST_WIDE_INT vars);
+static void or32_output_function_epilogue (FILE * file, HOST_WIDE_INT vars);
+static bool or32_save_reg_p (int regno);
+HOST_WIDE_INT or32_compute_frame_size (HOST_WIDE_INT size);
+static rtx emit_frame_insn (rtx insn);
+static rtx indexed_memory (rtx base, HOST_WIDE_INT disp);
+void or32_expand_prologue (void);
+void or32_expand_epilogue (int sibcall);
+const char *or32_output_move_double (rtx * operands);
+enum rtx_code or32_reverse_condition (enum machine_mode mode,
+				      enum rtx_code code);
+enum machine_mode or32_cc_mode (enum rtx_code code, rtx op0, rtx op1);
+rtx or32_expand_compare (enum rtx_code code, rtx op0, rtx op1);
+void or32_expand_branch (enum rtx_code code, rtx label);
+static int or32_emit_int_cmove (rtx dest, rtx op, rtx true_cond,
+				rtx false_cond);
+int or32_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond);
+const char *output_cmov (rtx * operands);
+const char *output_bf (rtx * operands);
+void or32_emit_set_const32 (rtx op0, rtx op1);
+int or32_register_move_cost (enum machine_mode mode, enum reg_class from,
+			     enum reg_class to);
+int or32_memory_move_cost (enum machine_mode mode, enum reg_class class,
+			   int in);
+int or32_branch_cost ();
+
+
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE or32_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE or32_output_function_epilogue
+
+static bool or32_function_ok_for_sibcall (tree decl, tree exp);
+
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL or32_function_ok_for_sibcall
+
+
+/* Initialize the GCC target structure.  */
+struct gcc_target targetm = TARGET_INITIALIZER;
+
+/* Stack layout we use for pushing and poping saved registers */
+struct or32_frame_info
+{
+  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;
+  HOST_WIDE_INT mask;
+};
+
+static struct or32_frame_info frame_info;
+
+/* Returns 1 if OP is either a pseudo-register or a register denoting a
+   CR field.  */
+
+int
+cc_reg_operand (rtx op, enum machine_mode mode)
+{
+  register_operand (op, mode);
+
+  if (GET_CODE (op) == REG && REGNO (op) == 32)
+    return 1;
+
+  return 0;
+}
+
+int
+sym_ref_mem_operand (op, mode)
+     register rtx op;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+  if (GET_CODE (op) == MEM)
+    {
+      rtx t1 = XEXP (op, 0);
+      if (GET_CODE (t1) == SYMBOL_REF)
+	return 1;
+    }
+  return 0;
+}
+
+/* Return 1 if OP is a valid operand for the source of a move insn.  */
+
+int
+input_operand (rtx op, enum machine_mode mode)
+{
+
+  /* If both modes are non-void they must be the same.  */
+  if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
+    return 0;
+
+  /* Accept CONSTANT_P_RTX, since it will be gone by CSE1 and result in 0/1.  */
+  if (GET_CODE (op) == CONSTANT_P_RTX)
+    return 1;
+
+  /* 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)
+	  && (CONST_OK_FOR_LETTER_P (INTVAL (op), 'K')
+	      || CONST_OK_FOR_LETTER_P (INTVAL (op), 'M')
+	      || CONST_OK_FOR_LETTER_P (INTVAL (op), 'I'))))
+    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;
+}
+
+/* Test for a valid operand for a call instruction.  Don't allow the
+   arg pointer register or virtual regs since they may decay into
+   reg + const, which the patterns can't handle.  */
+
+int
+sibcall_insn_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+
+
+  /* Disallow indirect through a virtual register.  This leads to
+     compiler aborts when trying to eliminate them.  */
+  if (GET_CODE (op) == REG
+      && (op == arg_pointer_rtx
+	  || op == frame_pointer_rtx
+	  || (REGNO (op) >= FIRST_PSEUDO_REGISTER
+	      && REGNO (op) <= LAST_VIRTUAL_REGISTER)))
+    {
+
+      fprintf (stderr, "0\n");
+      return 0;
+    }
+
+  /* Explicitly allow SYMBOL_REF even if pic.  */
+  if (GET_CODE (op) == SYMBOL_REF)
+    return 1;
+
+  /* Otherwise we can only allow register operands.  */
+  return register_operand (op, Pmode);
+}
+
+
+/* Add a REG_MAYBE_DEAD note to the insn.  */
+static void
+or32_maybe_dead (rtx insn)
+{
+  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
+					const0_rtx, REG_NOTES (insn));
+}
+
+int
+print_operand_punct_valid_p (code)
+     int code;
+{
+  switch (code)
+    {
+    case '(':			/* idea taken from sparc; output nop for %( if
+				   not optimizing or the slot is not filled. */
+    case '%':
+      return 1;
+    }
+  return 0;
+}
+
+void
+print_operand_address (file, addr)
+     FILE *file;
+     register rtx addr;
+{
+  register rtx reg1, reg2, breg, ireg;
+  rtx offset;
+
+  switch (GET_CODE (addr))
+    {
+    case MEM:
+      if (GET_CODE (XEXP (addr, 0)) == REG)
+	fprintf (file, "%s", reg_names[REGNO (addr)]);
+      else
+	abort ();
+      break;
+
+    case REG:
+      fprintf (file, "0(%s)", reg_names[REGNO (addr)]);
+      break;
+
+    case PLUS:
+      reg1 = 0;
+      reg2 = 0;
+      ireg = 0;
+      breg = 0;
+      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 (file, "(%s)", reg_names[REGNO (addr)]);
+      break;
+
+    default:
+      /* fprintf(file, "{%d}", GET_CODE (addr)); */
+      output_addr_const (file, addr);
+    }
+}
+
+/* Calulcate and return stack size for current function.  */
+static int
+calculate_stack_size (int vars, int *lr_save_area,
+		      int *fp_save_area, int *gpr_save_area, int *save_area)
+{
+  int regno;
+
+  *gpr_save_area = 0;
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+    {
+      if (regs_ever_live[regno] && !call_used_regs[regno])
+	*gpr_save_area += 4;
+    }
+
+  *lr_save_area = (!current_function_is_leaf
+		   || regs_ever_live[LINK_REGNUM]) ? 4 : 0;
+  *fp_save_area = frame_pointer_needed ? 4 : 0;
+
+  *save_area = (OR32_ALIGN (current_function_outgoing_args_size, 4)
+		+ *lr_save_area + *fp_save_area);
+
+  return
+    (OR32_ALIGN (current_function_outgoing_args_size, 4)
+     + *lr_save_area + *fp_save_area + *gpr_save_area + OR32_ALIGN (vars, 4));
+}
+
+/* Set up the stack and frame pointer (if desired) for the
+   function.  */
+static void
+or32_output_function_prologue (FILE * file, HOST_WIDE_INT vars)
+{
+  int save_area;
+  int gpr_save_area;
+  int lr_save_area;
+  int fp_save_area;
+  int stack_size;
+  int regno;
+
+  if (TARGET_SCHED_LOGUE)
+    return;
+
+#if 0
+  save_area = 0;
+
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+    {
+      if (regs_ever_live[regno] && !call_used_regs[regno])
+	{
+	  save_area += 1;
+	}
+    }
+
+  if (save_area != 0)
+    fprintf (file, "\tl.nop \t0x%x\n", 0x100 + save_area);
+
+  return;
+#endif
+
+  if (vars < 0)
+    abort ();
+
+  stack_size = calculate_stack_size
+    (vars, &lr_save_area, &fp_save_area, &gpr_save_area, &save_area);
+
+  fprintf (file,
+	   "\n\t# gpr_save_area %d vars %ld current_function_outgoing_args_size %d\n",
+	   gpr_save_area, vars, current_function_outgoing_args_size);
+
+  if (stack_size >= 0x8000)
+    {
+      fprintf (file, "\tl.movhi   \tr%d,hi(%d)\n", GP_ARG_RETURN, stack_size);
+      fprintf (file, "\tl.ori   \tr%d,r%d,lo(%d)\n", GP_ARG_RETURN,
+	       GP_ARG_RETURN, stack_size);
+      fprintf (file, "\tl.sub   \tr%d,r%d,r%d\n", STACK_POINTER_REGNUM,
+	       STACK_POINTER_REGNUM, GP_ARG_RETURN);
+    }
+  else if (stack_size > 0)
+    {
+      fprintf (file, "\tl.addi   \tr%d,r%d,%d\n", STACK_POINTER_REGNUM,
+	       STACK_POINTER_REGNUM, -stack_size);
+    }
+
+  if (fp_save_area)
+    {
+      fprintf (file, "\tl.sw     \t%d(r%d),r%d\n",
+	       OR32_ALIGN (current_function_outgoing_args_size, 4)
+	       + lr_save_area, STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM);
+      if (stack_size >= 0x8000)
+	fprintf (file, "\tl.add   \tr%d,r%d,r%d\n", FRAME_POINTER_REGNUM,
+		 STACK_POINTER_REGNUM, GP_ARG_RETURN);
+      else
+	fprintf (file, "\tl.addi   \tr%d,r%d,%d\n", FRAME_POINTER_REGNUM,
+		 STACK_POINTER_REGNUM, stack_size);
+    }
+
+  if (lr_save_area)
+    {
+      fprintf (file, "\tl.sw     \t%d(r%d),r%d\n",
+	       OR32_ALIGN (current_function_outgoing_args_size, 4),
+	       STACK_POINTER_REGNUM, LINK_REGNUM);
+    }
+
+  save_area = (OR32_ALIGN (current_function_outgoing_args_size, 4)
+	       + lr_save_area + fp_save_area);
+
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+    {
+      if (regs_ever_live[regno] && !call_used_regs[regno])
+	{
+	  fprintf (file, "\tl.sw    \t%d(r%d),r%d\n", save_area,
+		   STACK_POINTER_REGNUM, regno);
+	  save_area += 4;
+	}
+    }
+}
+
+/* Do any necessary cleanup after a function to restore stack, frame,
+   and regs.  */
+static void
+or32_output_function_epilogue (FILE * file, HOST_WIDE_INT vars)
+{
+  int save_area;
+  int gpr_save_area;
+  int lr_save_area;
+  int fp_save_area;
+  int stack_size;
+  int regno;
+
+  if (TARGET_SCHED_LOGUE)
+    return;
+
+#if 0
+  save_area = 0;
+
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+    {
+      if (regs_ever_live[regno] && !call_used_regs[regno])
+	{
+	  save_area += 1;
+	}
+    }
+
+  fprintf (file, "\tl.nop \t0x%x\n", 0x200 + save_area);
+  return;
+#endif
+
+  stack_size = calculate_stack_size
+    (vars, &lr_save_area, &fp_save_area, &gpr_save_area, &save_area);
+
+  if (lr_save_area)
+    {
+      fprintf (file, "\tl.lwz    \tr%d,%d(r%d)\n", LINK_REGNUM,
+	       OR32_ALIGN (current_function_outgoing_args_size, 4),
+	       STACK_POINTER_REGNUM);
+    }
+  if (fp_save_area)
+    {
+      fprintf (file, "\tl.lwz    \tr%d,%d(r%d)\n", FRAME_POINTER_REGNUM,
+	       OR32_ALIGN (current_function_outgoing_args_size, 4)
+	       + lr_save_area, STACK_POINTER_REGNUM);
+    }
+  save_area = (OR32_ALIGN (current_function_outgoing_args_size, 4)
+	       + lr_save_area + fp_save_area);
+
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+    {
+      if (regs_ever_live[regno] && !call_used_regs[regno])
+	{
+	  fprintf (file, "\tl.lwz    \tr%d,%d(r%d)\n", regno, save_area,
+		   STACK_POINTER_REGNUM);
+	  save_area += 4;
+	}
+    }
+
+  if (stack_size >= 0x8000)
+    {
+      fprintf (file, "\tl.movhi   \tr3,hi(%d)\n", stack_size);
+      fprintf (file, "\tl.ori   \tr3,r3,lo(%d)\n", stack_size);
+
+      if (!TARGET_ALIGNED_JUMPS)
+	fprintf (file, "\tl.jr  \tr%d\n", LINK_REGNUM);
+      else
+	fprintf (file, "\t.balignl 0x8,0x15000015,0x4;l.jr  \tr%d\n",
+		 LINK_REGNUM);
+
+      fprintf (file, "\tl.add   \tr%d,r%d,r3\n", STACK_POINTER_REGNUM,
+	       STACK_POINTER_REGNUM);
+    }
+  else if (stack_size > 0)
+    {
+      if (!TARGET_ALIGNED_JUMPS)
+	fprintf (file, "\tl.jr  \tr%d\n", LINK_REGNUM);
+      else
+	fprintf (file, "\t.balignl 0x8,0x15000015,0x4;l.jr  \tr%d\n",
+		 LINK_REGNUM);
+
+      fprintf (file, "\tl.addi   \tr%d,r%d,%d\n", STACK_POINTER_REGNUM,
+	       STACK_POINTER_REGNUM, stack_size);
+    }
+  else
+    {
+      if (!TARGET_ALIGNED_JUMPS)
+	fprintf (file, "\tl.jr  \tr%d\n", LINK_REGNUM);
+      else
+	fprintf (file, "\t.balignl 0x8,0x15000015,0x4;l.jr  \tr%d\n",
+		 LINK_REGNUM);
+
+      fprintf (file, "\tl.nop\n");
+    }
+
+#if 0
+  fprintf (file, ".endproc _%s\n", get_function_name ());
+#endif
+}
+
+/* Compuate full frame size and layout.  SIZE is the size of the
+   functions local variables.  Store information in FRAME_INFO and
+   return total size of stack frame.  */
+
+HOST_WIDE_INT
+or32_compute_frame_size (HOST_WIDE_INT size)
+{
+  HOST_WIDE_INT args_size;
+  HOST_WIDE_INT vars_size;
+  HOST_WIDE_INT stack_offset;
+  int regno;
+
+  args_size = current_function_outgoing_args_size;
+  vars_size = OR32_ALIGN (size, 4);
+
+  frame_info.args_size = args_size;
+  frame_info.vars_size = vars_size;
+
+  /* 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 && current_function_is_leaf)
+    args_size = 0;
+
+  stack_offset = args_size;
+
+  /* Save link register right after possible outgoing arguments.  */
+  if (or32_save_reg_p (LINK_REGNUM))
+    {
+      frame_info.lr_save_offset = stack_offset;
+      frame_info.save_lr_p = true;
+      stack_offset = stack_offset + UNITS_PER_WORD;
+    }
+  else
+    frame_info.save_lr_p = false;
+
+  /* Save frame pointer right after possible link register.  */
+  if (or32_save_reg_p (FRAME_POINTER_REGNUM))
+    {
+      frame_info.fp_save_offset = stack_offset;
+      frame_info.save_fp_p = true;
+      stack_offset = stack_offset + UNITS_PER_WORD;
+    }
+  else
+    frame_info.save_fp_p = false;
+
+  frame_info.gpr_size = 0;
+  frame_info.mask = 0;
+  frame_info.gpr_offset = stack_offset;
+
+  for (regno = 0; regno <= LAST_INT_REG; regno++)
+    {
+      if (regno == LINK_REGNUM || regno == FRAME_POINTER_REGNUM)
+	/* These has already been saved if so needed.  */
+	continue;
+
+      if (or32_save_reg_p (regno))
+	{
+	  frame_info.gpr_size += UNITS_PER_WORD;
+	  frame_info.mask |= (1 << regno);
+	}
+    }
+
+  frame_info.total_size = ((frame_info.save_fp_p ? UNITS_PER_WORD : 0)
+			   + (frame_info.save_lr_p ? UNITS_PER_WORD : 0)
+			   + args_size + frame_info.gpr_size + vars_size);
+
+  return frame_info.total_size;
+}
+
+
+/* Return true if current function must save REGNO.  */
+static bool
+or32_save_reg_p (int regno)
+{
+  /* No need to save the faked cc0 register.  */
+  if (regno == FLAGS_REG)
+    return false;
+
+  /* Check call-saved registers.  */
+  if (regs_ever_live[regno] && !call_used_regs[regno])
+    return true;
+
+  /* We need to save the old frame pointer before setting up a new
+     one.  */
+  if (regno == FRAME_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 && regs_ever_live[regno])
+    return true;
+
+  return false;
+}
+
+/* Emit a frame related insn.  Same as emit_insn, but sets
+   RTX_FRAME_RELATED_P to one.  */
+
+static rtx
+emit_frame_insn (rtx insn)
+{
+  insn = emit_insn (insn);
+  RTX_FRAME_RELATED_P (insn) = 1;
+  return (insn);
+}
+
+static rtx
+indexed_memory (rtx base, HOST_WIDE_INT disp)
+{
+  return gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, base, GEN_INT (disp)));
+}
+
+/* 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
+or32_expand_prologue ()
+{
+  int total_size = or32_compute_frame_size (get_frame_size ());
+  rtx sp_rtx;
+  rtx value_rtx;
+
+  if (!total_size)
+    /* No frame needed.  */
+    return;
+
+  sp_rtx = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
+
+  if (total_size > 32767)
+    {
+      value_rtx = gen_rtx_REG (Pmode, GP_ARG_RETURN);
+      emit_frame_insn (gen_rtx_SET (Pmode, value_rtx, GEN_INT (total_size)));
+    }
+  else
+    value_rtx = GEN_INT (total_size);
+
+  /* Update the stack pointer to reflect frame size.  */
+  emit_frame_insn
+    (gen_rtx_SET (Pmode, stack_pointer_rtx,
+		  gen_rtx_MINUS (Pmode, stack_pointer_rtx, value_rtx)));
+
+  if (frame_info.save_fp_p)
+    {
+      emit_frame_insn
+	(gen_rtx_SET (Pmode,
+		      indexed_memory (stack_pointer_rtx,
+				      frame_info.fp_save_offset),
+		      frame_pointer_rtx));
+
+      emit_frame_insn
+	(gen_rtx_SET (Pmode, frame_pointer_rtx,
+		      gen_rtx_PLUS (Pmode, frame_pointer_rtx, value_rtx)));
+    }
+  if (frame_info.save_lr_p)
+    {
+
+      emit_frame_insn
+	(gen_rtx_SET (Pmode,
+		      indexed_memory (stack_pointer_rtx,
+				      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 <= LAST_INT_REG; regno++)
+	{
+	  HOST_WIDE_INT disp = frame_info.gpr_offset + offset;
+
+	  if (!(frame_info.mask & (1 << regno)))
+	    continue;
+
+	  emit_frame_insn
+	    (gen_rtx_SET (Pmode,
+			  indexed_memory (stack_pointer_rtx, disp),
+			  gen_rtx_REG (Pmode, regno)));
+	  offset = offset + UNITS_PER_WORD;
+	}
+    }
+}
+
+/* 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
+or32_expand_epilogue (int sibcall)
+{
+  int total_size = or32_compute_frame_size (get_frame_size ());
+  rtx value_rtx;
+
+  if (total_size > 32767)
+    {
+      value_rtx = gen_rtx_REG (Pmode, 3);
+
+      emit_insn (gen_rtx_SET (Pmode, value_rtx, GEN_INT (total_size)));
+    }
+  else
+    value_rtx = GEN_INT (total_size);
+
+  if (frame_info.save_lr_p)
+    {
+      or32_maybe_dead
+	(emit_insn
+	 (gen_rtx_SET (Pmode, gen_rtx_REG (Pmode, LINK_REGNUM),
+		       indexed_memory (stack_pointer_rtx,
+				       frame_info.lr_save_offset))));
+    }
+  if (frame_info.save_fp_p)
+    {
+      emit_insn
+	(gen_rtx_SET (Pmode, gen_rtx_REG (Pmode, FRAME_POINTER_REGNUM),
+		      indexed_memory (stack_pointer_rtx,
+				      frame_info.fp_save_offset)));
+    }
+
+  if (frame_info.gpr_size)
+    {
+      int offset = 0;
+      int regno;
+
+      for (regno = 0; regno <= LAST_INT_REG; regno++)
+	{
+	  HOST_WIDE_INT disp = frame_info.gpr_offset + offset;
+
+	  if (!(frame_info.mask & (1 << regno)))
+	    continue;
+
+	  emit_insn
+	    (gen_rtx_SET (Pmode, gen_rtx_REG (Pmode, regno),
+			  indexed_memory (stack_pointer_rtx, disp)));
+	  offset = offset + UNITS_PER_WORD;
+	}
+    }
+
+  if (total_size)
+    {
+      emit_insn (gen_rtx_SET (Pmode, stack_pointer_rtx,
+			      gen_rtx_PLUS (Pmode,
+					    stack_pointer_rtx, value_rtx)));
+    }
+
+  if (!sibcall)
+    emit_jump_insn (gen_return_internal (gen_rtx (REG, Pmode, 9)));
+}
+
+
+void
+print_operand (FILE * file, rtx x, int code)
+{
+  if (code == 'r' && GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == REG)
+    fprintf (file, "%s", reg_names[REGNO (XEXP (x, 0))]);
+  else if (code == '(')
+    {
+      if (dbr_sequence_length ())
+	fprintf (file, "\t# delay slot filled");
+      else
+	fprintf (file, "\n\tl.nop\t\t\t# nop delay slot");
+    }
+  else if (code == 'C')
+    {
+      switch (GET_CODE (x))
+	{
+	case EQ:
+	  fputs ("eq", file);
+	  break;
+	case NE:
+	  fputs ("ne", file);
+	  break;
+	case GT:
+	  fputs ("gts", file);
+	  break;
+	case GE:
+	  fputs ("ges", file);
+	  break;
+	case LT:
+	  fputs ("lts", file);
+	  break;
+	case LE:
+	  fputs ("les", file);
+	  break;
+	case GTU:
+	  fputs ("gtu", file);
+	  break;
+	case GEU:
+	  fputs ("geu", file);
+	  break;
+	case LTU:
+	  fputs ("ltu", file);
+	  break;
+	case LEU:
+	  fputs ("leu", file);
+	  break;
+	default:
+	  abort ();
+	}
+    }
+  else if (code == 'H')
+    {
+      if (GET_CODE (x) == REG)
+	fprintf (file, "%s", reg_names[REGNO (x) + 1]);
+      else
+	abort ();
+    }
+  else if (GET_CODE (x) == REG)
+    fprintf (file, "%s", reg_names[REGNO (x)]);
+  else if (GET_CODE (x) == MEM)
+    output_address (XEXP (x, 0));
+  else
+    output_addr_const (file, x);
+}
+
+/* Generate assembler code for a movdi/movdf */
+
+const char *
+or32_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 if (GET_CODE (operands[1]) == CONST_INT)
+	{
+	  if (INTVAL (operands[1]) < 0)
+	    output_asm_insn ("\tl.addi  \t%0, r0, -1", operands);
+	  else
+	    output_asm_insn ("\tl.or    \t%0, r0, r0", operands);
+	  output_asm_insn ("\tl.movhi \t%H0, hi(%1)", operands);
+	  output_asm_insn ("\tl.ori   \t%H0, %H0, lo(%1)", operands);
+	  return "";
+	}
+      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
+	abort ();
+    default:
+      abort ();
+    }
+}
+
+enum rtx_code
+or32_reverse_condition (enum machine_mode mode ATTRIBUTE_UNUSED,
+			enum rtx_code code)
+{
+  return reverse_condition (code);
+}
+
+enum machine_mode
+or32_cc_mode (enum rtx_code code,
+	      rtx op0 ATTRIBUTE_UNUSED, rtx op1 ATTRIBUTE_UNUSED)
+{
+
+  switch (code)
+    {
+    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:
+      abort ();
+    }
+}
+
+/* Generate insn patterns to do an integer compare of OPERANDS.  */
+
+static rtx
+or32_expand_int_compare (enum rtx_code code, rtx op0, rtx op1)
+{
+  enum machine_mode cmpmode;
+  rtx tmp, flags;
+
+  cmpmode = SELECT_CC_MODE (code, op0, op1);
+  flags = gen_rtx_REG (cmpmode, 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);
+}
+
+rtx
+or32_expand_compare (enum rtx_code code, rtx op0, rtx op1)
+{
+  return or32_expand_int_compare (code, op0, op1);
+}
+
+void
+or32_expand_branch (enum rtx_code code, rtx label)
+{
+  rtx tmp;
+
+  switch (GET_MODE (or32_compare_op0))
+    {
+    case SImode:
+      tmp = or32_expand_compare (code, or32_compare_op0, or32_compare_op1);
+      tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
+				  tmp,
+				  gen_rtx_LABEL_REF (VOIDmode, label),
+				  pc_rtx);
+      emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
+      return;
+
+
+    default:
+      abort ();
+    }
+
+}
+
+static int
+or32_emit_int_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
+{
+  rtx condition_rtx, cr;
+
+  if ((GET_MODE (or32_compare_op0) != SImode) &&
+      (GET_MODE (or32_compare_op0) != HImode) &&
+      (GET_MODE (or32_compare_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 = or32_expand_compare (GET_CODE (op),
+				       or32_compare_op0, or32_compare_op1);
+
+  cr = XEXP (condition_rtx, 0);
+
+  emit_insn (gen_cmov (dest, condition_rtx, true_cond, false_cond, cr));
+
+  return 1;
+}
+
+
+/* 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.  Return 0 if the hardware has no such operation.  */
+
+int
+or32_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 or32_emit_int_cmove (dest, op, true_cond, false_cond);
+}
+
+const char *
+output_bf (rtx * operands)
+{
+  enum rtx_code code;
+  enum machine_mode mode_calc, mode_got;
+
+  code = GET_CODE (operands[1]);
+  mode_calc = SELECT_CC_MODE (code, or32_compare_op0, or32_compare_op1);
+  mode_got = GET_MODE (operands[2]);
+
+  if (!TARGET_ALIGNED_JUMPS)
+    {
+      if (mode_calc != mode_got)
+	return "l.bnf   \t%l0%(";
+      else
+	return "l.bf    \t%l0%(";
+    }
+  else
+    {
+      if (mode_calc != mode_got)
+	return "\t.balignl 0x8,0x15000015,0x4;l.bnf   \t%l0%(";
+      else
+	return "\t.balignl 0x8,0x15000015,0x4;l.bf    \t%l0%(";
+    }
+}
+
+const char *
+output_cmov (rtx * operands)
+{
+  enum rtx_code code;
+  enum machine_mode mode_calc, mode_got;
+
+  code = GET_CODE (operands[1]);
+  mode_calc = SELECT_CC_MODE (code, or32_compare_op0, or32_compare_op1);
+  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";
+}
+
+/* Any function is ok for sibcall optimization if we allow this optimization
+ */
+static bool
+or32_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
+			      tree exp ATTRIBUTE_UNUSED)
+{
+  return TARGET_SIBCALL;
+}
+
+/* For now this is very simple way for sibcall support */
+
+void
+or32_expand_sibcall (rtx result, rtx addr, rtx args_size)
+{
+  emit_call_insn (gen_sibcall_internal (addr, args_size));
+}
+
+
+/* We know it can't be done in one insn when we get here,
+   the movsi expander guarantees this.  */
+void
+or32_emit_set_const32 (rtx op0, rtx op1)
+{
+  enum machine_mode mode = GET_MODE (op0);
+  rtx temp;
+
+
+  if (GET_CODE (op1) == CONST_INT)
+    {
+      HOST_WIDE_INT value = INTVAL (op1);
+
+      if (CONST_OK_FOR_LETTER_P (value & GET_MODE_MASK (mode), 'K')
+	  || CONST_OK_FOR_LETTER_P (value, 'M')
+	  || CONST_OK_FOR_LETTER_P (value, 'I'))
+	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
+    {
+
+#if 0
+      /* A symbol, emit in the traditional way.  */
+
+      emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_HIGH (mode, op1)));
+      emit_insn (gen_rtx_SET (VOIDmode,
+			      op0, gen_rtx_LO_SUM (mode, temp, op1)));
+#else
+      /* since or32 bfd can not deal with relocs that are not of type
+         OR32_CONSTH_RELOC + OR32_CONST_RELOC (ie move high must be
+         followed by exactly one lo_sum)
+       */
+      emit_insn (gen_movsi_insn_big (op0, op1));
+#endif
+    }
+}
+
+
+/* Functions returning costs and making code size/performance tradeoffs */
+
+int
+or32_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+			 enum reg_class from ATTRIBUTE_UNUSED,
+			 enum reg_class to ATTRIBUTE_UNUSED)
+{
+  return 2;
+}
+
+/* A C expressions returning the cost of moving data of MODE from a register to
+   or from memory.  */
+
+int
+or32_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+		       enum reg_class class ATTRIBUTE_UNUSED,
+		       int in ATTRIBUTE_UNUSED)
+{
+  return 2;
+}
+
+/* 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 or32 since that is roughly the average cost of an
+   unscheduled conditional branch.  
+
+   Cost of 2 and 3 give equal and ~0.7% bigger binaries
+
+*/
+int
+or32_branch_cost ()
+{
+  return 1;
+}
diff -Nru gcc-3.4.4.orig/gcc/config/or32/or32.h gcc-3.4.4-DONE/gcc/config/or32/or32.h
--- gcc-3.4.4.orig/gcc/config/or32/or32.h	1970-01-01 02:00:00.000000000 +0200
+++ gcc-3.4.4-DONE/gcc/config/or32/or32.h	2005-11-29 17:01:54.000000000 +0200
@@ -0,0 +1,1361 @@
+/* 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.
+   Contributed by Damjan Lampret <damjanl@bsemi.com> in 1999.
+   Major optimizations by Matjaz Breskvar <matjazb@bsemi.com> 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 _OR32_H_
+#define _OR32_H_
+
+/* Target CPU builtins */
+#define TARGET_CPU_CPP_BUILTINS()		\
+  do						\
+    {						\
+      builtin_define_std ("OR1K");		\
+      builtin_define_std ("or1k");		\
+      builtin_assert ("cpu=or1k");		\
+      builtin_assert ("machine=or1k");		\
+    }						\
+  while (0)
+
+#if 0
+
+/* Which library to get.  The only difference from the default is to get
+   libsc.a if -sim is given to the driver.  Repeat -lc -lsysX
+   {X=sim,linux}, because libsysX needs (at least) errno from libc, and
+   then we want to resolve new unknowns in libc against libsysX, not
+   libnosys.  */
+/* Override previous definitions (linux.h).  */
+#undef LIB_SPEC
+#define LIB_SPEC \
+ "%{sim*:-lc -lsyssim -lc -lsyssim}\
+  %{!sim*:%{g*:-lg}\
+    %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} -lbsp}\
+  -lnosys"
+#endif
+
+#define TARGET_VERSION fprintf (stderr, " (OpenRISC 1000)");
+
+/* Run-time compilation parameters selecting different hardware subsets.  */
+
+extern int target_flags;
+
+/* Enable hardware fp support. */
+#define MASK_HARD_FLOAT		0x00000001
+
+/* Enable hardware div instruction. */
+#define MASK_HARD_DIV		0x00000002
+
+/* Enable hardware mul instruction. */
+#define MASK_HARD_MUL           0x00000004
+
+/* Use aligned jumps. */
+#define MASK_ALIGNED_JUMPS      0x00000008
+
+/* Use l.extbs and l.exths instructions. */
+#define MASK_SEXT               0x00000010
+
+/* Use l.cmov instruction. */
+#define MASK_CMOV               0x00000020
+
+/* Emit prologue and epilogue. */
+#define MASK_SCHED_LOGUE        0x00000040
+
+/* Emit prologue and epilogue. */
+#define MASK_ROR                0x00000080
+
+/* Emit prologue and epilogue. */
+#define MASK_SIBCALL            0x00000100
+
+
+/* Macros used in the machine description to test the flags.  */
+
+#define TARGET_HARD_FLOAT	(target_flags & MASK_HARD_FLOAT)
+#define TARGET_HARD_DIV		(target_flags & MASK_HARD_DIV)
+#define TARGET_HARD_MUL         (target_flags & MASK_HARD_MUL)
+#define TARGET_ALIGNED_JUMPS    (target_flags & MASK_ALIGNED_JUMPS)
+#define TARGET_SEXT             (target_flags & MASK_SEXT)
+#define TARGET_CMOV             (target_flags & MASK_CMOV)
+#define TARGET_SCHED_LOGUE      (target_flags & MASK_SCHED_LOGUE)
+#define TARGET_ROR              (target_flags & MASK_ROR)
+#define TARGET_SIBCALL          (target_flags & MASK_SIBCALL)
+
+/* Macro to define tables used to set the flags.
+   This is a list in braces of pairs in braces,
+   each pair being { "NAME", VALUE }
+   where VALUE is the bits to set or minus the bits to clear.
+   An empty string NAME is used to identify the default VALUE.  */
+
+#define TARGET_SWITCHES						        	         \
+  { {"hard-float",	MASK_HARD_FLOAT,        N_("Use hardware floating point.")},     \
+    {"soft-float",	- MASK_HARD_FLOAT,      N_("Use software floating point.")},	 \
+    {"hard-div",	MASK_HARD_DIV,          N_("Use hardware divison.")},   	 \
+    {"soft-div",	- MASK_HARD_DIV,	N_("Use software divison.")},   	 \
+    {"hard-mul",	MASK_HARD_MUL,          N_("Use hardware multiplication.")},   	 \
+    {"soft-mul",	- MASK_HARD_MUL,	N_("Use software multiplication.")},   	 \
+    {"aj",              MASK_ALIGNED_JUMPS,     N_("Use aligned jumps.")},               \
+    {"no-aj",           - MASK_ALIGNED_JUMPS,   N_("Do not use aligned jumps.")},        \
+    {"sext",            MASK_SEXT,              N_("Use sign extending instructions.")}, \
+    {"no-sext",         - MASK_SEXT,            N_("Do not use sign extending insn.")},  \
+    {"cmov",            MASK_CMOV,              N_("Use conditional move insn.")},       \
+    {"no-cmov",         - MASK_CMOV,            N_("Do not use conditional move insn.")},\
+    {"logue",           MASK_SCHED_LOGUE,       N_("Schedule pro/epi-logue.")},          \
+    {"no-logue",        - MASK_SCHED_LOGUE,     N_("Do not schedule pro/epi-logue.")},   \
+    {"ror",             MASK_ROR,               N_("Emit ror insns.")},                  \
+    {"no-ror",          - MASK_ROR,             N_("Do not emit ror insns.")},           \
+    {"sibcall",         MASK_SIBCALL,           N_("Enable sibcall optimization.")},     \
+    {"no-sibcall",      - MASK_SIBCALL,         N_("Disable sibcall optimization.")},    \
+    { "",		TARGET_DEFAULT,         0}}
+
+/* Default target_flags if no switches specified.  */
+
+#ifndef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_HARD_MUL)
+#endif
+
+#undef TARGET_ASM_NAMED_SECTION
+#define TARGET_ASM_NAMED_SECTION  default_elf_asm_named_section
+
+/* 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 32
+
+/* 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
+
+/* 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 this if move instructions will actually fail to work
+   when given unaligned data.  */
+#define STRICT_ALIGNMENT 1 /* CHECK */
+
+/* Align an address */
+#define OR32_ALIGN(n,a) (((n) + (a) - 1) & ~((a) - 1))
+
+/* Define this macro if an argument declared as `char' or `short' in a
+   prototype 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. */
+#define PROMOTE_PROTOTYPES  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 */
+
+/* Define this if function arguments should also be promoted using the above
+   procedure.  */
+   
+#define PROMOTE_FUNCTION_ARGS
+   
+/* Likewise, if the function return value is promoted.  */
+   
+#define PROMOTE_FUNCTION_RETURN
+
+/*
+ * 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 */
+   
+/* Define this macro if it is as good or better for a function to
+   call itself with an explicit address than to call an address
+   kept in a register.  */
+#define NO_RECURSIVE_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 FIRST_PSEUDO_REGISTER 33
+#define LAST_INT_REG (FIRST_PSEUDO_REGISTER - 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.  */
+#define FIXED_REGISTERS {1, 1, 1, 0, 0, 0, 0, 0,   0, 1, 0, 0, 0, 0, 0, 0, \
+			 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1,  1, 1, 0, 1, 0, 1, 0, 1, \
+			     0, 1, 0, 1, 0, 1, 0, 1,  0, 1, 0, 1, 0, 1, 0, 1, 1}
+
+/* stack pointer: must be FIXED and CALL_USED */
+/* frame 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 returning the cost of moving data from a register of class
+   CLASS1 to one of CLASS2.  */
+#define REGISTER_MOVE_COST or32_register_move_cost
+
+/* A C expressions returning the cost of moving data of MODE from a register to
+   or from memory.  */
+#define MEMORY_MOVE_COST or32_memory_move_cost
+
+/* Specify the cost of a branch insn; roughly the number of extra insns that
+   should be added to avoid a branch. */
+#define BRANCH_COST or32_branch_cost()
+
+/* 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 FRAME_POINTER_REGNUM 2
+
+/* Link register. */
+#define LINK_REGNUM 9
+
+/* Value should be nonzero if functions must have frame pointers.
+   Zero means the frame pointer need not be set up (and parms
+   may be accessed via the stack pointer) in functions that seem suitable.
+   This is computed in `reload', in reload1.c.  */
+#define FRAME_POINTER_REQUIRED 0
+
+/* De ne this macro if debugging can be performed even without a frame pointer.
+   If this macro is de ned, GCC will turn on the `-fomit-frame-pointer' option
+   whenever `-O' is specifed.
+ */
+/*
+#define CAN_DEBUG_WITHOUT_FP 
+ */
+
+#define INITIAL_FRAME_POINTER_OFFSET(DEPTH)						\
+{ int regno;										\
+  int offset = 0;									\
+  for( regno=0; regno < FIRST_PSEUDO_REGISTER;  regno++ )				\
+    if( regs_ever_live[regno] && !call_used_regs[regno] )				\
+      offset += 4;									\
+  (DEPTH) = (!current_function_is_leaf || regs_ever_live[LINK_REGNUM] ? 4 : 0)	+	\
+		(frame_pointer_needed ? 4 : 0)					+	\
+		offset								+	\
+		OR32_ALIGN(current_function_outgoing_args_size,4)		+	\
+		OR32_ALIGN(get_frame_size(),4);						\
+}
+
+/* Base register for access to arguments of the function.  */
+#define ARG_POINTER_REGNUM FRAME_POINTER_REGNUM
+
+/* Register in which static-chain is passed to a function.  */
+#define STATIC_CHAIN_REGNUM 0
+
+/* 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 or32.
+
+   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.  */
+
+enum reg_class 
+{ 
+  NO_REGS,
+  GENERAL_REGS,
+  CR_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'.  */
+
+#define REG_CLASS_CONTENTS			     \
+{						     \
+  { 0x00000000, 0x00000000 }, /* NO_REGS */	     \
+  { 0xffffffff, 0x00000001 }, /* GENERAL_REGS */     \
+  { 0xffffffff, 0x00000000 }  /* 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.  */
+
+#define REGNO_REG_CLASS(REGNO)			\
+ ((REGNO) < 32 ? 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
+
+/* Get reg_class from a letter such as appears in the machine description.  */
+
+#define REG_CLASS_FROM_LETTER(C) NO_REGS
+
+#if 1
+/* The letters I, J, K, L and M in a register constraint string
+   can be used to stand for particular ranges of immediate operands.
+   This macro defines what the ranges are.
+   C is the letter, and VALUE is a constant value.
+   Return 1 if VALUE is in the range specified by C.  */
+
+#define CONST_OK_FOR_LETTER_P(VALUE, C)  \
+    (  (C) == 'I' ? ((VALUE) >=-32768 && (VALUE) <=32767) \
+     : (C) == 'J' ? ((VALUE) >=0 && (VALUE) <=0) \
+     : (C) == 'K' ? ((VALUE) >=0 && (VALUE) <=65535) \
+     : (C) == 'L' ? ((VALUE) >=0 && (VALUE) <=31) \
+     : (C) == 'M' ? (((VALUE) & 0xffff) == 0 )		\
+     : (C) == 'N' ? ((VALUE) >=-33554432 && (VALUE) <=33554431) \
+     : (C) == 'O' ? ((VALUE) >=0 && (VALUE) <=0) \
+     : 0 )
+#else
+
+/* The letters I, J, K, L, M, N, and P in a register constraint string
+   can be used to stand for particular ranges of immediate operands.
+   This macro defines what the ranges are.
+   C is the letter, and VALUE is a constant value.
+   Return 1 if VALUE is in the range specified by C.
+
+   `I' is a signed 16-bit constant
+   `J' is a constant with only the high-order 16 bits nonzero
+   `K' is a constant with only the low-order 16 bits nonzero
+   `L' is a signed 16-bit constant shifted left 16 bits
+   `M' is a constant that is greater than 31
+   `N' is a positive constant that is an exact power of two
+   `O' is the constant zero
+   `P' is a constant whose negation is a signed 16-bit constant */
+
+#define CONST_OK_FOR_LETTER_P(VALUE, C)					\
+   ( (C) == 'I' ? (unsigned HOST_WIDE_INT) ((VALUE) + 0x8000) < 0x10000	\
+   : (C) == 'J' ? ((VALUE) & (~ (unsigned HOST_WIDE_INT) 0xffff0000)) == 0 \
+   : (C) == 'K' ? ((VALUE) & (~ (HOST_WIDE_INT) 0xffff)) == 0		\
+   : (C) == 'L' ? (((VALUE) & 0xffff) == 0				\
+		   && ((VALUE) >> 31 == -1 || (VALUE) >> 31 == 0))	\
+   : (C) == 'M' ? (VALUE) > 31						\
+   : (C) == 'N' ? (VALUE) > 0 && exact_log2 (VALUE) >= 0		\
+   : (C) == 'O' ? (VALUE) == 0						\
+   : (C) == 'P' ? (unsigned HOST_WIDE_INT) ((- (VALUE)) + 0x8000) < 0x10000 \
+   : 0)
+#endif
+
+/* -----------------------[ PHX stop ]-------------------------------- */
+
+/* Similar, but for floating constants, and defining letters G and H.
+   Here VALUE is the CONST_DOUBLE rtx itself.  */
+
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 1
+
+/* 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)
+
+/* Define the codes that are matched by predicates in or32.c.  */
+
+#define PREDICATE_CODES                                                    \
+  {"cc_reg_operand", {SUBREG, REG}},				           \
+  {"branch_comparison_operator", {EQ, NE, LE, LT, GE,			   \
+				  GT, LEU, LTU, GEU, GTU,		   \
+				  UNORDERED, ORDERED,			   \
+				  UNGE, UNLE }},			   \
+  {"sibcall_insn_operand", {REG, SUBREG, SYMBOL_REF}},			   \
+  {"input_operand", {SUBREG, REG, CONST_INT, MEM, CONST}},		   \
+  {"sym_ref_mem_operand", {MEM} },
+
+/* 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
+
+/* 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
+
+/* 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.  */
+/*
+#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.  */
+/*
+#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. */
+/*
+#define STACK_PARMS_IN_REG_PARM_AREA
+*/
+/* Define this if the maximum size of all the outgoing args is to be
+   accumulated and pushed during the prologue.  The amount can be
+   found in the variable current_function_outgoing_args_size.  */
+#define ACCUMULATE_OUTGOING_ARGS 1
+
+/* Value is 1 if returning from a function call automatically
+   pops the arguments described by the number-of-args field in the call.
+   FUNDECL is the declaration node of the function (as a tree),
+   FUNTYPE is the data type of the function (as a tree),
+   or for a library call it is an identifier node for the subroutine name.
+
+   On the Vax, the RET insn always pops all the args for any function.  */
+/* SIMON */
+/*#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) (SIZE)*/
+#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0
+
+/* 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 registers */
+#define GP_ARG_RETURN 11 
+
+/* Define how to find the value returned by a function.
+   VALTYPE is the data type of the value (as a tree).
+   If the precise function being called is known, FUNC is its FUNCTION_DECL;
+   otherwise, FUNC is 0.  */
+
+/* Return value is in R11.  */
+#define FUNCTION_VALUE(VALTYPE, FUNC) LIBCALL_VALUE (TYPE_MODE (VALTYPE))
+
+/* Define how to find the value returned by a library function
+   assuming the value has mode MODE.  */
+
+/* Return value is in R11.  */   
+
+#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.  */
+
+/*#define PCC_STATIC_STRUCT_RETURN */
+
+/* 1 if N is a possible register number for a function value.
+   R3 to R8 are possible (set to 1 in CALL_USED_REGISTERS)  */
+
+#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
+       
+/* Define a data type for recording info about an argument list
+   during the scan of that argument list.  This data type should
+   hold all necessary information about the function itself
+   and about the args processed so far, enough to enable macros
+   such as FUNCTION_ARG to determine where the next arg should go.
+
+   On the vax, this is a single integer, which is a number of bytes
+   of arguments scanned so far.  */
+
+#define CUMULATIVE_ARGS int
+
+/* Initialize a variable CUM of type CUMULATIVE_ARGS
+   for a call to a function whose data type is FNTYPE.
+   For a library call, FNTYPE is 0.
+
+   On the vax, the offset starts at 0.  */
+
+/* The regs member is an integer, the number of arguments got into
+   registers so far.  */
+#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 ROUND_ADVANCE* macros are local to this file.  */
+/* Round SIZE up to a word boundary.  */
+#define ROUND_ADVANCE(SIZE) \
+(((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* Round arg MODE/TYPE up to the next word boundary.  */
+#define ROUND_ADVANCE_ARG(MODE, TYPE) \
+((MODE) == BLKmode				\
+ ? ROUND_ADVANCE (int_size_in_bytes (TYPE))	\
+ : ROUND_ADVANCE (GET_MODE_SIZE (MODE)))
+
+/* Round CUM up to the necessary point for argument MODE/TYPE.  */
+/* This is either rounded to nearest reg or nearest double-reg boundary */
+#define ROUND_ADVANCE_CUM(CUM, MODE, TYPE) \
+((((MODE) == BLKmode ? TYPE_ALIGN (TYPE) : GET_MODE_BITSIZE (MODE)) \
+  > BITS_PER_WORD)	\
+ ? (((CUM) + 1) & ~1)	\
+ : (CUM))
+  
+/* A C expression that indicates when an argument must be passed by
+   reference.  If nonzero for an argument, 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.  */
+/* All aggregates and arguments greater than 8 bytes are passed this way.  */
+#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
+(TYPE					\
+ && (AGGREGATE_TYPE_P (TYPE)		\
+     || int_size_in_bytes (TYPE) > 8))
+
+/* 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.)  */
+           
+/* 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.)  */
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
+((CUM) = (ROUND_ADVANCE_CUM ((CUM), (MODE), (TYPE)) \
+	  + ROUND_ADVANCE_ARG ((MODE), (TYPE))))
+                       
+/* Return boolean indicating 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 PASS_IN_REG_P(CUM, MODE, TYPE, NAMED) \
+((NAMED)                         					\
+ && ((ROUND_ADVANCE_CUM ((CUM), (MODE), (TYPE))				\
+      + ROUND_ADVANCE_ARG ((MODE), (TYPE))				\
+      <= GP_ARG_NUM_REG)))
+
+/* 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.  */
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+(PASS_IN_REG_P ((CUM), (MODE), (TYPE), (NAMED))				\
+ ? gen_rtx_REG ((MODE), ROUND_ADVANCE_CUM ((CUM), (MODE), (TYPE)) + GP_ARG_MIN_REG)	\
+ : 0)
+
+/* For an arg passed partly in registers and partly in memory,
+   this is the number of registers used.
+   For args passed entirely in registers or entirely in memory, zero.  */
+
+#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED)      0
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+   for profiling a function entry.  */
+
+#define FUNCTION_PROFILER(FILE, LABELNO)  \
+   fprintf (FILE, "\tl.load32u\tr0,LP%d\n\tcall\tmcount\n", (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.  */
+
+#define EXIT_IGNORE_STACK 0
+
+/* If the memory address ADDR is relative to the frame pointer,
+   correct it to be relative to the stack pointer instead.
+   This is for when we don't use a frame pointer.
+   ADDR should be a variable name.  */
+
+#define FIX_FRAME_POINTER_ADDRESS(ADDR,DEPTH) \
+{ int offset = -1;							\
+  rtx regs = stack_pointer_rtx;						\
+  if (ADDR == frame_pointer_rtx)					\
+    offset = 0;								\
+  else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 1) == frame_pointer_rtx \
+	   && GET_CODE (XEXP (ADDR, 0)) == CONST_INT)			\
+    offset = INTVAL (XEXP (ADDR, 0));					\
+  else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 0) == frame_pointer_rtx \
+	   && GET_CODE (XEXP (ADDR, 1)) == CONST_INT)			\
+    offset = INTVAL (XEXP (ADDR, 1));					\
+  else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 0) == frame_pointer_rtx) \
+    { rtx other_reg = XEXP (ADDR, 1);					\
+      offset = 0;							\
+      regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); }	\
+  else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 1) == frame_pointer_rtx) \
+    { rtx other_reg = XEXP (ADDR, 0);					\
+      offset = 0;							\
+      regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); }	\
+  if (offset >= 0)							\
+    { int regno;							\
+      extern char call_used_regs[];					\
+      offset += 4; /* I don't know why??? */				\
+      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)		\
+        if (regs_ever_live[regno] && ! call_used_regs[regno])		\
+          offset += 4;							\
+      ADDR = plus_constant (regs, offset + (DEPTH)); } }
+
+
+/* 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.  */
+#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)        
+
+#define REGNO_OK_FOR_BASE_P(REGNO)                                          \
+((REGNO) < FIRST_PSEUDO_REGISTER ? ((REGNO) > 0 && (REGNO) <= LAST_INT_REG) \
+ : (reg_renumber[REGNO] > 0 && (reg_renumber[REGNO] <= LAST_INT_REG )))
+
+#ifdef REG_OK_STRICT
+/* Strict version, used in reload pass. This should not
+ * accept pseudo registers.
+ */
+#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P(REGNO(X))
+#else
+/* Accept an int register or a pseudo reg. */
+#define REG_OK_FOR_BASE_P(X) (REGNO(X) <= LAST_INT_REG || \
+                              REGNO(X) >= 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
+
+#define LEGITIMATE_ADDRESS_INTEGER_P(X,OFFSET)          \
+ (GET_CODE (X) == CONST_INT && SMALL_INT(X))
+
+#define LEGITIMATE_OFFSET_ADDRESS_P(MODE,X)             \
+ (GET_CODE (X) == PLUS                                  \
+  && GET_CODE (XEXP (X, 0)) == REG                      \
+  && REG_OK_FOR_BASE_P (XEXP (X, 0))                    \
+  && LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 0)      \
+  && (((MODE) != DFmode && (MODE) != DImode)            \
+      || LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 4)))
+
+#define LEGITIMATE_NONOFFSET_ADDRESS_P(MODE,X)          \
+             (GET_CODE(X) == REG && REG_OK_FOR_BASE_P(X))
+/*
+ * OR1K only has one addressing mode:
+ * register + 16 bit signed offset.
+ */
+#define GO_IF_LEGITIMATE_ADDRESS(MODE,X,ADDR)           \
+  if(LEGITIMATE_OFFSET_ADDRESS_P(MODE,X)) goto ADDR;    \
+  if(LEGITIMATE_NONOFFSET_ADDRESS_P(MODE,X)) goto ADDR;
+
+/*
+  if(GET_CODE(X) == SYMBOL_REF) goto ADDR;  */ /* If used, smaller code */
+
+/* Alternative */
+#if 0
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)  \
+{                                                                       \
+  if (GET_CODE (X) == REG) goto ADDR;                                   \
+  if (GET_CODE (X) == SYMBOL_REF) goto ADDR;				\
+  if (CONSTANT_ADDRESS_P (X)) goto ADDR;                                \
+  if (GET_CODE (X) == PLUS)                                             \
+    {                                                                   \
+      /* Handle [index]<address> represented with index-sum outermost */\
+      if (GET_CODE (XEXP (X, 0)) == REG                                 \
+          && REG_OK_FOR_BASE_P (XEXP (X, 0))                            \
+          && GET_CODE (XEXP (X, 1)) == CONST_INT)                       \
+        goto ADDR;                                                      \
+      if (GET_CODE (XEXP (X, 1)) == REG                                 \
+          && REG_OK_FOR_BASE_P (XEXP (X, 0))                            \
+          && GET_CODE (XEXP (X, 0)) == CONST_INT)                       \
+        goto ADDR;                                                      \
+    }                                                                   \
+ }
+#endif
+/*
+ * We have to force symbol_ref's into registers here
+ * because nobody else seems to want to do that!
+ */
+#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) {}
+/*
+{ if (GET_CODE (x) == SYMBOL_REF)                               \
+    (X) = copy_to_reg (X);                                      \
+  if (memory_address_p (MODE, X))                               \
+    goto WIN;                                                   \
+}
+*/
+
+/*
+ * OR1K addresses do not depend on the machine mode they are
+ * being used in.
+ */
+#define GO_IF_MODE_DEPENDENT_ADDRESS(addr,label)
+
+/* OR1K has 16 bit immediates.
+ */
+#define SMALL_INT(X) (INTVAL(X) >= -32768 && INTVAL(X) <= 32767)
+
+#define LEGITIMATE_CONSTANT_P(x) (GET_CODE(x) != CONST_DOUBLE)
+
+/* 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
+
+/* This flag, if defined, says the same insns that convert to a signed fixnum
+   also convert validly to an unsigned one.  */
+#define FIXUNS_TRUNC_LIKE_FIX_TRUNC
+
+/* Max number of bytes we can move from memory to memory
+   in one reasonably fast instruction.  */
+#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
+
+/* Compute the cost of computing a constant rtl expression RTX
+   whose rtx-code is CODE.  The body of this macro is a portion
+   of a switch statement.  If the code is computed here,
+   return it with a return statement.  Otherwise, break from the switch.  */
+#if 0
+__PHX__ cleanup
+#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
+  case CONST_INT:						\
+    /* Constant zero is super cheap due to clr instruction.  */	\
+    if (RTX == const0_rtx) return 0;				\
+    if ((unsigned) INTVAL (RTX) < 077) return 1;		\
+  case CONST:							\
+  case LABEL_REF:						\
+  case SYMBOL_REF:						\
+    return 3;							\
+  case CONST_DOUBLE:						\
+    return 5;
+#endif
+
+
+/* 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) or32_cc_mode ((OP), (X), (Y))
+
+/* 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.  */
+#define REVERSE_CONDITION(CODE, MODE) or32_reverse_condition (MODE, 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 at beginning of assembler file.  */
+/*
+__PHX__ clenup
+#ifndef ASM_FILE_START
+#define ASM_FILE_START(FILE) do {\
+fprintf (FILE, "%s file %s\n", ASM_COMMENT_START, main_input_filename);\
+fprintf (FILE, ".file\t");   \
+  output_quoted_string (FILE, main_input_filename);\
+  fputc ('\n', FILE);} while (0)
+#endif
+*/
+/* Output to assembler file text saying following lines
+   may contain character constants, extra white space, comments, etc.  */
+
+#define ASM_APP_ON ""
+
+/* Output to assembler file text saying following lines
+   no longer contain unusual constructs.  */
+
+#define ASM_APP_OFF ""
+
+/* Switch to the text or data segment.  */
+
+/* Output before read-only data.  */
+#define TEXT_SECTION_ASM_OP ".section .text"
+
+/* Output before writable data.  */
+#define DATA_SECTION_ASM_OP ".section .data"
+
+/* Output before uninitialized data. */
+#define BSS_SECTION_ASM_OP  ".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", "cc-flag"}
+
+
+/* Define this to be the delimiter between SDB sub-sections.  The default
+   is ";".  */
+#define SDB_DELIM       "\n"
+   
+/* Do not break .stabs pseudos into continuations.  */
+#define DBX_CONTIN_LENGTH 0
+   
+/* 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.  */
+#define DBX_NO_XREFS
+         
+/* How to renumber registers for dbx and gdb.
+   Vax needs no change in the numeration.  */
+
+#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
+
+/* This is the char to use for continuation (in case we need to turn
+   continuation back on).  */
+
+#define DBX_CONTIN_CHAR '?'
+
+
+
+
+
+/* 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); }
+#if 0
+/* This is how to output a command to make the user-level label named NAME
+   defined for reference from other files.  */
+/*
+ __PHX__ CLEANUP
+#define ASM_GLOBALIZE_LABEL(FILE,NAME)	\
+ { fputs ("\t.global ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE); }
+*/
+
+/* SIMON */
+/*#define ASM_OUTPUT_LABELREF(stream,name)                \
+ { fputc('_',stream); fputs(name,stream); }
+*/
+#define ASM_OUTPUT_LABELREF(stream,name)                \
+{if(name[0] == '*') 					\
+   fputs(name,stream);					\
+else {							\
+   fputc('_',stream); fputs(name,stream); 		\
+}}
+#endif
+
+/* The prefix to add to user-visible assembler symbols. */
+
+/* Remove any previous definition (elfos.h).  */
+/* We use -fno-leading-underscore to remove it, when necessary.  */
+#undef  USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX "_"
+
+/* Remove any previous definition (elfos.h).  */
+#ifndef ASM_GENERATE_INTERNAL_LABEL
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM)	\
+  sprintf (LABEL, "*%s%d", PREFIX, NUM)
+#endif
+
+/* This is how to output an assembler line defining an `int' constant.  */
+
+#define ASM_OUTPUT_INT(FILE,VALUE)  	\
+( 					\
+	fprintf (FILE, "\t.word "),	\
+  output_addr_const (FILE, (VALUE)),	\
+  fprintf (FILE, "\n"))
+
+#define ASM_OUTPUT_FLOAT(stream,value) \
+   { long l;                                 \
+      REAL_VALUE_TO_TARGET_SINGLE(value,l); \
+      fprintf(stream,"\t.word 0x%08x\t\n# float %26.7e\n",l,value); }
+
+#define ASM_OUTPUT_DOUBLE(stream,value)                         \
+   { long l[2];                                                 \
+      REAL_VALUE_TO_TARGET_DOUBLE(value,&l[0]);                 \
+      fprintf(stream,"\t.word 0x%08x,0x%08x\t\n# float %26.16le\n",  \
+              l[0],l[1],value); }
+
+#define ASM_OUTPUT_LONG_DOUBLE(stream,value) \
+   { long l[4];                                 \
+      REAL_VALUE_TO_TARGET_DOUBLE(value,&l[0]); \
+      fprintf(stream,"\t.word 0x%08x,0x%08x,0x%08x,0x%08x\t\n# float %26.18lle\n", \
+              l[0],l[1],l[2],l[3],value); }
+
+/* Likewise for `char' and `short' constants.  */
+
+#define ASM_OUTPUT_SHORT(FILE,VALUE)  \
+( fprintf (FILE, "\t.half "),			\
+  output_addr_const (FILE, (VALUE)),		\
+  fprintf (FILE, "\n"))
+
+#define ASM_OUTPUT_CHAR(FILE,VALUE)  \
+( fprintf (FILE, "\t.byte "),			\
+  output_addr_const (FILE, (VALUE)),		\
+  fprintf (FILE, "\n"))
+
+/* This is how to output an assembler line for a numeric constant byte.  */
+
+#define ASM_OUTPUT_BYTE(FILE,VALUE)  \
+  fprintf (FILE, "\t.byte 0x%02x\n", (VALUE))
+
+/* This is how to output an insn to push a register on the stack.
+   It need not be very fast code.  */
+
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO)  \
+  fprintf (FILE, "\tl.sub   \tr1,4\n\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(FILE,REGNO)  \
+  fprintf (FILE, "\tl.lwz   \t%s,0(r1)\n\tl.addi   \tr1,4\n", reg_names[REGNO])
+
+/* 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(FILE, VALUE)  \
+  fprintf (FILE, "\t.word .L%d\n", VALUE)
+
+/* This is how to output an element of a case-vector that is relative.  */
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)  \
+  fprintf (FILE, "\t.word .L%d-.L%d\n", VALUE, REL)
+
+/* 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(FILE,LOG)  \
+  if ((LOG) != 0) fprintf (FILE, "\t.align %d\n", 1 << (LOG))
+
+/* This is how to output an assembler line
+   that says to advance the location counter by SIZE bytes.  */
+
+#ifndef ASM_OUTPUT_SKIP
+#define ASM_OUTPUT_SKIP(FILE,SIZE)  \
+  fprintf (FILE, "\t.space %d\n", (SIZE))
+#endif
+
+/* Need to split up .ascii directives to avoid breaking
+   the linker. */
+
+/* This is how to output a string.  */
+#ifndef ASM_OUTPUT_ASCII
+#define ASM_OUTPUT_ASCII(STREAM, STRING, LEN)                           \
+do {                                                                    \
+  register int i, c, len = (LEN), cur_pos = 17;                         \
+  register unsigned char *string = (unsigned char *)(STRING);           \
+  fprintf ((STREAM), "\t.ascii\t\"");                                   \
+  for (i = 0; i < len; i++)                                             \
+    {                                                                   \
+      register int c = string[i];                                       \
+                                                                        \
+      switch (c)                                                        \
+        {                                                               \
+        case '\"':                                                      \
+        case '\\':                                                      \
+          putc ('\\', (STREAM));                                        \
+          putc (c, (STREAM));                                           \
+          cur_pos += 2;                                                 \
+          break;                                                        \
+                                                                        \
+        case TARGET_NEWLINE:                                            \
+          fputs ("\\n", (STREAM));                                      \
+          if (i+1 < len                                                 \
+              && (((c = string[i+1]) >= '\040' && c <= '~')             \
+                  || c == TARGET_TAB))                                  \
+            cur_pos = 32767;            /* break right here */          \
+          else                                                          \
+            cur_pos += 2;                                               \
+          break;                                                        \
+                                                                        \
+        case TARGET_TAB:                                                \
+          fputs ("\\t", (STREAM));                                      \
+          cur_pos += 2;                                                 \
+          break;                                                        \
+                                                                        \
+        case TARGET_FF:                                                 \
+          fputs ("\\f", (STREAM));                                      \
+          cur_pos += 2;                                                 \
+          break;                                                        \
+                                                                        \
+        case TARGET_BS:                                                 \
+          fputs ("\\b", (STREAM));                                      \
+          cur_pos += 2;                                                 \
+          break;                                                        \
+                                                                        \
+        case TARGET_CR:                                                 \
+          fputs ("\\r", (STREAM));                                      \
+          cur_pos += 2;                                                 \
+          break;                                                        \
+                                                                        \
+        default:                                                        \
+          if (c >= ' ' && c < 0177)                                     \
+            {                                                           \
+              putc (c, (STREAM));                                       \
+              cur_pos++;                                                \
+            }                                                           \
+          else                                                          \
+            {                                                           \
+              fprintf ((STREAM), "\\%03o", c);                          \
+              cur_pos += 4;                                             \
+            }                                                           \
+        }                                                               \
+                                                                        \
+      if (cur_pos > 72 && i+1 < len)                                    \
+        {                                                               \
+          cur_pos = 17;                                                 \
+          fprintf ((STREAM), "\"\n\t.ascii\t\"");                       \
+        }                                                               \
+    }                                                                   \
+  fprintf ((STREAM), "\"\n");                                           \
+} while (0)
+#endif /* ASM_OUTPUT_ASCII */
+
+/* Invoked just before function output. */
+
+#define ASM_OUTPUT_FUNCTION_PREFIX(stream, fnname)              \
+  fputs(".proc ",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(".global\t",stream); assemble_name(stream,name);        \
+  fputs("\n",stream); assemble_name(stream,name);               \
+  fprintf(stream,":\n\t.space %d\n",rounded); }
+
+/* This says how to output an assembler line
+   to define a local common symbol.  */
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED)  \
+( fputs (".bss ", (FILE)),			\
+  assemble_name ((FILE), (NAME)),		\
+  fprintf ((FILE), ",%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).  */
+#ifndef ASM_OUTPUT_ALIGNED_COMMON
+#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN)	\
+{ data_section();                                           	\
+  if ((ALIGN) > 8)                                          	\
+	fprintf(FILE, "\t.align %d\n", ((ALIGN) / BITS_PER_UNIT)); \
+  fputs(".global\t", FILE); assemble_name(FILE, NAME);      	\
+  fputs("\n", FILE);                                        	\
+  assemble_name(FILE, NAME);                                	\
+  fprintf(FILE, ":\n\t.space %d\n", SIZE);		    	\
+}
+#endif /* ASM_OUTPUT_ALIGNED_COMMON */
+  
+/* This says how to output an assembler line to define a local common symbol
+   with size SIZE (in bytes) and alignment ALIGN (in bits).  */
+
+#ifndef ASM_OUTPUT_ALIGNED_LOCAL
+#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
+{ data_section();                                               \
+  if ((ALIGN) > 8)                                              \
+	fprintf(FILE, "\t.align %d\n", ((ALIGN) / BITS_PER_UNIT)); \
+  assemble_name(FILE, NAME);                                    \
+  fprintf(FILE, ":\n\t.space %d\n", SIZE);			\
+}
+#endif /* ASM_OUTPUT_ALIGNED_LOCAL */
+                                                     
+/* 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.%d", (NAME), (LABELNO)))
+
+/* Macro for %code validation. Returns nonzero if valid. */
+#define PRINT_OPERAND_PUNCT_VALID_P(code) print_operand_punct_valid_p(code)
+
+/* Print an instruction operand X on file FILE.
+   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(FILE, X, CODE) print_operand(FILE, X, CODE)
+
+/* Print a memory operand whose address is X, on file FILE.
+   This uses a function in output-vax.c.  */
+
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)
+
+/* These are stubs, and have yet to bee written. */
+
+#define TRAMPOLINE_SIZE 26
+#define TRAMPOLINE_TEMPLATE(FILE)
+#define INITIALIZE_TRAMPOLINE(TRAMP,FNADDR,CXT)
+
+extern GTY(()) rtx or32_compare_op0;
+extern GTY(()) rtx or32_compare_op1;
+
+/* We don't use libg.a */
+#undef LIB_SPEC 
+#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}"
+#endif /* _OR32_H_ */
diff -Nru gcc-3.4.4.orig/gcc/config/or32/or32.md gcc-3.4.4-DONE/gcc/config/or32/or32.md
--- gcc-3.4.4.orig/gcc/config/or32/or32.md	1970-01-01 02:00:00.000000000 +0200
+++ gcc-3.4.4-DONE/gcc/config/or32/or32.md	2005-11-29 16:23:09.000000000 +0200
@@ -0,0 +1,1281 @@
+;; Machine description for GNU compiler, OpenRISC 1000 family, OR32 ISA
+;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+;; Contributed by Damjan Lampret <damjanl@bsemi.com> in 1999.
+;; Major optimizations by Matjaz Breskvar <matjazb@bsemi.com> 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.
+
+(define_attr "type"
+  "unknown,load,store,move,extend,logic,add,mul,shift,compare,branch,jump,fp"
+  (const_string "unknown"))
+
+;; Number of instructions
+(define_attr "length" "" (const_int 1))
+
+(define_delay (eq_attr "type" "branch,jump")
+               [(and (eq_attr "type" "!branch,jump")
+		     (eq_attr "length" "1")) (nil) (nil)])
+
+;; (define_function_unit NAME MULTIPLICITY SIMULTANEITY
+;;                       TEST READY-DELAY ISSUE-DELAY [CONFLICT-LIST])
+;; MULTIPLICITY - Number of functional units of this type
+;; SIMULTANEITY - Zero for pipelined functional unit
+;; READY-DELAY - Number of cycles before result is available
+;; ISSUE-DELAY - Number of cycles before unit can accept new instruction
+;;
+(define_function_unit "bit_unit" 1 0 (eq_attr "type" "shift") 3 1)
+(define_function_unit "lsu" 1 0 (eq_attr "type" "load") 3 3)
+(define_function_unit "lsu" 1 0 (eq_attr "type" "store") 2 1)
+(define_function_unit "alu" 1 0 (eq_attr "type" "add,logic,extend,move,compare") 2 1)
+(define_function_unit "mul_unit" 1 0 (eq_attr "type" "mul") 16 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))]
+  "TARGET_SCHED_LOGUE"
+{
+  or32_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))]
+  "TARGET_SCHED_LOGUE"
+{
+  or32_expand_epilogue (false);
+  DONE;
+})
+
+(define_expand "sibcall_epilogue"
+  [(use (const_int 2))]
+  "TARGET_SCHED_LOGUE"
+{
+  or32_expand_epilogue (true);
+  DONE;
+})
+
+(define_insn "return_internal"
+  [(return)
+   (use (match_operand 0 "pmode_register_operand" ""))]
+  "TARGET_SCHED_LOGUE"
+  "l.jr    \t%0%("
+  [(set_attr "type" "jump")
+   (set_attr "length" "1")])
+
+;;
+;; Sibcalls
+;;
+
+(define_expand "sibcall"
+  [(parallel [(call (match_operand 0 "" "")
+                    (match_operand 1 "" ""))
+              (use (match_operand 2 "" ""))     ;; next_arg_reg
+              (use (match_operand 3 "" ""))])]  ;; struct_value_size_rtx
+  "TARGET_SIBCALL"
+  "
+{
+  or32_expand_sibcall (0, XEXP (operands[0], 0), operands[1]); 
+  DONE;
+}")
+
+(define_expand "sibcall_value"
+  [(set (match_operand 0 "" "")
+                   (call (match_operand:SI 1 "" "")
+                         (match_operand 2 "" "")))]
+  "TARGET_SIBCALL"
+  "
+{
+  or32_expand_sibcall (operands[0], XEXP (operands[1], 0), operands[2]); 
+  DONE; 
+}")
+
+(define_insn "sibcall_internal"
+  [(call (mem:SI (match_operand:SI 0 "sibcall_insn_operand" "s,r"))
+         (match_operand 1 "" ""))
+   (use (reg:SI 9))]
+  "TARGET_SIBCALL"
+  "@
+   l.j     \t%S0%(\t    # sibcall s
+   l.jr    \t%0%(\t     # sibcall r"
+  [(set_attr "type" "jump,jump")])
+
+
+
+;;
+;; movQI
+;;
+
+(define_expand "movqi"
+  [(set (match_operand:QI 0 "general_operand" "")
+	(match_operand:QI 1 "general_operand" ""))]
+  ""
+  "
+      if (!no_new_pseudos)
+        {
+          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 (!no_new_pseudos)
+        {
+          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);
+	    }
+	  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" ""))]
+  ""
+{
+  /* 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)
+    {
+      or32_emit_set_const32 (operands[0], operands[1]);
+      DONE;
+    }
+ movsi_is_ok:
+  ;
+})
+
+;;
+;; 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)"
+ [(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)"
+[(set_attr "type" "move")
+   (set_attr "length" "1")])
+
+(define_insn "movsi_insn_big"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
+	(match_operand:SI 1 "immediate_operand" "i"))]
+  "GET_CODE(operands[1]) != CONST_INT"
+  "l.movhi \t%0,hi(%1)\;l.ori   \t%0,%0,lo(%1)"
+  [(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_CMOV"
+  "
+{
+  if (or32_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_CMOV"
+  "*
+{ 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.
+
+(define_expand "cmpsi"
+  [(set (reg:CC 32)
+	(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]);
+  or32_compare_op0 = operands[0];
+  or32_compare_op1 = operands[1];
+  DONE;
+})
+
+
+
+;;
+;; Conditional branches
+;;
+
+(define_expand "beq"
+  [(use (match_operand 0 "" ""))]
+  ""
+  "or32_expand_branch (EQ, operands[0]); DONE;")
+
+(define_expand "bne"
+  [(use (match_operand 0 "" ""))]
+  ""
+  "or32_expand_branch (NE, operands[0]); DONE;")
+
+(define_expand "bgt"
+  [(use (match_operand 0 "" ""))]
+  ""
+  "or32_expand_branch (GT, operands[0]); DONE;")
+
+(define_expand "bgtu"
+  [(use (match_operand 0 "" ""))]
+  ""
+  "or32_expand_branch (GTU, operands[0]); DONE;")
+
+(define_expand "blt"
+  [(use (match_operand 0 "" ""))]
+  ""
+  "or32_expand_branch (LT, operands[0]); DONE;")
+
+(define_expand "bltu"
+  [(use (match_operand 0 "" ""))]
+  ""
+  "or32_expand_branch (LTU, operands[0]); DONE;")
+
+(define_expand "bge"
+  [(use (match_operand 0 "" ""))]
+  ""
+  "or32_expand_branch (GE, operands[0]); DONE;")
+
+(define_expand "bgeu"
+  [(use (match_operand 0 "" ""))]
+  ""
+  "or32_expand_branch (GEU, operands[0]); DONE;")
+
+(define_expand "ble"
+  [(use (match_operand 0 "" ""))]
+  ""
+  "or32_expand_branch (LE, operands[0]); DONE;")
+
+(define_expand "bleu"
+  [(use (match_operand 0 "" ""))]
+  ""
+  "or32_expand_branch (LEU, operands[0]); DONE;")
+
+
+
+;;
+;; Setting a CCxx registers from comparision
+;;
+
+
+
+;; Here are the actual compare insns.
+(define_insn "*cmpsi_eq"
+  [(set (reg:CCEQ 32)
+	(compare:CCEQ (match_operand:SI 0 "register_operand" "r,r")
+		      (match_operand:SI 1 "nonmemory_operand" "I,r")))]
+  ""
+  "@
+   l.sfeqi\t%0,%1
+   l.sfeq \t%0,%1")
+
+(define_insn "*cmpsi_ne"
+  [(set (reg:CCNE 32)
+	(compare:CCNE (match_operand:SI 0 "register_operand" "r,r")
+		      (match_operand:SI 1 "nonmemory_operand" "I,r")))]
+  ""
+  "@
+   l.sfnei\t%0,%1
+   l.sfne \t%0,%1")
+
+(define_insn "*cmpsi_gt"
+  [(set (reg:CCGT 32)
+	(compare:CCGT (match_operand:SI 0 "register_operand" "r,r")
+		      (match_operand:SI 1 "nonmemory_operand" "I,r")))]
+  ""
+  "@
+   l.sfgtsi\t%0,%1
+   l.sfgts \t%0,%1")
+
+(define_insn "*cmpsi_gtu"
+  [(set (reg:CCGTU 32)
+	(compare:CCGTU (match_operand:SI 0 "register_operand" "r,r")
+		       (match_operand:SI 1 "nonmemory_operand" "I,r")))]
+  ""
+  "@
+   l.sfgtui\t%0,%1
+   l.sfgtu \t%0,%1")
+
+(define_insn "*cmpsi_lt"
+  [(set (reg:CCLT 32)
+	(compare:CCLT (match_operand:SI 0 "register_operand" "r,r")
+		      (match_operand:SI 1 "nonmemory_operand" "I,r")))]
+  ""
+  "@
+   l.sfltsi\t%0,%1
+   l.sflts \t%0,%1")
+
+(define_insn "*cmpsi_ltu"
+  [(set (reg:CCLTU 32)
+	(compare:CCLTU (match_operand:SI 0 "register_operand" "r,r")
+		       (match_operand:SI 1 "nonmemory_operand" "I,r")))]
+  ""
+  "@
+   l.sfltui\t%0,%1
+   l.sfltu \t%0,%1")
+
+(define_insn "*cmpsi_ge"
+  [(set (reg:CCGE 32)
+	(compare:CCGE (match_operand:SI 0 "register_operand" "r,r")
+		      (match_operand:SI 1 "nonmemory_operand" "I,r")))]
+  ""
+  "@
+   l.sfgesi\t%0,%1
+   l.sfges \t%0,%1")
+
+
+(define_insn "*cmpsi_geu"
+  [(set (reg:CCGEU 32)
+	(compare:CCGEU (match_operand:SI 0 "register_operand" "r,r")
+		       (match_operand:SI 1 "nonmemory_operand" "I,r")))]
+  ""
+  "@
+   l.sfgeui\t%0,%1
+   l.sfgeu \t%0,%1")
+
+
+(define_insn "*cmpsi_le"
+  [(set (reg:CCLE 32)
+	(compare:CCLE (match_operand:SI 0 "register_operand" "r,r")
+		      (match_operand:SI 1 "nonmemory_operand" "I,r")))]
+  ""
+  "@
+   l.sflesi\t%0,%1
+   l.sfles \t%0,%1")
+
+(define_insn "*cmpsi_leu"
+  [(set (reg:CCLEU 32)
+	(compare:CCLEU (match_operand:SI 0 "register_operand" "r,r")
+		       (match_operand:SI 1 "nonmemory_operand" "I,r")))]
+  ""
+  "@
+   l.sfleui\t%0,%1
+   l.sfleu \t%0,%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)))]
+  ""
+  "*
+{ output_bf(operands); }"
+  [(set_attr "type" "branch")
+   (set_attr "length" "1")])
+
+;;
+;;
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;
+
+
+(define_insn "movdi"
+        [(set (match_operand:DI 0 "nonimmediate_operand" "=r, r, m, r")
+              (match_operand:DI 1 "general_operand"      " r, m, r, i"))]
+        ""
+        "*
+         return or32_output_move_double (operands);
+	"
+	[(set_attr "length" "2,2,2,3")])
+
+(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 or32_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_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_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_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_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_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_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_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_SEXT"
+  "
+{
+  operands[1] = gen_lowpart (SImode, operands[1]);
+  operands[2] = gen_reg_rtx (SImode); }")
+
+
+;;
+;; zero_extend<m><n>2
+;;
+
+(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
+   l.slli  \t%0,%1,%2"
+  [(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
+   l.srai  \t%0,%1,%2"
+  [(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
+   l.srli  \t%0,%1,%2"
+  [(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_ROR"
+  "@
+   l.ror   \t%0,%1,%2
+   l.rori  \t%0,%1,%2"
+  [(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
+   l.andi  \t%0,%1,%2"
+  [(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
+   l.ori   \t%0,%1,%2"
+  [(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
+   l.xori  \t%0,%1,%2"
+  [(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"
+  [(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"
+  [(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"
+  [(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
+   l.addi  \t%0,%1,%2"
+  [(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
+   l.addi  \t%0,%1,%n2"
+  [(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"
+  [(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"
+  [(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"
+  [(set_attr "type" "mul")
+   (set_attr "length" "1")])
+
+;;
+;; jumps 
+;;
+
+;; jump
+
+(define_expand "jump"
+  [(set (pc)
+	(label_ref (match_operand 0 "" "")))]
+  ""
+  "
+{
+  if (!TARGET_ALIGNED_JUMPS)
+    emit_jump_insn (gen_jump_internal (operands[0]));
+  else
+    emit_jump_insn (gen_jump_aligned (operands[0]));
+  DONE;
+}")
+
+(define_insn "jump_internal"
+  [(set (pc)
+	(label_ref (match_operand 0 "" "")))]
+  "!TARGET_ALIGNED_JUMPS"
+  "l.j     \t%l0%("
+  [(set_attr "type" "jump")
+   (set_attr "length" "1")])
+
+(define_insn "jump_aligned"
+  [(set (pc)
+	(label_ref (match_operand 0 "" "")))]
+  "TARGET_ALIGNED_JUMPS"
+  ".balignl 0x8,0x15000015,0x4\;l.j     \t%l0%("
+  [(set_attr "type" "jump")
+   (set_attr "length" "1")])
+
+;; indirect jump
+
+(define_expand "indirect_jump"
+  [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
+  ""
+  "
+{
+  if (!TARGET_ALIGNED_JUMPS)
+    emit_jump_insn (gen_indirect_jump_internal (operands[0]));
+  else
+    emit_jump_insn (gen_indirect_jump_aligned (operands[0]));
+  DONE;
+
+}")
+
+(define_insn "indirect_jump_internal"
+  [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
+  "!TARGET_ALIGNED_JUMPS"
+  "l.jr    \t%0%("
+  [(set_attr "type" "jump")
+   (set_attr "length" "1")])
+
+(define_insn "indirect_jump_aligned"
+  [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
+  "TARGET_ALIGNED_JUMPS"
+  ".balignl 0x8,0x15000015,0x4\;l.jr    \t%0%("
+  [(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))])]
+  ""
+  "
+{
+  if (!TARGET_ALIGNED_JUMPS)
+    emit_call_insn (gen_call_internal (operands[0], operands[1]));
+  else
+    emit_call_insn (gen_call_aligned (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))])]
+  "!TARGET_ALIGNED_JUMPS"
+  "l.jal   \t%S0%("
+  [(set_attr "type" "jump")
+   (set_attr "length" "1")])
+
+(define_insn "call_aligned"
+[(parallel [(call (match_operand:SI 0 "sym_ref_mem_operand" "")
+                  (match_operand 1 "" "i"))
+            (clobber (reg:SI 9))])]
+  "TARGET_ALIGNED_JUMPS"
+  ".balignl 0x8,0x15000015,0x4\;l.jal   \t%S0%("
+  [(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))])]
+  ""
+  "
+{
+  if (!TARGET_ALIGNED_JUMPS)
+    emit_call_insn (gen_call_value_internal (operands[0], operands[1], operands[2]));
+  else
+    emit_call_insn (gen_call_value_aligned (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))])]
+  "!TARGET_ALIGNED_JUMPS"
+  "l.jal   \t%S1%("
+  [(set_attr "type" "jump")
+   (set_attr "length" "1")])
+
+(define_insn "call_value_aligned"
+[(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))])]
+  "TARGET_ALIGNED_JUMPS"
+  ".balignl 0x8,0x15000015,0x4\;l.jal   \t%S1%("
+  [(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))])]
+  ""
+  "
+{
+  if (!TARGET_ALIGNED_JUMPS)
+    emit_call_insn (gen_call_value_indirect_internal (operands[0], operands[1], operands[2]));
+  else
+    emit_call_insn (gen_call_value_indirect_aligned (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))])]
+  "!TARGET_ALIGNED_JUMPS"
+  "l.jalr  \t%1%("
+  [(set_attr "type" "jump")
+   (set_attr "length" "1")])
+
+(define_insn "call_value_indirect_aligned"
+  [(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))])]
+  "TARGET_ALIGNED_JUMPS"
+  ".balignl 0x8,0x15000015,0x4\;l.jalr  \t%1%("
+  [(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))])]
+  ""
+  "
+{
+  if (!TARGET_ALIGNED_JUMPS)
+    emit_call_insn (gen_call_indirect_internal (operands[0], operands[1]));
+  else
+    emit_call_insn (gen_call_indirect_aligned (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))])]
+  "!TARGET_ALIGNED_JUMPS"
+  "l.jalr  \t%0%("
+  [(set_attr "type" "jump")
+   (set_attr "length" "1")])
+
+(define_insn "call_indirect_aligned"
+[(parallel [(call (mem:SI (match_operand:SI 0 "register_operand" "r"))
+                  (match_operand 1 "" "i"))
+              (clobber (reg:SI 9))])]
+  "TARGET_ALIGNED_JUMPS"
+  ".balignl 0x8,0x15000015,0x4\;l.jalr  \t%0%("
+  [(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 (!TARGET_ALIGNED_JUMPS)
+    emit_jump_insn (gen_tablejump_internal (operands[0], operands[1]));
+  else
+    emit_jump_insn (gen_tablejump_aligned (operands[0], operands[1]));
+  DONE;
+}")
+
+(define_insn "tablejump_internal"
+  [(set (pc) (match_operand:SI 0 "register_operand" "r"))
+   (use (label_ref (match_operand 1 "" "")))]
+  "!TARGET_ALIGNED_JUMPS"
+  "l.jr    \t%0%("
+  [(set_attr "type" "jump")
+   (set_attr "length" "1")])
+
+(define_insn "tablejump_aligned"
+  [(set (pc) (match_operand:SI 0 "register_operand" "r"))
+   (use (label_ref (match_operand 1 "" "")))]
+  "TARGET_ALIGNED_JUMPS"
+  ".balignl 0x8,0x15000015,0x4\;l.jr    \t%0%("
+  [(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
+;;
+
+(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"
+  [(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"
+  "lf.add.d\t%0,%1,%2"
+  [(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"
+  [(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"
+  "lf.sub.d\t%0,%1,%2"
+  [(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"
+  [(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"
+  "lf.mul.d\t%0,%1,%2"
+  [(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"
+  [(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"
+  "lf.div.d\t%0,%1,%2"
+  [(set_attr "type"     "fp")
+   (set_attr "length"   "1")])
+
+
+;; 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 -Nru gcc-3.4.4.orig/gcc/config/or32/or32-modes.def gcc-3.4.4-DONE/gcc/config/or32/or32-modes.def
--- gcc-3.4.4.orig/gcc/config/or32/or32-modes.def	1970-01-01 02:00:00.000000000 +0200
+++ gcc-3.4.4-DONE/gcc/config/or32/or32-modes.def	2005-11-29 16:23:09.000000000 +0200
@@ -0,0 +1,39 @@
+/* Definitions of target machine for GNU compiler, for IBM RS/6000.
+   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
+
+   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 -Nru gcc-3.4.4.orig/gcc/config/or32/or32-protos.h gcc-3.4.4-DONE/gcc/config/or32/or32-protos.h
--- gcc-3.4.4.orig/gcc/config/or32/or32-protos.h	1970-01-01 02:00:00.000000000 +0200
+++ gcc-3.4.4-DONE/gcc/config/or32/or32-protos.h	2005-11-29 16:23:09.000000000 +0200
@@ -0,0 +1,37 @@
+/* Definitions of target machine for GNU compiler, Argonaut ARC cpu.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+
+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.  */
+
+#ifdef RTX_CODE
+#ifdef TREE_CODE
+#endif /* TREE_CODE */
+
+extern void print_operand PARAMS ((FILE *, rtx, int));
+extern void print_operand_address PARAMS ((FILE *, register rtx));
+extern const char *or1k_output_move_double PARAMS ((rtx *operands));
+
+extern rtx or1k_cmp_op[];
+
+#endif /* RTX_CODE */
+
+#ifdef TREE_CODE
+
+#endif /* TREE_CODE */
+
+extern int print_operand_punct_valid_p PARAMS ((int));
diff -Nru gcc-3.4.4.orig/gcc/config/or32/or32.S gcc-3.4.4-DONE/gcc/config/or32/or32.S
--- gcc-3.4.4.orig/gcc/config/or32/or32.S	1970-01-01 02:00:00.000000000 +0200
+++ gcc-3.4.4-DONE/gcc/config/or32/or32.S	2005-11-29 16:23:09.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),r10
+        l.addi          r5,r3,0
+        l.addi          r10,r0,0
+        l.sflts         r5,r0
+        l.bnf           1f
+        l.addi          r3,r0,0
+        l.addi          r10,r0,1
+        l.sub           r5,r0,r5
+1:
+        l.sflts         r4,r0
+        l.bnf           1f
+        l.nop           0
+        l.addi          r10,r10,1
+        l.sub           r4,r0,r4
+1:
+        l.jal           ___udivsi3
+        l.addi          r3,r5,0
+        l.sfeqi         r10,1
+        l.bnf           1f
+        l.nop           0
+        l.sub           r11,r0,r11
+1:
+        l.lwz           r9,0(r1)
+        l.lwz           r10,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),r10
+        l.addi          r10,r0,0
+        l.sflts         r3,r0
+        l.bnf           1f
+        l.nop           0
+        l.addi          r10,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         r10,1
+        l.bnf           1f
+        l.addi		r11,r7,0
+        l.sub           r11,r0,r11
+1:
+        l.lwz           r9,0(r1)
+        l.lwz           r10,4(r1)
+        l.jr            r9
+        l.addi          r1,r1,8	
+#endif
diff -Nru gcc-3.4.4.orig/gcc/config/or32/rtems.h gcc-3.4.4-DONE/gcc/config/or32/rtems.h
--- gcc-3.4.4.orig/gcc/config/or32/rtems.h	1970-01-01 02:00:00.000000000 +0200
+++ gcc-3.4.4-DONE/gcc/config/or32/rtems.h	2005-11-29 16:23:09.000000000 +0200
@@ -0,0 +1,37 @@
+/* Definitions for rtems targeting an OpenRisc OR32 using COFF
+   Copyright (C) 1996, 1997 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.  */
+
+/* Specify predefined symbols in preprocessor.  */
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-DOR1K -Dor1k -D__or1k__ -D__OR1K__ \
+  -Drtems -D__rtems__ -Asystem(rtems) -Acpu(or1k) -Amachine(or1k)"
+
+/* Generate calls to memcpy, memcmp and memset.  */
+#ifndef TARGET_MEM_FUNCTIONS
+#define TARGET_MEM_FUNCTIONS
+#endif
+
+/* We use COFF, so we need SDB format.  */
+#define SDB_DEBUGGING_INFO
+
+/* Get machine-independent configuration parameters for RTEMS.  */
+#include <rtems.h>
diff -Nru gcc-3.4.4.orig/gcc/config/or32/t-default gcc-3.4.4-DONE/gcc/config/or32/t-default
--- gcc-3.4.4.orig/gcc/config/or32/t-default	1970-01-01 02:00:00.000000000 +0200
+++ gcc-3.4.4-DONE/gcc/config/or32/t-default	2005-11-29 16:23:09.000000000 +0200
@@ -0,0 +1,34 @@
+#
+# t-default is Makefile fragment to be included when
+#           building gcc for or32 target
+#
+
+# we don't support -g so don't use it
+LIBGCC2_DEBUG_CFLAGS =
+
+TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer
+
+LIB1ASMSRC = or32/or32.S
+LIB1ASMFUNCS = __mulsi3 __udivsi3 __divsi3 __umodsi3 __modsi3
+
+# These are really part of libgcc1, but this will cause them to be
+# built correctly, so... [taken from t-sparclite]
+LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+	cat $(srcdir)/config/fp-bit.c > dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+	echo '#define FLOAT' > fp-bit.c
+	cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+# Build the libraries for both hard and soft floating point
+
+#MULTILIB_OPTIONS = msoft-float
+#MULTILIB_DIRNAMES = soft-float
+
+#LIBGCC = stmp-multilib
+#INSTALL_LIBGCC = install-multilib
+
+#LIBGCC = 
+#INSTALL_LIBGCC = 
diff -Nru gcc-3.4.4.orig/gcc/config.gcc gcc-3.4.4-DONE/gcc/config.gcc
--- gcc-3.4.4.orig/gcc/config.gcc	2005-04-25 07:47:59.000000000 +0300
+++ gcc-3.4.4-DONE/gcc/config.gcc	2005-12-13 17:38:36.000000000 +0200
@@ -1681,6 +1681,21 @@
 	extra_parts=""
 	use_collect2=yes
 	;;
+or32-*-coff*)
+	tm_file="${tm_file} or32/or32.h"
+	tmake_file=or32/t-default
+	;;
+or32-*-elf*)
+	tm_file="${tm_file} dbxelf.h elfos.h or32/or32.h or32/elf.h"
+	tmake_file=or32/t-default
+	if test x$enable_threads = xyes; then
+	  thread_file='rtems'
+	fi
+	;;
+or32-*linux*)
+	tm_file="${tm_file} dbxelf.h elfos.h or32/or32.h or32/elf.h or32/linux-gas.h or32/linux-elf.h"
+	tmake_file=or32/t-default
+	;;
 pdp11-*-bsd)
 	tm_file="${tm_file} pdp11/2bsd.h"
 	use_fixproto=yes
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.