<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">diff -burN orig.gcc-3.2.2/config.sub gcc-3.2.2/config.sub
--- orig.gcc-3.2.2/config.sub	2003-01-30 18:32:36.000000000 -0400
+++ gcc-3.2.2/config.sub	2007-04-29 05:10:04.000000000 -0300
@@ -236,6 +236,7 @@
 	| i370 | i860 | i960 | ia64 \
 	| ip2k \
 	| m32r | m68000 | m68k | m88k | mcore \
+	| mips64r5900 | mips64r5900el \
 	| mips | mipsbe | mipseb | mipsel | mipsle \
 	| mips16 \
 	| mips64 | mips64el \
@@ -308,6 +309,7 @@
 	| m32r-* \
 	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
 	| m88110-* | m88k-* | mcore-* \
+	| mips64r5900-* | mips64r5900el-* \
 	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
 	| mips16-* \
 	| mips64-* | mips64el-* \
@@ -594,6 +596,10 @@
 		basic_machine=i386-unknown
 		os=-vsta
 		;;
+	iop)
+		basic_machine=mipsel-scei
+		os=-irx
+		;;
 	iris | iris4d)
 		basic_machine=mips-sgi
 		case $os in
@@ -630,6 +636,16 @@
 		basic_machine=m68k-atari
 		os=-mint
 		;;
+	mipsEE* | ee | ps2)
+		basic_machine=mips64r5900el-scei
+		case $os in
+		    -linux*)
+			;;
+		    *)
+			os=-elf
+			;;
+		esac
+		;;
 	mips3*-*)
 		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
 		;;
@@ -1118,7 +1134,8 @@
 	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
 	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
 	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
-	      | -powermax* | -dnix* | -microbsd*)
+	      | -powermax* | -dnix* | -microbsd* \
+	      | -irx* )
 	# Remember, each alternative MUST END IN *, to match a version number.
 		;;
 	-qnx*)
diff -burN orig.gcc-3.2.2/configure gcc-3.2.2/configure
--- orig.gcc-3.2.2/configure	2002-06-24 13:14:28.000000000 -0300
+++ gcc-3.2.2/configure	2007-04-29 05:10:04.000000000 -0300
@@ -89,7 +89,7 @@
 target_alias=NOTARGET
 target_makefile_frag=
 undefs=NOUNDEFS
-version="$Revision: 1.40.6.3 $"
+version="$Revision: 1.8 $"
 x11=default
 bindir='${exec_prefix}/bin'
 sbindir='${exec_prefix}/sbin'
@@ -697,7 +697,7 @@
 if test -f skip-this-dir; then
 	# Perform the same cleanup as the trap handler, minus the "exit 1" of course,
 	# and reset the trap handler.
-	trap 0
+	trap - 0
 	rm -rf Makefile* ${tmpdir}
 	# Execute the final clean-up actions
 	${config_shell} skip-this-dir
@@ -1615,7 +1615,7 @@
 # Perform the same cleanup as the trap handler, minus the "exit 1" of course,
 # and reset the trap handler.
 rm -rf ${tmpdir}
-trap 0
+trap - 0
 
 exit 0
 
diff -burN orig.gcc-3.2.2/configure.in gcc-3.2.2/configure.in
--- orig.gcc-3.2.2/configure.in	2002-07-08 07:00:57.000000000 -0300
+++ gcc-3.2.2/configure.in	2007-04-29 05:10:04.000000000 -0300
@@ -980,6 +980,9 @@
   mips*-*-linux*)
     noconfigdirs="$noconfigdirs target-libffi"
     ;;
+  mipsel-*-irx*)
+    noconfigdirs="$noconfigdirs target-libiberty target-newlib target-libgloss target-libstdc++-v3 ${libgcj}"
+    ;;
   mips*-*-*)
     noconfigdirs="$noconfigdirs gprof ${libgcj}"
     ;;
diff -burN orig.gcc-3.2.2/gcc/caller-save.c gcc-3.2.2/gcc/caller-save.c
--- orig.gcc-3.2.2/gcc/caller-save.c	2002-01-01 18:22:25.000000000 -0400
+++ gcc-3.2.2/gcc/caller-save.c	2007-04-29 05:10:04.000000000 -0300
@@ -50,13 +50,21 @@
    If that is not possible the save is done one register at a time.  */
 
 static enum machine_mode 
+#if TARGET_MIPS5900
+  regno_save_mode[FIRST_PSEUDO_REGISTER][16 / MIN_UNITS_PER_WORD + 1];
+#else
   regno_save_mode[FIRST_PSEUDO_REGISTER][MAX_MOVE_MAX / MIN_UNITS_PER_WORD + 1];
+#endif
 
 /* For each hard register, a place on the stack where it can be saved,
    if needed.  */
 
 static rtx 
+#if TARGET_MIPS5900
+  regno_save_mem[FIRST_PSEUDO_REGISTER][16 / MIN_UNITS_PER_WORD + 1];
+#else
   regno_save_mem[FIRST_PSEUDO_REGISTER][MAX_MOVE_MAX / MIN_UNITS_PER_WORD + 1];
+#endif
 
 /* We will only make a register eligible for caller-save if it can be
    saved in its widest mode with a simple SET insn as long as the memory
diff -burN orig.gcc-3.2.2/gcc/c-common.c gcc-3.2.2/gcc/c-common.c
--- orig.gcc-3.2.2/gcc/c-common.c	2002-12-01 14:19:08.000000000 -0400
+++ gcc-3.2.2/gcc/c-common.c	2007-04-29 05:10:04.000000000 -0300
@@ -1336,6 +1336,9 @@
   if (bits &lt;= TYPE_PRECISION (intDI_type_node))
     return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
 
+   if (bits &lt;= TYPE_PRECISION (intTI_type_node))
+    return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
+
   return 0;
 }
 
@@ -1379,10 +1382,8 @@
   if (mode == DImode)
     return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
 
-#if HOST_BITS_PER_WIDE_INT &gt;= 64
   if (mode == TYPE_MODE (intTI_type_node))
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
-#endif
 
   if (mode == TYPE_MODE (float_type_node))
     return float_type_node;
@@ -1449,10 +1450,8 @@
     return long_long_unsigned_type_node;
   if (type1 == widest_integer_literal_type_node)
     return widest_unsigned_literal_type_node;
-#if HOST_BITS_PER_WIDE_INT &gt;= 64
   if (type1 == intTI_type_node)
     return unsigned_intTI_type_node;
-#endif
   if (type1 == intDI_type_node)
     return unsigned_intDI_type_node;
   if (type1 == intSI_type_node)
@@ -1484,10 +1483,8 @@
     return long_long_integer_type_node;
   if (type1 == widest_unsigned_literal_type_node)
     return widest_integer_literal_type_node;
-#if HOST_BITS_PER_WIDE_INT &gt;= 64
   if (type1 == unsigned_intTI_type_node)
     return intTI_type_node;
-#endif
   if (type1 == unsigned_intDI_type_node)
     return intDI_type_node;
   if (type1 == unsigned_intSI_type_node)
@@ -1527,10 +1524,8 @@
     return (unsignedp ? widest_unsigned_literal_type_node
 	    : widest_integer_literal_type_node);
 
-#if HOST_BITS_PER_WIDE_INT &gt;= 64
   if (TYPE_PRECISION (type) == TYPE_PRECISION (intTI_type_node))
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
-#endif
   if (TYPE_PRECISION (type) == TYPE_PRECISION (intDI_type_node))
     return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
   if (TYPE_PRECISION (type) == TYPE_PRECISION (intSI_type_node))
@@ -2576,16 +2571,12 @@
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, intHI_type_node));
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, intSI_type_node));
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node));
-#if HOST_BITS_PER_WIDE_INT &gt;= 64
   pushdecl (build_decl (TYPE_DECL, get_identifier ("__int128_t"), intTI_type_node));
-#endif
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node));
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intHI_type_node));
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intSI_type_node));
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intDI_type_node));
-#if HOST_BITS_PER_WIDE_INT &gt;= 64
   pushdecl (build_decl (TYPE_DECL, get_identifier ("__uint128_t"), unsigned_intTI_type_node));
-#endif
 
   /* Create the widest literal types.  */
   widest_integer_literal_type_node
diff -burN orig.gcc-3.2.2/gcc/config/mips/core-mmi.h gcc-3.2.2/gcc/config/mips/core-mmi.h
--- orig.gcc-3.2.2/gcc/config/mips/core-mmi.h	1969-12-31 20:00:00.000000000 -0400
+++ gcc-3.2.2/gcc/config/mips/core-mmi.h	2007-04-29 05:10:04.000000000 -0300
@@ -0,0 +1,104 @@
+/*
+ * mmi-intrinsics.h - R5900 MMI compiler intrinsics.
+ *
+ * Copyright (c) 2003  M. R. Brown &lt;mrbrown@0xd6.org&gt;
+ *
+ * This file is licensed under the GNU GPL version 2.
+ *
+ * As a special exception, if you include this header file into source
+ * files compiled by GCC, this header file does not by itself cause
+ * the resulting executable to be covered by the GNU General Public
+ * License.  This exception does not however invalidate any other
+ * reasons why the executable file might be covered by the GNU General
+ * Public License.
+ *
+ */
+
+/* Based off of the mmintrin.h file in GCC 3.2.1 */
+
+#ifndef __mmi_intrinsics_h
+#define __mmi_intrinsics_h
+
+/* This for user programs. */
+typedef int __m128 __attribute__ ((mode(TI)));
+
+#define __vector __attribute__((vector_size(16)))
+
+/* These are internal. */
+typedef int __v16qi __attribute__ ((mode(V16QI)));
+typedef int __v8hi __attribute__ ((mode(V8HI)));
+typedef int __v4si __attribute__ ((mode(V4SI)));
+
+#if !defined(__u128)
+typedef unsigned int __u128 __attribute__((mode(TI)));
+#endif
+#if !defined(__s128)
+typedef __signed__ int __s128 __attribute__((mode(TI)));
+#endif
+
+/* Convert i to a __m128 object.  The integer is zero-extended to 128-bits. */
+/* XXX: No, not really.  Figure out why. */
+static __inline __m128 _mmi_cvtsi32_si128(int i)
+{
+	__u128 tmp = (unsigned int)i;
+	return (__m128)tmp;
+}
+
+/* Add the 8-bit values in m1 to the 8-bit values in m2. */
+
+static inline __m128
+_mmi_paddb(__m128 m1, __m128 m2)
+{
+	return (__m128) __builtin_mmi_paddb((__v16qi)m1, (__v16qi)m2);
+}
+
+/* Creates a vector of two 64-bit values; d0 is least significant. */
+static inline __m128
+_mmi_create_vec64(long d1, long d0)
+{
+	union {
+		__m128 q;
+		struct {
+			unsigned long d0;
+			unsigned long d1;
+		} s;
+	} u;
+
+	u.s.d0 = d0;
+	u.s.d1 = d1;
+	return u.q;
+}
+
+/* Convienence routines for creating vectors. */
+
+/* Creates a vector of 4 32-bit values; w0 is least significant. */
+static inline __m128
+_mmi_create_vec32(int w3, int w2, int w1, int w0)
+{
+	unsigned long d1 = (unsigned int)w3 &lt;&lt; 32 | (unsigned int)w2;
+	unsigned long d0 = (unsigned int)w1 &lt;&lt; 32 | (unsigned int)w0;
+	return _mmi_create_vec64(d1, d0);
+}
+
+/* Creates a vector of 8 16-bit values; h0 is least significant. */
+static inline __m128
+_mmi_create_vec16(short h7, short h6, short h5, short h4,
+		  short h3, short h2, short h1, short h0)
+{
+	unsigned long d1, d0;
+
+	d1 = (unsigned short)h7;
+	d1 = d1 &lt;&lt; 16 | (unsigned short)h6;
+	d1 = d1 &lt;&lt; 16 | (unsigned short)h5;
+	d1 = d1 &lt;&lt; 16 | (unsigned short)h4;
+
+	d0 = (unsigned short)h3;
+	d0 = d0 &lt;&lt; 16 | (unsigned short)h2;
+	d0 = d0 &lt;&lt; 16 | (unsigned short)h1;
+	d0 = d0 &lt;&lt; 16 | (unsigned short)h0;
+
+	return _mmi_create_vec64(d1, d0);
+}
+
+#endif /* __mmi_intrinsics_h */
+
diff -burN orig.gcc-3.2.2/gcc/config/mips/core-vumm.h gcc-3.2.2/gcc/config/mips/core-vumm.h
--- orig.gcc-3.2.2/gcc/config/mips/core-vumm.h	1969-12-31 20:00:00.000000000 -0400
+++ gcc-3.2.2/gcc/config/mips/core-vumm.h	2007-04-29 05:10:04.000000000 -0300
@@ -0,0 +1 @@
+#define __THIS__IS__A__BLANK__FILE__
diff -burN orig.gcc-3.2.2/gcc/config/mips/crti5900.asm gcc-3.2.2/gcc/config/mips/crti5900.asm
--- orig.gcc-3.2.2/gcc/config/mips/crti5900.asm	1969-12-31 20:00:00.000000000 -0400
+++ gcc-3.2.2/gcc/config/mips/crti5900.asm	2007-04-29 05:10:04.000000000 -0300
@@ -0,0 +1,16 @@
+/* 4 slots for argument spill area.  1 for cpreturn, 1 for stack.
+   Return spill offset of 80.  */
+
+	.section .init,"ax",@progbits
+	.globl	_init
+	.type	_init,@function
+_init:
+	addu    $sp,$sp,-96
+	sq      $31,80($sp)
+
+	.section .fini,"ax",@progbits
+	.globl	_fini
+	.type	_fini,@function
+_fini:
+	addu    $sp,$sp,-96
+	sq      $31,80($sp)
diff -burN orig.gcc-3.2.2/gcc/config/mips/crtn5900.asm gcc-3.2.2/gcc/config/mips/crtn5900.asm
--- orig.gcc-3.2.2/gcc/config/mips/crtn5900.asm	1969-12-31 20:00:00.000000000 -0400
+++ gcc-3.2.2/gcc/config/mips/crtn5900.asm	2007-04-29 05:10:04.000000000 -0300
@@ -0,0 +1,12 @@
+/* 4 slots for argument spill area.  1 for cpreturn, 1 for stack.
+   Return spill offset of 80.  */
+
+	.section .init,"ax",@progbits
+	lq      $31,80($sp)
+	addu	$sp,$sp,96
+	j	$31
+
+	.section .fini,"ax",@progbits
+	lq	$31,80($sp)
+	addu	$sp,$sp,96
+	j	$31
diff -burN orig.gcc-3.2.2/gcc/config/mips/mips.c gcc-3.2.2/gcc/config/mips/mips.c
--- orig.gcc-3.2.2/gcc/config/mips/mips.c	2002-07-26 20:23:02.000000000 -0300
+++ gcc-3.2.2/gcc/config/mips/mips.c	2007-04-29 05:10:04.000000000 -0300
@@ -51,6 +51,7 @@
 #include "gstab.h"
 #include "hashtab.h"
 #include "debug.h"
+#include "optabs.h"
 #include "target.h"
 #include "target-def.h"
 
@@ -102,6 +103,7 @@
 							 int, int));
 static void mips_emit_frame_related_store	PARAMS ((rtx, rtx,
 							 HOST_WIDE_INT));
+static void mips_check_reg_mode			PARAMS ((rtx, rtx, void *));
 static void save_restore_insns			PARAMS ((int, rtx,
 							long, FILE *));
 static void mips16_output_gp_offset		PARAMS ((FILE *, rtx));
@@ -135,6 +137,23 @@
 #endif
 static int mips_adjust_cost			PARAMS ((rtx, rtx, rtx, int));
 
+/* R5900 (Emotion Engine) support. */
+static enum sequence_type r5900_detect_sequence_type PARAMS ((rtx, int *, rtx *,
+							    int *, int));
+static void r5900_lengthen_loops		PARAMS ((rtx, int));
+static void r5900_sched_init			PARAMS ((void));
+static void mips_sched_init			PARAMS ((FILE *, int, int));
+static void r5900_sched_reorder			PARAMS ((FILE *, int, rtx *, int));
+static int mips_sched_reorder			PARAMS ((FILE *, int, rtx *,
+							int *, int));
+static void r5900_init_builtins			PARAMS ((void));
+static rtx r5900_expand_binop_builtin		PARAMS ((enum insn_code, tree,
+							rtx));
+static rtx r5900_expand_builtin			PARAMS ((tree, rtx));
+static rtx mips_expand_builtin			PARAMS ((tree, rtx, rtx,
+							enum machine_mode, int));
+static void mips_init_builtins			PARAMS ((void));
+
 /* Global variables for machine-dependent things.  */
 
 /* Threshold for data being put into the small data/bss area, instead
@@ -232,6 +251,8 @@
 /* which abi to use.  */
 int mips_abi;
 
+int mips_alignment;
+
 /* Strings to hold which cpu and instruction set architecture to use.  */
 const char *mips_cpu_string;	/* for -mcpu=&lt;xxx&gt; */
 const char *mips_arch_string;   /* for -march=&lt;xxx&gt; */
@@ -253,6 +274,18 @@
    set this option if such an option is used.  */
 const char *mips_explicit_type_size_string;
 
+#ifdef DEFAULT_MIPS_ALIGNMENT
+int mips_alignment=DEFAULT_MIPS_ALIGNMENT;	/* biggest alignment bits */
+#else
+int mips_alignment=BIGGEST_ALIGNMENT;		/* biggest alignment bits */
+#endif
+const char * mips_no_align128_string;
+const char * mips_align128_string;
+const char * mips_use_128_string;
+const char * mips_align_all_string;
+int mips_align_all = 1;
+int mips_use_128 = 0;
+
 /* Whether we are generating mips16 hard float code.  In mips16 mode
    we always set TARGET_SOFT_FLOAT; this variable is nonzero if
    -msoft-float was not specified by the user, which means that we
@@ -280,8 +313,11 @@
    initialized in override_options.  */
 REAL_VALUE_TYPE dfhigh, dflow, sfhigh, sflow;
 
-/* Mode used for saving/restoring general purpose registers.  */
-static enum machine_mode gpr_mode;
+/* The mode that will be used to save a given gpr on the stack.  Note
+   the entry for $0 is special; it indicates the generic size of a gpr
+   save/restore by the prologue/epilogue and must be the maximum mode
+   ever used to save a GPR.  This is typically WORD_MODE.  */
+enum machine_mode mips_reg_mode[GP_REG_NUM];
 
 /* Array giving truth value on whether or not a given hard register
    can support a given mode.  */
@@ -343,7 +379,8 @@
  "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
  "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31",
  "hi",   "lo",   "accum","$fcc0","$fcc1","$fcc2","$fcc3","$fcc4",
- "$fcc5","$fcc6","$fcc7","$rap"
+ "$fcc5","$fcc6","$fcc7","$rap",
+ "hi1",  "lo1",  "accum1"
 };
 
 /* Mips software names for the registers, used to overwrite the
@@ -360,7 +397,8 @@
   "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
   "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31",
   "hi",   "lo",   "accum","$fcc0","$fcc1","$fcc2","$fcc3","$fcc4",
-  "$fcc5","$fcc6","$fcc7","$rap"
+  "$fcc5","$fcc6","$fcc7","$rap",
+  "hi1",  "lo1",  "accum1"
 };
 
 /* Map hard register number to register class */
@@ -384,7 +422,8 @@
   FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,
   HI_REG,	LO_REG,		HILO_REG,	ST_REGS,
   ST_REGS,	ST_REGS,	ST_REGS,	ST_REGS,
-  ST_REGS,	ST_REGS,	ST_REGS,	GR_REGS
+  ST_REGS,	ST_REGS,	ST_REGS,	GR_REGS,
+  HI1_REG,	LO1_REG,	HILO1_REG
 };
 
 /* Map register constraint character to register class.  */
@@ -479,6 +518,18 @@
 #undef TARGET_SCHED_ADJUST_COST
 #define TARGET_SCHED_ADJUST_COST mips_adjust_cost
 
+#undef TARGET_SCHED_INIT
+#define TARGET_SCHED_INIT mips_sched_init
+
+#undef TARGET_SCHED_REORDER
+#define TARGET_SCHED_REORDER mips_sched_reorder
+
+#undef TARGET_INIT_BUILTINS
+#define TARGET_INIT_BUILTINS mips_init_builtins
+
+#undef TARGET_EXPAND_BUILTIN
+#define TARGET_EXPAND_BUILTIN mips_expand_builtin
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Return truth value of whether OP can be used as an operands
@@ -1111,6 +1162,38 @@
 		&amp;&amp; ! mips16_constant (op, mode, 1, 0)));
 }
 
+/* Return truth value of whether OP is a register, a memory operand, 
+   or a constant.  This is used by the r5900 lq/sq support.  */
+
+int
+movti_operand (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  switch (GET_CODE (op))
+    {
+    case CONST_INT:
+      if (TARGET_MIPS16)
+	return FALSE;
+      return TRUE;
+
+    case CONST_DOUBLE:
+      if (TARGET_MIPS16 || GET_MODE (op) != VOIDmode)
+	return FALSE;
+      return TRUE;
+
+    case REG:
+    case SUBREG:
+      return register_operand (op, mode);
+
+    case MEM:
+      return memory_operand (op, mode);
+
+    default:
+      return FALSE;
+    }
+}
+
 /* Like register_operand, but when in 64 bit mode also accept a sign
    extend of a 32 bit register, since the value is known to be already
    sign extended.  */
@@ -1315,6 +1398,7 @@
      accept (subreg (const_int)) which will fail to reload.  */
   if (CONSTANT_ADDRESS_P (xinsn)
       &amp;&amp; ! (mips_split_addresses &amp;&amp; mips_check_split (xinsn, mode))
+      &amp;&amp; ! (TARGET_MIPS5900 &amp;&amp; mode == TImode)
       &amp;&amp; (! TARGET_MIPS16 || mips16_constant (xinsn, mode, 1, 0)))
     return 1;
 
@@ -1651,7 +1735,7 @@
   if (type == DELAY_LOAD || type == DELAY_FCMP)
     num_nops = 1;
 
-  else if (type == DELAY_HILO)
+  else if (type == DELAY_HILO || type == DELAY_HILO1)
     num_nops = 2;
 
   else
@@ -1663,6 +1747,7 @@
     next_insn = NEXT_INSN (next_insn);
 
   dslots_load_total += num_nops;
+
   if (TARGET_DEBUG_F_MODE
       || !optimize
       || type == DELAY_NONE
@@ -1701,6 +1786,11 @@
       mips_load_reg3 = gen_rtx_REG (SImode, MD_REG_FIRST);
       mips_load_reg4 = gen_rtx_REG (SImode, MD_REG_FIRST+1);
     }
+  else if (type == DELAY_HILO1)
+    {
+      mips_load_reg3 = gen_rtx_REG (SImode, MD1_REG_FIRST);
+      mips_load_reg4 = gen_rtx_REG (SImode, MD1_REG_FIRST+1);
+    }
   else
     {
       mips_load_reg3 = 0;
@@ -1935,6 +2025,15 @@
 		    ret = "mflo\t%0";
 		}
 
+	      else if (MD1_REG_P (regno1))
+		{
+		  delay = DELAY_HILO1;
+		  if (regno1 != HILO1_REGNUM)
+		    ret = "mf%1\t%0";
+		  else
+		    ret = "mflo1\t%0";
+		}
+
 	      else if (ST_REG_P (regno1) &amp;&amp; ISA_HAS_8CC)
 		ret = "li\t%0,1\n\tmovf\t%0,%.,%1";
 
@@ -1971,6 +2070,16 @@
 		}
 	    }
 
+	  else if (MD1_REG_P (regno0))
+	    {
+	      if (GP_REG_P (regno1))
+		{
+		  delay = DELAY_HILO1;
+		  if (regno0 != HILO1_REGNUM &amp;&amp; ! TARGET_MIPS16)
+		    ret = "mt%0\t%1";
+		}
+	    }
+
 	  else if (regno0 == FPSW_REGNUM &amp;&amp; ! ISA_HAS_8CC)
 	    {
 	      if (GP_REG_P (regno1))
@@ -2056,6 +2165,12 @@
 		  delay = DELAY_HILO;
 		  ret = "mt%0\t%.";
 		}
+
+	      else if (MD1_REG_P (regno0))
+		{
+		  delay = DELAY_HILO1;
+		  ret = "mt%0\t%.";
+		}
 	    }
 
 	  else if (GP_REG_P (regno0))
@@ -2390,6 +2505,20 @@
 		ret = "mthi\t%M1\n\tmtlo\t%L1";
 	    }
 
+	  else if (MD1_REG_P (regno0) &amp;&amp; GP_REG_P (regno1) &amp;&amp; !TARGET_MIPS16)
+	    {
+	      delay = DELAY_HILO1;
+	      if (TARGET_64BIT)
+		{
+		  if (regno0 != HILO1_REGNUM)
+		    ret = "mt%0\t%1";
+		  else if (regno1 == 0)
+		    ret = "mtlo%H0\t%.\n\tmthi%H0\t%.";
+		}
+	      else
+		ret = "mthi%H0\t%M1\n\tmtlo%H0\t%L1";
+	    }
+
 	  else if (GP_REG_P (regno0) &amp;&amp; MD_REG_P (regno1))
 	    {
 	      delay = DELAY_HILO;
@@ -2402,6 +2531,18 @@
 		ret = "mfhi\t%M0\n\tmflo\t%L0";
 	    }
 
+	  else if (GP_REG_P (regno0) &amp;&amp; MD1_REG_P (regno1))
+	    {
+	      delay = DELAY_HILO1;
+	      if (TARGET_64BIT)
+		{
+		  if (regno1 != HILO1_REGNUM)
+		    ret = "mf%1\t%0";
+		}
+	      else
+		ret = "mfhi%H1\t%M0\n\tmflo%H1\t%L0";
+	    }
+
 	  else if (TARGET_64BIT)
 	    ret = "move\t%0,%1";
 
@@ -2507,6 +2648,14 @@
 		      ? "mtlo\t%.\n\tmthi\t%."
 		      : "mt%0\t%.\n");
 	    }
+
+	  else if (MD1_REG_P (regno0))
+	    {
+	      delay = DELAY_HILO1;
+	      ret =  (regno0 == HILO1_REGNUM
+		      ? "mtlo%H0\t%.\n\tmthi%H0\t%."
+		      : "mt%0\t%.\n");
+	    }
 	}
 
       else if (code1 == CONST_INT &amp;&amp; GET_MODE (op0) == DImode
@@ -3970,6 +4119,14 @@
       cum-&gt;gp_reg_found = 1;
       cum-&gt;arg_words++;
       break;
+
+    case V16QImode:
+    case V8HImode:
+    case V4SImode:
+      if (! TARGET_MMI)
+	abort ();
+      cum-&gt;gp_reg_found = 1;
+      cum-&gt;arg_words++;
     }
 }
 
@@ -4090,6 +4247,15 @@
       if (! TARGET_64BIT)
 	cum-&gt;arg_words += (cum-&gt;arg_words &amp; 1);
       regbase = GP_ARG_FIRST;
+      break;
+
+    case V4SImode:
+    case V8HImode:
+    case V16QImode:
+      if (! TARGET_MMI)
+	abort ();
+      regbase = GP_ARG_FIRST;
+
     }
 
   if (*arg_words &gt;= (unsigned) MAX_ARGS_IN_REGISTERS)
@@ -4266,6 +4432,7 @@
      int named ATTRIBUTE_UNUSED;/* != 0 for normal args, == 0 for ... args */
 {
   if ((mode == BLKmode
+       || (mode == TImode &amp;&amp; TARGET_MIPS5900)
        || GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
        || GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)
       &amp;&amp; cum-&gt;arg_words &lt; (unsigned) MAX_ARGS_IN_REGISTERS
@@ -4806,6 +4973,14 @@
     target_flags &amp;= ~((TARGET_DEFAULT) &amp; (MASK_SOFT_FLOAT | MASK_SINGLE_FLOAT));
 #endif
 
+  if (mips_align_all_string == 0)
+    mips_align_all = 1;
+
+  else if (ISDIGIT (*mips_align_all_string))
+    {
+      mips_align_all = atoi (mips_align_all_string);
+    }
+
   /* Get the architectural level.  */
   if (mips_isa_string == 0)
     mips_isa = MIPS_ISA_DEFAULT;
@@ -5036,6 +5211,10 @@
 	}
     }
 
+  /* Humf... */
+  if (mips_arch == PROCESSOR_R3000)
+    mips_isa = 1;
+
   /* make sure sizes of ints/longs/etc. are ok */
   if (! ISA_HAS_64BIT_REGS)
     {
@@ -5189,6 +5368,10 @@
   mips_char_to_class['l'] = LO_REG;
   mips_char_to_class['a'] = HILO_REG;
   mips_char_to_class['x'] = MD_REGS;
+  mips_char_to_class['u'] = HI1_REG;
+  mips_char_to_class['v'] = LO1_REG;
+  mips_char_to_class['q'] = HILO1_REG;
+  mips_char_to_class['w'] = MD1_REGS;
   mips_char_to_class['b'] = ALL_REGS;
   mips_char_to_class['y'] = GR_REGS;
   mips_char_to_class['z'] = ST_REGS;
@@ -5234,6 +5417,10 @@
 			|| FP_REG_P (regno));
 	    }
 
+	  /* General registers can hold TImode values on the r5900.  */
+	  else if (GP_REG_P (regno) &amp;&amp; mode == TImode &amp;&amp; TARGET_MIPS5900)
+	    temp = 1;
+
 	  else if (GP_REG_P (regno))
 	    temp = ((regno &amp; 1) == 0 || size &lt;= UNITS_PER_WORD);
 
@@ -5257,6 +5444,12 @@
 			|| (regno == MD_REG_FIRST
 			    &amp;&amp; size == 2 * UNITS_PER_WORD)));
 
+	  else if (MD1_REG_P (regno))
+	    temp = (class == MODE_INT
+		    &amp;&amp; (size &lt;= UNITS_PER_WORD
+			|| (regno == MD1_REG_FIRST
+			    &amp;&amp; size == 2 * UNITS_PER_WORD)));
+
 	  else
 	    temp = 0;
 
@@ -5266,9 +5459,18 @@
 
   /* Save GPR registers in word_mode sized hunks.  word_mode hasn't been
      initialized yet, so we can't use that here.  */
-  gpr_mode = TARGET_64BIT ? DImode : SImode;
+  for (regno = GP_REG_FIRST; regno &lt;= GP_REG_LAST; regno++)
+    {
+      mips_reg_mode[regno] = TARGET_64BIT ? DImode : SImode;
+    }
+
+  /* Saves/restores of general purpose registers on the r5900 use
+     a mode wider than word_mode.  */
+  if (TARGET_MIPS5900)
+    mips_reg_mode[0] = TImode;
 
   /* Provide default values for align_* for 64-bit targets.  */
+  /* XXX: fix this up for the r5900. */
   if (TARGET_64BIT &amp;&amp; !TARGET_MIPS16)
     {
       if (align_loops == 0)
@@ -5279,6 +5481,21 @@
 	align_functions = 8;
     }
 
+#ifdef DEFAULT_MIPS_ALIGNMENT
+  if (mips_align128_string != NULL) {
+	/* -malign128 */
+  	mips_alignment=128;
+  } 
+  if (mips_no_align128_string != NULL) {
+	/* -mno-align128 */
+  	mips_alignment=64;
+  }
+#endif
+
+  if (mips_use_128_string != NULL) {
+	mips_use_128=1;
+  }
+
   /* Register global variables with the garbage collector.  */
   mips_add_gc_roots ();
 }
@@ -5380,6 +5597,7 @@
    'M'  print high-order register of double-word register operand.
    'C'  print part of opcode for a branch condition.
    'F'  print part of opcode for a floating-point branch condition.
+   'H'  print the appropiate Integer pipe # for r5900 mult/div instructions.
    'N'  print part of opcode for a branch condition, inverted.
    'W'  print part of opcode for a floating-point branch condition, inverted.
    'S'  X is CODE_LABEL, print with prefix of "LS" (for embedded switch).
@@ -5604,7 +5822,17 @@
       default:
 	abort_with_insn (op, "PRINT_OPERAND, invalid insn for %%W");
       }
+  else if (letter == 'H')
+    {
+      if (true_regnum (op) &gt;= MD_REG_FIRST
+	       &amp;&amp; true_regnum (op) &lt;= MD_REG_LAST)
+	     ;
+
+      else if (true_regnum (op) &gt;= MD1_REG_FIRST
+	       &amp;&amp; true_regnum (op) &lt;= MD1_REG_LAST)
+	fputs ("1", file);
 
+    }
   else if (letter == 'S')
     {
       char buffer[100];
@@ -5628,6 +5856,16 @@
 	fprintf (file, "%s,", reg_names[regnum]);
     }
 
+  else if ((letter == 'L' || letter == 'M')
+	   &amp;&amp; code == CONST_DOUBLE
+	   &amp;&amp; GET_MODE (op) == VOIDmode)
+    {
+      if (letter == 'L')
+	fprintf (file, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (op));
+      else
+	fprintf (file, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_HIGH (op));
+    }
+
   else if (code == REG || code == SUBREG)
     {
       register int regnum;
@@ -6099,8 +6337,7 @@
 	  || (mips_load_reg != 0 &amp;&amp; reg_mentioned_p (mips_load_reg,  pattern))
 	  || (mips_load_reg2 != 0 &amp;&amp; reg_mentioned_p (mips_load_reg2, pattern))
 	  || (mips_load_reg3 != 0 &amp;&amp; reg_mentioned_p (mips_load_reg3, pattern))
-	  || (mips_load_reg4 != 0
-	      &amp;&amp; reg_mentioned_p (mips_load_reg4, pattern)))
+	  || (mips_load_reg4 != 0 &amp;&amp; reg_mentioned_p (mips_load_reg4, pattern)))
 	fputs ("\t#nop\n", asm_out_file);
 
       else
@@ -6298,6 +6535,27 @@
     }
 }
 
+void
+mips_declare_object_align (stream, name, init_string, final_string, size, align)
+     FILE *stream;
+     const char *name;
+     const char *init_string;
+     const char *final_string;
+     int size;
+     int align;
+{
+  fputs (init_string, stream);		/* "", "\t.comm\t", or "\t.lcomm\t" */
+  assemble_name (stream, name);
+  fprintf (stream, final_string, size, align);	/* ":\n", ",%u\n", ",%u\n" */
+
+  if (TARGET_GP_OPT)
+    {
+      tree name_tree = get_identifier (name);
+      TREE_ASM_WRITTEN (name_tree) = 1;
+    }
+}
+
+
 /* Return the bytes needed to compute the frame pointer from the current
    stack pointer.
 
@@ -6410,7 +6668,7 @@
 		  || (GET_MODE_SIZE (DECL_MODE (DECL_RESULT (current_function_decl)))
 		      &lt;= 4))))
 	{
-	  gp_reg_size += GET_MODE_SIZE (gpr_mode);
+	  gp_reg_size += GET_MODE_SIZE (mips_reg_mode[0]);
 	  mask |= 1L &lt;&lt; (regno - GP_REG_FIRST);
 
 	  /* The entry and exit pseudo instructions can not save $17
@@ -6434,7 +6692,7 @@
 	  regno = EH_RETURN_DATA_REGNO (i);
 	  if (regno == INVALID_REGNUM)
 	    break;
-	  gp_reg_size += GET_MODE_SIZE (gpr_mode);
+	  gp_reg_size += GET_MODE_SIZE (mips_reg_mode[0]);
 	  mask |= 1L &lt;&lt; (regno - GP_REG_FIRST);
 	}
     }
@@ -6516,9 +6774,9 @@
          top of the stack.  */
       if (! mips_entry)
 	offset = (args_size + extra_size + var_size
-		  + gp_reg_size - GET_MODE_SIZE (gpr_mode));
+		  + gp_reg_size - GET_MODE_SIZE (mips_reg_mode[0]));
       else
-	offset = total_size - GET_MODE_SIZE (gpr_mode);
+	offset = total_size - GET_MODE_SIZE (mips_reg_mode[0]);
 
       current_frame_info.gp_sp_offset = offset;
       current_frame_info.gp_save_offset = offset - total_size;
@@ -6654,6 +6912,24 @@
   mips_annotate_frame_insn (emit_move_insn (mem, reg), dwarf_expr);
 }
 
+/* If modifying X uses a larger mode than in mips_reg_mode,
+   indicate that fact by setting mips_reg_mode.  */
+
+static void
+mips_check_reg_mode (x, set, data)
+     rtx x;
+     rtx set ATTRIBUTE_UNUSED;
+     void *data ATTRIBUTE_UNUSED;
+{
+  if (GET_CODE (x) == REG 
+      &amp;&amp; REGNO (x) &lt;= GP_REG_LAST
+      &amp;&amp; (GET_MODE_SIZE (GET_MODE (x))
+	  &gt; GET_MODE_SIZE (mips_reg_mode[REGNO (x)])))
+    {
+      mips_reg_mode[REGNO (x)] = GET_MODE (x);
+    }
+}
+
 static void
 save_restore_insns (store_p, large_reg, large_offset, file)
      int store_p;	/* true if this is prologue */
@@ -6690,6 +6966,47 @@
      need a nop in the epilog if at least one register is reloaded in
      addition to return address.  */
 
+  if (TARGET_MIPS5900 &amp;&amp; store_p)
+    {
+      rtx insn;
+      tree attr;
+
+      for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn))
+	{
+	  if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+	    note_stores (PATTERN (insn), mips_check_reg_mode, NULL);
+	}
+
+      if ((attr = lookup_attribute
+	   ("register_precision", DECL_ATTRIBUTES (current_function_decl)))
+	  != 0)
+	for (; attr; attr = TREE_CHAIN (attr))
+	  {
+	    const char *reg_expr = IDENTIFIER_POINTER (TREE_VALUE (TREE_VALUE (attr)));
+	    tree reg_length = TREE_VALUE (TREE_CHAIN (TREE_VALUE (attr)));
+	    enum machine_mode mode = VOIDmode;
+	    int j;
+	    switch (TREE_INT_CST_LOW (reg_length))
+	      {
+	      case 32:
+		mode= SImode;
+		break;
+	      case 64:
+		mode= DImode;
+		break;
+	      case 128:
+		mode= TImode;
+		break;
+	      }
+
+	    if ((j = decode_reg_name (reg_expr)) &gt;= 0)
+	      {
+		if (j != 0)
+		  mips_reg_mode[j] = mode;
+	      }
+	  }
+    }
+
   /* Save GP registers if needed.  */
   if (mask)
     {
@@ -6702,7 +7019,7 @@
       gp_offset = current_frame_info.gp_sp_offset;
       end_offset
 	= gp_offset - (current_frame_info.gp_reg_size
-		       - GET_MODE_SIZE (gpr_mode));
+		       - GET_MODE_SIZE (mips_reg_mode[0]));
 
       if (gp_offset &lt; 0 || end_offset &lt; 0)
 	internal_error
@@ -6765,7 +7082,8 @@
 	      {
 		rtx reg_rtx;
 		rtx mem_rtx
-		  = gen_rtx (MEM, gpr_mode,
+		  = gen_rtx (MEM,
+			     mips_reg_mode[regno],
 			     gen_rtx (PLUS, Pmode, base_reg_rtx,
 				      GEN_INT (gp_offset - base_offset)));
 
@@ -6776,23 +7094,24 @@
                    $31, so we load $7 instead, and work things out
                    in mips_expand_epilogue.  */
 		if (TARGET_MIPS16 &amp;&amp; ! store_p &amp;&amp; regno == GP_REG_FIRST + 31)
-		  reg_rtx = gen_rtx (REG, gpr_mode, GP_REG_FIRST + 7);
+		  reg_rtx = gen_rtx (REG, mips_reg_mode[7], GP_REG_FIRST + 7);
 		/* The mips16 sometimes needs to save $18.  */
 		else if (TARGET_MIPS16
 			 &amp;&amp; regno != GP_REG_FIRST + 31
 			 &amp;&amp; ! M16_REG_P (regno))
 		  {
 		    if (! store_p)
-		      reg_rtx = gen_rtx (REG, gpr_mode, 6);
+		      reg_rtx = gen_rtx (REG, mips_reg_mode[6], 6);
 		    else
 		      {
-			reg_rtx = gen_rtx (REG, gpr_mode, 3);
+			reg_rtx = gen_rtx (REG, mips_reg_mode[3], 3);
 			emit_move_insn (reg_rtx,
-					gen_rtx (REG, gpr_mode, regno));
+					gen_rtx (REG, mips_reg_mode[regno],
+						 regno));
 		      }
 		  }
 		else
-		  reg_rtx = gen_rtx (REG, gpr_mode, regno);
+		  reg_rtx = gen_rtx (REG, mips_reg_mode[regno], regno);
 
 		if (store_p)
 		  mips_emit_frame_related_store (mem_rtx, reg_rtx, gp_offset);
@@ -6802,7 +7121,7 @@
 		    if (TARGET_MIPS16
 			&amp;&amp; regno != GP_REG_FIRST + 31
 			&amp;&amp; ! M16_REG_P (regno))
-		      emit_move_insn (gen_rtx (REG, gpr_mode, regno),
+		      emit_move_insn (gen_rtx (REG, mips_reg_mode[regno], regno),
 				      reg_rtx);
 		  }
 	      }
@@ -6844,13 +7163,13 @@
 		  fprintf (file, "\tmove\t%s,%s\n",
 			   reg_names[regno], reg_names[r]);
 	      }
-	    gp_offset -= GET_MODE_SIZE (gpr_mode);
+	    gp_offset -= GET_MODE_SIZE (mips_reg_mode[0]);
 	  }
         /* If the restore is being supressed, still take into account
 	   the offset at which it is stored.  */
  	else if (BITSET_P (real_mask, regno - GP_REG_FIRST))
  	  {
-	    gp_offset -= GET_MODE_SIZE (gpr_mode);
+	    gp_offset -= GET_MODE_SIZE (mips_reg_mode[0]);
 	  }
     }
   else
@@ -6875,13 +7194,13 @@
 	base_reg_rtx = stack_pointer_rtx, base_offset  = 0;
 
       else if (base_reg_rtx != 0
-	       &amp;&amp; (unsigned HOST_WIDE_INT) (base_offset - fp_offset) &lt; 32768
-	       &amp;&amp; (unsigned HOST_WIDE_INT) (base_offset - end_offset) &lt; 32768)
+	       &amp;&amp; (((unsigned HOST_WIDE_INT) (base_offset - fp_offset)) &lt; 32768)
+	       &amp;&amp; (((unsigned HOST_WIDE_INT) (base_offset - end_offset)) &lt; 32768))
 	;			/* already set up for gp registers above */
 
       else if (large_reg != 0
-	       &amp;&amp; (unsigned HOST_WIDE_INT) (large_offset - fp_offset) &lt; 32768
-	       &amp;&amp; (unsigned HOST_WIDE_INT) (large_offset - end_offset) &lt; 32768)
+	       &amp;&amp; (((unsigned HOST_WIDE_INT) (large_offset - fp_offset)) &lt; 32768)
+	       &amp;&amp; (((unsigned HOST_WIDE_INT) (large_offset - end_offset)) &lt; 32768))
 	{
 	  base_reg_rtx = gen_rtx_REG (Pmode, MIPS_TEMP2_REGNUM);
 	  base_offset = large_offset;
@@ -7313,10 +7632,10 @@
 	{
 	  if (offset != 0)
 	    ptr = gen_rtx (PLUS, Pmode, stack_pointer_rtx, GEN_INT (offset));
-	  emit_move_insn (gen_rtx (MEM, gpr_mode, ptr),
-			  gen_rtx (REG, gpr_mode, regno));
+	  emit_move_insn (gen_rtx (MEM, mips_reg_mode[regno], ptr),
+			  gen_rtx (REG, mips_reg_mode[regno], regno));
 
-	  offset += GET_MODE_SIZE (gpr_mode);
+	  offset += GET_MODE_SIZE (mips_reg_mode[0]);
 	}
     }
 
@@ -7361,7 +7680,8 @@
 	 moment.  */
       if (TARGET_MIPS16 &amp;&amp; BITSET_P (current_frame_info.mask, 18))
 	{
-	  rtx reg_rtx = gen_rtx (REG, gpr_mode, GP_REG_FIRST + 3);
+	  rtx reg_rtx = gen_rtx (REG, mips_reg_mode[GP_REG_FIRST + 3],
+			  	 GP_REG_FIRST + 3);
 	  long gp_offset, base_offset;
 
 	  gp_offset = current_frame_info.gp_sp_offset;
@@ -7377,8 +7697,9 @@
 	    base_offset = 0;
 	  start_sequence ();
 	  emit_move_insn (reg_rtx,
-			  gen_rtx (REG, gpr_mode, GP_REG_FIRST + 18));
-	  emit_move_insn (gen_rtx (MEM, gpr_mode,
+			  gen_rtx (REG, mips_reg_mode[GP_REG_FIRST + 18],
+				   GP_REG_FIRST + 18));
+	  emit_move_insn (gen_rtx (MEM, mips_reg_mode[GP_REG_FIRST + 18],
 				   gen_rtx (PLUS, Pmode, stack_pointer_rtx,
 					    GEN_INT (gp_offset
 						     - base_offset))),
@@ -8108,6 +8429,11 @@
   if (type == NULL_TREE || mode == DImode || mode == DFmode)
     return 0;
 
+  /* The r5900 can pass TImode values in a single register, so
+     there is no need to pass it by reference.  */
+  if (mode == TImode &amp;&amp; TARGET_MIPS5900)
+    return 0;
+
   size = int_size_in_bytes (type);
   return size == -1 || size &gt; UNITS_PER_WORD;
 }
@@ -8168,15 +8494,30 @@
 	     &amp;&amp; gp_reg_p
 	     &amp;&amp; GET_MODE_SIZE (mode) &lt;= GET_MODE_SIZE (SImode))
 	    ? NO_REGS : gr_regs);
+
+  else if (class == HILO1_REG &amp;&amp; regno != GP_REG_FIRST + 0)
+    return ((! in_p
+	     &amp;&amp; gp_reg_p
+	     &amp;&amp; GET_MODE_SIZE (mode) &lt;= GET_MODE_SIZE (SImode))
+	    ? NO_REGS : gr_regs);
+
   else if (regno == HILO_REGNUM)
     return ((in_p
 	     &amp;&amp; class == gr_regs
 	     &amp;&amp; GET_MODE_SIZE (mode) &lt;= GET_MODE_SIZE (SImode))
 	    ? NO_REGS : gr_regs);
 
+  else if (regno == HILO1_REGNUM)
+    return ((in_p
+	     &amp;&amp; class == gr_regs
+	     &amp;&amp; GET_MODE_SIZE (mode) &lt;= GET_MODE_SIZE (SImode))
+	    ? NO_REGS : gr_regs);
+
   /* Copying from HI or LO to anywhere other than a general register
      requires a general register.  */
-  if (class == HI_REG || class == LO_REG || class == MD_REGS)
+
+  if (class == HI_REG  || class == LO_REG  || class == MD_REGS
+   || class == HI1_REG || class == LO1_REG || class == MD1_REGS)
     {
       if (TARGET_MIPS16 &amp;&amp; in_p)
 	{
@@ -8185,7 +8526,8 @@
 	}
       return gp_reg_p ? NO_REGS : gr_regs;
     }
-  if (MD_REG_P (regno))
+
+  if (MD_REG_P (regno) || MD1_REG_P (regno))
     {
       if (TARGET_MIPS16 &amp;&amp; ! in_p)
 	{
@@ -9344,6 +9686,11 @@
   if (! TARGET_MIPS16)
     return;
 
+#ifdef FILL_BDSLOT_WITH_NOP
+  if (TARGET_MIPS5900 &amp;&amp; !TARGET_NO_LENGTHEN_LOOP)
+    r5900_lengthen_loops (first,0);
+#endif
+
   /* If $gp is used, try to remove stores, and replace loads with
      copies from $gp.  */
   if (optimize)
@@ -9533,6 +9880,205 @@
      constant table, but we have no way to prevent that.  */
 }
 
+
+/* On the R5900, we must ensure that the compiler never generates loops
+   that satisfy all of the following conditions:
+   
+   * a loop consists of less than equal to six instructions (including the
+     branch delay slot).
+   
+   * a loop contains only one conditional branch instruction at the
+     end of the loop.
+     
+   * a loop does not contain any other branch or jump instructions.
+
+   * a branch delay slot of the loop is not nop. ( EE#2.9 or later )
+
+   We need to do this because of a bug in the chip.
+
+   */
+
+#define NOP_INSN_P(INSN) (rtx_equal_p (INSN, gen_nop ()))
+
+enum sequence_type {Jump, Reset, Other};
+
+/* Detect if possible loop jump presents in the sequence */
+
+static enum sequence_type 
+r5900_detect_sequence_type (insn, count_p, jump_insn_p, seen_before, 
+			after_delayed_branch_sched)
+	rtx insn;
+	int *count_p;
+	rtx *jump_insn_p;
+	int *seen_before;
+	int after_delayed_branch_sched;
+{
+  int i;
+  int detect_later = 0;
+
+  for (i = 0; i &lt; XVECLEN (PATTERN (insn), 0); i++)
+    {
+      rtx v_insn;
+      v_insn = XVECEXP (PATTERN (insn), 0, i);
+
+      switch (GET_CODE (v_insn))
+        {
+	case CODE_LABEL:
+	  seen_before [INSN_UID (v_insn)] = *count_p;
+	  break;
+	case INSN:
+	  /* The attr_length may be bigger than acctual insn length.
+	     So don't use it in the after_delayed_branch_sched phase. */
+	  *count_p  += ( get_attr_length (insn) &gt; 0 
+			&amp;&amp; !after_delayed_branch_sched ) 
+		        ?  get_attr_length (insn) : 4 ; 
+	  if (detect_later)
+	    {
+	      /* inspect BD slot */
+	      if (NOP_INSN_P (PATTERN (v_insn)))
+		return Reset;
+	      return Jump;
+	    }
+	  break;
+	case JUMP_INSN:
+	  *jump_insn_p = v_insn;
+	  detect_later = 1;
+	  break;
+	case CALL_INSN:
+	  return Reset;
+	  break;
+	default:
+	  break;
+	}
+    }
+
+  if (detect_later) 
+    /* Since there's no instruction in the delay slot, the assembler will
+       insert a "nop" later.  */
+    return  Reset;
+
+  return Other;
+}
+
+/* XXX: Fix this.  */
+
+static void
+r5900_lengthen_loops (first, after_delayed_branch_sched)
+  rtx first;
+  int after_delayed_branch_sched;
+{
+  rtx insn;
+  rtx this_jump_insn;
+  const int hazardous_distance = 6;
+  int n = 4;
+  int max_uid = get_max_uid ();
+  int *seen_before = alloca (sizeof seen_before[0] * max_uid);
+  int in_sequence = 0;
+  enum sequence_type result;
+
+  /*bzero ((char *) seen_before, sizeof seen_before[0] * max_uid);*/
+  memset((char *) seen_before, 0, sizeof seen_before[0] * max_uid);
+      
+  for (insn = first; insn; insn = NEXT_INSN (insn))
+    {
+      in_sequence = 0;
+      switch (GET_CODE (insn))
+	{
+	case CODE_LABEL:
+	  seen_before [INSN_UID (insn)] = n;
+	  break;
+
+	case INSN:
+	  if (GET_CODE (PATTERN (insn)) != SEQUENCE ) 
+	    {
+	      /* The attr_length may be bigger than acctual insn length.
+	         So don't use it in the after_delayed_branch_sched phase. */
+	      n += ( get_attr_length (insn) &gt; 0 
+	            &amp;&amp; !after_delayed_branch_sched ) 
+		 ?  get_attr_length (insn) : 4 ; 
+	      break;
+	    }
+	  result = r5900_detect_sequence_type(insn, &amp;n, &amp;this_jump_insn, 
+				  seen_before, after_delayed_branch_sched);
+	  switch(result) 
+	    {
+	    case Reset:
+	      goto reset;
+	    case Jump:
+	      in_sequence=1;
+	      goto jump_insn;
+	    case Other:
+	    default:
+	      break;
+	    }
+	  break;
+
+	case JUMP_INSN:
+          this_jump_insn = insn;
+	  in_sequence=0;
+      jump_insn:
+	  if (condjump_p (this_jump_insn))
+	    {
+	      rtx target = condjump_label (this_jump_insn);
+
+	      if (seen_before [INSN_UID (XEXP (target, 0))])
+		{
+		  int distance 
+		    = (n - seen_before [INSN_UID (XEXP (target, 0))]) &gt;&gt; 2;
+
+		  if (!in_sequence) 
+		    {
+		    /* try to insert one nop before jump 
+		     * if distance is in hazardous_distance */
+
+	 	    if  ( distance &lt;=  hazardous_distance )
+		      {
+		        rtx prev_insn = PREV_INSN (this_jump_insn);
+		        while ( prev_insn &amp;&amp; ( GET_CODE (prev_insn) != INSN ))
+			    prev_insn =  PREV_INSN (prev_insn);
+			if (prev_insn &amp;&amp; ! NOP_INSN_P (PATTERN (prev_insn)))
+			      emit_insn_before (gen_nop (), this_jump_insn);
+
+		      }
+		    }
+		  else 
+		    {
+		      if ( distance &lt;= hazardous_distance ) 
+		        {
+	     	          for (; distance &lt;= hazardous_distance; distance++) 
+		            emit_insn_before (gen_nop(), insn);
+		        }
+		    }
+		}
+	    }
+
+	  /* Falls through */
+
+	case CALL_INSN:
+      reset:
+	  /*bzero ((char *) seen_before, sizeof seen_before[0] * max_uid);*/
+          memset((char *) seen_before, 0, sizeof seen_before[0] * max_uid);
+	  break;
+	    
+	default:
+	  break;
+	}
+    }
+}
+ 
+/* Exported to toplev.c.
+
+   Do a final pass over the function, just before rtl to asm conversion
+   (after "delayed branch scheduling" and "shorten jump").  */
+
+void
+machine_dependent_reorg_final (first)
+     rtx first;
+{
+  if (TARGET_MIPS5900 &amp;&amp; ! TARGET_NO_LENGTHEN_LOOP)
+    r5900_lengthen_loops (first, 1);
+}
+
 /* Return nonzero if X is a SIGN or ZERO extend operator.  */
 int
 extend_operator (x, mode)
@@ -9933,6 +10479,8 @@
     case '5':
       if (!strcmp (p, "5000") || !strcmp (p, "5k") || !strcmp (p, "5K"))
 	cpu = PROCESSOR_R5000;
+      else if (!strcmp (p, "5900"))
+	cpu = PROCESSOR_R5900;
       else if (!strcmp (p, "5kc") || !strcmp (p, "5Kc") )
           cpu = PROCESSOR_R5KC;
       break;
@@ -10057,7 +10605,10 @@
     int regno;
     enum machine_mode mode;
 {
-  if (! FP_REG_P (regno))
+  /* TODO: Add r5900 dual mode register support. */
+  if (TARGET_MIPS5900 &amp;&amp; GP_REG_P (regno) &amp;&amp; mode == TImode)
+    return 1;
+  else if (! FP_REG_P (regno))
     return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
   else
     return ((GET_MODE_SIZE (mode) + UNITS_PER_FPREG - 1) / UNITS_PER_FPREG);
@@ -10223,3 +10774,345 @@
   mips_asm_file_end (stream);
 }
 #endif /* TARGET_IRIX6 */
+
+static void
+r5900_sched_init ()
+{
+}
+
+static void
+mips_sched_init (dump, sched_verbose, veclen)
+     FILE *dump ATTRIBUTE_UNUSED;
+     int sched_verbose ATTRIBUTE_UNUSED;
+     int veclen ATTRIBUTE_UNUSED;
+{
+  if (TARGET_MIPS5900)
+    r5900_sched_init ();
+}
+
+static void
+r5900_sched_reorder (dump, sched_verbose, ready, n_ready)
+     FILE *dump;
+     int sched_verbose;
+     rtx *ready;
+     int n_ready;
+{
+  static int imuldivunit = -1;
+
+  return;
+  /* There is also no point in trying these tweaks after reload has
+     completed.  */
+  if (reload_completed)
+    return;
+
+  /* If there are less than three insns on the queue, then there's nothing
+     to do.  */
+  if (n_ready &lt; 3)
+    return;
+
+  /* We need to know what value will be returned by function_units_used for
+     the r5900's multiply/divide units.  If we have not computed it yet,
+     do so now.  */
+  if (imuldivunit == -1)
+    {
+      int i;
+
+      for (i = 0; i &lt; FUNCTION_UNITS_SIZE; i++)
+	{
+	  if (!strcmp ("r5900imuldiv", function_units[i].name))
+	    {
+	      imuldivunit = i;
+	      break;
+	    }
+	}
+      if (imuldivunit == -1)
+	return;
+    }
+
+    {
+      int i;
+
+      /* Loop through the instructions and try to pair up two instructions
+	 which use the imuldiv pipelines.
+
+	 We want such instructions to appear back to back in the RTL chain
+	 so that the register allocator will allocate a different HILO
+	 register for the two imuldiv instructions.
+
+	 Note the ready list is ordered backwards. 
+
+	 If we do not find an idivmul insn which could issue this cycle, quit
+	 to save time.  */
+      for (i = n_ready - 1; i &gt;= n_ready - 2; i--)
+	{
+	  rtx insn = ready[i];
+	  enum rtx_code code;
+
+	  /* Ignore anything we do not understand.  */
+	  if (GET_RTX_CLASS (GET_CODE (insn)) != 'i'
+	      || (code = GET_CODE (PATTERN (insn))) == USE
+	      || code == CLOBBER || code == ADDR_VEC)
+	    continue;
+	  else
+	    {
+	      /* We are looking for instructions that issue to the imuldiv
+		 pipelines.  */
+	      if (function_units_used (insn) == imuldivunit)
+		{
+		  int j;
+
+		  /* We have found one insn that uses the imuldiv pipeline, so
+		     now look for another imuldiv instruction.  */
+		  for (j = i - 1; j &gt;= 0; j--)
+		    {
+		      rtx temp = ready[j];
+
+		      /* Ignore anything we do not understand.  */
+		      if (GET_RTX_CLASS (GET_CODE (temp)) != 'i'
+			  || (code = GET_CODE (PATTERN (temp))) == USE
+			  || code == CLOBBER || code == ADDR_VEC)
+			continue;
+
+		      /* Again, we are looking for an imuldiv insn.  */
+		      if (function_units_used (temp) == imuldivunit)
+			{
+
+			  /* Make the idivmul insns consecutive if they were
+			     not already consecutive.  */
+			  if (i - j != 1)
+			    {
+			      rtx temp = ready[j];
+			      /*bcopy (&amp;ready[j+1], &amp;ready[j],
+				       (i - j - 1) * sizeof (rtx *));*/
+			      memcpy(&amp;ready[j], &amp;ready[j+1], (i - j - 1) * sizeof (rtx *));
+			      ready[i - 1] = temp;
+			    }
+
+			  /* Now the imuldiv insns are consecutive.  We can
+			     still lose if they issue at different clocks, so
+			     move them as a pair to the head of ready list. 
+
+			     Note I must either be the head of the queue or
+			     the second insn in the queue.  */
+			  if (i != n_ready - 1)
+			    {
+			      rtx temp1, temp2;
+
+			      /* Rotate the first three elements in the
+				 ready queue.  */
+			      temp1 = ready[n_ready - 1];
+			      temp2 = ready[n_ready - 2];
+			      ready[n_ready - 2] = ready[n_ready - 3];
+			      ready[n_ready - 3] = temp1;
+			      ready[n_ready - 1] = temp2;
+			    }
+			  return;
+			}
+		    }
+		}
+	    }
+	}
+    }
+}
+
+/* Reorder the ready list as needed to improve performance.  */
+
+static int
+mips_sched_reorder (dump, sched_verbose, ready, n_readyp, clock_var)
+     FILE *dump ATTRIBUTE_UNUSED;
+     int sched_verbose ATTRIBUTE_UNUSED;
+     rtx *ready;
+     int *n_readyp;
+     int clock_var ATTRIBUTE_UNUSED;
+{
+  if (TARGET_MIPS5900)
+    r5900_sched_reorder (dump, sched_verbose, ready, *n_readyp);
+  return ISSUE_RATE;
+}
+
+/* R5900 built-ins support.  This is largely based off of the ix86 SSE/MMX
+   and rs6000 Altivec implementations. */
+
+#define def_builtin(MASK, NAME, TYPE, CODE)				\
+do {									\
+  if ((MASK) &amp; target_flags) 						\
+    builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL);	\
+} while (0)
+
+struct builtin_description
+{
+  const unsigned int mask;
+  const enum insn_code icode;
+  const char *const name;
+  const enum r5900_builtins code;
+};
+
+/* Builtins that take 2 arguments. */
+static struct builtin_description bdesc_2arg[] =
+{
+  { MASK_MMI, CODE_FOR_addv16qi3,   "__builtin_mmi_paddb", MMI_BUILTIN_PADDB },
+  { MASK_MMI, CODE_FOR_addv8hi3,    "__builtin_mmi_paddh", MMI_BUILTIN_PADDH },
+  { MASK_MMI, CODE_FOR_addv4si3,    "__builtin_mmi_paddw", MMI_BUILTIN_PADDW },
+  { MASK_MMI, CODE_FOR_ssaddv16qi3, "__builtin_mmi_paddsb", MMI_BUILTIN_PADDSB },
+  { MASK_MMI, CODE_FOR_ssaddv8hi3,  "__builtin_mmi_paddsh", MMI_BUILTIN_PADDSW },
+  { MASK_MMI, CODE_FOR_ssaddv4si3,  "__builtin_mmi_paddsw", MMI_BUILTIN_PADDSH },
+  { MASK_MMI, CODE_FOR_usaddv16qi3, "__builtin_mmi_paddub", MMI_BUILTIN_PADDUB },
+  { MASK_MMI, CODE_FOR_usaddv8hi3,  "__builtin_mmi_padduh", MMI_BUILTIN_PADDUW },
+  { MASK_MMI, CODE_FOR_usaddv4si3,  "__builtin_mmi_padduw", MMI_BUILTIN_PADDUH },
+
+  { MASK_MMI, CODE_FOR_subv16qi3,   "__builtin_mmi_psubb", MMI_BUILTIN_PSUBB },
+  { MASK_MMI, CODE_FOR_subv8hi3,    "__builtin_mmi_psubh", MMI_BUILTIN_PSUBH },
+  { MASK_MMI, CODE_FOR_subv4si3,    "__builtin_mmi_psubw", MMI_BUILTIN_PSUBW },
+  { MASK_MMI, CODE_FOR_sssubv16qi3, "__builtin_mmi_psubsb", MMI_BUILTIN_PSUBSB },
+  { MASK_MMI, CODE_FOR_sssubv8hi3,  "__builtin_mmi_psubsh", MMI_BUILTIN_PSUBSW },
+  { MASK_MMI, CODE_FOR_sssubv4si3,  "__builtin_mmi_psubsw", MMI_BUILTIN_PSUBSH },
+  { MASK_MMI, CODE_FOR_ussubv16qi3, "__builtin_mmi_psubub", MMI_BUILTIN_PSUBUB },
+  { MASK_MMI, CODE_FOR_ussubv8hi3,  "__builtin_mmi_psubuh", MMI_BUILTIN_PSUBUW },
+  { MASK_MMI, CODE_FOR_ussubv4si3,  "__builtin_mmi_psubuw", MMI_BUILTIN_PSUBUH },
+
+};
+
+/* Expand all r5900-specific builtins.  This is only called if TARGET_MMI or
+   TARGET_VUMM are true.  */
+static void
+r5900_init_builtins()
+{
+  struct builtin_description *d;
+  size_t i;
+  tree endlink = void_list_node;
+
+  /* Normal vector binops. */
+  tree v16qi_ftype_v16qi_v16qi
+    = build_function_type (V16QI_type_node,
+		    	   tree_cons (NULL_TREE, V16QI_type_node,
+				      tree_cons (NULL_TREE, V16QI_type_node,
+					         endlink)));
+
+  tree v8hi_ftype_v8hi_v8hi
+    = build_function_type (V8HI_type_node,
+		    	   tree_cons (NULL_TREE, V8HI_type_node,
+				      tree_cons (NULL_TREE, V8HI_type_node,
+					         endlink)));
+
+  tree v4si_ftype_v4si_v4si
+    = build_function_type (V4SI_type_node,
+		    	   tree_cons (NULL_TREE, V4SI_type_node,
+				      tree_cons (NULL_TREE, V4SI_type_node,
+					         endlink)));
+
+  tree ti_ftype_ti_ti
+    = build_function_type (intTI_type_node,
+		    	   tree_cons (NULL_TREE, intTI_type_node,
+				      tree_cons (NULL_TREE, intTI_type_node,
+					         endlink)));
+
+  /* Add all builtins that are simple binary operations. */
+  for (i = 0, d = bdesc_2arg; i &lt; sizeof (bdesc_2arg) / sizeof *d; i++, d++)
+    {
+      enum machine_mode mode;
+      tree type;
+
+      if (d-&gt;name == 0)
+	continue;
+      mode = insn_data[d-&gt;icode].operand[1].mode;
+
+      switch (mode)
+        {
+	case V16QImode:
+	  type = v16qi_ftype_v16qi_v16qi;
+	  break;
+	case V8HImode:
+	  type = v8hi_ftype_v8hi_v8hi;
+	case V4SImode:
+	  type = v4si_ftype_v4si_v4si;
+	case TImode:
+	  type = ti_ftype_ti_ti;
+	  break;
+
+	default:
+	  abort ();
+	}
+
+      def_builtin (d-&gt;mask, d-&gt;name, type, d-&gt;code);
+    }
+}
+
+static rtx
+r5900_expand_binop_builtin (icode, arglist, target)
+     enum insn_code icode;
+     tree arglist;
+     rtx target;
+{
+  rtx pat;
+  tree arg0 = TREE_VALUE (arglist);
+  tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+  rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+  rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+  enum machine_mode tmode = insn_data[icode].operand[0].mode;
+  enum machine_mode mode0 = insn_data[icode].operand[1].mode;
+  enum machine_mode mode1 = insn_data[icode].operand[2].mode;
+
+  if (! target
+      || GET_MODE (target) != tmode
+      || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
+    target = gen_reg_rtx (tmode);
+
+  /* In case the insn wants input operands in modes different fro
+     the result, abort.  */
+  if (GET_MODE (op0) != mode0 || GET_MODE (op1) != mode1)
+    abort ();
+
+  if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
+    op0 = copy_to_mode_reg (mode0, op0);
+  if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
+    op1 = copy_to_mode_reg (mode1, op1);
+
+  pat = GEN_FCN (icode) (target, op0, op1);
+  if (! pat)
+    return 0;
+  emit_insn (pat);
+  return target;
+}
+
+static rtx
+r5900_expand_builtin (exp, target)
+     tree exp;
+     rtx target;
+{
+  struct builtin_description *d;
+  size_t i;
+  enum insn_code icode;
+  tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+  tree arglist = TREE_OPERAND (exp, 1);
+  tree arg0, arg1, arg2, arg3;
+  rtx op0, op1, op2, pat;
+  enum machine_mode tmode, mode0, mode1, mode2;
+  unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+
+  for (i = 0, d = bdesc_2arg; i &lt; sizeof (bdesc_2arg) / sizeof *d; i++, d++)
+    if (d-&gt;code == fcode)
+      return r5900_expand_binop_builtin (d-&gt;icode, arglist, target);
+
+  return 0;
+}
+
+static rtx
+mips_expand_builtin (exp, target, subtarget, mode, ignore)
+     tree exp;
+     rtx target;
+     rtx subtarget ATTRIBUTE_UNUSED;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
+     int ignore ATTRIBUTE_UNUSED;
+{
+  if (TARGET_MIPS5900)
+    return r5900_expand_builtin (exp, target);
+
+  abort ();
+}
+
+static void
+mips_init_builtins ()
+{
+  if (TARGET_MIPS5900)
+    r5900_init_builtins ();
+}
diff -burN orig.gcc-3.2.2/gcc/config/mips/mips.h gcc-3.2.2/gcc/config/mips/mips.h
--- orig.gcc-3.2.2/gcc/config/mips/mips.h	2002-04-26 18:32:14.000000000 -0300
+++ gcc-3.2.2/gcc/config/mips/mips.h	2007-04-29 05:10:04.000000000 -0300
@@ -48,6 +48,7 @@
   DELAY_NONE,				/* no delay slot */
   DELAY_LOAD,				/* load from memory delay */
   DELAY_HILO,				/* move from/to hi/lo registers */
+  DELAY_HILO1,				/* move from/to hi1/lo1 registers */
   DELAY_FCMP				/* delay after doing c.&lt;xx&gt;.{d,s} */
 };
 
@@ -67,6 +68,7 @@
   PROCESSOR_R4600,
   PROCESSOR_R4650,
   PROCESSOR_R5000,
+  PROCESSOR_R5900,
   PROCESSOR_R8000,
   PROCESSOR_R4KC,
   PROCESSOR_R5KC,
@@ -146,6 +148,7 @@
 extern int mips16;			/* whether generating mips16 code */
 extern int mips16_hard_float;		/* mips16 without -msoft-float */
 extern int mips_entry;			/* generate entry/exit for mips16 */
+extern int mips_alignment;		/* max alignment bits */
 extern const char *mips_cpu_string;	/* for -mcpu=&lt;xxx&gt; */
 extern const char *mips_arch_string;    /* for -march=&lt;xxx&gt; */
 extern const char *mips_tune_string;    /* for -mtune=&lt;xxx&gt; */
@@ -155,6 +158,11 @@
 extern const char *mips_no_mips16_string;/* for -mno-mips16 */
 extern const char *mips_explicit_type_size_string;/* for -mexplicit-type-size */
 extern const char *mips_cache_flush_func;/* for -mflush-func= and -mno-flush-func */
+extern const char *mips_align_all_string;/* for -malign-all= */
+extern const char * mips_align128_string;/* for -malign128 */
+extern const char * mips_no_align128_string;/* for -mno-align128 */
+extern const char * mips_use_128_string; /* for -muse-128 */
+extern int mips_use_128;                /* the boolean for -muse-128 */
 extern int mips_split_addresses;	/* perform high/lo_sum support */
 extern int dslots_load_total;		/* total # load related delay slots */
 extern int dslots_load_filled;		/* # filled load delay slots */
@@ -175,6 +183,8 @@
 extern void		sdata_section PARAMS ((void));
 extern void		sbss_section PARAMS ((void));
 
+extern int mips_align_all;
+
 /* Stubs for half-pic support if not OSF/1 reference platform.  */
 
 #ifndef HALF_PIC_P
@@ -232,6 +242,10 @@
 					   consts in rodata */
 #define MASK_NO_FUSED_MADD 0x01000000   /* Don't generate floating point
 					   multiply-add operations.  */
+#define MASK_MMI	    0x02000000	/* r5900 MultiMedia Instructions (MMI) */
+#define MASK_VUMM	    0x04000000	/* r5900 VU0 macro mode (COP2) */
+#define MASK_NO_LENGTHEN_LOOP \
+			    0x08000000	/* Disable r5900 loop bug workaround */
 
 					/* Debug switches, not documented */
 #define MASK_DEBUG	0		/* unused */
@@ -327,6 +341,16 @@
 #define TARGET_NO_CHECK_ZERO_DIV (target_flags &amp; MASK_NO_CHECK_ZERO_DIV)
 #define TARGET_CHECK_RANGE_DIV  (target_flags &amp; MASK_CHECK_RANGE_DIV)
 
+					/* enable r5900 multimedia
+					   instructions.  */
+#define TARGET_MMI		(target_flags &amp; MASK_MMI)
+
+			   		/* enable r5900 macro mode for VU0 */
+#define TARGET_VUMM		(target_flags &amp; MASK_VUMM)
+
+					/* disable r5900 loop bug workaround */
+#define	TARGET_NO_LENGTHEN_LOOP	(target_flags &amp; MASK_NO_LENGTHEN_LOOP)
+
 /* This is true if we must enable the assembly language file switching
    code.  */
 
@@ -346,6 +370,7 @@
 #define TARGET_MIPS4000             (mips_arch == PROCESSOR_R4000)
 #define TARGET_MIPS4100             (mips_arch == PROCESSOR_R4100)
 #define TARGET_MIPS4300             (mips_arch == PROCESSOR_R4300)
+#define TARGET_MIPS5900             (mips_arch == PROCESSOR_R5900)
 #define TARGET_MIPS4KC              (mips_arch == PROCESSOR_R4KC)
 #define TARGET_MIPS5KC              (mips_arch == PROCESSOR_R5KC)
 
@@ -354,6 +379,7 @@
 #define TUNE_MIPS3900               (mips_tune == PROCESSOR_R3900)
 #define TUNE_MIPS4000               (mips_tune == PROCESSOR_R4000)
 #define TUNE_MIPS5000               (mips_tune == PROCESSOR_R5000)
+#define TUNE_MIPS5900               (mips_tune == PROCESSOR_R5900)
 #define TUNE_MIPS6000               (mips_tune == PROCESSOR_R6000)
 
 /* Macro to define tables used to set the flags.
@@ -464,6 +490,18 @@
      N_("Optimize for 3900")},						\
   {"4650",		  0,                    			\
      N_("Optimize for 4650")},						\
+  {"5900",		  0,						\
+     N_("Optimize for 5900")},						\
+  {"mmi",		  MASK_MMI,					\
+     N_("Use r5900 multimedia instructions")},				\
+  {"no-mmi",		  -MASK_MMI,					\
+     N_("Don't use r5900 multimedia instructions")},			\
+  {"vumm",		  MASK_VUMM,					\
+     N_("Use r5900 VU0 macro mode instructions")},			\
+  {"no-vumm",		  -MASK_VUMM,					\
+     N_("Don't use r5900 VU0 macro mode instructions")},		\
+  {"no-lengthen-loop",	  MASK_NO_LENGTHEN_LOOP,			\
+     N_("Don't workaround r5900 short loop bug")},			\
   {"check-zero-division",-MASK_NO_CHECK_ZERO_DIV,			\
      N_("Trap on integer divide by zero")},				\
   {"no-check-zero-division", MASK_NO_CHECK_ZERO_DIV,			\
@@ -472,6 +510,8 @@
      N_("Trap on integer divide overflow")},				\
   {"no-check-range-division",-MASK_CHECK_RANGE_DIV,			\
      N_("Don't trap on integer divide overflow")},			\
+  {"iop",                 0,                                            \
+     N_("Output IOP's IRX file")},                                      \
   {"debug",		  MASK_DEBUG,					\
      NULL},								\
   {"debuga",		  MASK_DEBUG_A,					\
@@ -604,6 +644,8 @@
       N_("Don't call any cache flush functions")},			\
   { "flush-func=", &amp;mips_cache_flush_func,				\
       N_("Specify cache flush function")},				\
+  { "align-all=",  &amp;mips_align_all_string,                              \
+      N_("Force lower alignment")},                                     \
 }
 
 /* This is meant to be redefined in the host dependent files.  */
@@ -613,6 +655,7 @@
 
 /* Generate three-operand multiply instructions for SImode.  */
 #define GENERATE_MULT3_SI       ((TARGET_MIPS3900                       \
+                                  || TARGET_MIPS5900                    \
                                   || mips_isa == 32                     \
                                   || mips_isa == 64)                    \
                                  &amp;&amp; !TARGET_MIPS16)
@@ -644,7 +687,7 @@
 				 || mips_isa == 64)
 
 /* ISA has just the integer condition move instructions (movn,movz) */
-#define ISA_HAS_INT_CONDMOVE     0
+#define ISA_HAS_INT_CONDMOVE     (TARGET_MIPS5900)
 
 
 
@@ -847,7 +890,7 @@
 /* GAS_ASM_SPEC is passed when using gas, rather than the MIPS
    assembler.  */
 
-#define GAS_ASM_SPEC "%{march=*} %{mtune=*} %{mcpu=*} %{m4650} %{mmad:-m4650} %{m3900} %{v} %{mgp32} %{mgp64} %(abi_gas_asm_spec) %{mabi=32:%{!mips*:-mips1}}"
+#define GAS_ASM_SPEC "%{march=*} %{mtune=*} %{mcpu=*} %{m4650} %{mmad:-m4650} %{m3900} %{m5900} %{v} %{mgp32} %{mgp64} %(abi_gas_asm_spec) %{mabi=32:%{!mips*:-mips1}}"
 
 
 extern int mips_abi;
@@ -964,7 +1007,7 @@
 #ifndef LINK_SPEC
 #define LINK_SPEC "\
 %(endian_spec) \
-%{G*} %{mips1} %{mips2} %{mips3} %{mips4} %{mips32} %{mips64} \
+%{G*} %{mips1} %{mips2} %{mips3} %{mips4} %{mips32} %{mips64} %{miop:-mmipsirx} \
 %{bestGnum} %{shared} %{non_shared}"
 #endif  /* LINK_SPEC defined */
 
@@ -984,7 +1027,9 @@
 %{m3900:-march=r3900 -mips1 -mfp32 -mgp32 \
 %n`-m3900' is deprecated. Use `-march=r3900' instead.\n} \
 %{m4650:-march=r4650 -mmad -msingle-float \
-%n`-m4650' is deprecated. Use `-march=r4650' instead.\n}}"
+%n`-m4650' is deprecated. Use `-march=r4650' instead.\n} \
+%{m5900:-march=r5900 -mips3 -mgp64 -mfp32 -mlong64 -mmmi -msingle-float \
+%n`-m5900' is deprecated. Use `-march=r5900' instead.\n}}"
 #endif
 
 /* CC1_SPEC is the set of arguments to pass to the compiler proper.  */
@@ -1003,6 +1048,7 @@
 %{mfp64:%{msingle-float:%emay not use both -mfp64 and -msingle-float}} \
 %{mfp64:%{m4650:%emay not use both -mfp64 and -m4650}} \
 %{mint64|mlong64|mlong32:-mexplicit-type-size }\
+%{miop:-march=r3000 -mfp32 -mgp32 -fno-builtin} \
 %{mgp32: %{mfp64:%emay not use both -mgp32 and -mfp64} %{!mfp32: -mfp32}} \
 %{G*} %{EB:-meb} %{EL:-mel} %{EB:%{EL:%emay not use both -EB and -EL}} \
 %{pic-none:   -mno-half-pic} \
@@ -1657,7 +1703,7 @@
 #define STRUCTURE_SIZE_BOUNDARY 8
 
 /* There is no point aligning anything to a rounder boundary than this.  */
-#define BIGGEST_ALIGNMENT 64
+#define BIGGEST_ALIGNMENT 128
 
 /* Set this nonzero if move instructions will actually fail to work
    when given unaligned data.  */
@@ -1792,20 +1838,20 @@
    address reg ($31) was stored.  This is needed for C++ exception
    handling.  */
 
-#define FIRST_PSEUDO_REGISTER 76
+#define FIRST_PSEUDO_REGISTER 79
 
 /* 1 for registers that have pervasive standard uses
    and are not available for the register allocator.
 
    On the MIPS, see conventions, page D-2  */
-
 #define FIXED_REGISTERS							\
 {									\
   1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,			\
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1,			\
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,			\
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,			\
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1					\
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,					\
+  0, 0, 0								\
 }
 
 
@@ -1822,7 +1868,8 @@
   0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1,			\
   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,			\
   1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,			\
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1					\
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,					\
+  1, 1, 1								\
 }
 
 /* Like `CALL_USED_REGISTERS' but used to overcome a historical
@@ -1842,7 +1889,8 @@
   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,			\
   1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,			\
   /* Others.  */                                                        \
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1					\
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,					\
+  1, 1, 1								\
 }
 
 /* Internal macros to classify a register number as to whether it's a
@@ -1863,6 +1911,10 @@
 #define MD_REG_LAST  66
 #define MD_REG_NUM   (MD_REG_LAST - MD_REG_FIRST + 1)
 
+#define MD1_REG_FIRST 76
+#define MD1_REG_LAST  78
+#define MD1_REG_NUM   (MD1_REG_LAST - MD1_REG_FIRST + 1)
+
 #define ST_REG_FIRST 67
 #define ST_REG_LAST  74
 #define ST_REG_NUM   (ST_REG_LAST - ST_REG_FIRST + 1)
@@ -1873,6 +1925,9 @@
 #define HI_REGNUM	(MD_REG_FIRST + 0)
 #define LO_REGNUM	(MD_REG_FIRST + 1)
 #define HILO_REGNUM	(MD_REG_FIRST + 2)
+#define HI1_REGNUM	(MD1_REG_FIRST + 0)
+#define LO1_REGNUM	(MD1_REG_FIRST + 1)
+#define HILO1_REGNUM	(MD1_REG_FIRST + 2)
 
 /* FPSW_REGNUM is the single condition code used if mips_isa &lt; 4.  If
    mips_isa &gt;= 4, it should not be used, and an arbitrary ST_REG
@@ -1887,6 +1942,8 @@
   ((unsigned int) ((int) (REGNO) - FP_REG_FIRST) &lt; FP_REG_NUM)
 #define MD_REG_P(REGNO) \
   ((unsigned int) ((int) (REGNO) - MD_REG_FIRST) &lt; MD_REG_NUM)
+#define MD1_REG_P(REGNO) \
+  ((unsigned int) ((int) (REGNO) - MD1_REG_FIRST) &lt; MD1_REG_NUM)
 #define ST_REG_P(REGNO) \
   ((unsigned int) ((int) (REGNO) - ST_REG_FIRST) &lt; ST_REG_NUM)
 
@@ -2053,6 +2110,20 @@
   LO_AND_GR_REGS,
   HILO_AND_GR_REGS,
   HI_AND_FP_REGS,
+  HI1_REG,			/* hi1 register */
+  LO1_REG,			/* lo1 register */
+  HILO1_REG,			/* hilo1 register pair for 64 bit mode mult */
+  MD1_REGS,			/* multiply/divide registers (hi/lo) */
+  HI1_AND_GR_REGS,		/* union classes */
+  LO1_AND_GR_REGS,
+  HILO1_AND_GR_REGS,
+  HI01_REG,			/* hi01 register */
+  LO01_REG,			/* lo01 register */
+  HILO01_REG,			/* hilo1 register pair for 64 bit mode mult */
+  MD01_REGS,			/* multiply/divide registers (hi1/lo1) */
+  HI01_AND_GR_REGS,		/* union classes */
+  LO01_AND_GR_REGS,
+  HILO01_AND_GR_REGS,
   ST_REGS,			/* status registers (fp status) */
   ALL_REGS,			/* all registers */
   LIM_REG_CLASSES		/* max value + 1 */
@@ -2083,6 +2154,20 @@
   "LO_AND_GR_REGS",							\
   "HILO_AND_GR_REGS",							\
   "HI_AND_FP_REGS",							\
+  "HI1_REG",								\
+  "LO1_REG",								\
+  "HILO1_REG",								\
+  "MD1_REGS",								\
+  "HI1_AND_GR_REGS",							\
+  "LO1_AND_GR_REGS",							\
+  "HILO1_AND_GR_REGS",							\
+  "HI01_REG",								\
+  "LO01_REG",								\
+  "HILO01_REG",							\
+  "MD01_REGS",								\
+  "HI01_AND_GR_REGS",							\
+  "LO01_AND_GR_REGS",							\
+  "HILO01_AND_GR_REGS",						\
   "ST_REGS",								\
   "ALL_REGS"								\
 }
@@ -2101,7 +2186,7 @@
 #define REG_CLASS_CONTENTS						\
 {									\
   { 0x00000000, 0x00000000, 0x00000000 },	/* no registers */	\
-  { 0x0003000c, 0x00000000, 0x00000000 },	/* mips16 nonarg regs */\
+  { 0x0003000c, 0x00000000, 0x00000000 },	/* mips16 nonarg regs */	\
   { 0x000300fc, 0x00000000, 0x00000000 },	/* mips16 registers */	\
   { 0x01000000, 0x00000000, 0x00000000 },	/* mips16 T register */	\
   { 0x010300fc, 0x00000000, 0x00000000 },	/* mips16 and T regs */ \
@@ -2115,8 +2200,24 @@
   { 0xffffffff, 0x00000000, 0x00000002 },				\
   { 0xffffffff, 0x00000000, 0x00000004 },				\
   { 0x00000000, 0xffffffff, 0x00000001 },				\
+  /* Start of r5900 extra registers. */					\
+  { 0x00000000, 0x00000000, 0x00001000 },       /* hi1 register */		\
+  { 0x00000000, 0x00000000, 0x00002000 },       /* lo1 register */		\
+  { 0x00000000, 0x00000000, 0x00004000 },       /* hilo1 register */		\
+  { 0x00000000, 0x00000000, 0x00003000 },       /* mul1/div1 registers */	\
+  { 0xffffffff, 0x00000000, 0x00001000 },       /* union classes */		\
+  { 0xffffffff, 0x00000000, 0x00002000 },					\
+  { 0xffffffff, 0x00000000, 0x00004000 },					\
+  { 0x00000000, 0x00000000, 0x00001001 },       /* hi01 registers */		\
+  { 0x00000000, 0x00000000, 0x00002002 },       /* lo01 registers */		\
+  { 0x00000000, 0x00000000, 0x00004004 },       /* hilo01 registers */		\
+  { 0x00000000, 0x00000000, 0x00003003 },       /* mul01/div01 registers */	\
+  { 0xffffffff, 0x00000000, 0x00001001 },       /* union classes */		\
+  { 0xffffffff, 0x00000000, 0x00002002 },					\
+  { 0xffffffff, 0x00000000, 0x00004004 },					\
+  /* End of r5900 extra registers. */						\
   { 0x00000000, 0x00000000, 0x000007f8 },	/* status registers */	\
-  { 0xffffffff, 0xffffffff, 0x000007ff }	/* all registers */	\
+  { 0xffffffff, 0xffffffff, 0x000078ff }	/* all registers */		\
 }
 
 
@@ -2165,7 +2266,8 @@
   16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,	\
   32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,	\
   48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,	\
-  64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75			\
+  64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,			\
+  76, 77, 78								\
 }
 
 /* ORDER_REGS_FOR_LOCAL_ALLOC is a macro which permits reg_alloc_order
@@ -2193,7 +2295,11 @@
    'x'	Multiply/divide registers
    'a'	HILO_REG
    'z'	FP Status register
-   'b'	All registers */
+   'b'	All registers
+   'u'	Hi1 register
+   'v'	Lo1 register
+   'w'	Multiply/divide1 registers
+   'q'	HILO1_REG  */
 
 extern enum reg_class mips_char_to_class[256];
 
@@ -2353,7 +2459,7 @@
 #define CLASS_CANNOT_CHANGE_MODE					\
   (TARGET_BIG_ENDIAN							\
    ? (TARGET_FLOAT64 &amp;&amp; ! TARGET_64BIT ? FP_REGS : NO_REGS)		\
-   : (TARGET_FLOAT64 &amp;&amp; ! TARGET_64BIT ? HI_AND_FP_REGS : HI_REG))
+   : (TARGET_FLOAT64 &amp;&amp; ! TARGET_64BIT ? HI_AND_FP_REGS : HI01_REG))
 
 /* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.  */
 
@@ -3466,8 +3572,9 @@
 
 /* Max number of bytes we can move from memory to memory
    in one reasonably fast instruction.  */
-#define MOVE_MAX (TARGET_64BIT ? 8 : 4)
-#define MAX_MOVE_MAX 8
+/* We can do 16 bytes using the r5900's MMI */
+#define MOVE_MAX (TARGET_MIPS5900 ? (mips_use_128 ? 16 : 8) : (TARGET_64BIT ? 8 : 4))
+#define MAX_MOVE_MAX (mips_use_128 ? 16 : 8)
 
 /* Define this macro as a C expression which is nonzero if
    accessing less than a word of memory (i.e. a `char' or a
@@ -3760,6 +3867,8 @@
 	return COSTS_N_INSNS (17);					\
       else if (TUNE_MIPS5000)				\
 	return COSTS_N_INSNS (5);					\
+      else if (TUNE_MIPS5900)				\
+	return (xmode == SImode ? COSTS_N_INSNS (3) : COSTS_N_INSNS (30));\
       else								\
 	return COSTS_N_INSNS (10);					\
     }									\
@@ -3801,6 +3910,8 @@
       return COSTS_N_INSNS (38);					\
     else if (TUNE_MIPS5000)				\
       return COSTS_N_INSNS (36);					\
+    else if (TUNE_MIPS5900)				\
+      return COSTS_N_INSNS (30);					\
     else								\
       return COSTS_N_INSNS (69);					\
 									\
@@ -3906,10 +4017,14 @@
    : GR_REG_CLASS_P (FROM) &amp;&amp; (TO) == FP_REGS ? 4			\
    : (FROM) == FP_REGS &amp;&amp; GR_REG_CLASS_P (TO) ? 4			\
    : (((FROM) == HI_REG || (FROM) == LO_REG				\
-       || (FROM) == MD_REGS || (FROM) == HILO_REG)			\
+       || (FROM) == MD_REGS || (FROM) == HILO_REG			\
+       || (FROM) == HI1_REG || (FROM) == LO1_REG			\
+       || (FROM) == MD1_REGS || (FROM) == HILO1_REG)			\
       &amp;&amp; GR_REG_CLASS_P (TO)) ? (TARGET_MIPS16 ? 12 : 6)		\
    : (((TO) == HI_REG || (TO) == LO_REG					\
-       || (TO) == MD_REGS || (TO) == HILO_REG)				\
+       || (TO) == MD_REGS || (TO) == HILO_REG				\
+       || (TO) == HI1_REG || (TO) == LO1_REG				\
+       || (TO) == MD1_REGS || (TO) == HILO1_REG)			\
       &amp;&amp; GR_REG_CLASS_P (FROM)) ? (TARGET_MIPS16 ? 12 : 6)		\
    : (FROM) == ST_REGS &amp;&amp; GR_REG_CLASS_P (TO) ? 4			\
    : (FROM) == FP_REGS &amp;&amp; (TO) == ST_REGS ? 8				\
@@ -3943,6 +4058,10 @@
 #define ADJUST_INSN_LENGTH(INSN, LENGTH) \
   ((LENGTH) = mips_adjust_insn_length ((INSN), (LENGTH)))
 
+/* The r5900 is a dual issue processor.  */
+#undef ISSUE_RATE
+#define ISSUE_RATE ((TARGET_MIPS5900) ? 2 : 1)
+
 
 /* Optionally define this if you have added predicates to
    `MACHINE.c'.  This macro is called within an initializer of an
@@ -3988,6 +4107,8 @@
   {"movdi_operand",		{ CONST_INT, CONST_DOUBLE, CONST,	\
 				  SYMBOL_REF, LABEL_REF, SUBREG, REG,	\
 				  MEM, SIGN_EXTEND }},			\
+  {"movti_operand",		{ REG, MEM, CONST_INT, CONST_DOUBLE,	\
+				  SUBREG }},				\
   {"se_register_operand",	{ SUBREG, REG, SIGN_EXTEND }},		\
   {"se_reg_or_0_operand",	{ REG, CONST_INT, CONST_DOUBLE, SUBREG,	\
 				  SIGN_EXTEND }},			\
@@ -4142,6 +4263,9 @@
   &amp;mips_reg_names[73][0],						\
   &amp;mips_reg_names[74][0],						\
   &amp;mips_reg_names[75][0],						\
+  &amp;mips_reg_names[76][0],						\
+  &amp;mips_reg_names[77][0],						\
+  &amp;mips_reg_names[78][0],						\
 }
 
 /* print-rtl.c can't use REGISTER_NAMES, since it depends on mips.c.
@@ -4157,7 +4281,8 @@
   "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",	\
   "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31",	\
   "hi",   "lo",   "accum","$fcc0","$fcc1","$fcc2","$fcc3","$fcc4",	\
-  "$fcc5","$fcc6","$fcc7","$rap"					\
+  "$fcc5","$fcc6","$fcc7","$rap",   					\
+  "hi1",  "lo1",  "accum1"						\
 }
 
 /* If defined, a C initializer for an array of structures
@@ -4410,6 +4535,7 @@
   } while (0)
 
 /* This says how to define a global common symbol.  */
+/*	ASM_OUTPUT_ALIGN (STREAM, floor_log2 (ALIGN / BITS_PER_UNIT)); */
 
 #define ASM_OUTPUT_ALIGNED_DECL_COMMON(STREAM, DECL, NAME, SIZE, ALIGN) \
   do {									\
@@ -4428,9 +4554,10 @@
 	mips_declare_object (STREAM, NAME, "", ":\n\t.space\t%u\n",	\
 	    (SIZE));							\
       }									\
-    else								\
-      mips_declare_object (STREAM, NAME, "\n\t.comm\t", ",%u\n",	\
-	  (SIZE));							\
+	else {								\
+	mips_declare_object_align (STREAM, NAME, "\n\t.comm\t", ",%u,%u\n",	\
+	  (SIZE),(ALIGN / BITS_PER_UNIT));				\
+	}								\
   } while (0)
 
 
@@ -4542,7 +4669,7 @@
    to a multiple of 2**LOG bytes.  */
 
 #define ASM_OUTPUT_ALIGN(STREAM,LOG)					\
-  fprintf (STREAM, "\t.align\t%d\n", (LOG))
+  fprintf (STREAM, "\t.align\t%d\n", (LOG) &gt; mips_align_all ? (LOG) : mips_align_all)
 
 /* This is how to output an assembler line to advance the location
    counter by SIZE bytes.  */
@@ -4716,6 +4843,15 @@
    PC relative loads that are out of range.  */
 #define MACHINE_DEPENDENT_REORG(X) machine_dependent_reorg (X)
 
+/* This is used to lengthen short loops on the r5900. */
+#define MACHINE_DEPENDENT_REORG_FINAL(X) 				\
+do									\
+  {									\
+    if (TARGET_MIPS5900 &amp;&amp; ! TARGET_NO_LENGTHEN_LOOP)			\
+      machine_dependent_reorg_final (X);				\
+  }									\
+while (0)
+
 /* We need to use a special set of functions to handle hard floating
    point code in mips16 mode.  */
 
@@ -4788,3 +4924,44 @@
       }									\
   }									\
 while (0)
+
+/* r5900 vector mode &amp; built-in support. */
+
+#define VALID_MMI_REG_MODE(MODE)					\
+  ((MODE) == TImode || (MODE) == V16QImode || (MODE) == V8HImode	\
+   || (MODE) == V4SImode || (MODE) == V4SFmode || (MODE) == V2DImode)
+
+#define VALID_VUMM_REG_MODE(MODE)					\
+  ((MODE) == TImode || (MODE) == V4SFmode)
+
+#define VECTOR_MODE_SUPPORTED_P(MODE)					\
+  ((VALID_MMI_REG_MODE (MODE) &amp;&amp; TARGET_MMI)				\
+   || (VALID_VUMM_REG_MODE (MODE) &amp;&amp; TARGET_VUMM) ? 1 : 0)
+
+enum r5900_builtins
+{
+  /* MMI built-ins */
+  MMI_BUILTIN_PADDB,
+  MMI_BUILTIN_PADDH,
+  MMI_BUILTIN_PADDW,
+  MMI_BUILTIN_PADDSB,
+  MMI_BUILTIN_PADDSH,
+  MMI_BUILTIN_PADDSW,
+  MMI_BUILTIN_PADDUB,
+  MMI_BUILTIN_PADDUH,
+  MMI_BUILTIN_PADDUW,
+
+  MMI_BUILTIN_PSUBB,
+  MMI_BUILTIN_PSUBH,
+  MMI_BUILTIN_PSUBW,
+  MMI_BUILTIN_PSUBSB,
+  MMI_BUILTIN_PSUBSH,
+  MMI_BUILTIN_PSUBSW,
+  MMI_BUILTIN_PSUBUB,
+  MMI_BUILTIN_PSUBUH,
+  MMI_BUILTIN_PSUBUW,
+
+  /* VU macro mode built-ins */
+
+  R5900_BUILTIN_MAX
+};
diff -burN orig.gcc-3.2.2/gcc/config/mips/mips.md gcc-3.2.2/gcc/config/mips/mips.md
--- orig.gcc-3.2.2/gcc/config/mips/mips.md	2002-11-11 01:57:14.000000000 -0400
+++ gcc-3.2.2/gcc/config/mips/mips.md	2007-04-29 05:10:04.000000000 -0300
@@ -84,11 +84,11 @@
 ;; nop		no operation
 
 (define_attr "type"
-  "unknown,branch,jump,call,load,store,move,xfer,hilo,arith,darith,imul,idiv,icmp,fadd,fmul,fmadd,fdiv,fabs,fneg,fcmp,fcvt,fsqrt,multi,nop"
+  "unknown,branch,jump,call,load,store,move,xfer,hilo,arith,darith,imul,idiv,icmp,fadd,fmul,fmadd,fdiv,fabs,fneg,fcmp,fcvt,fsqrt,frsqrt,multi,nop,mmi,mmi_mul,mmi_div,vmm_mul,vmm_div"
   (const_string "unknown"))
 
 ;; Main data type used by the insn
-(define_attr "mode" "unknown,none,QI,HI,SI,DI,SF,DF,FPSW" (const_string "unknown"))
+(define_attr "mode" "unknown,none,QI,HI,SI,DI,TI,SF,DF,FPSW" (const_string "unknown"))
 
 ;; Length (in # of bytes).  A conditional branch is allowed only to a
 ;; location within a signed 18-bit offset of the delay slot.  If that
@@ -121,7 +121,7 @@
 
 ;; ??? Fix everything that tests this attribute.
 (define_attr "cpu"
-  "default,r3000,r3900,r6000,r4000,r4100,r4300,r4600,r4650,r5000,r8000,r4kc,r5kc,r20kc"
+  "default,r3000,r3900,r6000,r4000,r4100,r4300,r4600,r4650,r5000,r5900,r8000,r4kc,r5kc,r20kc"
   (const (symbol_ref "mips_cpu_attr")))
 
 ;; Does the instruction have a mandatory delay slot?
@@ -206,7 +206,7 @@
 
 (define_function_unit "memory" 1 0
   (and (eq_attr "type" "load")
-       (eq_attr "cpu" "!r3000,r3900,r4600,r4650,r4100,r4300,r5000"))
+       (eq_attr "cpu" "!r3000,r3900,r4600,r4650,r4100,r4300,r5000,r5900"))
   3 0)
 
 (define_function_unit "memory" 1 0
@@ -214,17 +214,20 @@
        (eq_attr "cpu" "r3000,r3900,r4600,r4650,r4100,r4300,r5000"))
   2 0)
 
-(define_function_unit "memory"   1 0 (eq_attr "type" "store") 1 0)
+(define_function_unit "memory"   1 0
+  (and (eq_attr "type" "store") (eq_attr "cpu" "!r5900")) 1 0)
 
-(define_function_unit "memory"   1 0 (eq_attr "type" "xfer") 2 0)
+(define_function_unit "memory"   1 0
+  (and (eq_attr "type" "xfer") (eq_attr "cpu" "!r5900")) 2 0)
 
 (define_function_unit "imuldiv"  1 0
-  (eq_attr "type" "hilo")
+  (and (eq_attr "type" "hilo")
+       (eq_attr "cpu" "!r5900"))
   1 3)
 
 (define_function_unit "imuldiv"  1 0
   (and (eq_attr "type" "imul")
-       (eq_attr "cpu" "!r3000,r3900,r4000,r4600,r4650,r4100,r4300,r5000"))
+       (eq_attr "cpu" "!r3000,r3900,r4000,r4600,r4650,r4100,r4300,r5000,r5900"))
   17 17)
 
 ;; On them mips16, we want to stronly discourage a mult from appearing
@@ -276,7 +279,7 @@
 
 (define_function_unit "imuldiv"  1 0
   (and (eq_attr "type" "idiv")
-       (eq_attr "cpu" "!r3000,r3900,r4000,r4600,r4650,r4100,r4300,r5000"))
+       (eq_attr "cpu" "!r3000,r3900,r4000,r4600,r4650,r4100,r4300,r5000,r5900"))
   38 38)
 
 (define_function_unit "imuldiv"  1 0
@@ -333,7 +336,7 @@
 ;; instructions to be processed in the "imuldiv" unit.
 
 (define_function_unit "adder" 1 1
-  (and (eq_attr "type" "fcmp") (eq_attr "cpu" "!r3000,r3900,r6000,r4300,r5000"))
+  (and (eq_attr "type" "fcmp") (eq_attr "cpu" "!r3000,r3900,r6000,r4300,r5000,r5900"))
   3 0)
 
 (define_function_unit "adder" 1 1
@@ -345,7 +348,7 @@
   1 0)
 
 (define_function_unit "adder" 1 1
-  (and (eq_attr "type" "fadd") (eq_attr "cpu" "!r3000,r3900,r6000,r4300"))
+  (and (eq_attr "type" "fadd") (eq_attr "cpu" "!r3000,r3900,r6000,r4300,r5900"))
   4 0)
 
 (define_function_unit "adder" 1 1
@@ -358,7 +361,7 @@
 
 (define_function_unit "adder" 1 1
   (and (eq_attr "type" "fabs,fneg")
-       (eq_attr "cpu" "!r3000,r3900,r4600,r4650,r4300,r5000"))
+       (eq_attr "cpu" "!r3000,r3900,r4600,r4650,r4300,r5000,r5900"))
   2 0)
 
 (define_function_unit "adder" 1 1
@@ -368,7 +371,7 @@
 (define_function_unit "mult" 1 1
   (and (eq_attr "type" "fmul")
        (and (eq_attr "mode" "SF")
-	    (eq_attr "cpu" "!r3000,r3900,r6000,r4600,r4650,r4300,r5000")))
+	    (eq_attr "cpu" "!r3000,r3900,r6000,r4600,r4650,r4300,r5000,r5900")))
   7 0)
 
 (define_function_unit "mult" 1 1
@@ -388,7 +391,7 @@
 
 (define_function_unit "mult" 1 1
   (and (eq_attr "type" "fmul")
-       (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r3000,r3900,r6000,r4300,r5000")))
+       (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r3000,r3900,r6000,r4300,r5000,r5900")))
   8 0)
 
 (define_function_unit "mult" 1 1
@@ -404,7 +407,7 @@
 (define_function_unit "divide" 1 1
   (and (eq_attr "type" "fdiv")
        (and (eq_attr "mode" "SF")
-	    (eq_attr "cpu" "!r3000,r3900,r6000,r4600,r4650,r4300,r5000")))
+	    (eq_attr "cpu" "!r3000,r3900,r6000,r4600,r4650,r4300,r5000,r5900")))
   23 0)
 
 (define_function_unit "divide" 1 1
@@ -430,7 +433,7 @@
 (define_function_unit "divide" 1 1
   (and (eq_attr "type" "fdiv")
        (and (eq_attr "mode" "DF")
-	    (eq_attr "cpu" "!r3000,r3900,r6000,r4600,r4650,r4300")))
+	    (eq_attr "cpu" "!r3000,r3900,r6000,r4600,r4650,r4300,r5900")))
   36 0)
 
 (define_function_unit "divide" 1 1
@@ -451,7 +454,7 @@
 ;;; ??? Is this number right?
 (define_function_unit "divide" 1 1
   (and (eq_attr "type" "fsqrt")
-       (and (eq_attr "mode" "SF") (eq_attr "cpu" "!r4600,r4650,r4300,r5000")))
+       (and (eq_attr "mode" "SF") (eq_attr "cpu" "!r4600,r4650,r4300,r5000,r5900")))
   54 0)
 
 (define_function_unit "divide" 1 1
@@ -467,7 +470,7 @@
 ;;; ??? Is this number right?
 (define_function_unit "divide" 1 1
   (and (eq_attr "type" "fsqrt")
-       (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r4600,r4650,r4300,r5000")))
+       (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r4600,r4650,r4300,r5000,r5900")))
   112 0)
 
 (define_function_unit "divide" 1 1
@@ -507,6 +510,63 @@
        (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4300")))
   58 58)
 
+;; Using a value immediately after a load causes a one cycle delay.
+(define_function_unit "memory" 1 0
+  (and (eq_attr "type" "load") (eq_attr "cpu" "r5900")) 2 0)
+
+;; The r5900 has a store buffer which can cause an interlock for
+;; consecutive stores in some cases.  So try to separate stores.
+(define_function_unit "memory"   1 0
+  (and (eq_attr "type" "store") (eq_attr "cpu" "r5900"))  2 1)
+
+;; Transfer to/from coprocessor.  This is just a guess.  There may or
+;; may not be an interlock for such transfers.
+(define_function_unit "memory"   1 0
+  (and (eq_attr "type" "xfer") (eq_attr "cpu" "r5900"))  2 0)
+
+;; The r5900 has two independent ALUs.
+;; XXX: MM instructions take up both ALUs, work that out properly here
+(define_function_unit "alu" 2 0
+  (and (eq_attr "type" "move,arith,darith,icmp,nop,mmi,mmi_mul,mmi_div")
+       (eq_attr "cpu" "r5900")) 1 0)
+
+;; It also has a seperate branch unit.
+(define_function_unit "branch" 1 0
+  (and (eq_attr "type" "branch,jump,call")
+       (eq_attr "cpu" "r5900")) 1 0)
+
+;; XXX There is differing data between the architecture manual
+;; about what these values should be.
+(define_function_unit "r5900imuldiv" 2 0
+  (and (eq_attr "type" "hilo") (eq_attr "cpu" "r5900")) 1 3)
+
+(define_function_unit "r5900imuldiv" 2 0
+  (and (eq_attr "type" "imul") (eq_attr "cpu" "r5900")) 4 2)
+
+(define_function_unit "r5900imuldiv" 2 0
+  (and (eq_attr "type" "idiv") (eq_attr "cpu" "r5900")) 37 37)
+
+;; The r5900 FP unit has three independent units.
+;; fmac  -- all computational instructions except fdiv, fsqrt, rsqrt
+;; fdiv  -- fdiv, fsqrt, rsqrt
+;; load/store -- load store and transfer unit
+;;
+;; It appears that fmac/fdiv can dual issue with load/store.
+(define_function_unit "fmac" 1 0
+  (and (eq_attr "type" "fadd,fmul,fmadd,fabs,fneg,fcmp,fcvt")
+       (eq_attr "cpu" "r5900")) 3 0)
+
+(define_function_unit "fdiv" 1 1
+  (and (eq_attr "type" "fdiv,fsqrt,frsqrt") (eq_attr "cpu" "r5900")) 6 0)
+  
+;; And now a few fake units to encourage dual issue.
+;; We can only issue one operation to the FPU per cycle.
+(define_function_unit "flop" 1 0
+  (and (eq_attr "type"
+		 "fadd,fmul,fmadd,fdiv,fabs,fneg,fcmp,fcvt,fsqrt,frsqrt,xfer")
+       (eq_attr "cpu" "r5900")) 1 0)
+
+
 ;; The following functional units do not use the cpu type, and use
 ;; much less memory in genattrtab.c.
 
@@ -1727,7 +1787,22 @@
   ""
   "
 {
-  if (GENERATE_MULT3_SI || TARGET_MAD)
+  /* mulsi3_mult3_r5900 is just like the other mulsi3_mult3 pattern, except
+     that it has additional alternatives, slightly different output
+     templates and clobbers pseudos instead of scratches.
+
+     We generate a different pattern merely to keep the sanitize issues from
+     driving us crazy. Long term we may want the other multiply patterns to
+     clobber pseudos instead of scratches.  */
+  if (TARGET_MIPS5900)
+    {
+      emit_insn (gen_mulsi3_mult3_r5900 (operands[0], operands[1], operands[2],
+				         gen_reg_rtx (SImode),
+				         gen_reg_rtx (SImode),
+				         gen_reg_rtx (SImode)));
+      DONE;
+    }
+  else if (GENERATE_MULT3_SI || TARGET_MAD)
     emit_insn (gen_mulsi3_mult3 (operands[0], operands[1], operands[2]));
   else if (!TARGET_MIPS4000 || TARGET_MIPS16)
     emit_insn (gen_mulsi3_internal (operands[0], operands[1], operands[2]));
@@ -1736,6 +1811,23 @@
   DONE;
 }")
 
+(define_insn "mulsi3_mult3_r5900"
+  [(set (match_operand:SI 0 "register_operand" "=d,l,d,v")
+	(mult:SI (match_operand:SI 1 "register_operand" "d,d,d,d")
+		 (match_operand:SI 2 "register_operand" "d,d,d,d")))
+   (clobber (match_operand:SI 3 "register_operand" "=h,h,u,u"))
+   (clobber (match_operand:SI 4 "register_operand" "=l,X,v,X"))
+   (clobber (match_operand:SI 5 "register_operand" "=a,a,q,q"))]
+  "TARGET_MIPS5900"
+  "*
+{
+  if (which_alternative == 1 || which_alternative == 3)
+    return \"mult%H5\\t%1,%2\";
+  return \"mult%H5\\t%0,%1,%2\";
+}"
+  [(set_attr "type"	"imul")
+   (set_attr "mode"	"SI")])
+
 (define_insn "mulsi3_mult3"
   [(set (match_operand:SI 0 "register_operand" "=d,l")
 	(mult:SI (match_operand:SI 1 "register_operand" "d,d")
@@ -1743,8 +1835,8 @@
    (clobber (match_scratch:SI 3 "=h,h"))
    (clobber (match_scratch:SI 4 "=l,X"))
    (clobber (match_scratch:SI 5 "=a,a"))]
-  "GENERATE_MULT3_SI
-   || TARGET_MAD"
+  "(GENERATE_MULT3_SI
+   || TARGET_MAD) &amp;&amp; !TARGET_MIPS5900"
   "*
 {
   if (which_alternative == 1)
@@ -1804,6 +1896,31 @@
 ;; "?" to the constraint is too strong, and causes values to be loaded into
 ;; LO even when that's more costly.  For now, using "*d" mostly does the
 ;; trick.
+
+;; Like the standard multiply-accumulate, except with more alternatives and
+;; works with both pipelines.
+;; XXX: Broken for now.
+(define_insn "*mul_acc_si_r5900"
+  [(set (match_operand:SI 0 "register_operand" "=l,*d,*d,v,*d,*d")
+	(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d,d,d,d,d")
+			  (match_operand:SI 2 "register_operand" "d,d,d,d,d,d"))
+		 (match_operand:SI 3 "register_operand" "0,l,*d,0,v,*d")))
+   (clobber (match_scratch:SI 4 "=h,h,h,u,u,u"))
+   (clobber (match_scratch:SI 5 "=X,3,l,X,3,v"))
+   (clobber (match_scratch:SI 6 "=a,a,a,q,q,q"))
+   (clobber (match_scratch:SI 7 "=X,X,d,X,X,d"))]
+  "TARGET_MIPS5900 &amp;&amp; !TARGET_MIPS16"
+  "*
+{
+  static char *const madd[] = { \"madd%H6\\t%1,%2\",
+				\"madd%H6\\t%0,%1,%2\",
+				\"#\" };
+  return madd[which_alternative % 3];
+}"
+  [(set_attr "type"	"imul")
+   (set_attr "mode"	"SI")
+   (set_attr "length"	"4,4,8,4,4,8")])
+
 (define_insn "*mul_acc_si"
   [(set (match_operand:SI 0 "register_operand" "=l,*d,*d")
 	(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d,d")
@@ -1964,7 +2081,7 @@
 		 (match_operand:DI 2 "register_operand" "d")))
    (clobber (match_scratch:DI 3 "=h"))
    (clobber (match_scratch:DI 4 "=a"))]
-  "TARGET_64BIT"
+  "TARGET_64BIT &amp;&amp; !TARGET_MIPS5900"
 
   "
 {
@@ -1986,7 +2103,7 @@
 		 (match_operand:DI 2 "register_operand" "d")))
    (clobber (match_scratch:DI 3 "=h"))
    (clobber (match_scratch:DI 4 "=a"))]
-  "TARGET_64BIT &amp;&amp; !TARGET_MIPS4000 &amp;&amp; !TARGET_MIPS16"
+  "TARGET_64BIT &amp;&amp; !TARGET_MIPS4000 &amp;&amp; !TARGET_MIPS16 &amp;&amp; !TARGET_MIPS5900"
   "dmult\\t%1,%2"
   [(set_attr "type"	"imul")
    (set_attr "mode"	"DI")])
@@ -2032,6 +2149,15 @@
   "
 {
   rtx dummy = gen_rtx (SIGN_EXTEND, DImode, const0_rtx);
+  if (TARGET_64BIT &amp;&amp; TARGET_MIPS5900)
+    {
+      emit_insn (gen_mulsidi3_64bit_r5900 (operands[0], operands[1],
+					   operands[2],
+					   dummy, dummy,
+					   gen_reg_rtx (DImode),
+					   gen_reg_rtx (DImode)));
+      DONE;
+    }
   if (TARGET_64BIT)
     emit_insn (gen_mulsidi3_64bit (operands[0], operands[1], operands[2],
 				   dummy, dummy));
@@ -2049,6 +2175,15 @@
   "
 {
   rtx dummy = gen_rtx (ZERO_EXTEND, DImode, const0_rtx);
+  if (TARGET_64BIT &amp;&amp; TARGET_MIPS5900)
+    {
+      emit_insn (gen_mulsidi3_64bit_r5900 (operands[0], operands[1],
+					   operands[2],
+					   dummy, dummy, 
+					   gen_reg_rtx (DImode),
+					   gen_reg_rtx (DImode)));
+      DONE;
+    }
   if (TARGET_64BIT)
     emit_insn (gen_mulsidi3_64bit (operands[0], operands[1], operands[2],
 				   dummy, dummy));
@@ -2075,6 +2210,25 @@
   [(set_attr "type"	"imul")
    (set_attr "mode"	"SI")])
 
+(define_insn "mulsidi3_64bit_r5900"
+  [(set (match_operand:DI 0 "register_operand" "=a,q")
+	(mult:DI (match_operator:DI 3 "extend_operator"
+				    [(match_operand:SI 1 "register_operand" "d,d")])
+		 (match_operator:DI 4 "extend_operator"
+				    [(match_operand:SI 2 "register_operand" "d,d")])))
+   (clobber (match_operand:DI 5 "register_operand" "=l,v"))
+   (clobber (match_operand:DI 6 "register_operand" "=h,u"))]
+  "TARGET_64BIT &amp;&amp; TARGET_MIPS5900
+   &amp;&amp; GET_CODE (operands[3]) == GET_CODE (operands[4])"
+  "*
+{
+  if (GET_CODE (operands[3]) == SIGN_EXTEND)
+    return \"mult%H0\\t%1,%2\";
+  return \"multu%H0\\t%1,%2\";
+}"
+  [(set_attr "type"	"imul")
+   (set_attr "mode"	"SI")])
+
 (define_insn "mulsidi3_64bit"
   [(set (match_operand:DI 0 "register_operand" "=a")
 	(mult:DI (match_operator:DI 3 "extend_operator"
@@ -2111,6 +2265,8 @@
   rtx (*genfn) ();
 #endif
   genfn = gen_xmulsi3_highpart_internal;
+  if (TARGET_MIPS5900)
+    genfn = gen_xmulsi3_highpart_r5900;
   emit_insn ((*genfn) (operands[0], operands[1], operands[2], dummy,
 		       dummy, dummy2));
   DONE;
@@ -2132,12 +2288,36 @@
 #else
   rtx (*genfn) ();
 #endif
+  if (TARGET_MIPS5900)
+    genfn = gen_xmulsi3_highpart_r5900;
   genfn = gen_xmulsi3_highpart_internal;
   emit_insn ((*genfn) (operands[0], operands[1], operands[2], dummy,
 		       dummy, dummy2));
   DONE;
 }")
 
+(define_insn "xmulsi3_highpart_r5900"
+  [(set (match_operand:SI 0 "register_operand" "=h,u")
+	(truncate:SI
+	 (match_operator:DI 5 "highpart_shift_operator"
+			    [(mult:DI (match_operator:DI 3 "extend_operator"
+							 [(match_operand:SI 1 "register_operand" "d,d")])
+				      (match_operator:DI 4 "extend_operator"
+							 [(match_operand:SI 2 "register_operand" "d,d")]))
+			     (const_int 32)])))
+   (clobber (match_scratch:SI 6 "=l,v"))
+   (clobber (match_scratch:SI 7 "=a,q"))]
+  "TARGET_MIPS5900 &amp;&amp; GET_CODE (operands[3]) == GET_CODE (operands[4])"
+  "*
+{
+  if (GET_CODE (operands[3]) == SIGN_EXTEND)
+    return \"mult%H0\\t%1,%2\";
+  else
+    return \"multu%H0\\t%1,%2\";
+}"
+  [(set_attr "type"	"imul")
+   (set_attr "mode"	"SI")])
+
 (define_insn "xmulsi3_highpart_internal"
   [(set (match_operand:SI 0 "register_operand" "=h")
 	(truncate:SI
@@ -2168,7 +2348,7 @@
 		      (const_int 64))))
    (clobber (match_scratch:DI 3 "=l"))
    (clobber (match_scratch:DI 4 "=a"))]
-  "TARGET_64BIT"
+  "TARGET_64BIT &amp;&amp; !TARGET_MIPS5900"
   "dmult\\t%1,%2"
   [(set_attr "type"	"imul")
    (set_attr "mode"	"DI")])
@@ -2181,7 +2361,7 @@
 		      (const_int 64))))
    (clobber (match_scratch:DI 3 "=l"))
    (clobber (match_scratch:DI 4 "=a"))]
-  "TARGET_64BIT"
+  "TARGET_64BIT &amp;&amp; !TARGET_MIPS5900"
   "dmultu\\t%1,%2"
   [(set_attr "type"	"imul")
    (set_attr "mode"	"DI")])
@@ -2397,8 +2577,15 @@
   "optimize"
   "
 {
+  if (TARGET_MIPS5900)
+    {
+      emit_insn (gen_divmodsi4_internal_r5900 (operands[0], operands[1],
+					       operands[2], operands[3]));
+      goto zero_div_check;
+    }
   emit_insn (gen_divmodsi4_internal (operands[0], operands[1], operands[2],
 	     operands[3]));
+zero_div_check:
   if (!TARGET_NO_CHECK_ZERO_DIV)
     {
       emit_insn (gen_div_trap (operands[2],
@@ -2421,6 +2608,19 @@
   DONE;
 }")
 
+(define_insn "divmodsi4_internal_r5900"
+  [(set (match_operand:SI 0 "register_operand" "=l,v")
+	(div:SI (match_operand:SI 1 "register_operand" "d,d")
+		(match_operand:SI 2 "register_operand" "d,d")))
+   (set (match_operand:SI 3 "register_operand" "=h,u")
+	(mod:SI (match_dup 1)
+		(match_dup 2)))
+   (clobber (match_scratch:SI 4 "=a,q"))]
+  "optimize &amp;&amp; TARGET_MIPS5900"
+  "div%H0\\t$0,%1,%2"
+  [(set_attr "type"	"idiv")
+   (set_attr "mode"	"SI")])
+
 (define_insn "divmodsi4_internal"
   [(set (match_operand:SI 0 "register_operand" "=l")
 	(div:SI (match_operand:SI 1 "register_operand" "d")
@@ -2429,7 +2629,7 @@
 	(mod:SI (match_dup 1)
 		(match_dup 2)))
    (clobber (match_scratch:SI 4 "=a"))]
-  "optimize"
+  "optimize &amp;&amp; !TARGET_MIPS5900"
   "div\\t$0,%1,%2"
   [(set_attr "type"	"idiv")
    (set_attr "mode"	"SI")])
@@ -2444,7 +2644,7 @@
    (clobber (match_scratch:DI 4 "=l"))
    (clobber (match_scratch:DI 5 "=h"))
    (clobber (match_scratch:DI 6 "=a"))]
-  "TARGET_64BIT &amp;&amp; optimize"
+  "TARGET_64BIT &amp;&amp; optimize &amp;&amp; !TARGET_MIPS5900"
   "
 {
   emit_insn (gen_divmoddi4_internal (operands[0], operands[1], operands[2],
@@ -2477,7 +2677,7 @@
 	(mod:DI (match_dup 1)
 		(match_dup 2)))
    (clobber (match_scratch:DI 4 "=a"))]
-  "TARGET_64BIT &amp;&amp; optimize"
+  "TARGET_64BIT &amp;&amp; optimize &amp;&amp; !TARGET_MIPS5900"
   "ddiv\\t$0,%1,%2"
   [(set_attr "type"	"idiv")
    (set_attr "mode"	"SI")])
@@ -2495,8 +2695,15 @@
   "optimize"
   "
 {
+  if (TARGET_MIPS5900)
+    {
+      emit_insn (gen_udivmodsi4_internal_r5900 (operands[0], operands[1],
+					        operands[2], operands[3]));
+      goto zero_div_check;
+    }
   emit_insn (gen_udivmodsi4_internal (operands[0], operands[1], operands[2],
                                       operands[3]));
+zero_div_check:
   if (!TARGET_NO_CHECK_ZERO_DIV)
     {
       emit_insn (gen_div_trap (operands[2],
@@ -2507,6 +2714,19 @@
   DONE;
 }")
 
+(define_insn "udivmodsi4_internal_r5900"
+  [(set (match_operand:SI 0 "register_operand" "=l,v")
+	(udiv:SI (match_operand:SI 1 "register_operand" "d,d")
+		 (match_operand:SI 2 "register_operand" "d,d")))
+   (set (match_operand:SI 3 "register_operand" "=h,u")
+	(umod:SI (match_dup 1)
+		 (match_dup 2)))
+   (clobber (match_scratch:SI 4 "=a,q"))]
+  "optimize &amp;&amp; TARGET_MIPS5900"
+  "divu%H0\\t$0,%1,%2"
+  [(set_attr "type"	"idiv")
+   (set_attr "mode"	"SI")])
+
 (define_insn "udivmodsi4_internal"
   [(set (match_operand:SI 0 "register_operand" "=l")
 	(udiv:SI (match_operand:SI 1 "register_operand" "d")
@@ -2515,7 +2735,7 @@
 	(umod:SI (match_dup 1)
 		 (match_dup 2)))
    (clobber (match_scratch:SI 4 "=a"))]
-  "optimize"
+  "optimize &amp;&amp; !TARGET_MIPS5900"
   "divu\\t$0,%1,%2"
   [(set_attr "type"	"idiv")
    (set_attr "mode"	"SI")])
@@ -2530,7 +2750,7 @@
    (clobber (match_scratch:DI 4 "=l"))
    (clobber (match_scratch:DI 5 "=h"))
    (clobber (match_scratch:DI 6 "=a"))]
-  "TARGET_64BIT &amp;&amp; optimize"
+  "TARGET_64BIT &amp;&amp; optimize &amp;&amp; !TARGET_MIPS5900"
   "
 {
   emit_insn (gen_udivmoddi4_internal (operands[0], operands[1], operands[2],
@@ -2553,7 +2773,7 @@
 	(umod:DI (match_dup 1)
 		 (match_dup 2)))
    (clobber (match_scratch:DI 4 "=a"))]
-  "TARGET_64BIT &amp;&amp; optimize"
+  "TARGET_64BIT &amp;&amp; optimize &amp;&amp; !TARGET_MIPS5900"
   "ddivu\\t$0,%1,%2"
   [(set_attr "type"	"idiv")
    (set_attr "mode"	"SI")])
@@ -2651,6 +2871,7 @@
   [(set_attr "type" "unknown")
    (set_attr "length" "12")])
 
+;; Add r5900-specific div here.
 (define_expand "divsi3"
   [(set (match_operand:SI 0 "register_operand" "=l")
 	(div:SI (match_operand:SI 1 "register_operand" "d")
@@ -2700,7 +2921,7 @@
 		(match_operand:DI 2 "se_register_operand" "d")))
    (clobber (match_scratch:DI 3 "=h"))
    (clobber (match_scratch:DI 4 "=a"))]
-  "TARGET_64BIT &amp;&amp; !optimize"
+  "TARGET_64BIT &amp;&amp; !optimize &amp;&amp; !TARGET_MIPS5900"
   "
 {
   emit_insn (gen_divdi3_internal (operands[0], operands[1], operands[2]));
@@ -2730,11 +2951,12 @@
 		(match_operand:DI 2 "se_nonmemory_operand" "di")))
    (clobber (match_scratch:SI 3 "=h"))
    (clobber (match_scratch:SI 4 "=a"))]
-  "TARGET_64BIT &amp;&amp; !optimize"
+  "TARGET_64BIT &amp;&amp; !optimize &amp;&amp; !TARGET_MIPS5900"
   "ddiv\\t$0,%1,%2"
   [(set_attr "type"	"idiv")
    (set_attr "mode"	"DI")])
 
+;; XXX: add r5900-specific support here
 (define_expand "modsi3"
   [(set (match_operand:SI 0 "register_operand" "=h")
 	(mod:SI (match_operand:SI 1 "register_operand" "d")
@@ -2784,7 +3006,7 @@
 		(match_operand:DI 2 "se_register_operand" "d")))
    (clobber (match_scratch:DI 3 "=l"))
    (clobber (match_scratch:DI 4 "=a"))]
-  "TARGET_64BIT &amp;&amp; !optimize"
+  "TARGET_64BIT &amp;&amp; !optimize &amp;&amp; !TARGET_MIPS5900"
   "
 {
   emit_insn (gen_moddi3_internal (operands[0], operands[1], operands[2]));
@@ -2814,11 +3036,12 @@
 		(match_operand:DI 2 "se_nonmemory_operand" "di")))
    (clobber (match_scratch:SI 3 "=l"))
    (clobber (match_scratch:SI 4 "=a"))]
-  "TARGET_64BIT &amp;&amp; !optimize"
+  "TARGET_64BIT &amp;&amp; !optimize &amp;&amp; !TARGET_MIPS5900"
   "ddiv\\t$0,%1,%2"
   [(set_attr "type"	"idiv")
    (set_attr "mode"	"DI")])
 
+;; XXX: Add r5900-specific support here
 (define_expand "udivsi3"
   [(set (match_operand:SI 0 "register_operand" "=l")
 	(udiv:SI (match_operand:SI 1 "register_operand" "d")
@@ -2856,7 +3079,7 @@
 		 (match_operand:DI 2 "se_register_operand" "di")))
    (clobber (match_scratch:DI 3 "=h"))
    (clobber (match_scratch:DI 4 "=a"))]
-  "TARGET_64BIT &amp;&amp; !optimize"
+  "TARGET_64BIT &amp;&amp; !optimize &amp;&amp; !TARGET_MIPS5900"
   "
 {
   emit_insn (gen_udivdi3_internal (operands[0], operands[1], operands[2]));
@@ -2876,11 +3099,12 @@
 		 (match_operand:DI 2 "se_nonmemory_operand" "di")))
    (clobber (match_scratch:SI 3 "=h"))
    (clobber (match_scratch:SI 4 "=a"))]
-  "TARGET_64BIT &amp;&amp; !optimize"
+  "TARGET_64BIT &amp;&amp; !optimize &amp;&amp; !TARGET_MIPS5900"
   "ddivu\\t$0,%1,%2"
   [(set_attr "type"	"idiv")
    (set_attr "mode"	"DI")])
 
+;; XXX: add r5900-specific support here
 (define_expand "umodsi3"
   [(set (match_operand:SI 0 "register_operand" "=h")
 	(umod:SI (match_operand:SI 1 "register_operand" "d")
@@ -2918,7 +3142,7 @@
 		 (match_operand:DI 2 "se_register_operand" "di")))
    (clobber (match_scratch:DI 3 "=l"))
    (clobber (match_scratch:DI 4 "=a"))]
-  "TARGET_64BIT &amp;&amp; !optimize"
+  "TARGET_64BIT &amp;&amp; !optimize &amp;&amp; !TARGET_MIPS5900"
   "
 {
   emit_insn (gen_umoddi3_internal (operands[0], operands[1], operands[2]));
@@ -2938,7 +3162,7 @@
 		 (match_operand:DI 2 "se_nonmemory_operand" "di")))
    (clobber (match_scratch:SI 3 "=l"))
    (clobber (match_scratch:SI 4 "=a"))]
-  "TARGET_64BIT &amp;&amp; !optimize"
+  "TARGET_64BIT &amp;&amp; !optimize &amp;&amp; !TARGET_MIPS5900"
   "ddivu\\t$0,%1,%2"
   [(set_attr "type"	"idiv")
    (set_attr "mode"	"DI")])
@@ -2979,7 +3203,7 @@
   [(set (match_operand:SF 0 "register_operand" "=f")
 	(div:SF (match_operand:SF 1 "const_float_1_operand" "")
 		(sqrt:SF (match_operand:SF 2 "register_operand" "f"))))]
-  "ISA_HAS_FP4 &amp;&amp; TARGET_HARD_FLOAT &amp;&amp; flag_unsafe_math_optimizations"
+  "ISA_HAS_FP4 &amp;&amp; TARGET_HARD_FLOAT &amp;&amp; TARGET_MIPS5900 &amp;&amp; flag_unsafe_math_optimizations"
   "rsqrt.s\\t%0,%2"
   [(set_attr "type"	"fsqrt")
    (set_attr "mode"	"SF")])
@@ -3061,6 +3285,37 @@
    (set_attr "mode"	"SF")])
 
 
+;;  ....................
+;;
+;;	MIN, MAX
+;;
+;;  ....................
+
+(define_insn "minsf3"
+  [(set (match_operand:SF 0 "register_operand" "=f")
+	(if_then_else (lt:SF 
+		(match_operand:SF 1 "register_operand" "f")
+		(match_operand:SF 2 "register_operand" "f"))
+	(match_dup 1) 
+	(match_dup 2)))]
+  "TARGET_HARD_FLOAT &amp;&amp; TARGET_MIPS5900"
+  "min.s\\t%0,%1,%2"
+  [(set_attr "type"	"fadd")
+   (set_attr "mode"	"SF")])
+
+(define_insn "maxsf3"
+  [(set (match_operand:SF 0 "register_operand" "=f")
+	(if_then_else (gt:SF 
+		(match_operand:SF 1 "register_operand" "f")
+		(match_operand:SF 2 "register_operand" "f"))
+	(match_dup 1) 
+	(match_dup 2)))]
+  "TARGET_HARD_FLOAT &amp;&amp; TARGET_MIPS5900"
+  "max.s\\t%0,%1,%2"
+  [(set_attr "type"	"fadd")
+   (set_attr "mode"	"SF")])
+
+ 
 ;;
 ;;  ....................
 ;;
@@ -3081,6 +3336,38 @@
   dslots_jump_filled += 2;
   operands[4] = const0_rtx;
 
+  if (TARGET_MIPS5900 &amp;&amp; !TARGET_NO_LENGTHEN_LOOP ) {
+    if (optimize &amp;&amp; find_reg_note (insn, REG_DEAD, operands[1]))
+      return \"%(\\
+move\\t%0,%z4\\n\\
+\\tbeq\\t%1,%z4,2f\\n\\
+1:\\tand\\t%2,%1,0x0001\\n\\
+\\taddu\\t%0,%0,1\\n\\
+\\tbne\\t%2,%z4,2f\\n\\
+\\tsrl\\t%1,%1,1\\n\\
+\\n\\
+\\tand\\t%2,%1,0x0001\\n\\
+\\taddu\\t%0,%0,1\\n\\
+\\tbeq\\t%2,%z4,1b\\n\\
+\\tsrl\\t%1,%1,1\\n\\
+2:%)\";
+
+    return \"%(\\
+move\\t%0,%z4\\n\\
+\\tmove\\t%3,%1\\n\\
+\\tbeq\\t%3,%z4,2f\\n\\
+1:\\tand\\t%2,%3,0x0001\\n\\
+\\taddu\\t%0,%0,1\\n\\
+\\tbne\\t%2,%z4,2f\\n\\
+\\tsrl\\t%3,%3,1\\n\\
+\\n\\
+\\tand\\t%2,%3,0x0001\\n\\
+\\taddu\\t%0,%0,1\\n\\
+\\tbeq\\t%2,%z4,1b\\n\\
+\\tsrl\\t%3,%3,1\\n\\
+2:%)\";
+  }
+
   if (optimize &amp;&amp; find_reg_note (insn, REG_DEAD, operands[1]))
     return \"%(\\
 move\\t%0,%z4\\n\\
@@ -3103,7 +3390,11 @@
 }"
   [(set_attr "type"	"multi")
    (set_attr "mode"	"SI")
-   (set_attr "length"	"12")])
+   (set (attr "length") 
+   	(if_then_else (and (ne (const_int 0) (symbol_ref "TARGET_MIPS5900") )
+   		(eq (const_int 0) (symbol_ref "TARGET_NO_LENGTHEN_LOOP")))
+	(const_int 44)
+	(const_int  24))) ])
 
 (define_insn "ffsdi2"
   [(set (match_operand:DI 0 "register_operand" "=&amp;d")
@@ -3117,6 +3408,38 @@
   dslots_jump_filled += 2;
   operands[4] = const0_rtx;
 
+  if (TARGET_MIPS5900 &amp;&amp; !TARGET_NO_LENGTHEN_LOOP ) {
+    if (optimize &amp;&amp; find_reg_note (insn, REG_DEAD, operands[1]))
+      return \"%(\\
+move\\t%0,%z4\\n\\
+\\tbeq\\t%1,%z4,2f\\n\\
+1:\\tand\\t%2,%1,0x0001\\n\\
+\\tdaddu\\t%0,%0,1\\n\\
+\\tbne\\t%2,%z4,2f\\n\\
+\\tdsrl\\t%1,%1,1\\n\\
+\\n\\
+\\tand\\t%2,%1,0x0001\\n\\
+\\tdaddu\\t%0,%0,1\\n\\
+\\tbeq\\t%2,%z4,1b\\n\\
+\\tdsrl\\t%1,%1,1\\n\\
+2:%)\";
+
+    return \"%(\\
+move\\t%0,%z4\\n\\
+\\tmove\\t%3,%1\\n\\
+\\tbeq\\t%3,%z4,2f\\n\\
+1:\\tand\\t%2,%3,0x0001\\n\\
+\\tdaddu\\t%0,%0,1\\n\\
+\\tbne\\t%2,%z4,2f\\n\\
+\\tdsrl\\t%3,%3,1\\n\\
+\\n\\
+\\tand\\t%2,%3,0x0001\\n\\
+\\tdaddu\\t%0,%0,1\\n\\
+\\tbeq\\t%2,%z4,1b\\n\\
+\\tdsrl\\t%3,%3,1\\n\\
+2:%)\";
+  }
+
   if (optimize &amp;&amp; find_reg_note (insn, REG_DEAD, operands[1]))
     return \"%(\\
 move\\t%0,%z4\\n\\
@@ -3139,7 +3462,11 @@
 }"
   [(set_attr "type"	"multi")
    (set_attr "mode"	"DI")
-   (set_attr "length"	"24")])
+   (set (attr "length") 
+   	(if_then_else (and (ne (const_int 0) (symbol_ref "TARGET_MIPS5900") )
+   		(eq (const_int 0) (symbol_ref "TARGET_NO_LENGTHEN_LOOP")))
+	(const_int 44)
+	(const_int  24))) ])
 
 
 ;;
@@ -3271,6 +3598,18 @@
    (set (subreg:SI (match_dup 0) 4) (not:SI (subreg:SI (match_dup 1) 4)))]
   "")
 
+(define_insn "one_cmplti2"
+  [(set (match_operand:TI 0 "register_operand" "=d")
+  	(not:TI (match_operand:TI 1 "register_operand" "d")))]
+  "TARGET_MIPS5900"
+  "*
+{
+  operands[2] = const0_rtx;
+  return \"pnor\\t%0,%z2,%1\";
+}"
+  [(set_attr "type" "mmi")
+   (set_attr "mode" "TI")])
+
 
 ;;
 ;;  ....................
@@ -3386,6 +3725,17 @@
   [(set_attr "type"	"arith")
    (set_attr "mode"	"DI")])
 
+(define_insn "andti3"
+  [(set (match_operand:TI 0 "register_operand" "=d,d")
+  	(and:TI (match_operand:TI 1 "register_operand" "%0,d")
+		(match_operand:TI 2 "register_operand" "d,d")))]
+  "TARGET_MIPS5900"
+  "@
+   pand\\t%0,%2
+   pand\\t%0,%1,%2"
+  [(set_attr "type" "mmi")
+   (set_attr "mode" "TI")])
+
 (define_expand "iorsi3"
   [(set (match_operand:SI 0 "register_operand" "=d,d")
 	(ior:SI (match_operand:SI 1 "uns_arith_operand" "%d,d")
@@ -3477,6 +3827,17 @@
    (set (subreg:SI (match_dup 0) 4) (ior:SI (subreg:SI (match_dup 1) 4) (subreg:SI (match_dup 2) 4)))]
   "")
 
+(define_insn "iorti3"
+  [(set (match_operand:TI 0 "register_operand" "=d,d")
+  	(ior:TI (match_operand:TI 1 "register_operand" "%0,d")
+		(match_operand:TI 2 "register_operand" "d,d")))]
+  "TARGET_MIPS5900"
+  "@
+   por\\t%0,%2
+   por\\t%0,%1,%2"
+  [(set_attr "type" "mmi")
+   (set_attr "mode" "TI")])
+
 (define_expand "xorsi3"
   [(set (match_operand:SI 0 "register_operand" "=d,d")
 	(xor:SI (match_operand:SI 1 "uns_arith_operand" "%d,d")
@@ -3591,6 +3952,17 @@
   [(set_attr "type"	"arith")
    (set_attr "mode"	"DI")])
 
+(define_insn "xorti3"
+  [(set (match_operand:TI 0 "register_operand" "=d,d")
+  	(xor:TI (match_operand:TI 1 "register_operand" "%0,d")
+		(match_operand:TI 2 "register_operand" "d,d")))]
+  "TARGET_MIPS5900"
+  "@
+   pxor\\t%0,%2
+   pxor\\t%0,%1,%2"
+  [(set_attr "type" "mmi")
+   (set_attr "mode" "TI")])
+
 (define_insn "*norsi3"
   [(set (match_operand:SI 0 "register_operand" "=d")
 	(and:SI (not:SI (match_operand:SI 1 "register_operand" "d"))
@@ -3632,6 +4004,18 @@
    (set (subreg:SI (match_dup 0) 4) (and:SI (not:SI (subreg:SI (match_dup 1) 4)) (not:SI (subreg:SI (match_dup 2) 4))))]
   "")
 
+(define_insn "*norti3"
+  [(set (match_operand:TI 0 "register_operand" "=d,d")
+  	(and:TI (not:TI (match_operand:TI 1 "register_operand" "%0,d"))
+		(not:TI (match_operand:TI 2 "register_operand" "d,d"))))]
+  "TARGET_MIPS5900"
+  "@
+   pnor\\t%0,%2
+   pnor\\t%0,%1,%2"
+  [(set_attr "type" "mmi")
+   (set_attr "mode" "TI")])
+
+
 ;;
 ;;  ....................
 ;;
@@ -4073,7 +4457,7 @@
 
 (define_insn "extendsidi2"
   [(set (match_operand:DI 0 "register_operand" "=d,y,d,*d,d,d")
-	(sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,d,y,*x,R,m")))]
+	(sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,d,y,*x*w,R,m")))]
   "TARGET_64BIT"
   "* return mips_move_1word (operands, insn, FALSE);"
   [(set_attr "type"	"move,move,move,hilo,load,load")
@@ -4299,6 +4683,21 @@
 {
   rtx xoperands[10];
 
+  /* trunc.w.s isn't implemented on the r5900, but cvt.w.s */
+  /* truncates, so use it here. */
+  if (TARGET_MIPS5900)
+    {
+      if (which_alternative == 1)
+        return \"cvt.w.s %0,%1\";
+
+      output_asm_insn (\"cvt.w.s %3,%1\", operands);
+
+      xoperands[0] = operands[0];
+      xoperands[1] = operands[3];
+      output_asm_insn (mips_move_1word (xoperands, insn, FALSE), xoperands);
+      return \"\";
+    }
+
   if (which_alternative == 1)
     return \"trunc.w.s %0,%1,%2\";
 
@@ -4912,6 +5311,86 @@
   [(set_attr "type"	"arith")
    (set_attr "mode"	"SI")])
 
+;; 128-bit integer moves
+
+;; Unlike most other insns, the move insns can't be split with
+;; different predicates, because register spilling and other parts of
+;; the compiler, have memoized the insn number already.
+
+(define_expand "movti"
+  [(set (match_operand:TI 0 "nonimmediate_operand" "")
+	(match_operand:TI 1 "general_operand" ""))]
+  "TARGET_MIPS5900"
+  "
+{
+  /* I think this code is unnecessary since we'll never split when
+     the mode is larger than UNITS_PER_WORD.  */
+  if (mips_split_addresses &amp;&amp; mips_check_split (operands[1], TImode))
+    {
+      enum machine_mode mode = GET_MODE (operands[0]);
+      rtx tem = ((reload_in_progress | reload_completed)
+		 ? operands[0] : gen_reg_rtx (mode));
+
+      emit_insn (gen_rtx (SET, VOIDmode, tem,
+			  gen_rtx (HIGH, mode, operands[1])));
+
+      operands[1] = gen_rtx (LO_SUM, mode, tem, operands[1]);
+    }
+
+  /* If we are generating embedded PIC code, and we are referring to a
+     symbol in the .text section, we must use an offset from the start
+     of the function. 
+
+     For now we abort this case on the R5900.  */
+  if (TARGET_EMBEDDED_PIC
+      &amp;&amp; (GET_CODE (operands[1]) == LABEL_REF
+	  || (GET_CODE (operands[1]) == SYMBOL_REF
+	      &amp;&amp; ! SYMBOL_REF_FLAG (operands[1]))))
+    abort ();
+
+  /* If operands[1] is a constant address illegal for pic, then we need to
+     handle it just like LEGITIMIZE_ADDRESS does.
+     For now we abort this case on the R5900.  */
+  if (flag_pic &amp;&amp; pic_address_needs_scratch (operands[1]))
+    abort ();
+
+  /* Make operand1 a register if it isn't already.  */
+  if ((reload_in_progress | reload_completed) == 0
+      &amp;&amp; !register_operand (operands[0], TImode)
+      &amp;&amp; !register_operand (operands[1], TImode)
+      &amp;&amp; (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0)
+      &amp;&amp; operands[1] != CONST0_RTX (TImode))
+    {
+      rtx temp = force_reg (TImode, operands[1]);
+      emit_move_insn (operands[0], temp);
+      DONE;
+    }
+}")
+
+(define_insn "movti_internal"
+  [(set (match_operand:TI 0 "nonimmediate_operand" "=d,d,d,R,m,d,d,d,d,d")
+	(match_operand:TI 1 "movti_operand"         "d,R,m,d,d,J,K,L,M,i"))]
+  "TARGET_MIPS5900
+   &amp;&amp; (register_operand (operands[0], TImode)
+       || se_register_operand (operands[1], TImode)
+       || (GET_CODE (operands[1]) == CONST_INT &amp;&amp; INTVAL (operands[1]) == 0)
+       || operands[1] == CONST0_RTX (TImode))"
+  "@
+  por %0,$0,%1
+  lq %0,%1
+  lq %0,%1
+  sq %1,%0
+  sq %1,%0
+  por %0,%.,%.
+  por\\t%0,%.,%.\;li\\t%0,%1 \\t\\t\\t# ori
+  por\\t%0,%.,%.\;li\\t%0,%1 \\t\\t\\t# lui
+  por\\t%0,%.,%.\;dli\\t%0,%1 \\t\\t\\t# general li macro
+  dli\\t%0,%M1\;pcpyld\\t%0,%0,%.\;dli\\t%0,%L1"
+  [(set_attr "type"	"mmi,load,load,store,store,mmi,mmi,mmi,mmi,mmi")
+   (set_attr "mode"	"TI")
+;; The general li macro on a 64 bit machine can be up to 7 instructions long.
+   (set_attr "length"	"4,4,4,4,4,4,16,16,32,60")])
+
 ;; 64-bit integer moves
 
 ;; Unlike most other insns, the move insns can't be split with
@@ -5039,7 +5518,7 @@
    (set_attr "length"	"4,8")])
 
 (define_insn "movdi_internal"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,R,o,*x,*d,*x")
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,R,o,*x*w,*d,*x*w")
 	(match_operand:DI 1 "general_operand" "d,iF,R,o,d,d,J,*x,*d"))]
   "!TARGET_64BIT &amp;&amp; !TARGET_MIPS16
    &amp;&amp; (register_operand (operands[0], DImode)
@@ -5075,8 +5554,8 @@
   "")
 
 (define_insn "movdi_internal2"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*x,*d,*x,*a")
-	(match_operand:DI 1 "movdi_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,J,*x,*d,*J"))]
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*x*w,*d,*x*w,*a*q")
+	(match_operand:DI 1 "movdi_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,J,*x*w,*d,*J"))]
   "TARGET_64BIT &amp;&amp; !TARGET_MIPS16
    &amp;&amp; (register_operand (operands[0], DImode)
        || se_register_operand (operands[1], DImode)
@@ -5089,7 +5568,7 @@
 
 (define_insn ""
   [(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,d,R,m,*d")
-	(match_operand:DI 1 "movdi_operand" "d,d,y,K,N,s,R,m,d,d,*x"))]
+	(match_operand:DI 1 "movdi_operand" "d,d,y,K,N,s,R,m,d,d,*x*w"))]
   "TARGET_64BIT &amp;&amp; TARGET_MIPS16
    &amp;&amp; (register_operand (operands[0], DImode)
        || se_register_operand (operands[1], DImode))"
@@ -5180,7 +5659,7 @@
 			      ? REGNO (operands[2]) + 1
 			      : REGNO (operands[2])));
 
-  if (GET_CODE (operands[0]) == REG &amp;&amp; REGNO (operands[0]) == HILO_REGNUM)
+  if (GET_CODE (operands[0]) == REG &amp;&amp; ( REGNO (operands[0]) == HILO_REGNUM || REGNO (operands[0]) == HILO1_REGNUM ) )
     {
       if (GET_CODE (operands[1]) == MEM)
 	{
@@ -5203,28 +5682,45 @@
 	      lo_word = memword;
 	    }
 	  emit_move_insn (scratch, hi_word);
+         if( REGNO (operands[0]) == HILO_REGNUM )
 	  emit_move_insn (gen_rtx_REG (SImode, 64), scratch);
+	  else
+           emit_move_insn (gen_rtx_REG (SImode, 76), scratch);
 	  emit_move_insn (scratch, lo_word);
+         if( REGNO (operands[0]) == HILO_REGNUM )
 	  emit_move_insn (gen_rtx (REG, SImode, 65), scratch);
+	  else
+           emit_move_insn (gen_rtx (REG, SImode, 77), scratch);
 	  emit_insn (gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, operands[0]), 2));
 	}
       else
 	{
 	  emit_insn (gen_ashrdi3 (scratch, operands[1], GEN_INT (32)));
+         if( REGNO (operands[0]) == HILO_REGNUM )
 	  emit_insn (gen_movdi (gen_rtx_REG (DImode, 64), scratch));
+         else
+           emit_insn (gen_movdi (gen_rtx_REG (DImode, 76), scratch));
 	  emit_insn (gen_ashldi3 (scratch, operands[1], GEN_INT (32)));
 	  emit_insn (gen_ashrdi3 (scratch, scratch, GEN_INT (32)));
+         if( REGNO (operands[0]) == HILO_REGNUM )
 	  emit_insn (gen_movdi (gen_rtx (REG, DImode, 65), scratch));
-          emit_insn (gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, operands[0]), 2));
+         else
+           emit_insn (gen_movdi (gen_rtx (REG, DImode, 77), scratch));
 	}
       DONE;
     }
-  if (GET_CODE (operands[1]) == REG &amp;&amp; REGNO (operands[1]) == HILO_REGNUM)
+  if (GET_CODE (operands[1]) == REG &amp;&amp; ( REGNO (operands[1]) == HILO_REGNUM || REGNO (operands[1]) == HILO1_REGNUM ) )
     {
+      if( REGNO (operands[1]) == HILO_REGNUM )
       emit_insn (gen_movdi (scratch, gen_rtx_REG (DImode, 65)));
+      else
+         emit_insn (gen_movdi (scratch, gen_rtx_REG (DImode, 76)));
       emit_insn (gen_ashldi3 (scratch, scratch, GEN_INT (32)));
       emit_insn (gen_lshrdi3 (scratch, scratch, GEN_INT (32)));
+      if( REGNO (operands[1]) == HILO_REGNUM )
       emit_insn (gen_movdi (operands[0], gen_rtx_REG (DImode, 64)));
+      else
+        emit_insn (gen_movdi (operands[0], gen_rtx_REG (DImode, 77)));
       emit_insn (gen_ashldi3 (operands[0], operands[0], GEN_INT (32)));
       emit_insn (gen_iordi3 (operands[0], operands[0], scratch));
       emit_insn (gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, operands[1]), 2));
@@ -5242,7 +5738,7 @@
 ;; use a TImode scratch reg.
 
 (define_expand "reload_outdi"
-  [(set (match_operand:DI 0 "general_operand" "=b")
+  [(set (match_operand:DI 0 "" "=b")
 	(match_operand:DI 1 "se_register_operand" "b"))
    (clobber (match_operand:TI 2 "register_operand" "=&amp;d"))]
   "TARGET_64BIT"
@@ -5250,17 +5746,23 @@
 {
   rtx scratch = gen_rtx_REG (DImode, REGNO (operands[2]));
 
-  if (GET_CODE (operands[0]) == REG &amp;&amp; REGNO (operands[0]) == HILO_REGNUM)
+  if (GET_CODE (operands[0]) == REG &amp;&amp; ( REGNO (operands[0]) == HILO_REGNUM || REGNO (operands[0]) == HILO1_REGNUM ) )
     {
       emit_insn (gen_ashrdi3 (scratch, operands[1], GEN_INT (32)));
+      if( REGNO (operands[0]) == HILO_REGNUM )
       emit_insn (gen_movdi (gen_rtx (REG, DImode, 64), scratch));
+      else
+        emit_insn (gen_movdi (gen_rtx (REG, DImode, 76), scratch));
       emit_insn (gen_ashldi3 (scratch, operands[1], GEN_INT (32)));
       emit_insn (gen_ashrdi3 (scratch, scratch, GEN_INT (32)));
+      if( REGNO (operands[0]) == HILO_REGNUM )
       emit_insn (gen_movdi (gen_rtx (REG, DImode, 65), scratch));
+      else
+        emit_insn (gen_movdi (gen_rtx (REG, DImode, 77), scratch));
       emit_insn (gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, operands[0]), 2));
       DONE;
     }
-  if (GET_CODE (operands[1]) == REG &amp;&amp; REGNO (operands[1]) == HILO_REGNUM)
+  if (GET_CODE (operands[1]) == REG &amp;&amp; ( REGNO (operands[1]) == HILO_REGNUM || REGNO (operands[1]) == HILO1_REGNUM ) )
     {
       if (GET_CODE (operands[0]) == MEM)
 	{
@@ -5282,9 +5784,15 @@
 	      hi_word = offword;
 	      lo_word = memword;
 	    }
+	  if( REGNO (operands[1]) == HILO_REGNUM )
 	  emit_move_insn (scratch, gen_rtx_REG (SImode, 64));
+	  else
+	    emit_move_insn (scratch, gen_rtx_REG (SImode, 76));
 	  emit_move_insn (hi_word, scratch);
+	  if( REGNO (operands[1]) == HILO_REGNUM )
 	  emit_move_insn (scratch, gen_rtx_REG (SImode, 65));
+         else
+	    emit_move_insn (scratch, gen_rtx_REG (SImode, 77));
 	  emit_move_insn (lo_word, scratch);
 	  emit_insn (gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, operands[1]), 2));
 	}
@@ -5294,10 +5802,16 @@
 	     and hence we can not directly move from the HILO register
 	     into it.  */
 	  rtx scratch2 = gen_rtx_REG (DImode, REGNO (operands[2]) + 1);
+	  if( REGNO (operands[1]) == HILO_REGNUM )
 	  emit_insn (gen_movdi (scratch, gen_rtx (REG, DImode, 65)));
+      else
+		emit_insn (gen_movdi (scratch, gen_rtx (REG, DImode, 77)));
 	  emit_insn (gen_ashldi3 (scratch, scratch, GEN_INT (32)));
 	  emit_insn (gen_lshrdi3 (scratch, scratch, GEN_INT (32)));
+	  if( REGNO (operands[1]) == HILO_REGNUM )
 	  emit_insn (gen_movdi (scratch2, gen_rtx (REG, DImode, 64)));
+	  else
+	    emit_insn (gen_movdi (scratch2, gen_rtx (REG, DImode, 76)));
 	  emit_insn (gen_ashldi3 (scratch2, scratch2, GEN_INT (32)));
 	  emit_insn (gen_iordi3 (scratch, scratch, scratch2));
 	  emit_insn (gen_movdi (operands[0], scratch));
@@ -5305,10 +5819,16 @@
 	}
       else
 	{
+	  if( REGNO (operands[1]) == HILO_REGNUM )
 	  emit_insn (gen_movdi (scratch, gen_rtx (REG, DImode, 65)));
+	  else
+	    emit_insn (gen_movdi (scratch, gen_rtx (REG, DImode, 77)));
 	  emit_insn (gen_ashldi3 (scratch, scratch, GEN_INT (32)));
 	  emit_insn (gen_lshrdi3 (scratch, scratch, GEN_INT (32)));
+	  if( REGNO (operands[1]) == HILO_REGNUM )
 	  emit_insn (gen_movdi (operands[0], gen_rtx (REG, DImode, 64)));
+	  else
+	    emit_insn (gen_movdi (operands[0], gen_rtx (REG, DImode, 76)));
 	  emit_insn (gen_ashldi3 (operands[0], operands[0], GEN_INT (32)));
 	  emit_insn (gen_iordi3 (operands[0], operands[0], scratch));
 	  emit_insn (gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, operands[1]), 2));
@@ -5468,8 +5988,8 @@
 ;; in FP registers (off by default, use -mdebugh to enable).
 
 (define_insn "movsi_internal1"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*f*z,*f,*f,*f,*R,*m,*x,*x,*d,*d")
-	(match_operand:SI 1 "move_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*f*z,*d,*f,*R,*m,*f,*f,J,*d,*x,*a"))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*f*z,*f,*f,*f,*R,*m,*x*w,*x*w,*d,*d")
+	(match_operand:SI 1 "move_operand"       "d,S,IKL,Mnis,R,m,dJ,dJ,*f*z,*d,*f,*R,*m,*f,*f,J,*d,*x*w,*a*q"))]
   "TARGET_DEBUG_H_MODE &amp;&amp; !TARGET_MIPS16
    &amp;&amp; (register_operand (operands[0], SImode)
        || register_operand (operands[1], SImode)
@@ -5480,8 +6000,8 @@
    (set_attr "length"	"4,8,4,8,4,8,4,8,4,4,4,4,8,4,8,4,4,4,4")])
 
 (define_insn "movsi_internal2"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*z,*x,*d,*x,*d")
-	(match_operand:SI 1 "move_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*z,*d,J,*x,*d,*a"))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,  d,   d,d,d, R, m,*d,*z,*x*w,*d,*x*w,*d")
+	(match_operand:SI 1 "move_operand"           "d,S,IKL,Mnis,R,m,dJ,dJ,*z,*d,J,*x*w,*d,*a*q"))]
   "!TARGET_DEBUG_H_MODE &amp;&amp; !TARGET_MIPS16
    &amp;&amp; (register_operand (operands[0], SImode)
        || register_operand (operands[1], SImode)
@@ -5764,7 +6284,7 @@
 
 ;; This insn is for the unspec delay for HILO.
 
-(define_insn "*HILO_delay"
+(define_insn "HILO_delay"
   [(unspec [(match_operand 0 "register_operand" "=b")] 2 )]
   ""
   ""
@@ -5975,8 +6495,8 @@
 ;; in FP registers (off by default, use -mdebugh to enable).
 
 (define_insn "movhi_internal1"
-  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*f,*f*z,*x,*d")
-	(match_operand:HI 1 "general_operand"       "d,IK,R,m,dJ,dJ,*f*z,*d,*f,*d,*x"))]
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*f,*f*z,*x*w,*d")
+	(match_operand:HI 1 "general_operand"       "d,IK,R,m,dJ,dJ,*f*z,*d,*f,*d,*x*w"))]
   "TARGET_DEBUG_H_MODE &amp;&amp; !TARGET_MIPS16
    &amp;&amp; (register_operand (operands[0], HImode)
        || register_operand (operands[1], HImode)
@@ -5987,8 +6507,8 @@
    (set_attr "length"	"4,4,4,8,4,8,4,4,4,4,4")])
 
 (define_insn "movhi_internal2"
-  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*z,*x,*d")
-	(match_operand:HI 1 "general_operand"       "d,IK,R,m,dJ,dJ,*z,*d,*d,*x"))]
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*z,*x*w,*d")
+	(match_operand:HI 1 "general_operand"       "d,IK,R,m,dJ,dJ,*z,*d,*d,*x*w"))]
   "!TARGET_DEBUG_H_MODE &amp;&amp; !TARGET_MIPS16
    &amp;&amp; (register_operand (operands[0], HImode)
        || register_operand (operands[1], HImode)
@@ -6000,7 +6520,7 @@
 
 (define_insn ""
   [(set (match_operand:HI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,R,m,*d")
-	(match_operand:HI 1 "general_operand"      "d,d,y,K,N,R,m,d,d,*x"))]
+	(match_operand:HI 1 "general_operand"      "d,d,y,K,N,R,m,d,d,*x*w"))]
   "TARGET_MIPS16
    &amp;&amp; (register_operand (operands[0], HImode)
        || register_operand (operands[1], HImode))"
@@ -6097,8 +6617,8 @@
 ;; in FP registers (off by default, use -mdebugh to enable).
 
 (define_insn "movqi_internal1"
-  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*f*z,*f,*x,*d")
-	(match_operand:QI 1 "general_operand"       "d,IK,R,m,dJ,dJ,*f*z,*d,*f,*d,*x"))]
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*f*z,*f,*x*w,*d")
+	(match_operand:QI 1 "general_operand"       "d,IK,R,m,dJ,dJ,*f*z,*d,*f,*d,*x*w"))]
   "TARGET_DEBUG_H_MODE &amp;&amp; !TARGET_MIPS16
    &amp;&amp; (register_operand (operands[0], QImode)
        || register_operand (operands[1], QImode)
@@ -6110,7 +6630,7 @@
 
 (define_insn "movqi_internal2"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*z,*x,*d")
-	(match_operand:QI 1 "general_operand"       "d,IK,R,m,dJ,dJ,*z,*d,*d,*x"))]
+	(match_operand:QI 1 "general_operand"       "d,IK,R,m,dJ,dJ,*z,*d,*d,*x*w"))]
   "!TARGET_DEBUG_H_MODE &amp;&amp; !TARGET_MIPS16
    &amp;&amp; (register_operand (operands[0], QImode)
        || register_operand (operands[1], QImode)
@@ -6327,12 +6847,13 @@
 ;; This is volatile to make sure that the scheduler won't move any symbol_ref
 ;; uses in front of it.  All symbol_refs implicitly use the gp reg.
 
+;; FIXME: what is this for? needed for r5900 PIC?
 (define_insn "loadgp"
   [(set (reg:DI 28)
 	(unspec_volatile:DI [(match_operand:DI 0 "address_operand" "")
 			     (match_operand:DI 1 "register_operand" "")] 2))
    (clobber (reg:DI 1))]
-  ""
+  "!TARGET_MIPS5900"
   "%[lui\\t$1,%%hi(%%neg(%%gp_rel(%a0)))\\n\\taddiu\\t$1,$1,%%lo(%%neg(%%gp_rel(%a0)))\\n\\tdaddu\\t$gp,$1,%1%]"
   [(set_attr "type"	"move")
    (set_attr "mode"	"DI")
@@ -9606,7 +10127,7 @@
 }")
 
 ;; Trivial return.  Make it look like a normal return insn as that
-;; allows jump optimizations to work better .
+;; allows jump optimizations to work better.
 (define_insn "return"
   [(return)]
   "mips_can_use_return_insn ()"
@@ -9811,6 +10332,37 @@
    (set_attr "mode"	"none")
    (set_attr "length"	"8")])
 
+;;
+;; use jalr instead of jal
+;;
+(define_insn "call_indirect_internal"
+  [ (unspec_volatile [ 
+  	(match_operand 0 "call_insn_operand" "ri")
+	(match_operand 1 "" "i")
+        (match_operand:SI 2 "register_operand" "=d") ] 30 )]
+  ""
+  "*
+{
+  register rtx target = operands[0];
+
+  if (GET_CODE (target) == SYMBOL_REF)
+    {
+      if (GET_MODE (target) == SImode)
+	return \"la\\t%^,%0\\n\\tjalr\\t%2,%^\";
+      else
+	return \"dla\\t%^,%0\\n\\tjalr\\t%2,%^\";
+    }
+  else if (GET_CODE (target) == CONST_INT)
+    return \"li\\t%^,%0\\n\\tjalr\\t%2,%^\";
+  else if (REGNO (target) != PIC_FUNCTION_ADDR_REGNUM)
+    return \"move\\t%^,%0\\n\\tjalr\\t%2,%^\";
+  else
+    return \"jalr\\t%2,%0\";
+}"
+  [(set_attr "type"	"call")
+   (set_attr "mode"	"none")
+   (set_attr "length"	"8")])
+
 (define_insn "call_internal1"
   [(call (mem (match_operand 0 "call_insn_operand" "ri"))
 	 (match_operand 1 "" "i"))
@@ -9843,6 +10395,8 @@
     return \"li\\t%^,%0\\n\\tjal\\t%2,%^\";
   else if (CONSTANT_ADDRESS_P (target))
     {
+      if (REGNO (operands[2]) == (31 + GP_REG_FIRST))
+	return \"jal\\t%0\";
       if (GET_MODE (target) == SImode)
 	return \"la\\t%^,%0\\n\\tjal\\t%2,%^\";
       else
@@ -10051,6 +10605,8 @@
     return \"li\\t%^,%1\\n\\tjal\\t%3,%^\";
   else if (CONSTANT_ADDRESS_P (target))
     {
+      if (REGNO (operands[3]) == (31 + GP_REG_FIRST))
+	return \"jal\\t%1\";
       if (GET_MODE (target) == SImode)
 	return \"la\\t%^,%1\\n\\tjal\\t%3,%^\";
       else
@@ -10186,6 +10742,8 @@
     return \"li\\t%^,%1\\n\\tjal\\t%4,%^\";
   else if (CONSTANT_ADDRESS_P (target))
     {
+      if (REGNO (operands[4]) == (31 + GP_REG_FIRST))
+	return \"jal\\t%1\";
       if (GET_MODE (target) == SImode)
 	return \"la\\t%^,%1\\n\\tjal\\t%4,%^\";
       else
@@ -10243,6 +10801,15 @@
   [(set_attr "type"	"nop")
    (set_attr "mode"	"none")])
 
+;; Used by the r5900 loop lengthening code.
+
+(define_insn "nop_internal"
+  [ (unspec_volatile [(const_int 0)] 31)]
+  "TARGET_MIPS5900"
+  "%(nop%)"
+  [(set_attr "type"	"nop")
+   (set_attr "mode"	"none")])
+
 ;; The MIPS chip does not seem to require stack probes.
 ;;
 ;; (define_expand "probe"
@@ -10457,6 +11024,11 @@
   "ISA_HAS_CONDMOVE || ISA_HAS_INT_CONDMOVE"
   "
 {
+  /* XXX: Verify this */
+  if (TARGET_MIPS5900
+      &amp;&amp; GET_MODE_CLASS (GET_MODE (branch_cmp[0])) == MODE_FLOAT)
+    FAIL;
+
   gen_conditional_move (operands);
   DONE;
 }")
@@ -10758,3 +11330,175 @@
   [(set_attr "type"	"arith")
    (set_attr "mode"	"DI")
    (set_attr "length"	"40")])
+
+;; r5900 MultiMedia Instructions (MMI)
+;; A lot of this code is based on the MMX implementation in i386.md.  The main
+;; differences between MMX and MMI is that MMI supports 128-bit wide vector
+;; operations and MMI operates directly on the r5900 128-bit GPRs vs. needing
+;; a special set of MM-dedicated registers.  Most of the instructions have the
+;; same mnemonics and perform similiar operations.
+
+;; Supported vector types
+;; 16 x 8 bits = V16QI
+;; 8 x 16 bits = V8HI
+;; 4 x 32 bits = V4SI and V4SF
+;; 2 x 64 bits = V2DI and V2SF
+;; 
+
+;; MMI arithmetic
+;; TODO: Add the alternative where operand 1 == operand 2
+
+(define_insn "addv16qi3"
+  [(set (match_operand:V16QI 0 "register_operand" "=d")
+	(plus:V16QI (match_operand:V16QI 1 "register_operand" "d")
+		    (match_operand:V16QI 2 "register_operand" "d")))]
+  "TARGET_MMI"
+  "paddb\\t%0,%1,%2"
+  [(set_attr "type" "mmi")])
+
+(define_insn "addv8hi3"
+  [(set (match_operand:V8HI 0 "register_operand" "=d")
+	(plus:V8HI (match_operand:V8HI 1 "register_operand" "d")
+		   (match_operand:V8HI 2 "register_operand" "d")))]
+  "TARGET_MMI"
+  "paddh\\t%0,%1,%2"
+  [(set_attr "type" "mmi")])
+
+(define_insn "addv4si3"
+  [(set (match_operand:V4SI 0 "register_operand" "=d")
+	(plus:V4SI (match_operand:V4SI 1 "register_operand" "d")
+		   (match_operand:V4SI 2 "register_operand" "d")))]
+  "TARGET_MMI"
+  "paddw\\t%0,%1,%2"
+  [(set_attr "type" "mmi")])
+
+;; Signed saturation
+
+(define_insn "ssaddv16qi3"
+  [(set (match_operand:V16QI 0 "register_operand" "=d")
+	(ss_plus:V16QI (match_operand:V16QI 1 "register_operand" "d")
+		       (match_operand:V16QI 2 "register_operand" "d")))]
+  "TARGET_MMI"
+  "paddsb\\t%0,%1,%2"
+  [(set_attr "type" "mmi")])
+
+(define_insn "ssaddv8hi3"
+  [(set (match_operand:V8HI 0 "register_operand" "=d")
+	(ss_plus:V8HI (match_operand:V8HI 1 "register_operand" "d")
+		      (match_operand:V8HI 2 "register_operand" "d")))]
+  "TARGET_MMI"
+  "paddsh\\t%0,%1,%2"
+  [(set_attr "type" "mmi")])
+
+(define_insn "ssaddv4si3"
+  [(set (match_operand:V4SI 0 "register_operand" "=d")
+	(ss_plus:V4SI (match_operand:V4SI 1 "register_operand" "d")
+		      (match_operand:V4SI 2 "register_operand" "d")))]
+  "TARGET_MMI"
+  "paddsw\\t%0,%1,%2"
+  [(set_attr "type" "mmi")])
+
+;; Unsigned saturation
+
+(define_insn "usaddv16qi3"
+  [(set (match_operand:V16QI 0 "register_operand" "=d")
+	(us_plus:V16QI (match_operand:V16QI 1 "register_operand" "d")
+		       (match_operand:V16QI 2 "register_operand" "d")))]
+  "TARGET_MMI"
+  "paddub\\t%0,%1,%2"
+  [(set_attr "type" "mmi")])
+
+(define_insn "usaddv8hi3"
+  [(set (match_operand:V8HI 0 "register_operand" "=d")
+	(us_plus:V8HI (match_operand:V8HI 1 "register_operand" "d")
+		      (match_operand:V8HI 2 "register_operand" "d")))]
+  "TARGET_MMI"
+  "padduh\\t%0,%1,%2"
+  [(set_attr "type" "mmi")])
+
+(define_insn "usaddv4si3"
+  [(set (match_operand:V4SI 0 "register_operand" "=d")
+	(us_plus:V4SI (match_operand:V4SI 1 "register_operand" "d")
+		      (match_operand:V4SI 2 "register_operand" "d")))]
+  "TARGET_MMI"
+  "padduw\\t%0,%1,%2"
+  [(set_attr "type" "mmi")])
+
+;; Subtraction
+
+(define_insn "subv16qi3"
+  [(set (match_operand:V16QI 0 "register_operand" "=d")
+	(minus:V16QI (match_operand:V16QI 1 "register_operand" "d")
+		     (match_operand:V16QI 2 "register_operand" "d")))]
+  "TARGET_MMI"
+  "psubb\\t%0,%1,%2"
+  [(set_attr "type" "mmi")])
+
+(define_insn "subv8hi3"
+  [(set (match_operand:V8HI 0 "register_operand" "=d")
+	(minus:V8HI (match_operand:V8HI 1 "register_operand" "d")
+		    (match_operand:V8HI 2 "register_operand" "d")))]
+  "TARGET_MMI"
+  "psubh\\t%0,%1,%2"
+  [(set_attr "type" "mmi")])
+
+(define_insn "subv4si3"
+  [(set (match_operand:V4SI 0 "register_operand" "=d")
+	(minus:V4SI (match_operand:V4SI 1 "register_operand" "d")
+		    (match_operand:V4SI 2 "register_operand" "d")))]
+  "TARGET_MMI"
+  "psubw\\t%0,%1,%2"
+  [(set_attr "type" "mmi")])
+
+;; Signed saturation
+
+(define_insn "sssubv16qi3"
+  [(set (match_operand:V16QI 0 "register_operand" "=d")
+	(ss_minus:V16QI (match_operand:V16QI 1 "register_operand" "d")
+		        (match_operand:V16QI 2 "register_operand" "d")))]
+  "TARGET_MMI"
+  "psubsb\\t%0,%1,%2"
+  [(set_attr "type" "mmi")])
+
+(define_insn "sssubv8hi3"
+  [(set (match_operand:V8HI 0 "register_operand" "=d")
+	(ss_minus:V8HI (match_operand:V8HI 1 "register_operand" "d")
+		       (match_operand:V8HI 2 "register_operand" "d")))]
+  "TARGET_MMI"
+  "psubsh\\t%0,%1,%2"
+  [(set_attr "type" "mmi")])
+
+(define_insn "sssubv4si3"
+  [(set (match_operand:V4SI 0 "register_operand" "=d")
+	(ss_minus:V4SI (match_operand:V4SI 1 "register_operand" "d")
+		       (match_operand:V4SI 2 "register_operand" "d")))]
+  "TARGET_MMI"
+  "psubsw\\t%0,%1,%2"
+  [(set_attr "type" "mmi")])
+
+;; Unsigned saturation
+
+(define_insn "ussubv16qi3"
+  [(set (match_operand:V16QI 0 "register_operand" "=d")
+	(us_minus:V16QI (match_operand:V16QI 1 "register_operand" "d")
+		        (match_operand:V16QI 2 "register_operand" "d")))]
+  "TARGET_MMI"
+  "psubub\\t%0,%1,%2"
+  [(set_attr "type" "mmi")])
+
+(define_insn "ussubv8hi3"
+  [(set (match_operand:V8HI 0 "register_operand" "=d")
+	(us_minus:V8HI (match_operand:V8HI 1 "register_operand" "d")
+		       (match_operand:V8HI 2 "register_operand" "d")))]
+  "TARGET_MMI"
+  "psubuh\\t%0,%1,%2"
+  [(set_attr "type" "mmi")])
+
+(define_insn "ussubv4si3"
+  [(set (match_operand:V4SI 0 "register_operand" "=d")
+	(us_minus:V4SI (match_operand:V4SI 1 "register_operand" "d")
+		       (match_operand:V4SI 2 "register_operand" "d")))]
+  "TARGET_MMI"
+  "psubuw\\t%0,%1,%2"
+  [(set_attr "type" "mmi")])
+
diff -burN orig.gcc-3.2.2/gcc/config/mips/mips-protos.h gcc-3.2.2/gcc/config/mips/mips-protos.h
--- orig.gcc-3.2.2/gcc/config/mips/mips-protos.h	2002-03-24 04:13:16.000000000 -0400
+++ gcc-3.2.2/gcc/config/mips/mips-protos.h	2007-04-29 05:10:04.000000000 -0300
@@ -81,6 +81,7 @@
 extern void		gen_conditional_move PARAMS ((rtx *));
 extern void		mips_gen_conditional_trap PARAMS ((rtx *));
 extern void		machine_dependent_reorg PARAMS ((rtx));
+extern void		machine_dependent_reorg_final PARAMS ((rtx));
 extern int		mips_address_cost PARAMS ((rtx));
 extern void		mips_count_memory_refs PARAMS ((rtx, int));
 extern HOST_WIDE_INT	mips_debugger_offset PARAMS ((rtx, HOST_WIDE_INT));
diff -burN orig.gcc-3.2.2/gcc/config/mips/r5900.h gcc-3.2.2/gcc/config/mips/r5900.h
--- orig.gcc-3.2.2/gcc/config/mips/r5900.h	1969-12-31 20:00:00.000000000 -0400
+++ gcc-3.2.2/gcc/config/mips/r5900.h	2007-04-29 05:10:04.000000000 -0300
@@ -0,0 +1,285 @@
+/*
+ * Target machine definitions for the Toshiba r5900.
+ *
+ * Copyright (c) 2003  M. R. Brown &lt;mrbrown@0xd6.org&gt;
+ *
+ * Based on the file elf5900.h, which originally bore
+ * the copyright banner:
+ *
+ *    Definitions of target machine for GNU compiler.
+ *    Toshiba r5900 little-endian
+ *    Copyright (c) 1995 Cygnus Support Inc.
+ *
+ * Also based on the PS2/Linux GCC port provided by SCEI and SCEA.
+ *
+ * Licensed under the terms of the GNU GPL version 2.
+ */
+
+/* TODO: Add Linux support. */
+
+#include "mips/elf64.h"
+#include "mips/abi64.h"
+
+#define MIPS_CPU_STRING_DEFAULT "R5900"
+
+#undef MIPS_ABI_DEFAULT
+#define MIPS_ABI_DEFAULT ABI_EABI
+
+#undef MIPS_ISA_DEFAULT
+#define MIPS_ISA_DEFAULT 3
+
+#undef MACHINE_TYPE
+#define MACHINE_TYPE "(MIPSel R5900 ELF)"
+
+/*
+ I started doing some macro fixes, but as we plan to use 3.4 soon I'm not risking changing stuff I'm not
+ certain about.
+*/
+/*
+#define USE_MACRO_FIXES
+*/
+
+/*
+ gcc-3.0.3-ps2linux has additional min.s and max.s floating point insns. These should be incorporate into mips.md.
+*/
+
+#define FILL_BDSLOT_WITH_NOP
+
+/*
+ * Use Gas, target r5900, -msingle-float, 64-bit CPU and longs, split-addr (avoids la insn emits), -mmmi
+ */
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT ( MASK_GAS | MASK_SINGLE_FLOAT | MASK_64BIT \
+			| MASK_LONG64 | MASK_MMI | MASK_VUMM | MASK_SPLIT_ADDR )
+
+/*
+ * Even though we're a 64-bit processor, we only support a 32-bit address
+ * space.
+ */
+#undef Pmode
+#define Pmode SImode
+
+/* 128-bit alignment options */
+#define DEFAULT_MIPS_ALIGNMENT 128
+
+/* TODO: need to make this variable */
+#undef  BIGGEST_ALIGNMENT 
+#define BIGGEST_ALIGNMENT  DEFAULT_MIPS_ALIGNMENT
+
+#undef SUBTARGET_TARGET_OPTIONS
+#define SUBTARGET_TARGET_OPTIONS					\
+  { "use-128", &amp;mips_use_128_string,					\
+      N_("Use 128-bit operations")},					\
+  { "align128", &amp;mips_align128_string,					\
+      N_("Use 128-bit alignment")},					\
+  { "no-align128", &amp;mips_no_align128_string,				\
+      N_("Don't use 128-bit alignment")},				\
+  { "abi=", &amp;mips_abi_string,						\
+      N_("Speciy ABI to use")},
+
+/* Stack alignment */
+#undef STACK_BOUNDARY
+#define STACK_BOUNDARY							\
+  ((mips_abi == ABI_32 || mips_abi == ABI_O64 || (mips_abi == ABI_EABI	\
+    &amp;&amp; !TARGET_MIPS5900))						\
+   ? 64 : 128)
+
+#undef MIPS_STACK_ALIGN
+#define MIPS_STACK_ALIGN(LOC)						\
+  (((mips_abi == ABI_32 || mips_abi == ABI_O64 || mips_abi == ABI_EABI)	\
+    &amp;&amp; mips_alignment != 128 )	 					\
+   ? ((LOC) + 7) &amp; ~7							\
+   : ((LOC) + 15) &amp; ~15)
+
+#define PREFERRED_STACK_BOUNDARY \
+(mips_alignment == 128 ? 128 : 						\
+  ((mips_abi == ABI_32 || mips_abi == ABI_O64 || mips_abi == ABI_EABI )	\
+   ? 64 : 128))
+
+/* TODO: Find a way to specify default alignments for functions, jumps,
+   and loops.  These used to be machine dependant, but now live as -f
+   parameters.  */
+
+/* prefer .p2align rather than .align (gas assumed) */
+#define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE,LOG,MAX_SKIP) \
+  if ((LOG)!=0) \
+    if ((MAX_SKIP)==0) fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
+    else fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP))
+
+/* How to output a quadword for the r5900.  */
+#define ASM_OUTPUT_QUADRUPLE_INT(STREAM,VALUE)                          \
+do {                                                                    \
+  if (TARGET_64BIT)                                                     \
+    {                                                                   \
+      fprintf (STREAM, "\t.octa\t");                                    \
+      if (HOST_BITS_PER_WIDE_INT &lt; 64 || GET_CODE (VALUE) != CONST_INT) \
+        /* We can't use 'X' for negative numbers, because then we won't \
+           get the right value for the upper 32 bits.  */               \
+        output_addr_const (STREAM, VALUE);                              \
+      else                                                              \
+        /* We must use 'X', because otherwise LONG_MIN will print as    \
+           a number that the Irix 6 assembler won't accept.  */         \
+        print_operand (STREAM, VALUE, 'X');                             \
+      fprintf (STREAM, "\n");                                           \
+    }                                                                   \
+  else                                                                  \
+    {                                                                   \
+      assemble_integer (operand_subword ((VALUE), 0, 0, TImode),        \
+                        UNITS_PER_WORD, 1);                             \
+      assemble_integer (operand_subword ((VALUE), 1, 0, TImode),        \
+                        UNITS_PER_WORD, 1);                             \
+    }                                                                   \
+} while (0)
+
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "\
+-D__ELF__ \
+-Dmips -D_mips -D__mips -D__mips__ \
+%{!miop: -DR5900 -D_R5900 -D__R5900 -D_EE } \
+%{miop: -DR3000 -D_3000 -D__3000 } \
+-DMIPSEL -D_MIPSEL -D__MIPSEL -D__MIPSEL__ \
+-Acpu(mips) -Amachine(mips) \
+"
+
+/* Default to 32-bit ints and 64-bit longs. */
+#undef SUBTARGET_CPP_SIZE_SPEC 
+#define SUBTARGET_CPP_SIZE_SPEC "\
+%{mgp64: -D_MIPS_SZPTR=32 } \
+%{!mgp64: -D_MIPS_SZPTR=32 } \
+\
+%{mlong64:-D__SIZE_TYPE__=long\\ unsigned\\ int \
+  -D__SSIZE_TYPE__=long\\ int \
+  -D__PTRDIFF_TYPE__=long\\ int \
+  -D_MIPS_SZLONG=64}  \
+\
+%{mint64:-D_MIPS_SZINT=64 \
+  %{!mlong64:-D__SIZE_TYPE__=long\\ unsigned\\ int \
+    -D__SSIZE_TYPE__=long\\ int \
+    -D__PTRDIFF_TYPE__=long\\ int \
+    -D_MIPS_SZLONG=64}} \
+\
+%{!mint64:-D_MIPS_SZINT=32 \
+  %{!mlong64:-D__SIZE_TYPE__=unsigned\\ int \
+    -D__SSIZE_TYPE__=int \
+    -D__PTRDIFF_TYPE__=int \
+    -D_MIPS_SZLONG=64}} \
+"
+
+#undef SUBTARGET_CPP_SPEC 
+#define SUBTARGET_CPP_SPEC "\
+%{mfp32: -D_MIPS_FPSET=16}%{!mfp32: -D_MIPS_FPSET=32} \
+%{mips1: -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS1} \
+%{mips2: -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS2} \
+%{mips3: -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS3 -UR3000 -U_R3000} \
+%{mips4: -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS4 -UR3000 -U_R3000} \
+%{!mips*: -U__mips -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS3 -D__mips=3 -D__mips64} \
+%{!mabi=32: %{!mabi=n32: %{!mabi=64: -D__mips_eabi}}} \
+%{!msoft-float: %{!mdouble-float : -D__mips_single_float}} \
+%{-D__HAVE_FPU__ } \
+%{posix: -D_POSIX_SOURCE} \
+%{.cc:	-D__LANGUAGE_C_PLUS_PLUS__  %{!ansi:-DLANGUAGE_C_PLUS_PLUS}} \
+%{.cxx:	-D__LANGUAGE_C_PLUS_PLUS__  %{!ansi:-DLANGUAGE_C_PLUS_PLUS}} \
+%{.C:	-D__LANGUAGE_C_PLUS_PLUS__  %{!ansi:-DLANGUAGE_C_PLUS_PLUS}} \
+%{.m:	-D__LANGUAGE_OBJECTIVE_C__ %{!ansi:-DLANGUAGE_OBJECTIVE_C}} \
+%{.S:	-D__LANGUAGE_ASSEMBLY__ %{!ansi:-DLANGUAGE_ASSEMBLY}} \
+%{.s:	-D__LANGUAGE_ASSEMBLY__ %{!ansi:-DLANGUAGE_ASSEMBLY}} \
+%{!.S: %{!.s: %{!.cc: %{!.cxx: %{!.C: %{!.m: -D__LANGUAGE_C__ %{!ansi:-DLANGUAGE_C}}}}}} } \
+%{ansi:-Uunix -Ulinux -Umips -UR3000 -UMIPSEB -UMIPSEL} \
+%{ffast-math: -D__FAST_MATH__} \
+ "
+
+/* The GNU C++ standard library requires that these macros be defined.  */
+#undef CPLUSPLUS_CPP_SPEC
+#define CPLUSPLUS_CPP_SPEC "\
+-D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS \
+-D_GNU_SOURCE %(cpp) \
+ "
+
+#undef SUBTARGET_ASM_SPEC
+#define SUBTARGET_ASM_SPEC "\
+%{!march*: %{!miop: -mwarn-short-loop -march=r5900} %{miop: -march=r3000}} \
+%{!mips*: %{!miop: -mips3 %{!mfp*: -mfp32} %{!mgp*: -mgp64}} %{miop: -mips1 %{!mfp*: -mfp32} %{!mgp*: -mgp32}}} \
+%{!mabi*: %{!miop: -mabi=eabi}} \
+%{!mdouble-float: -msingle-float} \
+ "
+
+/*
+ * We want to include alignment directives for the r5900 to ensure that
+ * TImode values are properly aligned.  It would be best to do this in
+ * mips.h, but it's unclear if all mips assemblers can handle alignments
+ * for local common/bss objects.
+ */
+#undef ASM_OUTPUT_LOCAL
+
+/* 
+ * This says how to output an assembler line to define a global common symbol
+ * with size SIZE (in bytes) and alignment ALIGN (in bits).
+ */
+
+#undef ASM_OUTPUT_ALIGNED_COMMON
+#define ASM_OUTPUT_ALIGNED_COMMON(STREAM, NAME, SIZE, ALIGN)		\
+do									\
+{									\
+  mips_declare_object (STREAM, NAME, "\n\t.comm\t", ",%u,", (SIZE));	\
+  fprintf ((STREAM), "%d\n", ((ALIGN) / BITS_PER_UNIT));  	\
+}									\
+while (0)
+
+#define POPSECTION_ASM_OP       "\t.previous"
+#define BSS_SECTION_ASM_OP      "\t.section\t.bss"
+#define SBSS_SECTION_ASM_OP     "\t.section\t.sbss"
+#undef ASM_OUTPUT_ALIGNED_LOCAL
+#define ASM_OUTPUT_ALIGNED_LOCAL(STREAM, NAME, SIZE, ALIGN)		\
+do									\
+  {									\
+    if ((SIZE) &gt; 0 &amp;&amp; (SIZE) &lt;= mips_section_threshold)			\
+      fprintf (STREAM, "%s\n", SBSS_SECTION_ASM_OP);			\
+    else				       				\
+      fprintf (STREAM, "%s\n", BSS_SECTION_ASM_OP);			\
+    mips_declare_object (STREAM, NAME, "", ":\n", 0);		   	\
+    ASM_OUTPUT_ALIGN (STREAM, floor_log2 (ALIGN / BITS_PER_UNIT));	\
+    ASM_OUTPUT_SKIP (STREAM, SIZE);					\
+    fprintf (STREAM, "%s\n", POPSECTION_ASM_OP);			\
+  }									\
+while (0)
+
+/* 
+ * Avoid returning unaligned structures &gt; 64bits, but &lt;= 128bits wide
+ * in registers.
+ *
+ * This avoids a bad interaction between the code to return BLKmode
+ * structures in registers and the wider than word_mode registers
+ * found on the r5900.
+ *
+ * This does not effect returning an aligned 128bit value in a register,
+ * which should work.
+ */
+
+#undef RETURN_IN_MEMORY
+#define RETURN_IN_MEMORY(TYPE)						\
+  ((mips_abi == ABI_32 || mips_abi == ABI_O64)				\
+   ? TYPE_MODE (TYPE) == BLKmode					\
+   : (mips_abi == ABI_EABI &amp;&amp; TYPE_MODE (TYPE) == BLKmode		\
+      ? (int_size_in_bytes (TYPE) &gt; UNITS_PER_WORD)			\
+      : (int_size_in_bytes (TYPE)					\
+	 &gt; (mips_abi == ABI_EABI ? 2 * UNITS_PER_WORD : 16))))
+
+#define EH_FRAME_IN_DATA_SECTION 1
+
+/*
+ * This patch is ugly. But it hopefully will put an end to that
+ * 128-bits alignment madness.
+ */
+
+#undef CONSTANT_ALIGNMENT
+#define CONSTANT_ALIGNMENT(EXP, ALIGN)                                  \
+  ((TREE_CODE (EXP) == STRING_CST  || TREE_CODE (EXP) == CONSTRUCTOR)   \
+   &amp;&amp; (ALIGN) &lt; (mips_use_128 ? 128 : 64) ? (mips_use_128 ? 128 : 64) : (ALIGN))
+
+#undef DATA_ALIGNMENT
+#define DATA_ALIGNMENT(TYPE, ALIGN)                                     \
+  ((((ALIGN) &lt; (mips_use_128 ? 128 : 64))                               \
+    &amp;&amp; (TREE_CODE (TYPE) == ARRAY_TYPE                                  \
+        || TREE_CODE (TYPE) == UNION_TYPE                               \
+        || TREE_CODE (TYPE) == RECORD_TYPE)) ? (mips_use_128 ? 128 : 64) : (ALIGN))
diff -burN orig.gcc-3.2.2/gcc/config/mips/t-irx gcc-3.2.2/gcc/config/mips/t-irx
--- orig.gcc-3.2.2/gcc/config/mips/t-irx	1969-12-31 20:00:00.000000000 -0400
+++ gcc-3.2.2/gcc/config/mips/t-irx	2007-04-29 05:10:04.000000000 -0300
@@ -0,0 +1,77 @@
+CONFIG2_H	= $(srcdir)/config/mips/ecoff.h
+
+# Don't run fixproto
+STMP_FIXPROTO =
+
+# Suppress building libgcc1.a, since the MIPS compiler port is complete
+# and does not need anything from libgcc1.a.
+LIBGCC1 =
+CROSS_LIBGCC1 =
+
+# We must build libgcc2.a with -G 0, in case the user wants to link
+# without the $gp register.
+TARGET_LIBGCC2_CFLAGS = -G 0
+
+# We want fine grained libraries, so use the new code to build the
+# floating point emulation libraries.
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+	echo '#ifdef __MIPSEL__' &gt; dp-bit.c
+	echo '#define FLOAT_BIT_ORDER_MISMATCH' &gt;&gt; dp-bit.c
+	echo '#endif' &gt;&gt; dp-bit.c
+	echo '#define US_SOFTWARE_GOFAST' &gt;&gt; dp-bit.c
+	cat $(srcdir)/config/fp-bit.c &gt;&gt; dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+	echo '#define FLOAT' &gt; fp-bit.c
+	echo '#ifdef __MIPSEL__' &gt;&gt; fp-bit.c
+	echo '#define FLOAT_BIT_ORDER_MISMATCH' &gt;&gt; fp-bit.c
+	echo '#endif' &gt;&gt; fp-bit.c
+	echo '#define US_SOFTWARE_GOFAST' &gt;&gt; fp-bit.c
+	cat $(srcdir)/config/fp-bit.c &gt;&gt; fp-bit.c
+
+# Build the libraries for both hard and soft floating point
+
+MULTILIB_OPTIONS =
+MULTILIB_DIRNAMES =
+MULTILIB_MATCHES =
+
+# Library members defined in libgcc2.c.
+# LIB2FUNCS = _muldi3 _divdi3 _moddi3 _udivdi3 _umoddi3 _negdi2 \
+#     _lshrdi3 _ashldi3 _ashrdi3 _ffsdi2 \
+#    _udiv_w_sdiv _udivmoddi4 _cmpdi2 _ucmpdi2 \
+#    __gcc_bcmp _varargs __dummy
+
+
+# Add additional dependencies to recompile selected modules whenever the
+# tm.h file changes.  The files compiled are:
+#
+#	gcc.c		(*_SPEC changes)
+#	toplev.c	(new switches + assembly output changes)
+#	sdbout.c	(debug format changes)
+#	dbxout.c	(debug format changes)
+#	dwarfout.c	(debug format changes)
+#	final.c		(assembly output changes)
+#	varasm.c	(assembly output changes)
+#	cse.c		(cost functions)
+#	insn-output.c	(possible ifdef changes in tm.h)
+#	regclass.c	(fixed/call used register changes)
+#	explow.c	(GO_IF_LEGITIMATE_ADDRESS)
+#	recog.c		(GO_IF_LEGITIMATE_ADDRESS)
+#	reload.c	(GO_IF_LEGITIMATE_ADDRESS)
+
+gcc.o: $(CONFIG2_H)
+toplev.o: $(CONFIG2_H)
+sdbout.o: $(CONFIG2_H)
+dbxout.o: $(CONFIG2_H)
+dwarfout.o: $(CONFIG2_H)
+final.o: $(CONFIG2_H)
+varasm.o: $(CONFIG2_H)
+cse.o: $(CONFIG2_H)
+insn-output.o: $(CONFIG2_H)
+regclass.o: $(CONFIG2_H)
+explow.o: $(CONFIG2_H)
+recog.o: $(CONFIG2_H)
+reload.o: $(CONFIG2_H)
diff -burN orig.gcc-3.2.2/gcc/config/mips/t-r5900 gcc-3.2.2/gcc/config/mips/t-r5900
--- orig.gcc-3.2.2/gcc/config/mips/t-r5900	1969-12-31 20:00:00.000000000 -0400
+++ gcc-3.2.2/gcc/config/mips/t-r5900	2007-04-29 05:10:04.000000000 -0300
@@ -0,0 +1,56 @@
+# Suppress building libgcc1.a, since the MIPS compiler port is complete
+# and does not need anything from libgcc1.a.
+LIBGCC1 =
+CROSS_LIBGCC1 =
+
+# We must build libgcc2.a with -G 0, in case the user wants to link
+# without the $gp register.
+TARGET_LIBGCC2_CFLAGS = -G 0
+
+# We want fine grained libraries, so use the new code to build the
+# floating point emulation libraries.
+FPBIT = fp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+	echo '#define FLOAT' &gt; fp-bit.c
+	echo '#ifdef __MIPSEL__' &gt;&gt; fp-bit.c
+	echo '#define FLOAT_BIT_ORDER_MISMATCH' &gt;&gt; fp-bit.c
+	echo '#endif' &gt;&gt; fp-bit.c
+	echo '#define US_SOFTWARE_GOFAST' &gt;&gt; fp-bit.c
+	cat $(srcdir)/config/fp-bit.c &gt;&gt; fp-bit.c
+
+# To reenable the double precision emulation code uncomment the next line and
+# the 6 lines that follow it.
+DPBIT = dp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+	echo '#ifdef __MIPSEL__' &gt; dp-bit.c
+	echo '#define FLOAT_BIT_ORDER_MISMATCH' &gt;&gt; dp-bit.c
+	echo '#endif' &gt;&gt; dp-bit.c
+	echo '#define US_SOFTWARE_GOFAST' &gt;&gt; dp-bit.c
+	cat $(srcdir)/config/fp-bit.c &gt;&gt; dp-bit.c
+
+# Don't let CTOR_LIST end up in sdata section.
+CRTSTUFF_T_CFLAGS = -G 0
+
+# Assemble startup files.
+$(T)crti.o: $(srcdir)/config/mips/crti5900.asm $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	-c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/mips/crti5900.asm
+
+$(T)crtn.o: $(srcdir)/config/mips/crtn5900.asm $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	-c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/mips/crtn5900.asm
+
+MULTILIB_OPTIONS =
+MULTILIB_DIRNAMES =
+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
+
+#
+# TImode runtime support
+#
+LIBGCC_TIMODE_SRC = $(srcdir)/config/mips/libgcc2-timode.c
+TIMODE_FUNCS_LIST = _ashlti3 _ashrti3 _cmpti2 _divti3 _ffsti2 _fixdfti _fixunsdfti \
+	_floattidf _floattisf _lshrti3 _modti3 _multi3 _negti2 _ucmpti2 _udivti3 _umodti3
+
+LIB2FUNCS_TI = $(TIMODE_FUNCS_LIST)
diff -burN orig.gcc-3.2.2/gcc/config.gcc gcc-3.2.2/gcc/config.gcc
--- orig.gcc-3.2.2/gcc/config.gcc	2003-01-30 10:03:42.000000000 -0400
+++ gcc-3.2.2/gcc/config.gcc	2007-04-29 05:10:04.000000000 -0300
@@ -1553,6 +1553,10 @@
 		*minwg32msv* | *mingw32*)
 			;;
 	esac
+	if test x$pass1done = xyes &amp;&amp; test x$pass2done = x
+	then
+		host_to_target_tmake_file=i386/t-mingw32
+	fi
 	;;
 i[34567]86-*-uwin*)
 	tm_file=i386/uwin.h
@@ -2387,6 +2391,13 @@
 	esac
 	tmake_file="t-slibgcc-elf-ver t-linux mips/t-linux"
 	extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o"
+	case $machine in
+	mips*r5900*-*)			# Linux for r5900 (EE)
+		tm_file="$tm_file mips/r5900.h"
+		tmake_file="$tmake_file t-r5900"
+		extra_headers="core-mmi.h core-vumm.h"
+		;;
+	esac
 	gnu_ld=yes
 	gas=yes
 	;;
@@ -2583,6 +2594,24 @@
 		use_collect2=yes
 	fi
 	;;
+mips*r5900*-*-elf*)			# MIPS r5900 ELF, either endian
+	tm_file="dbxelf.h elfos.h mips/r5900.h"
+	tmake_file=mips/t-r5900
+	case $machine in
+	mips*el-*)
+		tm_file="mips/little.h $tm_file"
+		;;
+	esac
+	gnu_ld=yes
+	gas=yes
+	extra_headers="core-mmi.h core-vumm.h"
+	;;
+mipsel-*-irx)
+	tm_file="mips/elfl.h libgloss.h"
+	tmake_file=mips/t-irx
+	target_cpu_default="MASK_GAS|MASK_SOFT_FLOAT"
+	fixincludes=Makefile.in
+	;;
 mipsel-*-ecoff*)
 	tm_file=mips/ecoffl.h
 	if test x$stabs = xyes; then
@@ -3673,5 +3702,8 @@
 		host_extra_objs=$extra_host_objs
 		host_exeext=$exeext
 		pass2done=yes
+	else
+		tmake_file="$tmake_file $host_to_target_tmake_file"
 	fi
 fi
+
diff -burN orig.gcc-3.2.2/gcc/cp/decl.c gcc-3.2.2/gcc/cp/decl.c
--- orig.gcc-3.2.2/gcc/cp/decl.c	2003-01-21 15:00:27.000000000 -0400
+++ gcc-3.2.2/gcc/cp/decl.c	2007-04-29 05:10:05.000000000 -0300
@@ -458,6 +458,10 @@
    ? cp_function_chain-&gt;bindings		\
    : scope_chain-&gt;bindings)
 
+#define set_current_binding_level(x)							\
+   if(cfun &amp;&amp; cp_function_chain-&gt;bindings) { cp_function_chain-&gt;bindings = (x); }	\
+   else { scope_chain-&gt;bindings = (x); }
+
 /* The binding level of the current class, if any.  */
 
 #define class_binding_level scope_chain-&gt;class_bindings
@@ -507,7 +511,7 @@
      are active.  */
   memset ((char*) newlevel, 0, sizeof (struct binding_level));
   newlevel-&gt;level_chain = current_binding_level;
-  current_binding_level = newlevel;
+  set_current_binding_level(newlevel);
   newlevel-&gt;tag_transparent = tag_transparent;
   newlevel-&gt;more_cleanups_ok = 1;
 
@@ -563,7 +567,7 @@
 #endif /* defined(DEBUG_CP_BINDING_LEVELS) */
   {
     register struct binding_level *level = current_binding_level;
-    current_binding_level = current_binding_level-&gt;level_chain;
+    set_current_binding_level(current_binding_level-&gt;level_chain);
     level-&gt;level_chain = free_binding_level;
 #if 0 /* defined(DEBUG_CP_BINDING_LEVELS) */
     if (level-&gt;binding_depth != binding_depth)
@@ -578,7 +582,9 @@
 suspend_binding_level ()
 {
   if (class_binding_level)
-    current_binding_level = class_binding_level;
+  {
+    set_current_binding_level(class_binding_level);
+  }
 
   if (global_binding_level)
     {
@@ -600,7 +606,7 @@
     }
   is_class_level = 0;
 #endif /* defined(DEBUG_CP_BINDING_LEVELS) */
-  current_binding_level = current_binding_level-&gt;level_chain;
+  set_current_binding_level(current_binding_level-&gt;level_chain);
   find_class_binding_level ();
 }
 
@@ -613,7 +619,7 @@
   my_friendly_assert(!class_binding_level, 386);
   /* Also, resuming a non-directly nested namespace is a no-no.  */
   my_friendly_assert(b-&gt;level_chain == current_binding_level, 386);
-  current_binding_level = b;
+  set_current_binding_level(b);
 #if defined(DEBUG_CP_BINDING_LEVELS)
   b-&gt;binding_depth = binding_depth;
   indent ();
@@ -4291,9 +4297,9 @@
   else
     {
       b = current_binding_level;
-      current_binding_level = level;
+      set_current_binding_level(level);
       x = pushdecl (x);
-      current_binding_level = b;
+      set_current_binding_level(b);
     }
   current_function_decl = function_decl;
   return x;
@@ -6536,7 +6542,7 @@
   current_lang_name = lang_name_c;
 
   current_function_decl = NULL_TREE;
-  current_binding_level = NULL_BINDING_LEVEL;
+  set_current_binding_level(NULL_BINDING_LEVEL);
   free_binding_level = NULL_BINDING_LEVEL;
 
   build_common_tree_nodes (flag_signed_char);
@@ -10122,10 +10128,10 @@
   if (decl_context == NORMAL &amp;&amp; !toplevel_bindings_p ())
     {
       struct binding_level *b = current_binding_level;
-      current_binding_level = b-&gt;level_chain;
+      set_current_binding_level(b-&gt;level_chain);
       if (current_binding_level != 0 &amp;&amp; toplevel_bindings_p ())
 	decl_context = PARM;
-      current_binding_level = b;
+      set_current_binding_level(b);
     }
 
   if (name == NULL)
@@ -13755,7 +13761,7 @@
      FIXME factor out the non-RTL stuff.  */
   bl = current_binding_level;
   init_function_start (decl1, input_filename, lineno);
-  current_binding_level = bl;
+  set_current_binding_level(bl); 
 
   /* Even though we're inside a function body, we still don't want to
      call expand_expr to calculate the size of a variable-sized array.
diff -burN orig.gcc-3.2.2/gcc/fixinc/gnu-regex.c gcc-3.2.2/gcc/fixinc/gnu-regex.c
--- orig.gcc-3.2.2/gcc/fixinc/gnu-regex.c	2002-02-26 20:23:56.000000000 -0400
+++ gcc-3.2.2/gcc/fixinc/gnu-regex.c	2007-04-29 05:10:05.000000000 -0300
@@ -26,6 +26,9 @@
 # include &lt;config.h&gt;
 #endif
 
+/* XXX :: Should find the correct way for other platforms that have mempcpy. this is a cygwin hack! */
+#undef HAVE_MEMPCPY
+
 /* GCC LOCAL: we don't need NLS here.  */
 #undef ENABLE_NLS
 /* GCC LOCAL: to handle defining alloca.  */
diff -burN orig.gcc-3.2.2/gcc/glimits.h gcc-3.2.2/gcc/glimits.h
--- orig.gcc-3.2.2/gcc/glimits.h	2001-08-13 21:53:23.000000000 -0300
+++ gcc-3.2.2/gcc/glimits.h	2007-04-29 05:10:05.000000000 -0300
@@ -67,11 +67,11 @@
 /* Minimum and maximum values a `signed long int' can hold.
    (Same as `int').  */
 #ifndef __LONG_MAX__
-#if defined (__alpha__) || (defined (__sparc__) &amp;&amp; defined(__arch64__)) || defined (__sparcv9)
+#if defined (__alpha__) || (defined (__sparc__) &amp;&amp; defined(__arch64__)) || defined (__sparcv9) || defined (__R5900)
 #define __LONG_MAX__ 9223372036854775807L
 #else
 #define __LONG_MAX__ 2147483647L
-#endif /* __alpha__ || sparc64 */
+#endif /* __alpha__ || sparc64 || R5900 */
 #endif
 #undef LONG_MIN
 #define LONG_MIN (-LONG_MAX-1)
diff -burN orig.gcc-3.2.2/gcc/integrate.c gcc-3.2.2/gcc/integrate.c
--- orig.gcc-3.2.2/gcc/integrate.c	2003-02-03 16:56:29.000000000 -0400
+++ gcc-3.2.2/gcc/integrate.c	2007-04-29 05:12:29.000000000 -0300
@@ -358,12 +358,18 @@
   /* Copy the declaration.  */
   if (TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == RESULT_DECL)
     {
+      tree type;
+      type = TREE_TYPE(decl);
+
       /* For a parameter, we must make an equivalent VAR_DECL, not a
 	 new PARM_DECL.  */
       copy = build_decl (VAR_DECL, DECL_NAME (decl), TREE_TYPE (decl));
       TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
       TREE_READONLY (copy) = TREE_READONLY (decl);
       TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
+
+      if (TYPE_RESTRICT(type))
+        DECL_POINTER_ALIAS_SET (copy) = -2;
     }
   else
     {
diff -burN orig.gcc-3.2.2/gcc/libgcc2-timode.c gcc-3.2.2/gcc/libgcc2-timode.c
--- orig.gcc-3.2.2/gcc/libgcc2-timode.c	1969-12-31 20:00:00.000000000 -0400
+++ gcc-3.2.2/gcc/libgcc2-timode.c	2007-04-29 05:10:05.000000000 -0300
@@ -0,0 +1,792 @@
+/* GCC rutime support routines for TI mode */
+
+/* Copyright (C) 2001  Sony Computer Entertainment Inc. 
+   Copyright 2001  Sony Corportaion.  */
+
+/* This file is derived from libgcc2.c and subject to the original 
+   license of libgcc2.c, as follows. */
+
+/* Compile this one with gcc.  */
+/* Copyright (C) 1989, 92-98, 1999 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.  */
+
+/* As a special exception, if you link this library with other files,
+   some of which are compiled with GCC, to produce an executable,
+   this library does not by itself cause the resulting executable
+   to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+
+#include "tconfig.h"
+
+/* We disable this when inhibit_libc, so that gcc can still be built without
+   needing header files first.  */
+/* ??? This is not a good solution, since prototypes may be required in
+   some cases for correct code.  See also frame.c.  */
+
+#include "machmode.h"
+#include "defaults.h"
+
+#ifndef LIBGCC2_WORDS_BIG_ENDIAN
+#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
+#endif
+
+
+/* In this file, we are interfacing to calls generated by the compiler 
+   itself.  These calls pass values into these routines which have very 
+   specific modes (rather than very specific types), and these 
+   compiler-generated calls also expect any return values to have very 
+   specific modes (rather than very specific types).  Thus, we need to 
+   avoid using regular C language type names in this part of the file
+   because the sizes for those types can be configured to be anything.
+   Instead we use the following special type names.  */
+
+typedef unsigned int UTItype __attribute__((mode(TI)));
+typedef          int  TItype __attribute__((mode(TI)));
+typedef unsigned int UDItype __attribute__((mode(DI)));
+typedef          int  DItype __attribute__((mode(DI)));
+typedef unsigned int UQItype __attribute__((mode(QI)));
+typedef          int  QItype __attribute__((mode(QI)));
+
+typedef		float SFtype	__attribute__ ((mode (SF)));
+typedef		float DFtype	__attribute__ ((mode (DF)));
+
+typedef int word_type __attribute__ ((mode (__word__)));
+
+/* Make sure that we don't accidentally use any normal C language 
+   built-in type names in the first part of this file.  Instead we want 
+   to use *only* the type names defined above.  
+   The following macro definitions insure that if we *do* accidentally 
+   use some normal C language built-in type name, we will get a syntax 
+   error.  */
+
+#define char bogus_type
+#define short bogus_type
+#define int bogus_type
+#define long bogus_type
+#define unsigned bogus_type
+#define float bogus_type
+#define double bogus_type
+
+
+#ifndef BITS_PER_UNIT
+#define BITS_PER_UNIT 8
+#endif
+#ifndef DI_TYPE_SIZE
+#define DI_TYPE_SIZE 64
+#endif
+
+
+/* TIstructs are pairs of DItype values in the order determined by
+   LIBGCC2_WORDS_BIG_ENDIAN.  */
+
+#if LIBGCC2_WORDS_BIG_ENDIAN
+struct TIstruct {DItype high, low;};
+#else
+struct TIstruct {DItype low, high;};
+#endif
+
+/* We need this union to unpack/pack TImode values, since we don't have
+   any arithmetic yet.  Incoming TImode parameters are stored into the
+   `ti' field, and the unpacked result is read from the struct `d'.  */
+
+typedef union
+{
+  struct TIstruct d;
+  TItype ti;
+} TIunion;
+
+/*  for  
+	__fixunsdfti
+	 __floattidf
+ */ 
+#define DI_WORD_SIZE (sizeof (DItype) * BITS_PER_UNIT)
+#define HIGH_DI_WORD_COEFF (((UTItype) 1) &lt;&lt; DI_WORD_SIZE)
+#define HIGH_DI_HALFWORD_COEFF (((UDItype) 1) &lt;&lt; (DI_WORD_SIZE / 2))
+
+
+
+#if (defined (L_udivti3) || defined (L_divti3) || defined (L_multi3) ||\
+     defined (L_umodti3) || defined (L_modti3))
+/* ----------------------------------------------------------------- */
+/* BEGIN: derived from longlog.h */
+/* for  
+	__udivmoddi4
+	__multi3
+	__dviti3
+	__udviti3
+	__modti3
+	__umodti3
+*/
+
+#define __ti_B (((UDItype)1) &lt;&lt; (DI_TYPE_SIZE / 2))
+#define __ti_lowpart(t) ((UDItype) (t) % __ti_B)
+#define __ti_highpart(t) ((UDItype) (t) / __ti_B)
+
+#define umul_ppmm_di(w1, w0, u, v) 					\
+do {									\
+    UDItype __x0, __x1, __x2, __x3;					\
+    UDItype __ul, __vl, __uh, __vh;					\
+									\
+    __ul = __ti_lowpart (u);						\
+    __uh = __ti_highpart (u);						\
+    __vl = __ti_lowpart (v);						\
+    __vh = __ti_highpart (v);						\
+									\
+    __x0 = (UDItype) __ul * __vl;					\
+    __x1 = (UDItype) __ul * __vh;					\
+    __x2 = (UDItype) __uh * __vl;					\
+    __x3 = (UDItype) __uh * __vh;					\
+									\
+    __x1 += __ti_highpart (__x0);/* this can't give carry */		\
+    __x1 += __x2;               /* but this indeed can */		\
+    if (__x1 &lt; __x2)            /* did we get it? */			\
+      __x3 += __ti_B;           /* yes, add it in the proper pos. */	\
+									\
+    (w1) = __x3 + __ti_highpart (__x1);					\
+    (w0) = __ti_lowpart (__x1) * __ti_B + __ti_lowpart (__x0);		\
+} while (0)
+
+#define __umulditi3(u, v) \
+  ({TIunion __w;                                                        \
+    umul_ppmm_di (__w.d.high, __w.d.low, u, v);                            \
+    __w.ti; })
+
+
+
+/* Define this unconditionally, so it can be used for debugging.  */
+#define udiv_qrnnd_c_di(q, r, n1, n0, d) \
+  do {                                                                  \
+    UDItype __d1, __d0, __q1, __q0;                                     \
+    UDItype __r1, __r0, __m;                                            \
+    __d1 = __ti_highpart (d);                                           \
+    __d0 = __ti_lowpart (d);                                            \
+                                                                        \
+    __r1 = (n1) % __d1;                                                 \
+    __q1 = (n1) / __d1;                                                 \
+    __m = (UDItype) __q1 * __d0;                                        \
+    __r1 = __r1 * __ti_B | __ti_highpart (n0);                          \
+    if (__r1 &lt; __m)                                                     \
+      {                                                                 \
+        __q1--, __r1 += (d);                                            \
+        if (__r1 &gt;= (d)) /* i.e. we didn't get carry when adding to __r1 */\
+          if (__r1 &lt; __m)                                               \
+            __q1--, __r1 += (d);                                        \
+      }                                                                 \
+    __r1 -= __m;                                                        \
+                                                                        \
+    __r0 = __r1 % __d1;                                                 \
+    __q0 = __r1 / __d1;                                                 \
+    __m = (UDItype) __q0 * __d0;                                        \
+    __r0 = __r0 * __ti_B | __ti_lowpart (n0);                           \
+    if (__r0 &lt; __m)                                                     \
+      {                                                                 \
+        __q0--, __r0 += (d);                                            \
+        if (__r0 &gt;= (d))                                                \
+          if (__r0 &lt; __m)                                               \
+            __q0--, __r0 += (d);                                        \
+      }                                                                 \
+    __r0 -= __m;                                                        \
+                                                                        \
+    (q) = (UDItype) __q1 * __ti_B | __q0;                               \
+    (r) = __r0;                                                         \
+  } while (0)
+
+
+#define sub_ddmmss_di(sh, sl, ah, al, bh, bl) \
+  do {                                                                  \
+    UDItype __x;                                                        \
+    __x = (al) - (bl);                                                  \
+    (sh) = (ah) - (bh) - (__x &gt; (al));                                  \
+    (sl) = __x;                                                         \
+  } while (0)
+
+#define count_leading_zeros_di(count, x) \
+  do {                                                                  \
+    UDItype __xr = (x);                                                 \
+    UDItype __a;                                                        \
+                                                                        \
+      {                                                                 \
+        for (__a = DI_TYPE_SIZE - 8; __a &gt; 0; __a -= 8)                 \
+          if (((__xr &gt;&gt; __a) &amp; 0xff) != 0)                              \
+            break;                                                      \
+      }                                                                 \
+                                                                        \
+    (count) = DI_TYPE_SIZE - (__clz_tab[__xr &gt;&gt; __a] + __a);            \
+  } while (0)
+
+
+
+/* END: derived from longlog.h */
+/* ----------------------------------------------------------------- */
+#endif /* (defined (L_udivti3) || defined (L_divti3) || defined (L_multi3) ||
+           defined (L_umodti3) || defined (L_modti3)) */
+
+
+#if defined (L_negti2) || defined (L_divti3) || defined (L_modti3)
+#if defined (L_divti3) || defined (L_modti3)
+static inline
+#endif
+TItype
+__negti2 (TItype u)
+{
+  TIunion w;
+  TIunion uu;
+
+  uu.ti = u;
+
+  w.d.low = -uu.d.low;
+  w.d.high = -uu.d.high - ((UDItype) w.d.low &gt; 0);
+
+  return w.ti;
+}
+#endif
+
+/* Unless shift functions are defined whith full ANSI prototypes,
+   parameter b will be promoted to int if word_type is smaller than an int.  */
+#ifdef L_lshrti3
+TItype
+__lshrti3 (TItype u, word_type b)
+{
+  TIunion w;
+  word_type bm;
+  TIunion uu;
+
+  if (b == 0)
+    return u;
+
+  uu.ti = u;
+
+  bm = (sizeof (DItype) * BITS_PER_UNIT) - b;
+  if (bm &lt;= 0)
+    {
+      w.d.high = 0;
+      w.d.low = (UDItype)uu.d.high &gt;&gt; -bm;
+    }
+  else
+    {
+      UDItype carries = (UDItype)uu.d.high &lt;&lt; bm;
+      w.d.high = (UDItype)uu.d.high &gt;&gt; b;
+      w.d.low = ((UDItype)uu.d.low &gt;&gt; b) | carries;
+    }
+
+  return w.ti;
+}
+#endif
+
+#ifdef L_ashlti3
+TItype
+__ashlti3 (TItype u, word_type b)
+{
+  TIunion w;
+  word_type bm;
+  TIunion uu;
+
+  if (b == 0)
+    return u;
+
+  uu.ti = u;
+
+  bm = (sizeof (DItype) * BITS_PER_UNIT) - b;
+  if (bm &lt;= 0)
+    {
+      w.d.low = 0;
+      w.d.high = (UDItype)uu.d.low &lt;&lt; -bm;
+    }
+  else
+    {
+      UDItype carries = (UDItype)uu.d.low &gt;&gt; bm;
+      w.d.low = (UDItype)uu.d.low &lt;&lt; b;
+      w.d.high = ((UDItype)uu.d.high &lt;&lt; b) | carries;
+    }
+
+  return w.ti;
+}
+#endif
+
+#ifdef L_ashrti3
+TItype
+__ashrti3 (TItype u, word_type b)
+{
+  TIunion w;
+  word_type bm;
+  TIunion uu;
+
+  if (b == 0)
+    return u;
+
+  uu.ti = u;
+
+  bm = (sizeof (DItype) * BITS_PER_UNIT) - b;
+  if (bm &lt;= 0)
+    {
+      /* w.d.high = 1..1 or 0..0 */
+      w.d.high = uu.d.high &gt;&gt; (sizeof (DItype) * BITS_PER_UNIT - 1);
+      w.d.low = uu.d.high &gt;&gt; -bm;
+    }
+  else
+    {
+      UDItype carries = (UDItype)uu.d.high &lt;&lt; bm;
+      w.d.high = uu.d.high &gt;&gt; b;
+      w.d.low = ((UDItype)uu.d.low &gt;&gt; b) | carries;
+    }
+
+  return w.ti;
+}
+#endif
+
+#ifdef L_ffsti2
+TItype
+__ffsti2 (TItype u)
+{
+  TIunion uu, w;
+  uu.ti = u;
+  w.d.high = 0;
+  w.d.low = __ffsdi2 (uu.d.low);
+  if (w.d.low != 0)
+    return w.ti;
+  w.d.low = __ffsdi2 (uu.d.high);
+  if (w.d.low != 0)
+    {
+      w.d.low += BITS_PER_UNIT * sizeof (DItype);
+      return w.ti;
+    }
+  return w.ti;
+}
+#endif
+
+
+#ifdef L_multi3
+TItype
+__multi3 (TItype u, TItype v)
+{
+  TIunion w;
+  TIunion uu, vv;
+
+  uu.ti = u,
+  vv.ti= v;
+
+  w.ti = __umulditi3 (uu.d.low, vv.d.low);
+  w.d.high += ((UDItype) uu.d.low * (UDItype) vv.d.high
+	       + (UDItype) uu.d.high * (UDItype) vv.d.low);
+
+  return w.ti;
+}
+#endif
+
+#if (defined (L_udivti3) || defined (L_divti3) || \
+     defined (L_umodti3) || defined (L_modti3))
+#define L_udivmodti4
+#endif
+
+#ifdef L_udivmodti4
+static const UQItype __clz_tab[] =
+{
+  0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+};
+
+#if (defined (L_udivti3) || defined (L_divti3) || \
+     defined (L_umodti3) || defined (L_modti3))
+static inline
+#endif
+UTItype
+__udivmodti4 (UTItype n, UTItype d, UTItype *rp)
+{
+  TIunion ww;
+  TIunion nn, dd;
+  TIunion rr;
+  UDItype d0, d1, n0, n1, n2;
+  UDItype q0, q1;
+  UDItype b, bm;
+
+  nn.ti = n;
+  dd.ti = d;
+
+  d0 = dd.d.low;
+  d1 = dd.d.high;
+  n0 = nn.d.low;
+  n1 = nn.d.high;
+
+
+  if (d1 == 0)
+    {
+      if (d0 &gt; n1)
+	{
+	  /* 0q = nn / 0D */
+
+	  count_leading_zeros_di (bm, d0);
+
+	  if (bm != 0)
+	    {
+	      /* Normalize, i.e. make the most significant bit of the
+		 denominator set.  */
+
+	      d0 = d0 &lt;&lt; bm;
+	      n1 = (n1 &lt;&lt; bm) | (n0 &gt;&gt; (DI_TYPE_SIZE - bm));
+	      n0 = n0 &lt;&lt; bm;
+	    }
+
+	  udiv_qrnnd_c_di (q0, n0, n1, n0, d0);
+	  q1 = 0;
+
+	  /* Remainder in n0 &gt;&gt; bm.  */
+	}
+      else
+	{
+	  /* qq = NN / 0d */
+
+	  if (d0 == 0)
+	    d0 = 1 / d0;	/* Divide intentionally by zero.  */
+
+	  count_leading_zeros_di (bm, d0);
+
+	  if (bm == 0)
+	    {
+	      /* From (n1 &gt;= d0) /\ (the most significant bit of d0 is set),
+		 conclude (the most significant bit of n1 is set) /\ (the
+		 leading quotient digit q1 = 1).
+
+		 This special case is necessary, not an optimization.
+		 (Shifts counts of DI_TYPE_SIZE are undefined.)  */
+
+	      n1 -= d0;
+	      q1 = 1;
+	    }
+	  else
+	    {
+	      /* Normalize.  */
+
+	      b = DI_TYPE_SIZE - bm;
+
+	      d0 = d0 &lt;&lt; bm;
+	      n2 = n1 &gt;&gt; b;
+	      n1 = (n1 &lt;&lt; bm) | (n0 &gt;&gt; b);
+	      n0 = n0 &lt;&lt; bm;
+
+	      udiv_qrnnd_c_di (q1, n1, n2, n1, d0);
+	    }
+
+	  /* n1 != d0...  */
+
+	  udiv_qrnnd_c_di (q0, n0, n1, n0, d0);
+
+	  /* Remainder in n0 &gt;&gt; bm.  */
+	}
+
+      if (rp != 0)
+	{
+	  rr.d.low = n0 &gt;&gt; bm;
+	  rr.d.high = 0;
+	  *rp = rr.ti;
+	}
+    }
+  else
+    {
+      if (d1 &gt; n1)
+	{
+	  /* 00 = nn / DD */
+
+	  q0 = 0;
+	  q1 = 0;
+
+	  /* Remainder in n1n0.  */
+	  if (rp != 0)
+	    {
+	      rr.d.low = n0;
+	      rr.d.high = n1;
+	      *rp = rr.ti;
+	    }
+	}
+      else
+	{
+	  /* 0q = NN / dd */
+
+	  count_leading_zeros_di (bm, d1);
+	  if (bm == 0)
+	    {
+	      /* From (n1 &gt;= d1) /\ (the most significant bit of d1 is set),
+		 conclude (the most significant bit of n1 is set) /\ (the
+		 quotient digit q0 = 0 or 1).
+
+		 This special case is necessary, not an optimization.  */
+
+	      /* The condition on the next line takes advantage of that
+		 n1 &gt;= d1 (true due to program flow).  */
+	      if (n1 &gt; d1 || n0 &gt;= d0)
+		{
+		  q0 = 1;
+		  sub_ddmmss_di (n1, n0, n1, n0, d1, d0);
+		}
+	      else
+		q0 = 0;
+
+	      q1 = 0;
+
+	      if (rp != 0)
+		{
+		  rr.d.low = n0;
+		  rr.d.high = n1;
+		  *rp = rr.ti;
+		}
+	    }
+	  else
+	    {
+	      UDItype m1, m0;
+	      /* Normalize.  */
+
+	      b = DI_TYPE_SIZE - bm;
+
+	      d1 = (d1 &lt;&lt; bm) | (d0 &gt;&gt; b);
+	      d0 = d0 &lt;&lt; bm;
+	      n2 = n1 &gt;&gt; b;
+	      n1 = (n1 &lt;&lt; bm) | (n0 &gt;&gt; b);
+	      n0 = n0 &lt;&lt; bm;
+
+	      udiv_qrnnd_c_di (q0, n1, n2, n1, d1);
+	      umul_ppmm_di (m1, m0, q0, d0);
+
+	      if (m1 &gt; n1 || (m1 == n1 &amp;&amp; m0 &gt; n0))
+		{
+		  q0--;
+		  sub_ddmmss_di (m1, m0, m1, m0, d1, d0);
+		}
+
+	      q1 = 0;
+
+	      /* Remainder in (n1n0 - m1m0) &gt;&gt; bm.  */
+	      if (rp != 0)
+		{
+		  sub_ddmmss_di (n1, n0, n1, n0, m1, m0);
+		  rr.d.low = (n1 &lt;&lt; b) | (n0 &gt;&gt; bm);
+		  rr.d.high = n1 &gt;&gt; bm;
+		  *rp = rr.ti;
+		}
+	    }
+	}
+    }
+
+  ww.d.low = q0;
+  ww.d.high = q1;
+  return ww.ti;
+}
+#endif
+
+#ifdef L_divti3
+UTItype __udivmodti4 ();
+
+TItype
+__divti3 (TItype u, TItype v)
+{
+  word_type c = 0;
+  TIunion uu, vv;
+  TItype w;
+
+  uu.ti = u;
+  vv.ti = v;
+
+  if (uu.d.high &lt; 0)
+    c = ~c,
+    uu.ti = __negti2 (uu.ti);
+  if (vv.d.high &lt; 0)
+    c = ~c,
+    vv.ti = __negti2 (vv.ti);
+
+  w = __udivmodti4 (uu.ti, vv.ti, (UTItype *) 0);
+  if (c)
+    w = __negti2 (w);
+
+  return w;
+}
+#endif
+
+#ifdef L_modti3
+UTItype __udivmodti4 ();
+
+TItype
+__modti3 (TItype u, TItype v)
+{
+  word_type c = 0;
+  TIunion uu, vv;
+  TItype w;
+
+  uu.ti = u;
+  vv.ti = v;
+
+  if (uu.d.high &lt; 0)
+    c = ~c,
+    uu.ti = __negti2 (uu.ti);
+  if (vv.d.high &lt; 0)
+    vv.ti = __negti2 (vv.ti);
+
+  (void) __udivmodti4 (uu.ti, vv.ti, (UTItype *)&amp;w);
+  if (c)
+    w = __negti2 (w);
+
+  return w;
+}
+#endif
+
+#ifdef L_umodti3
+UTItype __udivmodti4 ();
+
+UTItype
+__umodti3 (UTItype u, UTItype v)
+{
+  UTItype w;
+
+  (void) __udivmodti4 (u, v, &amp;w);
+
+  return w;
+}
+#endif
+
+
+#ifdef L_udivti3
+UTItype __udivmodti4 ();
+UTItype
+__udivti3 (UTItype n, UTItype d)
+{
+  return __udivmodti4 (n, d, (UTItype *) 0);
+}
+#endif
+
+#ifdef L_cmpti2
+word_type
+__cmpti2 (TItype a, TItype b)
+{
+  TIunion au, bu;
+
+  au.ti = a, bu.ti = b;
+
+  if (au.d.high &lt; bu.d.high)
+    return 0;
+  else if (au.d.high &gt; bu.d.high)
+    return 2;
+  if ((UDItype) au.d.low &lt; (UDItype) bu.d.low)
+    return 0;
+  else if ((UDItype) au.d.low &gt; (UDItype) bu.d.low)
+    return 2;
+  return 1;
+}
+#endif
+
+#ifdef L_ucmpti2
+word_type
+__ucmpti2 (UTItype a, UTItype b)
+{
+  TIunion au, bu;
+
+  au.ti = a, bu.ti = b;
+
+  if ((UDItype) au.d.high &lt; (UDItype) bu.d.high)
+    return 0;
+  else if ((UDItype) au.d.high &gt; (UDItype) bu.d.high)
+    return 2;
+  if ((UDItype) au.d.low &lt; (UDItype) bu.d.low)
+    return 0;
+  else if ((UDItype) au.d.low &gt; (UDItype) bu.d.low)
+    return 2;
+  return 1;
+}
+#endif
+
+
+/*
+  Followings are not neeeded, because TF or XF mode is not supported. 
+   __fixunstfti(), __fixtfdi()
+   __fixunsxfti(), __fixxfti()
+*/
+
+#ifdef L_fixunsdfti
+TItype
+__fixunsdfti (DFtype a)
+{
+  DFtype b;
+  UTItype v;
+
+  if (a &lt; 0)
+    return 0;
+
+  /* Compute high word of result, as a flonum.  */
+  b = (a / HIGH_DI_WORD_COEFF);
+  /* Convert that to fixed (but not to DItype!),
+     and shift it into the high word.  */
+  v = (UDItype) b;
+  v &lt;&lt;= DI_WORD_SIZE;
+  /* Remove high part from the DFtype, leaving the low part as flonum.  */
+  a -= (DFtype)v;
+  /* Convert that to fixed (but not to DItype!) and add it in.
+     Sometimes A comes out negative.  This is significant, since
+     A has more bits than a long int does.  */
+  if (a &lt; 0)
+    v -= (UDItype) (- a);
+  else
+    v += (UDItype) a;
+  return v;
+}
+#endif
+
+#ifdef L_fixdfti
+TItype
+__fixdfti (DFtype a)
+{
+  if (a &lt; 0)
+    return - __fixunsdfti (-a);
+  return __fixunsdfti (a);
+}
+#endif
+
+/*
+  Followings are not neeeded, because TF or XF mode is not supported. 
+	__floattixf
+	__floattitf
+*/
+
+#ifdef L_floattidf
+DFtype
+__floattidf (TItype u)
+{
+  DFtype d;
+
+  d = (DItype) (u &gt;&gt; DI_WORD_SIZE);
+  d *= HIGH_DI_HALFWORD_COEFF;
+  d *= HIGH_DI_HALFWORD_COEFF;
+  d += (UDItype) (u &amp; (HIGH_DI_WORD_COEFF - 1));
+
+  return d;
+}
+#endif
+
+#ifdef L_floattisf
+SFtype
+__floattisf (TItype u)
+{
+  DFtype df;
+  df = __floattidf (u);
+  return (SFtype) df;
+}
+#endif
diff -burN orig.gcc-3.2.2/gcc/Makefile.in gcc-3.2.2/gcc/Makefile.in
--- orig.gcc-3.2.2/gcc/Makefile.in	2003-01-28 17:54:07.000000000 -0400
+++ gcc-3.2.2/gcc/Makefile.in	2007-04-29 05:10:05.000000000 -0300
@@ -987,6 +987,7 @@
 	LIB2FUNCS_ST='$(LIB2FUNCS_ST)' \
 	LIB2ADD='$(LIB2ADD)' \
 	LIB2ADD_ST='$(LIB2ADD_ST)' \
+	LIB2FUNCS_TI='$(LIB2FUNCS_TI)' \
 	LIB2ADDEH='$(LIB2ADDEH)' \
 	LIB2ADDEHDEP='$(LIB2ADDEHDEP)' \
 	FPBIT='$(FPBIT)' \
diff -burN orig.gcc-3.2.2/gcc/mklibgcc.in gcc-3.2.2/gcc/mklibgcc.in
--- orig.gcc-3.2.2/gcc/mklibgcc.in	2003-01-28 17:57:40.000000000 -0400
+++ gcc-3.2.2/gcc/mklibgcc.in	2007-04-29 05:10:05.000000000 -0300
@@ -232,6 +232,21 @@
   libgcc2_st_objs="$libgcc2_st_objs ${oname}${objext}"
 done
 
+if [ "$LIB2FUNCS_TI" ]; then
+  for name in $LIB2FUNCS_TI; do
+    for ml in $MULTILIBS; do
+      dir=`echo ${ml} | sed -e 's/;.*$//' -e 's/=/$(EQ)/g'`
+      flags=`echo ${ml} | sed -e 's/^[^;]*;//' -e 's/@/ -/g'`;
+      out="libgcc/${dir}/${name}${objext}"
+  
+      echo $out: $libgcc2_c_dep
+      echo "	$gcc_compile" '$(MAYBE_USE_COLLECT2)' $flags -DL$name \
+        -c '$(srcdir)/libgcc2-timode.c' -o $out
+    done
+    libgcc2_objs="$libgcc2_objs ${name}${objext}"
+  done
+fi
+
 # SHLIB_MKMAP
 # SHLIB_MKMAP_OPTS
 # SHLIB_MAPFILES
diff -burN orig.gcc-3.2.2/gcc/toplev.c gcc-3.2.2/gcc/toplev.c
--- orig.gcc-3.2.2/gcc/toplev.c	2002-11-01 20:57:23.000000000 -0400
+++ gcc-3.2.2/gcc/toplev.c	2007-04-29 05:10:05.000000000 -0300
@@ -3469,6 +3469,18 @@
 
   convert_to_eh_region_ranges ();
 
+#ifdef MACHINE_DEPENDENT_REORG_FINAL
+  timevar_push (TV_MACH_DEP);
+  open_dump_file (DFI_mach, decl);
+
+  MACHINE_DEPENDENT_REORG_FINAL (insns);
+
+  close_dump_file (DFI_mach, print_rtl, insns);
+  timevar_pop (TV_MACH_DEP);
+
+  ggc_collect ();
+#endif
+
   /* Shorten branches.  */
   timevar_push (TV_SHORTEN_BRANCH);
   shorten_branches (get_insns ());
diff -burN orig.gcc-3.2.2/include/obstack.h gcc-3.2.2/include/obstack.h
--- orig.gcc-3.2.2/include/obstack.h	2001-03-14 15:44:38.000000000 -0400
+++ gcc-3.2.2/include/obstack.h	2007-04-29 05:10:05.000000000 -0300
@@ -423,7 +423,8 @@
 ({ struct obstack *__o = (OBSTACK);					\
    if (__o-&gt;next_free + sizeof (void *) &gt; __o-&gt;chunk_limit)		\
      _obstack_newchunk (__o, sizeof (void *));				\
-   *((void **)__o-&gt;next_free)++ = ((void *)datum);			\
+   *((void **)__o-&gt;next_free) = ((void *)datum);			\
+   __o-&gt;next_free += sizeof(void *);					\
    (void) 0; })
 
 # define obstack_int_grow(OBSTACK,datum)				\
diff -burN orig.gcc-3.2.2/libstdc++-v3/configure.target gcc-3.2.2/libstdc++-v3/configure.target
--- orig.gcc-3.2.2/libstdc++-v3/configure.target	2002-09-06 15:32:08.000000000 -0300
+++ gcc-3.2.2/libstdc++-v3/configure.target	2007-04-29 05:10:05.000000000 -0300
@@ -55,6 +55,9 @@
   m68k | m680[246]0)
     cpu_include_dir="config/cpu/m68k"
     ;;
+  mips)
+    cpu_include_dir="config/cpu/mips"
+    ;;
   powerpc | rs6000)
     cpu_include_dir="config/cpu/powerpc"
     ;;
diff -burN orig.gcc-3.2.2/libstdc++-v3/libsupc++/pure.cc gcc-3.2.2/libstdc++-v3/libsupc++/pure.cc
--- orig.gcc-3.2.2/libstdc++-v3/libsupc++/pure.cc	2002-06-28 05:22:38.000000000 -0300
+++ gcc-3.2.2/libstdc++-v3/libsupc++/pure.cc	2007-04-29 05:10:05.000000000 -0300
@@ -46,6 +46,6 @@
 extern "C" void
 __cxa_pure_virtual (void)
 {
-  writestr ("pure virtual method called\n");
+//  writestr ("pure virtual method called\n");
   std::terminate ();
 }
diff -burN orig.gcc-3.2.2/README.PS2 gcc-3.2.2/README.PS2
--- orig.gcc-3.2.2/README.PS2	1969-12-31 20:00:00.000000000 -0400
+++ gcc-3.2.2/README.PS2	2007-04-29 05:10:05.000000000 -0300
@@ -0,0 +1,80 @@
+Apologies to mrbrown, who's README.PS2 this was based on.
+GCC for Sony Playstation 2
+http://www.ps2dev.org/
+BETA 3 Release 3.2.2-20040214-1
+==
+
+This patch contains a port of the GNU Compiler Collection (http://gcc.gnu.org)
+version 3.2.2 (prerelease) to the Sony Playstation 2.  It supports a C and C++
+cross-compiler targeting the Emotion Engine (Toshiba MIPS R5900).  It is based
+off of the port that Cygnus (now Red Hat) created for the original PS2 SDK,
+and contains a number of changes and updates that mrbrown has incorporated,
+plus some fixes by me.
+
+Unfortunately, there is no ChangeLog in this release.
+
+The Playstation 2 Linux kit is NOT supported in this release.  There are a
+number of issues related to the deployment of this version of GCC in that
+environment.  This is left as an exercise for the ps2linux folks.
+
+You can grab the source to the GCC 3.2.2 release from
+ftp://ftp.gnu.org/pub/gnu/gcc/gcc-3.2.2.tar.gz or a mirror site.
+
+
+Features
+--
+
+- Basic support for the R5900 and COP1.
+- Initial support for 128-bit logical/arith operations (pand, pnor, etc.).
+- Initial support for MMI built-in functions (__builtin_paddb, etc.) and vector
+  types.
+- The main "feature" of this release is the port to the 3.2.2 compiler and fixes
+  to the HILO1 code, allowing re-enabling of double precision emulation and also
+  C++ global constructor fixes.  This release may fix the 64bit shift bug, but
+  if that's the case then it's a side effect of another fix. 
+- Used in conjunction with my binutils-2.13.2.1 patch, you should be able to use
+  -O0 and -O1 without causing bad code generation.
+- Alignment in bss sections bug fix.
+
+To configure the compiler, you can use one of the following configuration
+names:
+
+        ee, mips64r5900[el], mipsEE[el]
+
+If you don't specify the OS portion of the name, -elf is assumed.  Note that
+even if you leave off the "el", you cannot build for big-endian R5900 (it's
+explicitly disabled).  I always use "ee".
+
+
+Known Bugs
+--
+
+[ I haven't found any serious codegen bugs yet. Mail to the ps2dev forums if
+  you find any. ]
+
+  If you wish to disable double precision emulation, comment out the text around
+  DPBIT (and the make target that follows it) in gcc/config/mips/t-r5900. If you
+  comment this section out and use double precision FP in your code, you WILL
+  receive link errors when linking with libgcc.  You can use this "feature" as a
+  tool to find all misuses of float constants and type conversions in your code.
+  Personally, I had trouble getting libstdc++-v3 to build without double precision
+  emulation but YMMV.  It should be possible to configure the compiler and libs
+  to use single precision doubles in place of doubles, however you'd have to make
+  sure that all your libs are built in this manner.
+
+
+Future Work
+--
+
+  Move over to gcc 3.4, once it's released. gcc 3.4 includes a re-write of the
+  entire mips back end and it looks a lot cleaner.
+
+
+Contact
+--
+
+  Use the forums at www.ps2dev.org or find me on IRC at #ps2dev on EFnet.
+
+--
+MrHTFord (mrhtford_ps2dev@hotmail.com)
+Friday 14th February 2004.
</pre></body></html>