diff -Naur gcc-4.1.2.orig/config.guess gcc-4.1.2-src/config.guess
--- gcc-4.1.2.orig/config.guess	2005-11-24 13:49:42.000000000 +0100
+++ gcc-4.1.2-src/config.guess	2007-02-19 02:32:34.000000000 +0100
@@ -770,11 +770,11 @@
 	echo ${UNAME_MACHINE}-pc-cygwin
 	exit ;;
     i*:MINGW*:*)
-	echo ${UNAME_MACHINE}-pc-mingw32
+	echo i386-pc-mingw32
 	exit ;;
     i*:windows32*:*)
     	# uname -m includes "-pc" on this system.
-    	echo ${UNAME_MACHINE}-mingw32
+    	echo i386-pc-mingw32
 	exit ;;
     i*:PW*:*)
 	echo ${UNAME_MACHINE}-pc-pw32
diff -Naur gcc-4.1.2.orig/gcc/attribs.c gcc-4.1.2-src/gcc/attribs.c
--- gcc-4.1.2.orig/gcc/attribs.c	2005-06-25 04:02:01.000000000 +0200
+++ gcc-4.1.2-src/gcc/attribs.c	2007-02-19 02:32:34.000000000 +0100
@@ -131,7 +131,11 @@
    information, in the form of a bitwise OR of flags in enum attribute_flags
    from tree.h.  Depending on these flags, some attributes may be
    returned to be applied at a later stage (for example, to apply
-   a decl attribute to the declaration rather than to its type).  */
+   a decl attribute to the declaration rather than to its type).  If
+   ATTR_FLAG_BUILT_IN is not set and *NODE is a DECL, then also consider
+   whether there might be some default attributes to apply to this DECL;
+   if so, decl_attributes will be called recursively with those attributes
+   and ATTR_FLAG_BUILT_IN set.  */
 
 tree
 decl_attributes (tree *node, tree attributes, int flags)
@@ -144,6 +148,10 @@
 
   targetm.insert_attributes (*node, &attributes);
 
+  if (DECL_P (*node) && TREE_CODE (*node) == FUNCTION_DECL
+      && !(flags & (int) ATTR_FLAG_BUILT_IN))
+    (*lang_hooks.insert_default_attributes) (*node);
+
   for (a = attributes; a; a = TREE_CHAIN (a))
     {
       tree name = TREE_PURPOSE (a);
diff -Naur gcc-4.1.2.orig/gcc/builtin-attrs.def gcc-4.1.2-src/gcc/builtin-attrs.def
--- gcc-4.1.2.orig/gcc/builtin-attrs.def	2005-06-27 14:17:39.000000000 +0200
+++ gcc-4.1.2-src/gcc/builtin-attrs.def	2007-02-19 02:32:34.000000000 +0100
@@ -169,6 +169,10 @@
 DEF_FORMAT_ATTRIBUTE(SCANF,1,1_2)
 DEF_FORMAT_ATTRIBUTE(SCANF,2,2_0)
 DEF_FORMAT_ATTRIBUTE(SCANF,2,2_3)
+DEF_FORMAT_ATTRIBUTE(SCANF,3,3_0)
+DEF_FORMAT_ATTRIBUTE(SCANF,3,3_4)
+DEF_FORMAT_ATTRIBUTE(SCANF,4,4_0)
+DEF_FORMAT_ATTRIBUTE(SCANF,4,4_5)
 DEF_FORMAT_ATTRIBUTE(STRFTIME,3,3_0)
 DEF_FORMAT_ATTRIBUTE(STRFMON,3,3_4)
 #undef DEF_FORMAT_ATTRIBUTE
@@ -181,3 +185,25 @@
 DEF_FORMAT_ARG_ATTRIBUTE(2)
 #undef DEF_FORMAT_ARG_ATTRIBUTE
 
+/* (TIGCC 20040219, 20050205) Default attributes. */
+#define DEF_FN_ATTR_IDENT(NAME, ATTRS, PREDICATE)	\
+  DEF_ATTR_IDENT (ATTR_ ## NAME, #NAME)	\
+  DEF_FN_ATTR (ATTR_ ## NAME, ATTRS, PREDICATE)
+#define DEF_C89_ATTR(NAME, ATTRS) DEF_FN_ATTR_IDENT (NAME, ATTRS, flag_hosted)
+DEF_C89_ATTR (printf, ATTR_FORMAT_PRINTF_1_2)
+DEF_C89_ATTR (fprintf, ATTR_FORMAT_PRINTF_2_3)
+DEF_C89_ATTR (sprintf, ATTR_FORMAT_PRINTF_2_3)
+DEF_C89_ATTR (scanf, ATTR_FORMAT_SCANF_1_2)
+DEF_C89_ATTR (fscanf, ATTR_FORMAT_SCANF_2_3)
+DEF_C89_ATTR (sscanf, ATTR_FORMAT_SCANF_2_3)
+DEF_C89_ATTR (vprintf, ATTR_FORMAT_PRINTF_1_0)
+DEF_C89_ATTR (vfprintf, ATTR_FORMAT_PRINTF_2_0)
+DEF_C89_ATTR (vsprintf, ATTR_FORMAT_PRINTF_2_0)
+DEF_C89_ATTR (vcbprintf, ATTR_FORMAT_PRINTF_3_0)
+DEF_C89_ATTR (cbprintf, ATTR_FORMAT_PRINTF_3_4)
+DEF_C89_ATTR (vcbscanf, ATTR_FORMAT_SCANF_4_0)
+DEF_C89_ATTR (cbscanf, ATTR_FORMAT_SCANF_4_5)
+DEF_C89_ATTR (vscanf, ATTR_FORMAT_SCANF_1_0)
+DEF_C89_ATTR (vfscanf, ATTR_FORMAT_SCANF_2_0)
+DEF_C89_ATTR (vsscanf, ATTR_FORMAT_SCANF_2_0)
+
diff -Naur gcc-4.1.2.orig/gcc/builtins.c gcc-4.1.2-src/gcc/builtins.c
--- gcc-4.1.2.orig/gcc/builtins.c	2006-10-06 19:06:52.000000000 +0200
+++ gcc-4.1.2-src/gcc/builtins.c	2007-02-19 02:32:34.000000000 +0100
@@ -47,6 +47,7 @@
 #include "langhooks.h"
 #include "basic-block.h"
 #include "tree-mudflap.h"
+#include "ggc.h"
 
 #ifndef PAD_VARARGS_DOWN
 #define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
@@ -76,7 +77,9 @@
 static rtx c_readstr (const char *, enum machine_mode);
 static int target_char_cast (tree, char *);
 static rtx get_memory_rtx (tree, tree);
+#if 0
 static tree build_string_literal (int, const char *);
+#endif /* 0 */
 static int apply_args_size (void);
 static int apply_result_size (void);
 #if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
@@ -91,25 +94,32 @@
 static void expand_builtin_return (rtx);
 static enum type_class type_to_class (tree);
 static rtx expand_builtin_classify_type (tree);
+#if 0
 static void expand_errno_check (tree, rtx);
 static rtx expand_builtin_mathfn (tree, rtx, rtx);
 static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
 static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
 static rtx expand_builtin_int_roundingfn (tree, rtx, rtx);
+#endif /* 0 */
 static rtx expand_builtin_args_info (tree);
 static rtx expand_builtin_next_arg (void);
 static rtx expand_builtin_va_start (tree);
 static rtx expand_builtin_va_end (tree);
 static rtx expand_builtin_va_copy (tree);
+#if 0
 static rtx expand_builtin_memcmp (tree, tree, rtx, enum machine_mode);
 static rtx expand_builtin_strcmp (tree, rtx, enum machine_mode);
 static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
+#endif /* 0 */
 static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
+#if 0
 static rtx expand_builtin_strcat (tree, tree, rtx, enum machine_mode);
 static rtx expand_builtin_strncat (tree, rtx, enum machine_mode);
 static rtx expand_builtin_strspn (tree, rtx, enum machine_mode);
 static rtx expand_builtin_strcspn (tree, rtx, enum machine_mode);
+#endif /* 0 */
 static rtx expand_builtin_memcpy (tree, rtx, enum machine_mode);
+#if 0
 static rtx expand_builtin_mempcpy (tree, tree, rtx, enum machine_mode, int);
 static rtx expand_builtin_memmove (tree, tree, rtx, enum machine_mode, tree);
 static rtx expand_builtin_bcopy (tree);
@@ -117,33 +127,43 @@
 static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
 static rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
 static rtx expand_builtin_strncpy (tree, rtx, enum machine_mode);
+#endif /* 0 */
 static rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
 static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
 static rtx expand_builtin_memset (tree, rtx, enum machine_mode, tree);
+#if 0
 static rtx expand_builtin_bzero (tree);
 static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
 static rtx expand_builtin_strstr (tree, tree, rtx, enum machine_mode);
 static rtx expand_builtin_strpbrk (tree, tree, rtx, enum machine_mode);
 static rtx expand_builtin_strchr (tree, tree, rtx, enum machine_mode);
 static rtx expand_builtin_strrchr (tree, tree, rtx, enum machine_mode);
+#endif /* 0 */
 static rtx expand_builtin_alloca (tree, rtx);
 static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
 static rtx expand_builtin_frame_address (tree, tree);
+#if 0
 static rtx expand_builtin_fputs (tree, rtx, bool);
 static rtx expand_builtin_printf (tree, rtx, enum machine_mode, bool);
 static rtx expand_builtin_fprintf (tree, rtx, enum machine_mode, bool);
 static rtx expand_builtin_sprintf (tree, rtx, enum machine_mode);
+#endif /* 0 */
 static tree stabilize_va_list (tree, int);
 static rtx expand_builtin_expect (tree, rtx);
 static tree fold_builtin_constant_p (tree);
 static tree fold_builtin_classify_type (tree);
+#if 0
 static tree fold_builtin_strlen (tree);
 static tree fold_builtin_inf (tree, int);
 static tree fold_builtin_nan (tree, tree, int);
+#endif /* 0 */
 static int validate_arglist (tree, ...);
+#if 0
 static bool integer_valued_real_p (tree);
 static tree fold_trunc_transparent_mathfn (tree, tree);
+#endif /* 0 */
 static bool readonly_data_expr (tree);
+#if 0
 static rtx expand_builtin_fabs (tree, rtx, rtx);
 static rtx expand_builtin_signbit (tree, rtx);
 static tree fold_builtin_cabs (tree, tree);
@@ -161,7 +181,9 @@
 static tree fold_builtin_round (tree, tree);
 static tree fold_builtin_int_roundingfn (tree, tree);
 static tree fold_builtin_bitop (tree, tree);
+#endif /* 0 */
 static tree fold_builtin_memcpy (tree, tree);
+#if 0
 static tree fold_builtin_mempcpy (tree, tree, int);
 static tree fold_builtin_memmove (tree, tree);
 static tree fold_builtin_strchr (tree, tree);
@@ -177,8 +199,10 @@
 static tree fold_builtin_abs (tree, tree);
 static tree fold_builtin_unordered_cmp (tree, tree, enum tree_code,
 					enum tree_code);
+#endif /* 0 */
 static tree fold_builtin_1 (tree, tree, bool);
 
+#if 0
 static tree fold_builtin_strpbrk (tree, tree);
 static tree fold_builtin_strstr (tree, tree);
 static tree fold_builtin_strrchr (tree, tree);
@@ -208,6 +232,10 @@
 static char target_percent_c[3];
 static char target_percent_s[3];
 static char target_percent_s_newline[4];
+#endif /* 0 */
+
+/* (TIGCC 20050206) Implement ER_throw. */
+static void expand_builtin_ER_throw (tree);
 
 /* Return true if NODE should be considered for inline expansion regardless
    of the optimization level.  This means whenever a function is invoked with
@@ -1233,7 +1261,13 @@
 	size += GET_MODE_SIZE (Pmode);
 
       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
-	if (FUNCTION_ARG_REGNO_P (regno))
+	if (0 /*FUNCTION_ARG_REGNO_P (regno)*/)
+	/* (TIGCC) Do NOT use register passing for __builtin_apply since:
+	           1. It doesn't work: ALL registers are POSSIBLE registers for
+	                               function parameters, so this code uses up all
+	                               registers.
+	           2. It significantly increases code size.
+	           3. The default calling convention is stkparm anyway. */
 	  {
 	    mode = reg_raw_mode[regno];
 
@@ -1686,6 +1720,7 @@
 tree
 mathfn_built_in (tree type, enum built_in_function fn)
 {
+#if 0
   enum built_in_function fcode, fcodef, fcodel;
 
   switch (fn)
@@ -1780,9 +1815,11 @@
   else if (TYPE_MAIN_VARIANT (type) == long_double_type_node)
     return implicit_built_in_decls[fcodel];
   else
+#endif /* 0 */
     return 0;
 }
 
+#if 0
 /* If errno must be maintained, expand the RTL to check if the result,
    TARGET, of a built-in function call, EXP, is NaN, and if so set
    errno to EDOM.  */
@@ -2893,6 +2930,7 @@
     }
   return 0;
 }
+#endif /* 0 */
 
 /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
    bytes from constant string DATA + OFFSET and return it as target
@@ -2986,6 +3024,7 @@
     }
 }
 
+#if 0
 /* Expand a call to the mempcpy builtin, with arguments in ARGLIST.
    Return 0 if we failed; the caller should emit a normal call,
    otherwise try to get the result in TARGET, if convenient (and in
@@ -3409,6 +3448,7 @@
     }
   return 0;
 }
+#endif /* 0 */
 
 /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
    bytes from constant string DATA + OFFSET and return it as target
@@ -3577,6 +3617,7 @@
     }
 }
 
+#if 0
 /* Expand expression EXP, which is a call to the bzero builtin.  Return 0
    if we failed the caller should emit a normal call.  */
 
@@ -4110,6 +4151,7 @@
     }
   return 0;
 }
+#endif /* 0 */
 
 /* Expand a call to __builtin_saveregs, generating the result in TARGET,
    if that's convenient.  */
@@ -4664,6 +4706,7 @@
   return convert_to_mode (target_mode, target, 0);
 }
 
+#if 0
 /* If the string passed to fputs is a constant and is one character
    long, we attempt to transform this call into __builtin_fputc().  */
 
@@ -4680,6 +4723,7 @@
     }
   return 0;
 }
+#endif /* 0 */
 
 /* Expand a call to __builtin_expect.  We return our argument and emit a
    NOTE_INSN_EXPECTED_VALUE note.  This is the expansion of __builtin_expect in
@@ -4852,6 +4896,35 @@
   emit_barrier ();
 }
 
+/* (TIGCC 20050206) Implement ER_throw. */
+static void
+expand_builtin_ER_throw (tree arglist)
+{
+  tree arg;
+  char buffer[40];
+
+  if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
+    {
+      error ("invalid argument list for ER_throw");
+      return;
+    }
+
+  arg = TREE_VALUE (arglist);
+
+  if (TREE_CODE (arg) != INTEGER_CST)
+    {
+      error ("argument to ER_throw must be a constant");
+      return;
+    }
+
+  sprintf (buffer, ".word _A_LINE+%d", (int) TREE_INT_CST_LOW (arg));
+
+  emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ggc_strdup (buffer)));
+
+  emit_barrier ();
+}
+
+#if 0
 /* Expand a call to fabs, fabsf or fabsl with arguments ARGLIST.
    Return 0 if a normal call should be emitted rather than expanding
    the function inline.  If convenient, the result should be placed
@@ -5220,6 +5293,7 @@
 
   return 0;
 }
+#endif /* 0 */
 
 /* Expand a call to either the entry or exit function profiler.  */
 
@@ -5324,6 +5398,7 @@
   return tramp;
 }
 
+#if 0
 /* Expand a call to the built-in signbit, signbitf or signbitl function.
    Return NULL_RTX if a normal call should be emitted rather than expanding
    the function in-line.  EXP is the expression that is a call to the builtin
@@ -5667,6 +5742,7 @@
   expand_builtin_synchronize ();
   emit_move_insn (mem, val);
 }
+#endif /* 0 */
 
 /* Expand an expression EXP that calls a built-in function,
    with result going to TARGET if that's convenient
@@ -5726,6 +5802,7 @@
 
   switch (fcode)
     {
+#if 0
     case BUILT_IN_FABS:
     case BUILT_IN_FABSF:
     case BUILT_IN_FABSL:
@@ -5894,6 +5971,7 @@
       if (target)
 	return target;
       break;
+#endif /* 0 */
 
     case BUILT_IN_APPLY_ARGS:
       return expand_builtin_apply_args ();
@@ -6030,6 +6108,7 @@
 	return target;
       break;
 
+#if 0
     case BUILT_IN_STRLEN:
       target = expand_builtin_strlen (arglist, target, target_mode);
       if (target)
@@ -6103,6 +6182,7 @@
       if (target)
 	return target;
       break;
+#endif /* 0 */
 
     case BUILT_IN_MEMCPY:
       target = expand_builtin_memcpy (exp, target, mode);
@@ -6110,6 +6190,7 @@
 	return target;
       break;
 
+#if 0
     case BUILT_IN_MEMPCPY:
       target = expand_builtin_mempcpy (arglist, TREE_TYPE (exp), target, mode, /*endp=*/ 1);
       if (target)
@@ -6128,6 +6209,7 @@
       if (target)
 	return target;
       break;
+#endif /* 0 */
 
     case BUILT_IN_MEMSET:
       target = expand_builtin_memset (arglist, target, mode, exp);
@@ -6135,6 +6217,7 @@
 	return target;
       break;
 
+#if 0
     case BUILT_IN_BZERO:
       target = expand_builtin_bzero (exp);
       if (target)
@@ -6159,6 +6242,7 @@
       if (target)
 	return target;
       break;
+#endif /* 0 */
 
     case BUILT_IN_SETJMP:
       target = expand_builtin_setjmp (arglist, target);
@@ -6212,6 +6296,7 @@
       expand_builtin_trap ();
       return const0_rtx;
 
+#if 0
     case BUILT_IN_PRINTF:
       target = expand_builtin_printf (exp, target, mode, false);
       if (target)
@@ -6260,6 +6345,7 @@
       if (target)
 	return target;
       break;
+#endif /* 0 */
 
       /* Various hooks for the DWARF 2 __throw routine.  */
     case BUILT_IN_UNWIND_INIT:
@@ -6312,6 +6398,7 @@
     case BUILT_IN_ADJUST_TRAMPOLINE:
       return expand_builtin_adjust_trampoline (arglist);
 
+#if 0
     case BUILT_IN_FORK:
     case BUILT_IN_EXECL:
     case BUILT_IN_EXECV:
@@ -6528,6 +6615,11 @@
     case BUILT_IN_VSPRINTF_CHK:
       maybe_emit_sprintf_chk_warning (exp, fcode);
       break;
+#endif /* 0 */
+
+    case BUILT_IN_ER_THROW:
+      expand_builtin_ER_throw (arglist);
+      return const0_rtx;
 
     default:	/* just do library call, if unknown builtin */
       break;
@@ -6547,6 +6639,7 @@
 enum built_in_function
 builtin_mathfn_code (tree t)
 {
+#if 0
   tree fndecl, arglist, parmlist;
   tree argtype, parmtype;
 
@@ -6601,13 +6694,16 @@
 	    return END_BUILTINS;
 	}
       else
+#endif /* 0 */
 	return END_BUILTINS;
+#if 0
 
       arglist = TREE_CHAIN (arglist);
     }
 
   /* Variable-length argument list.  */
   return DECL_FUNCTION_CODE (fndecl);
+#endif /* 0 */
 }
 
 /* Fold a call to __builtin_constant_p, if we know it will evaluate to a
@@ -6707,6 +6803,7 @@
 			type_to_class (TREE_TYPE (TREE_VALUE (arglist))));
 }
 
+#if 0
 /* Fold a call to __builtin_strlen.  */
 
 static tree
@@ -7520,6 +7617,7 @@
 
   return fold_fixed_mathfn (fndecl, arglist);
 }
+#endif /* 0 */
 
 /* Fold function call to builtin ffs, clz, ctz, popcount and parity
    and their long and long long variants (i.e. ffsl and ffsll).
@@ -7625,6 +7723,7 @@
   return NULL_TREE;
 }
 
+#if 0
 /* Return true if EXPR is the real constant contained in VALUE.  */
 
 static bool
@@ -8015,6 +8114,7 @@
 
   return 0;
 }
+#endif /* 0 */
 
 /* Fold function call to builtin memcpy.  Return
    NULL_TREE if no simplification can be made.  */
@@ -8043,6 +8143,7 @@
   return 0;
 }
 
+#if 0
 /* Fold function call to builtin mempcpy.  Return
    NULL_TREE if no simplification can be made.  */
 
@@ -8776,6 +8877,7 @@
   return fold_build1 (TRUTH_NOT_EXPR, type,
 		      fold_build2 (code, type, arg0, arg1));
 }
+#endif /* 0 */
 
 /* Used by constant folding to simplify calls to builtin functions.  EXP is
    the CALL_EXPR of a call to a builtin function.  IGNORE is true if the
@@ -8794,6 +8896,7 @@
   fcode = DECL_FUNCTION_CODE (fndecl);
   switch (fcode)
     {
+#if 0
     case BUILT_IN_FPUTS:
       return fold_builtin_fputs (arglist, ignore, false, NULL_TREE);
 
@@ -8844,6 +8947,7 @@
 
     case BUILT_IN_SPRINTF:
       return fold_builtin_sprintf (arglist, ignore);
+#endif /* 0 */
 
     case BUILT_IN_CONSTANT_P:
       {
@@ -8865,6 +8969,7 @@
     case BUILT_IN_CLASSIFY_TYPE:
       return fold_builtin_classify_type (arglist);
 
+#if 0
     case BUILT_IN_STRLEN:
       return fold_builtin_strlen (arglist);
 
@@ -9055,6 +9160,7 @@
     case BUILT_IN_LLRINTF:
     case BUILT_IN_LLRINTL:
       return fold_fixed_mathfn (fndecl, arglist);
+#endif /* 0 */
 
     case BUILT_IN_FFS:
     case BUILT_IN_FFSL:
@@ -9076,6 +9182,7 @@
     case BUILT_IN_MEMCPY:
       return fold_builtin_memcpy (fndecl, arglist);
 
+#if 0
     case BUILT_IN_MEMPCPY:
       return fold_builtin_mempcpy (arglist, type, /*endp=*/1);
 
@@ -9129,11 +9236,13 @@
     case BUILT_IN_ISUNORDERED:
       return fold_builtin_unordered_cmp (fndecl, arglist, UNORDERED_EXPR,
 					 NOP_EXPR);
+#endif /* 0 */
 
       /* We do the folding for va_start in the expander.  */
     case BUILT_IN_VA_START:
       break;
 
+#if 0
     case BUILT_IN_OBJECT_SIZE:
       return fold_builtin_object_size (arglist);
     case BUILT_IN_MEMCPY_CHK:
@@ -9175,6 +9284,7 @@
     case BUILT_IN_VFPRINTF_CHK:
       return fold_builtin_fprintf (fndecl, arglist, ignore,
 				   DECL_FUNCTION_CODE (fndecl));
+#endif /* 0 */
 
     default:
       break;
@@ -9305,6 +9415,7 @@
     return false;
 }
 
+#if 0
 /* Simplify a call to the strstr builtin.
 
    Return 0 if no simplification was possible, otherwise return the
@@ -9843,6 +9954,7 @@
      hence there's no need to cast the result to integer_type_node.  */
   return build_function_call_expr (fn, arglist);
 }
+#endif /* 0 */
 
 /* Fold the new_arg's arguments (ARGLIST). Returns true if there was an error
    produced.  False otherwise.  This is done so that we don't output the error
@@ -9912,6 +10024,7 @@
 }
 
 
+#if 0
 /* Simplify a call to the sprintf builtin.
 
    Return 0 if no simplification was possible, otherwise return the
@@ -11194,3 +11307,5 @@
     }
   return true;
 }
+#endif /* 0 */
+
diff -Naur gcc-4.1.2.orig/gcc/builtins.def gcc-4.1.2-src/gcc/builtins.def
--- gcc-4.1.2.orig/gcc/builtins.def	2006-11-01 06:59:44.000000000 +0100
+++ gcc-4.1.2-src/gcc/builtins.def	2007-02-19 02:32:34.000000000 +0100
@@ -507,6 +507,7 @@
 DEF_LIB_BUILTIN        (BUILT_IN_STRSPN, "strspn", BT_FN_SIZE_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL)
 DEF_LIB_BUILTIN        (BUILT_IN_STRSTR, "strstr", BT_FN_STRING_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL)
 
+#if 0
 /* Category: stdio builtins.  */
 DEF_LIB_BUILTIN        (BUILT_IN_FPRINTF, "fprintf", BT_FN_INT_FILEPTR_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_2_3)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_FPRINTF_UNLOCKED, "fprintf_unlocked", BT_FN_INT_FILEPTR_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_2_3)
@@ -568,6 +569,7 @@
 DEF_C94_BUILTIN        (BUILT_IN_ISWXDIGIT, "iswxdigit", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LIST)
 DEF_C94_BUILTIN        (BUILT_IN_TOWLOWER, "towlower", BT_FN_WINT_WINT, ATTR_PURE_NOTHROW_LIST)
 DEF_C94_BUILTIN        (BUILT_IN_TOWUPPER, "towupper", BT_FN_WINT_WINT, ATTR_PURE_NOTHROW_LIST)
+#endif /* 0 */
 
 /* Category: miscellaneous builtins.  */
 DEF_LIB_BUILTIN        (BUILT_IN_ABORT, "abort", BT_FN_VOID, ATTR_NORETURN_NOTHROW_LIST)
@@ -577,7 +579,9 @@
 DEF_GCC_BUILTIN        (BUILT_IN_APPLY, "apply", BT_FN_PTR_PTR_FN_VOID_VAR_PTR_SIZE, ATTR_NULL)
 DEF_GCC_BUILTIN        (BUILT_IN_APPLY_ARGS, "apply_args", BT_FN_PTR_VAR, ATTR_NULL)
 DEF_GCC_BUILTIN        (BUILT_IN_ARGS_INFO, "args_info", BT_FN_INT_INT, ATTR_NULL)
+#if 0
 DEF_LIB_BUILTIN        (BUILT_IN_CALLOC, "calloc", BT_FN_PTR_SIZE_SIZE, ATTR_MALLOC_NOTHROW_LIST)
+#endif /* 0 */
 DEF_GCC_BUILTIN        (BUILT_IN_CLASSIFY_TYPE, "classify_type", BT_FN_INT_VAR, ATTR_NULL)
 DEF_GCC_BUILTIN        (BUILT_IN_CLZ, "clz", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_CLZIMAX, "clzimax", BT_FN_INT_UINTMAX, ATTR_CONST_NOTHROW_LIST)
@@ -659,6 +663,9 @@
 DEF_EXT_LIB_BUILTIN    (BUILT_IN__EXIT, "_exit", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LIST)
 DEF_C99_BUILTIN        (BUILT_IN__EXIT2, "_Exit", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LIST)
 
+/* (TIGCC 20050206) Implement ER_throw. */
+DEF_GCC_BUILTIN        (BUILT_IN_ER_THROW, "ER_throw", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LIST)
+
 /* Implementing nested functions.  */
 DEF_BUILTIN_STUB (BUILT_IN_INIT_TRAMPOLINE, "__builtin_init_trampoline")
 DEF_BUILTIN_STUB (BUILT_IN_ADJUST_TRAMPOLINE, "__builtin_adjust_trampoline")
@@ -670,6 +677,7 @@
 
 /* Object size checking builtins.  */
 DEF_GCC_BUILTIN	       (BUILT_IN_OBJECT_SIZE, "object_size", BT_FN_SIZE_CONST_PTR_INT, ATTR_PURE_NOTHROW_LIST)
+#if 0
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_MEMCPY_CHK, "__memcpy_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_NOTHROW_NONNULL)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_MEMMOVE_CHK, "__memmove_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_NOTHROW_NONNULL)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_MEMPCPY_CHK, "__mempcpy_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_NOTHROW_NONNULL)
@@ -687,6 +695,7 @@
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_PRINTF_CHK, "__printf_chk", BT_FN_INT_INT_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_2_3)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_VFPRINTF_CHK, "__vfprintf_chk", BT_FN_INT_FILEPTR_INT_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_3_0)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_VPRINTF_CHK, "__vprintf_chk", BT_FN_INT_INT_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_2_0)
+#endif /* 0 */
 
 /* Profiling hooks.  */
 DEF_BUILTIN_STUB (BUILT_IN_PROFILE_FUNC_ENTER, "profile_func_enter")
diff -Naur gcc-4.1.2.orig/gcc/c-common.c gcc-4.1.2-src/gcc/c-common.c
--- gcc-4.1.2.orig/gcc/c-common.c	2007-01-05 20:44:10.000000000 +0100
+++ gcc-4.1.2-src/gcc/c-common.c	2007-02-19 02:32:34.000000000 +0100
@@ -2934,16 +2934,20 @@
 #define DEF_ATTR_INT(ENUM, VALUE) ENUM,
 #define DEF_ATTR_IDENT(ENUM, STRING) ENUM,
 #define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) ENUM,
+#define DEF_FN_ATTR(NAME, ATTRS, PREDICATE) /* No entry needed in enum.  */
 #include "builtin-attrs.def"
 #undef DEF_ATTR_NULL_TREE
 #undef DEF_ATTR_INT
 #undef DEF_ATTR_IDENT
 #undef DEF_ATTR_TREE_LIST
+#undef DEF_FN_ATTR
   ATTR_LAST
 };
 
 static GTY(()) tree built_in_attributes[(int) ATTR_LAST];
 
+static bool c_attrs_initialized = false;
+
 static void c_init_attributes (void);
 
 /* Build tree nodes and builtin functions common to both C and C++ language
@@ -3354,7 +3358,8 @@
 #undef DEF_POINTER_TYPE
   builtin_types[(int) BT_LAST] = NULL_TREE;
 
-  c_init_attributes ();
+  if (!c_attrs_initialized)
+    c_init_attributes ();
 
 #define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P, \
 		    NONANSI_P, ATTRS, IMPLICIT, COND)			\
@@ -4052,11 +4057,40 @@
     = tree_cons (built_in_attributes[(int) PURPOSE],	\
 		 built_in_attributes[(int) VALUE],	\
 		 built_in_attributes[(int) CHAIN]);
+#define DEF_FN_ATTR(NAME, ATTRS, PREDICATE) /* No initialization needed.  */
+#include "builtin-attrs.def"
+#undef DEF_ATTR_NULL_TREE
+#undef DEF_ATTR_INT
+#undef DEF_ATTR_IDENT
+#undef DEF_ATTR_TREE_LIST
+#undef DEF_FN_ATTR
+  c_attrs_initialized = true;
+}
+
+/* Depending on the name of DECL, apply default attributes to it.  */
+
+void
+c_common_insert_default_attributes (tree decl)
+{
+  tree name = DECL_NAME (decl);
+
+  if (!c_attrs_initialized)
+    c_init_attributes ();
+
+#define DEF_ATTR_NULL_TREE(ENUM) /* Nothing needed after initialization.  */
+#define DEF_ATTR_INT(ENUM, VALUE)
+#define DEF_ATTR_IDENT(ENUM, STRING)
+#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN)
+#define DEF_FN_ATTR(NAME, ATTRS, PREDICATE)			\
+  if ((PREDICATE) && name == built_in_attributes[(int) NAME])	\
+    decl_attributes (&decl, built_in_attributes[(int) ATTRS],	\
+		     ATTR_FLAG_BUILT_IN);
 #include "builtin-attrs.def"
 #undef DEF_ATTR_NULL_TREE
 #undef DEF_ATTR_INT
 #undef DEF_ATTR_IDENT
 #undef DEF_ATTR_TREE_LIST
+#undef DEF_FN_ATTR
 }
 
 /* Attribute handlers common to C front ends.  */
diff -Naur gcc-4.1.2.orig/gcc/c-common.h gcc-4.1.2-src/gcc/c-common.h
--- gcc-4.1.2.orig/gcc/c-common.h	2005-12-27 18:18:05.000000000 +0100
+++ gcc-4.1.2-src/gcc/c-common.h	2007-02-19 02:32:34.000000000 +0100
@@ -632,6 +632,7 @@
 extern void set_Wformat (int);
 extern tree handle_format_attribute (tree *, tree, tree, int, bool *);
 extern tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
+extern void c_common_insert_default_attributes (tree);
 extern int c_common_handle_option (size_t code, const char *arg, int value);
 extern bool c_common_missing_argument (const char *opt, size_t code);
 extern tree c_common_type_for_mode (enum machine_mode, int);
diff -Naur gcc-4.1.2.orig/gcc/c-cppbuiltin.c gcc-4.1.2-src/gcc/c-cppbuiltin.c
--- gcc-4.1.2.orig/gcc/c-cppbuiltin.c	2005-08-13 22:58:02.000000000 +0200
+++ gcc-4.1.2-src/gcc/c-cppbuiltin.c	2007-02-19 02:32:34.000000000 +0100
@@ -51,9 +51,11 @@
 static void builtin_define_with_value_n (const char *, const char *,
 					 size_t);
 static void builtin_define_with_int_value (const char *, HOST_WIDE_INT);
+#if 0
 static void builtin_define_with_hex_fp_value (const char *, tree,
 					      int, const char *,
 					      const char *);
+#endif /* 0 */
 static void builtin_define_stdint_macros (void);
 static void builtin_define_type_max (const char *, tree, int);
 static void builtin_define_type_precision (const char *, tree);
@@ -72,6 +74,7 @@
 static void
 builtin_define_float_constants (const char *name_prefix, const char *fp_suffix, tree type)
 {
+#if 0 /* (TIGCC) Do nothing. We have our own float.h! */
   /* Used to convert radix-based values to base 10 values in several cases.
 
      In the max_exp -> max_10_exp conversion for 128-bit IEEE, we need at
@@ -254,6 +257,7 @@
      NaN has quiet NaNs.  */
   sprintf (name, "__%s_HAS_QUIET_NAN__", name_prefix);
   builtin_define_with_int_value (name, MODE_HAS_NANS (TYPE_MODE (type)));
+#endif /* 0 */
 }
 
 /* Define __GNUC__, __GNUC_MINOR__ and __GNUC_PATCHLEVEL__.  */
@@ -571,6 +575,7 @@
   cpp_define (parse_in, buf);
 }
 
+#if 0
 /* Pass an object-like macro a hexadecimal floating-point value.  */
 static void
 builtin_define_with_hex_fp_value (const char *macro,
@@ -596,6 +601,7 @@
   sprintf (buf, "%s=%s%s", macro, dec_str, fp_suffix);
   cpp_define (parse_in, buf);
 }
+#endif /* 0 */
 
 /* Define MAX for TYPE based on the precision of the type.  IS_LONG is
    1 for type "long" and 2 for "long long".  We have to handle
diff -Naur gcc-4.1.2.orig/gcc/c-decl.c gcc-4.1.2-src/gcc/c-decl.c
--- gcc-4.1.2.orig/gcc/c-decl.c	2007-01-05 20:44:10.000000000 +0100
+++ gcc-4.1.2-src/gcc/c-decl.c	2007-02-19 03:32:04.000000000 +0100
@@ -2418,7 +2418,6 @@
 void
 undeclared_variable (tree id, location_t loc)
 {
-  static bool already = false;
   struct c_scope *scope;
 
   if (current_function_decl == 0)
@@ -2430,13 +2429,6 @@
     {
       error ("%H%qE undeclared (first use in this function)", &loc, id);
 
-      if (!already)
-	{
-	  error ("%H(Each undeclared identifier is reported only once", &loc);
-	  error ("%Hfor each function it appears in.)", &loc);
-	  already = true;
-	}
-
       /* If we are parsing old-style parameter decls, current_function_decl
          will be nonnull but current_function_scope will be null.  */
       scope = current_function_scope ? current_function_scope : current_scope;
@@ -2730,7 +2722,7 @@
 
   input_location = save_loc;
 
-  pedantic_lvalues = true;
+  pedantic_lvalues = pedantic;
 
   make_fname_decl = c_make_fname_decl;
   start_fname_decls ();
@@ -2825,6 +2817,17 @@
 
   return decl;
 }
+
+/* Apply default attributes to a function, if a system function with default
+   attributes.  */
+
+void
+c_insert_default_attributes (tree decl)
+{
+  if (!TREE_PUBLIC (decl))
+    return;
+  c_common_insert_default_attributes (decl);
+}
 
 /* Called when a declaration is seen that contains no names to declare.
    If its type is a reference to a structure, union or enum inherited
@@ -3605,10 +3608,86 @@
 push_parm_decl (const struct c_parm *parm)
 {
   tree decl;
+/* begin-TIGCC-local (regparms): explicit register specification for parameters */
+  tree asmspec;
 
+  asmspec = parm->asmspec;
+/* end-TIGCC-local (regparms) */
   decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL);
   decl_attributes (&decl, parm->attrs, 0);
 
+  /* begin-TIGCC-local (regparms): explicit register specification for parameters */
+  if (asmspec)
+#ifdef EXPLICIT_REGPARM
+    {
+      const char *regname=TREE_STRING_POINTER(asmspec);
+      int regnum;
+      if ((regnum=decode_reg_name(regname))>=0)
+	{
+	  tree type=TREE_TYPE(decl);
+	  if (HARD_REGNO_MODE_OK(regnum, TYPE_MODE(type)))
+	    {
+	      tree t, attrs;
+/*	      push_obstacks_nochange();
+	      end_temporary_allocation(); */
+	      /* Build tree for __attribute__ ((asm(regnum))). */
+#if 0
+	      /* This doesn't work well because of a bug in
+		 attribute_list_contained(), which passes list of arguments to
+		 simple_cst_equal() instead of passing every argument
+		 separately. */
+	      attrs=tree_cons(get_identifier("asm"), tree_cons(NULL_TREE,
+		    build_int_cstu(NULL_TREE, regnum), NULL_TREE), NULL_TREE);
+#else
+	      attrs=tree_cons(get_identifier("asm"),
+			      build_int_cstu(NULL_TREE, regnum), NULL_TREE);
+#endif
+#if 0
+	      /* build_type_attribute_variant() would seem to be more
+		 appropriate here. However, that function does not support
+		 attributes for parameters properly. It modifies
+		 TYPE_MAIN_VARIANT of a new type. As a result, comptypes()
+		 thinks that types of parameters in prototype and definition
+		 are different and issues error messages. See also comment
+		 below. */
+	      type=build_type_attribute_variant(type, attrs);
+#else
+	      /* First check whether such a type already exists - if yes, use
+		 that one. This is very important, since otherwise
+		 common_type() would think that it sees two different
+		 types and would try to merge them - this could result in
+		 warning messages. */
+	      for (t=TYPE_MAIN_VARIANT(type); t; t=TYPE_NEXT_VARIANT(t))
+		if (comptypes(t, type)==1
+		    && attribute_list_equal(TYPE_ATTRIBUTES(t), attrs))
+		      break;
+	      if (t)
+		type=t;
+	      else
+		{
+		  /* Create a new variant, with differing attributes.
+		     (Hack! Type with differing attributes should no longer be
+		     a variant of its main type. See comment above for
+		     explanation why this was necessary). */
+		  type=build_variant_type_copy(type);
+		  TYPE_ATTRIBUTES(type)=attrs;
+		}
+#endif
+	      TREE_TYPE(decl)=type;
+/*	      pop_obstacks(); */
+	    }
+	  else
+	    error("%Jregister number for `%s' isn't suitable for the data type",
+	          decl, regname);
+	}
+      else
+	error("invalid register name `%s'", regname);
+    }
+#else /* !EXPLICIT_REGPARM */
+    error("explicit register specification for parameters is not supported for this target");
+#endif
+  /* end-TIGCC-local (regparms) */
+
   decl = pushdecl (decl);
 
   finish_decl (decl, NULL_TREE, NULL_TREE);
@@ -3658,7 +3737,11 @@
   DECL_CONTEXT (decl) = current_function_decl;
   TREE_USED (decl) = 1;
   TREE_TYPE (decl) = type;
-  TREE_READONLY (decl) = TYPE_READONLY (type);
+  /* (TIGCC 20050206) If -fglobal-compound-literals (on by default) is given,
+     for constant constructors, the compound literal is written out as if it was
+     const, which gets GCC to output it as a global, avoiding the copy.  */
+  TREE_READONLY (decl) = TYPE_READONLY (type)
+                         || (flag_global_compound_literals && TREE_CONSTANT (init));
   store_init_value (decl, init);
 
   if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
@@ -6900,12 +6983,13 @@
 
 struct c_parm *
 build_c_parm (struct c_declspecs *specs, tree attrs,
-	      struct c_declarator *declarator)
+	      struct c_declarator *declarator, tree asmspec)
 {
   struct c_parm *ret = XOBNEW (&parser_obstack, struct c_parm);
   ret->specs = specs;
   ret->attrs = attrs;
   ret->declarator = declarator;
+  ret->asmspec = asmspec; /* (TIGCC 20050203) */
   return ret;
 }
 
diff -Naur gcc-4.1.2.orig/gcc/cfgexpand.c gcc-4.1.2-src/gcc/cfgexpand.c
--- gcc-4.1.2.orig/gcc/cfgexpand.c	2006-09-01 09:48:22.000000000 +0200
+++ gcc-4.1.2-src/gcc/cfgexpand.c	2007-02-19 02:32:34.000000000 +0100
@@ -1363,6 +1363,23 @@
 	    }
 	  else
 	    {
+	      /* (TIGCC 20050206) If -fno-function-cse, restore function call
+	                          sequences to their expected form. */
+	      if (flag_no_function_cse && TREE_CODE (stmt) == MODIFY_EXPR)
+	        {
+	          block_stmt_iterator bsi2 = bsi;
+	          bsi_next (&bsi2);
+	          if (!bsi_end_p (bsi2))
+	            {
+	              tree call = get_call_expr_in (bsi_stmt (bsi2));
+	              if (call && TREE_OPERAND (stmt, 0) == TREE_OPERAND (call, 0)
+	                  && !TREE_SIDE_EFFECTS (TREE_OPERAND (stmt, 0))
+	                  && !TREE_SIDE_EFFECTS (TREE_OPERAND (stmt, 1)))
+	              {
+	                TREE_OPERAND (call, 0) = TREE_OPERAND (stmt, 1);
+	              }
+	            }
+	        }
 	      last = get_last_insn ();
 	      expand_expr_stmt (stmt);
 	      maybe_dump_rtl_for_tree_stmt (stmt, last);
diff -Naur gcc-4.1.2.orig/gcc/c-format.c gcc-4.1.2-src/gcc/c-format.c
--- gcc-4.1.2.orig/gcc/c-format.c	2005-10-26 04:15:02.000000000 +0200
+++ gcc-4.1.2-src/gcc/c-format.c	2007-02-19 02:32:34.000000000 +0100
@@ -281,16 +281,12 @@
 } format_wanted_type;
 
 
+/* (TIGCC 20040219) AMS doesn't support any C99 or extended modifiers.
+    -- Kevin Kofler */
 static const format_length_info printf_length_specs[] =
 {
-  { "h", FMT_LEN_h, STD_C89, "hh", FMT_LEN_hh, STD_C99 },
-  { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C9L },
-  { "q", FMT_LEN_ll, STD_EXT, NULL, 0, 0 },
-  { "L", FMT_LEN_L, STD_C89, NULL, 0, 0 },
-  { "z", FMT_LEN_z, STD_C99, NULL, 0, 0 },
-  { "Z", FMT_LEN_z, STD_EXT, NULL, 0, 0 },
-  { "t", FMT_LEN_t, STD_C99, NULL, 0, 0 },
-  { "j", FMT_LEN_j, STD_C99, NULL, 0, 0 },
+  { "h", FMT_LEN_h, STD_C89, NULL, 0, 0 },
+  { "l", FMT_LEN_l, STD_C89, NULL, 0, 0 },
   { NULL, 0, 0, NULL, 0, 0 }
 };
 
@@ -315,16 +311,12 @@
 #define gcc_cdiag_length_specs gcc_diag_length_specs
 #define gcc_cxxdiag_length_specs gcc_diag_length_specs
 
-/* This differs from printf_length_specs only in that "Z" is not accepted.  */
+/* (TIGCC 20040219) My *scanf doesn't support any C99 or extended modifiers.
+    -- Kevin Kofler */
 static const format_length_info scanf_length_specs[] =
 {
-  { "h", FMT_LEN_h, STD_C89, "hh", FMT_LEN_hh, STD_C99 },
-  { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C9L },
-  { "q", FMT_LEN_ll, STD_EXT, NULL, 0, 0 },
-  { "L", FMT_LEN_L, STD_C89, NULL, 0, 0 },
-  { "z", FMT_LEN_z, STD_C99, NULL, 0, 0 },
-  { "t", FMT_LEN_t, STD_C99, NULL, 0, 0 },
-  { "j", FMT_LEN_j, STD_C99, NULL, 0, 0 },
+  { "h", FMT_LEN_h, STD_C89, NULL, 0, 0 },
+  { "l", FMT_LEN_l, STD_C89, NULL, 0, 0 },
   { NULL, 0, 0, NULL, 0, 0 }
 };
 
@@ -338,6 +330,9 @@
   { NULL, 0, 0, NULL, 0, 0 }
 };
 
+/* (TIGCC 20040219) AMS doesn't support any of the GNU extended modifiers.
+                    However, it supports some of its own.
+    -- Kevin Kofler */
 static const format_flag_spec printf_flag_specs[] =
 {
   { ' ',  0, 0, N_("' ' flag"),        N_("the ' ' printf flag"),              STD_C89 },
@@ -345,8 +340,9 @@
   { '#',  0, 0, N_("'#' flag"),        N_("the '#' printf flag"),              STD_C89 },
   { '0',  0, 0, N_("'0' flag"),        N_("the '0' printf flag"),              STD_C89 },
   { '-',  0, 0, N_("'-' flag"),        N_("the '-' printf flag"),              STD_C89 },
-  { '\'', 0, 0, N_("''' flag"),        N_("the ''' printf flag"),              STD_EXT },
-  { 'I',  0, 0, N_("'I' flag"),        N_("the 'I' printf flag"),              STD_EXT },
+  { 'z',  0, 0, N_("'z' flag"),        N_("the 'z' printf flag"),              STD_EXT },
+  { '^',  0, 0, N_("'^' flag"),        N_("the '^' printf flag"),              STD_EXT },
+  { '|',  0, 0, N_("'|' flag"),        N_("the '|' printf flag"),              STD_EXT },
   { 'w',  0, 0, N_("field width"),     N_("field width in printf format"),     STD_C89 },
   { 'p',  0, 0, N_("precision"),       N_("precision in printf format"),       STD_C89 },
   { 'L',  0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 },
@@ -419,14 +415,13 @@
   { 0, 0, 0, NULL, NULL, 0 }
 };
 
+/* (TIGCC 20040219) My *scanf doesn't support any extended modifiers.
+    -- Kevin Kofler */
 static const format_flag_spec scanf_flag_specs[] =
 {
   { '*',  0, 0, N_("assignment suppression"), N_("the assignment suppression scanf feature"), STD_C89 },
-  { 'a',  0, 0, N_("'a' flag"),               N_("the 'a' scanf flag"),                       STD_EXT },
   { 'w',  0, 0, N_("field width"),            N_("field width in scanf format"),              STD_C89 },
   { 'L',  0, 0, N_("length modifier"),        N_("length modifier in scanf format"),          STD_C89 },
-  { '\'', 0, 0, N_("''' flag"),               N_("the ''' scanf flag"),                       STD_EXT },
-  { 'I',  0, 0, N_("'I' flag"),               N_("the 'I' scanf flag"),                       STD_EXT },
   { 0, 0, 0, NULL, NULL, 0 }
 };
 
@@ -486,26 +481,22 @@
 };
 
 
+/* (TIGCC 20040219) AMS doesn't support any of the C99 or GNU extended
+                    modifiers. However, it supports some of its own.
+    -- Kevin Kofler */
 static const format_char_info print_char_table[] =
 {
   /* C89 conversion specifiers.  */
-  { "di",  0, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  TEX_LL,  T99_SST, T99_PD,  T99_IM  }, "-wp0 +'I",  "i",  NULL },
-  { "oxX", 0, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM }, "-wp0#",     "i",  NULL },
-  { "u",   0, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM }, "-wp0'I",    "i",  NULL },
-  { "fgG", 0, STD_C89, { T89_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#'I", "",   NULL },
-  { "eE",  0, STD_C89, { T89_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#I",  "",   NULL },
-  { "c",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T94_WI,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-w",        "",   NULL },
-  { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp",       "cR", NULL },
-  { "p",   1, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-w",        "c",  NULL },
-  { "n",   1, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  BADLEN,  T99_SST, T99_PD,  T99_IM  }, "",          "W",  NULL },
-  /* C99 conversion specifiers.  */
-  { "F",   0, STD_C99, { T99_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#'I", "",   NULL },
-  { "aA",  0, STD_C99, { T99_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#",   "",   NULL },
-  /* X/Open conversion specifiers.  */
-  { "C",   0, STD_EXT, { TEX_WI,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-w",        "",   NULL },
-  { "S",   1, STD_EXT, { TEX_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp",       "R",  NULL },
-  /* GNU conversion specifiers.  */
-  { "m",   0, STD_EXT, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp",       "",   NULL },
+  { "di",  0, STD_C89, { T89_S,   BADLEN,  T89_S,   T89_L,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +|z",  "i", NULL  },
+  { "xX", 0, STD_C89, { T89_US,  BADLEN,  T89_US,  T89_UL,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp0#|z",     "i", NULL  },
+  { "u",   0, STD_C89, { T89_US,  BADLEN,  T89_US,  T89_UL,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp0|z",    "i", NULL  },
+  { "fgG", 0, STD_C89, { T89_D,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#^|z", "", NULL   },
+  { "eE",  0, STD_C89, { T89_D,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#^|z",  "", NULL   },
+  { "rR",  0, STD_EXT, { T89_D,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#^|z",  "", NULL   },
+  { "yY",  0, STD_EXT, { T89_D,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#^|z",  "", NULL   },
+  { "c",   0, STD_C89, { T89_S,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-w|z",        "", NULL   },
+  { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp|z",       "cR", NULL },
+  { "p",   1, STD_C89, { BADLEN,  BADLEN,  BADLEN,  T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-w|z",        "c", NULL  },
   { NULL,  0, 0, NOLENGTHS, NULL, NULL, NULL }
 };
 
@@ -641,23 +632,18 @@
   { NULL,  0, 0, NOLENGTHS, NULL, NULL, NULL }
 };
 
+/* (TIGCC 20040219) My *scanf doesn't support any extended modifiers. -- Kevin Kofler */
 static const format_char_info scan_char_table[] =
 {
   /* C89 conversion specifiers.  */
-  { "di",    1, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  TEX_LL,  T99_SST, T99_PD,  T99_IM  }, "*w'I", "W",   NULL },
-  { "u",     1, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM }, "*w'I", "W",   NULL },
-  { "oxX",   1, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM }, "*w",   "W",   NULL },
-  { "efgEG", 1, STD_C89, { T89_F,   BADLEN,  BADLEN,  T89_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN  }, "*w'",  "W",   NULL },
+  { "di",    1, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  TEX_LL,  T99_SST, T99_PD,  T99_IM  }, "*w", "W", NULL   },
+  { "u",     1, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM }, "*w", "W", NULL   },
+  { "oxX",   1, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM }, "*w",   "W", NULL   },
+  { "efgEG", 1, STD_C89, { T89_F,   BADLEN,  BADLEN,  T89_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN  }, "*w",  "W", NULL   },
   { "c",     1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "*w",   "cW",  NULL },
   { "s",     1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "*aw",  "cW",  NULL },
   { "[",     1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "*aw",  "cW[", NULL },
   { "p",     2, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "*w",   "W",   NULL },
-  { "n",     1, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  BADLEN,  T99_SST, T99_PD,  T99_IM  }, "",     "W",   NULL },
-  /* C99 conversion specifiers.  */
-  { "FaA",   1, STD_C99, { T99_F,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN  }, "*w'",  "W",   NULL },
-  /* X/Open conversion specifiers.  */
-  { "C",     1, STD_EXT, { TEX_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "*w",   "W",   NULL },
-  { "S",     1, STD_EXT, { TEX_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "*aw",  "W",   NULL },
   { NULL, 0, 0, NOLENGTHS, NULL, NULL, NULL }
 };
 
@@ -695,9 +681,10 @@
 };
 
 /* This must be in the same order as enum format_type.  */
+/* (TIGCC 20040219) Changed the flag chars. See the *f_flag_specs comments. */
 static const format_kind_info format_types_orig[] =
 {
-  { "printf",   printf_length_specs,  print_char_table, " +#0-'I", NULL, 
+  { "printf",   printf_length_specs,  print_char_table, " +#0-z^|", NULL, 
     printf_flag_specs, printf_flag_pairs,
     FMT_FLAG_ARG_CONVERT|FMT_FLAG_DOLLAR_MULTIPLE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_EMPTY_PREC_OK,
     'w', 0, 'p', 0, 'L',
@@ -739,7 +726,7 @@
     0, 0, 0, 0, 0,
     NULL, NULL
   },
-  { "scanf",    scanf_length_specs,   scan_char_table,  "*'I", NULL, 
+  { "scanf",    scanf_length_specs,   scan_char_table,  "*", NULL, 
     scanf_flag_specs, scanf_flag_pairs,
     FMT_FLAG_ARG_CONVERT|FMT_FLAG_SCANF_A_KLUDGE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_ZERO_WIDTH_BAD|FMT_FLAG_DOLLAR_GAP_POINTER_OK,
     'w', 0, 0, '*', 'L',
@@ -2215,6 +2202,17 @@
 			  || cur_type == signed_char_type_node
 			  || cur_type == unsigned_char_type_node);
 
+      /* (TIGCC) Account for *printf and *scanf not actually supporting -mlong.  */
+      if (!TARGET_SHORT) {
+        if (cur_type == short_integer_type_node
+            || cur_type == integer_type_node)
+          orig_cur_type = cur_type = long_integer_type_node;
+
+        if (cur_type == short_unsigned_type_node
+            || cur_type == unsigned_type_node)
+          orig_cur_type = cur_type = long_unsigned_type_node;
+      }
+
       /* Check the type of the "real" argument, if there's a type we want.  */
       if (lang_hooks.types_compatible_p (wanted_type, cur_type))
 	continue;
@@ -2229,12 +2227,18 @@
 	 -pedantic.  With -pedantic, warn if the type is a pointer
 	 target and not a character type, and for character types at
 	 a second level of indirection.  */
-      if (TREE_CODE (wanted_type) == INTEGER_TYPE
+      /* TIGCC Patch: Don't warn about differences in floating point
+         format; they're all the same.
+         (TIGCC 20040728) But do warn if someone passes an integer where a float
+                          is expected! -- Kevin Kofler  */
+      if ((TREE_CODE (wanted_type) == REAL_TYPE
+           && TREE_CODE (cur_type) == REAL_TYPE)
+	  || (TREE_CODE (wanted_type) == INTEGER_TYPE
 	  && TREE_CODE (cur_type) == INTEGER_TYPE
 	  && (!pedantic || i == 0 || (i == 1 && char_type_flag))
 	  && (TYPE_UNSIGNED (wanted_type)
 	      ? wanted_type == c_common_unsigned_type (cur_type)
-	      : wanted_type == c_common_signed_type (cur_type)))
+	      : wanted_type == c_common_signed_type (cur_type))))
 	continue;
       /* Likewise, "signed char", "unsigned char" and "char" are
 	 equivalent but the above test won't consider them equivalent.  */
diff -Naur gcc-4.1.2.orig/gcc/c-incpath.c gcc-4.1.2-src/gcc/c-incpath.c
--- gcc-4.1.2.orig/gcc/c-incpath.c	2005-06-25 04:02:01.000000000 +0200
+++ gcc-4.1.2-src/gcc/c-incpath.c	2007-02-19 02:32:34.000000000 +0100
@@ -335,9 +335,13 @@
      function does not recognize a directory that ends in a backslash
      (unless it is a drive root dir, such "c:\").  Forward slashes,
      trailing or otherwise, cause no problems for stat().  */
+  /* (TIGCC 20050206) This is entirely backwards! We need backslashes.
+                      Forward-slashes are no good. But we need to get rid of
+                      trailing backslashes. -- Kevin Kofler  */
   char* c;
   for (c = path; *c; c++)
-    if (*c == '\\') *c = '/';
+    if (*c == '/') *c = '\\';
+  if (c[strlen(c)-1] == '\\') c[strlen(c)-1] = '\0';
 #endif
 
   p = xmalloc (sizeof (cpp_dir));
@@ -360,6 +364,7 @@
 			 const char *iprefix, int stdinc, int cxx_stdinc,
 			 int verbose)
 {
+#if 0 /* (TIGCC 20050205) Don't use environment variables. */
   static const char *const lang_env_vars[] =
     { "C_INCLUDE_PATH", "CPLUS_INCLUDE_PATH",
       "OBJC_INCLUDE_PATH", "OBJCPLUS_INCLUDE_PATH" };
@@ -375,11 +380,14 @@
      include chain.  */
   add_env_var_paths ("CPATH", BRACKET);
   add_env_var_paths (lang_env_vars[idx], SYSTEM);
+#endif /* 0 */
   
   target_c_incpath.extra_pre_includes (sysroot, iprefix, stdinc);
 
   /* Finally chain on the standard directories.  */
-  if (stdinc)
+  /* (TIGCC 20031007) We don't want any "standard" include directories.
+                      -- Kevin Kofler  */
+  if (0 /*stdinc*/)
     add_standard_paths (sysroot, iprefix, cxx_stdinc);
 
   target_c_incpath.extra_includes (sysroot, iprefix, stdinc);
diff -Naur gcc-4.1.2.orig/gcc/c-lang.c gcc-4.1.2-src/gcc/c-lang.c
--- gcc-4.1.2.orig/gcc/c-lang.c	2005-07-01 01:09:06.000000000 +0200
+++ gcc-4.1.2-src/gcc/c-lang.c	2007-02-19 02:32:34.000000000 +0100
@@ -44,6 +44,8 @@
 #define LANG_HOOKS_NAME "GNU C"
 #undef LANG_HOOKS_INIT
 #define LANG_HOOKS_INIT c_objc_common_init
+#undef LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES
+#define LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES c_insert_default_attributes
 
 /* Each front end provides its own lang hook initializer.  */
 const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
diff -Naur gcc-4.1.2.orig/gcc/c-lex.c gcc-4.1.2-src/gcc/c-lex.c
--- gcc-4.1.2.orig/gcc/c-lex.c	2006-07-01 18:32:00.000000000 +0200
+++ gcc-4.1.2-src/gcc/c-lex.c	2007-02-19 02:32:34.000000000 +0100
@@ -434,7 +434,7 @@
 	cppchar_t c = tok->val.str.text[0];
 
 	if (c == '"' || c == '\'')
-	  error ("missing terminating %c character", (int) c);
+	  cpp_unterminated (parse_in, c);
 	else if (ISGRAPH (c))
 	  error ("stray %qc in program", (int) c);
 	else
diff -Naur gcc-4.1.2.orig/gcc/combine.c gcc-4.1.2-src/gcc/combine.c
--- gcc-4.1.2.orig/gcc/combine.c	2007-01-21 23:34:57.000000000 +0100
+++ gcc-4.1.2-src/gcc/combine.c	2007-02-19 02:32:34.000000000 +0100
@@ -4423,8 +4423,10 @@
       /* x - 0 is the same as x unless x's mode has signed zeros and
 	 allows rounding towards -infinity.  Under those conditions,
 	 0 - 0 is -0.  */
+      /* (TIGCC 20050210) This is invalid independently of the rounding mode
+                          for 3-sign-zeros. */
       if (!(HONOR_SIGNED_ZEROS (GET_MODE (XEXP (x, 0)))
-	    && HONOR_SIGN_DEPENDENT_ROUNDING (GET_MODE (XEXP (x, 0))))
+	    /*&& HONOR_SIGN_DEPENDENT_ROUNDING (GET_MODE (XEXP (x, 0)))*/)
 	  && XEXP (x, 1) == CONST0_RTX (GET_MODE (XEXP (x, 0))))
 	return XEXP (x, 0);
       break;
diff -Naur gcc-4.1.2.orig/gcc/common.opt gcc-4.1.2-src/gcc/common.opt
--- gcc-4.1.2.orig/gcc/common.opt	2006-05-17 20:38:58.000000000 +0200
+++ gcc-4.1.2-src/gcc/common.opt	2007-02-19 02:32:34.000000000 +0100
@@ -447,6 +447,14 @@
 Perform global common subexpression elimination after register allocation
 has finished
 
+fglobal-cast-constructors
+Common Report Var(flag_global_compound_literals) Init(1)
+Make compound literals (cast constructors) global for backwards compatibility
+
+fglobal-compound-literals
+Common Report Var(flag_global_compound_literals) VarExists
+Make compound literals (cast constructors) global for backwards compatibility
+
 fguess-branch-probability
 Common Report Var(flag_guess_branch_prob)
 Enable guessing of branch probabilities
@@ -562,6 +570,10 @@
 Common Report Var(flag_merge_constants,2) Init(1)
 Attempt to merge identical constants and constant variables
 
+fmerge-constant-pools
+Common Report Var(flag_merge_constant_pools) Init(1)
+When merging constants, also merge constant pools
+
 fmerge-constants
 Common Report Var(flag_merge_constants,1) VarExists
 Attempt to merge identical constants across compilation units
@@ -590,6 +602,10 @@
 Common RejectNegative Report Var(flag_mudflap_ignore_reads)
 Ignore read operations when inserting mudflap instrumentation
 
+freg-relative-
+Common Joined RejectNegative
+-freg-relative-<register>	Emit code relative to the base register <register>
+
 freschedule-modulo-scheduled-loops
 Common Report Var(flag_resched_modulo_sched)
 Enable/Disable the traditional scheduling in loops that already passed modulo scheduling
@@ -1042,7 +1058,7 @@
 Assume signed arithmetic overflow wraps around
 
 fzero-initialized-in-bss
-Common Report Var(flag_zero_initialized_in_bss) Init(1)
+Common Report Var(flag_zero_initialized_in_bss) Init(0)
 Put zero initialized data in the bss section
 
 g
diff -Naur gcc-4.1.2.orig/gcc/config/dbxcoff.h gcc-4.1.2-src/gcc/config/dbxcoff.h
--- gcc-4.1.2.orig/gcc/config/dbxcoff.h	2005-06-25 03:22:41.000000000 +0200
+++ gcc-4.1.2-src/gcc/config/dbxcoff.h	2007-02-19 02:32:34.000000000 +0100
@@ -48,8 +48,13 @@
 
 /* Like block addresses, stabs line numbers are relative to the
    current function.  */
+/* TIGCC Patch: We don't want COFF line numbers to be function-relative.
+   That's why we write '.ln LINE'. This will break support for existing
+   debuggers, but there are none for TIGCC. The line numbers can be
+   extracted from the .s file, plus they are passed on to the object file
+   symbol table. */
 
-#define DBX_LINES_FUNCTION_RELATIVE 1
+#define DBX_LINES_FUNCTION_RELATIVE (!TARGET_COFFABSLINES)
 
 /* When generating stabs debugging, use N_BINCL entries.  */
 
diff -Naur gcc-4.1.2.orig/gcc/config/i386/xm-mingw32.h gcc-4.1.2-src/gcc/config/i386/xm-mingw32.h
--- gcc-4.1.2.orig/gcc/config/i386/xm-mingw32.h	2005-06-25 03:22:41.000000000 +0200
+++ gcc-4.1.2-src/gcc/config/i386/xm-mingw32.h	2007-02-19 02:32:34.000000000 +0100
@@ -20,6 +20,10 @@
 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 02110-1301, USA.  */
 
+/* Mingw32 does not try to hide the underlying DOS-based file system
+   like Cygwin does.  */
+#define HAVE_DOS_BASED_FILE_SYSTEM
+
 #define HOST_EXECUTABLE_SUFFIX ".exe"
 
 #undef PATH_SEPARATOR
diff -Naur gcc-4.1.2.orig/gcc/config/m68k/m68k.c gcc-4.1.2-src/gcc/config/m68k/m68k.c
--- gcc-4.1.2.orig/gcc/config/m68k/m68k.c	2005-12-29 16:10:35.000000000 +0100
+++ gcc-4.1.2-src/gcc/config/m68k/m68k.c	2007-02-19 02:32:34.000000000 +0100
@@ -43,6 +43,11 @@
 #include "target-def.h"
 #include "debug.h"
 #include "flags.h"
+#include "c-pragma.h"
+#include "cgraph.h"
+
+/* TIGCC register for reg-relative code.  */
+char TARGET_RELATION_REG[10] = "a4";
 
 enum reg_class regno_reg_class[] =
 {
@@ -122,10 +127,20 @@
 static bool m68k_save_reg (unsigned int regno, bool interrupt_handler);
 static int const_int_cost (rtx);
 static bool m68k_rtx_costs (rtx, int, int, int *);
+static bool m68k_cannot_force_const_mem (rtx); /* (TIGCC 20050424) */
+
+static int comp_m68k_type_attributes (tree, tree);
+static int comp_amigaos_type_attributes (tree, tree);
+static tree m68k_handle_stkparm_attribute (tree *, tree, tree, int, bool *);
+static tree m68k_handle_regparm_attribute (tree *, tree, tree, int, bool *);
 
 
 /* Specify the identification number of the library being built */
 const char *m68k_library_id_string = "_current_shared_library_a5_offset_";
+/* Specify number of registers for integer, pointer and float arguments.  */
+const char *m68k_regparm_string;
+/* Specify number of registers for integer, pointer and float arguments.  */
+int m68k_regparm;
 
 /* Nonzero if the last compare/test insn had FP operands.  The
    sCC expanders peek at this to determine what to do for the
@@ -133,6 +148,8 @@
 int m68k_last_compare_had_fp_operands;
 
 /* Initialize the GCC target structure.  */
+#undef TARGET_COMP_TYPE_ATTRIBUTES
+#define TARGET_COMP_TYPE_ATTRIBUTES comp_amigaos_type_attributes
 
 #if INT_OP_GROUP == INT_OP_DOT_WORD
 #undef TARGET_ASM_ALIGNED_HI_OP
@@ -186,15 +203,35 @@
 #undef TARGET_ATTRIBUTE_TABLE
 #define TARGET_ATTRIBUTE_TABLE m68k_attribute_table
 
+/* Pass the right values to functions whose prototypes contain "char"
+   or "short". */
+#if 0
 #undef TARGET_PROMOTE_PROTOTYPES
 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
+#endif /* 0 */
 
 #undef TARGET_STRUCT_VALUE_RTX
 #define TARGET_STRUCT_VALUE_RTX m68k_struct_value_rtx
 
+#undef TARGET_ASM_FILE_START
+#define TARGET_ASM_FILE_START m68k_asm_file_start
+
+/* (TIGCC 20050424) Everything which is not a CONST_DOUBLE has no business of
+                    being in the constant pool. This is especially valid for
+                    expressions containing relocations. -- Kevin Kofler */
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM m68k_cannot_force_const_mem
+
 static const struct attribute_spec m68k_attribute_table[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
+  /* The stkparm attribute means a function takes its parameters on the stack
+     (AMS calling convention). */
+  { "stkparm",   0, 0, false, true,  true,  m68k_handle_stkparm_attribute },
+  /* The regparm attribute means a function takes its parameters in registers.
+     Its optional argument specifies the maximum number of arguments to be
+     passed in each category of registers (data registers, address registers). */
+  { "regparm",   0, 1, false, true,  true,  m68k_handle_regparm_attribute },
   { "interrupt_handler", 0, 0, true,  false, false, m68k_handle_fndecl_attribute },
   { NULL,                0, 0, false, false, false, NULL }
 };
@@ -314,6 +351,19 @@
 void
 override_options (void)
 {
+   /* Validate -mregparm and -mregparm= value.  */
+   if (m68k_regparm_string)
+     {
+       m68k_regparm = atoi (m68k_regparm_string);
+       if (m68k_regparm < 1 || m68k_regparm > M68K_MAX_REGPARM)
+ 	error ("-mregparm=%d is not between 1 and %d",
+ 	       m68k_regparm, M68K_MAX_REGPARM);
+       target_flags |= MASK_REGPARM;
+     }
+   else
+     if (TARGET_REGPARM)
+       m68k_regparm = M68K_DEFAULT_REGPARM;
+
   /* Sanity check to ensure that msep-data and mid-sahred-library are not
    * both specified together.  Doing so simply doesn't make sense.
    */
@@ -349,6 +399,116 @@
   SUBTARGET_OVERRIDE_OPTIONS;
 }
 
+/* Handle a "stkparm" attribute;
+   arguments as in struct attribute_spec.handler. */
+static tree
+m68k_handle_stkparm_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
+                               int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+{
+  if (lookup_attribute ("regparm", TYPE_ATTRIBUTES (*node)))
+  {
+    error ("`regparm' and `stkparm' are mutually exclusive");
+    *no_add_attrs = true;
+  }
+
+  if (TREE_CODE (*node) != FUNCTION_TYPE
+      && TREE_CODE (*node) != METHOD_TYPE
+      && TREE_CODE (*node) != FIELD_DECL
+      && TREE_CODE (*node) != TYPE_DECL)
+    {
+      warning (0, "`%s' attribute only applies to functions",
+	       IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
+/* Handle a "regparm" attribute;
+   arguments as in struct attribute_spec.handler. */
+static tree
+m68k_handle_regparm_attribute (tree *node, tree name, tree args,
+                               int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+{
+  if (lookup_attribute ("stkparm", TYPE_ATTRIBUTES (*node)))
+  {
+    error ("`regparm' and `stkparm' are mutually exclusive");
+    *no_add_attrs = true;
+  }
+
+  if (TREE_CODE (*node) != FUNCTION_TYPE
+      && TREE_CODE (*node) != METHOD_TYPE
+      && TREE_CODE (*node) != FIELD_DECL
+      && TREE_CODE (*node) != TYPE_DECL)
+    {
+      warning (0, "`%s' attribute only applies to functions",
+	       IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+  else
+    {
+      /* 'regparm' accepts one optional argument - number of registers per
+         single class (data, address) that should be used to pass arguments. */
+      if (args && TREE_CODE (args) == TREE_LIST)
+      {
+        tree numofregs = TREE_VALUE (args);
+        if (numofregs)
+          if (TREE_CODE (numofregs) != INTEGER_CST
+              || TREE_INT_CST_HIGH (numofregs)
+              || TREE_INT_CST_LOW (numofregs) < 1
+              || TREE_INT_CST_LOW (numofregs) > M68K_MAX_REGPARM)
+          {
+            error ("invalid argument to `regparm' attribute");
+       	    *no_add_attrs = true;
+          }
+      }
+    }
+
+  return NULL_TREE;
+}
+
+/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible,
+   one if they are compatible, and two if they are nearly compatible
+   (which causes a warning to be generated). */
+
+int
+comp_m68k_type_attributes (tree type1, tree type2)
+{
+  /* Functions or methods are incompatible if they specify mutually
+     exclusive ways of passing arguments.  */
+  if (TREE_CODE (type1) == FUNCTION_TYPE || TREE_CODE (type1) == METHOD_TYPE)
+    {
+      tree arg1, arg2;
+      if (!! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type1)) !=
+	     !! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type2))
+	  || !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1)) !=
+	     !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2)))
+	return 0; /* 'regparm' and 'stkparm' are mutually exclusive.  */
+
+      arg1 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1));
+      arg2 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2));
+      if (arg1 && arg2)
+	{
+	  int num1 = 0, num2 = 0;
+	  if (TREE_VALUE (arg1) && TREE_CODE (TREE_VALUE (arg1)) == TREE_LIST)
+	    {
+	      tree numofregs = TREE_VALUE (TREE_VALUE (arg1));
+	      if (numofregs)
+		num1 = TREE_INT_CST_LOW (numofregs);
+	    }
+	  if (TREE_VALUE (arg2) && TREE_CODE (TREE_VALUE (arg2)) == TREE_LIST)
+	    {
+	      tree numofregs = TREE_VALUE (TREE_VALUE (arg2));
+	      if (numofregs)
+		num2 = TREE_INT_CST_LOW (numofregs);
+	    }
+	  if (num1 != num2)
+	    return 0; /* Different numbers, or no number in one type.  */
+	}
+    }
+  return 1;
+}
+
 /* Return nonzero if FUNC is an interrupt function as specified by the
    "interrupt_handler" attribute.  */
 static bool
@@ -464,6 +624,11 @@
 static bool
 m68k_save_reg (unsigned int regno, bool interrupt_handler)
 {
+  /* (TIGCC 20050208) Handle OPTIMIZE_ROM_CALLS. Register #13 is %a5. */
+  if (interrupt_handler && regno == 13 && global_regs[13]
+      && cpp_defined (parse_in, (unsigned char *)"OPTIMIZE_ROM_CALLS", 18))
+    return true;
+
   if (flag_pic && regno == PIC_OFFSET_TABLE_REGNUM)
     {
       if (current_function_uses_pic_offset_table)
@@ -603,7 +768,8 @@
 
       if (dwarf2out_do_frame ())
 	{
-	  cfa_offset += current_frame.size + 4;
+	  /* (TIGCC 20050407) This +4 seems wrong from my tests. */
+	  cfa_offset += current_frame.size /*+ 4*/;
 	  dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, cfa_offset);
 	}
     } /* !frame_pointer_needed */
@@ -724,6 +890,11 @@
 	    }
 	}
     }
+
+  /* (TIGCC 20050208) Handle OPTIMIZE_ROM_CALLS. Register #13 is %a5. */
+  if (global_regs[13] && m68k_interrupt_function_p (current_function_decl)
+      && cpp_defined (parse_in, (unsigned char *)"OPTIMIZE_ROM_CALLS", 18))
+    asm_fprintf (stream, "\tmove.l 200.w,%%a5\n");
 }
 
 /* Return true if this function's epilogue can be output as RTL.  */
@@ -763,9 +934,11 @@
     insn = prev_nonnote_insn (insn);
   if (insn && GET_CODE (insn) == BARRIER)
     {
+#if 0 /* (TIGCC 20050206) */
       /* Output just a no-op so that debuggers don't get confused
 	 about which function the pc is in at this address.  */
       fprintf (stream, "\tnop\n");
+#endif /* 0 */
       return;
     }
 
@@ -1052,8 +1225,17 @@
          a shorter one that uses a GOT entry or a longer one that doesn't.
          We use the -Os command-line flag to decide which to generate.
          Both sequences take the same time to execute on the ColdFire.  */
+/* (TIGCC 20040222, 20050204) No long branches please... */
+/* (TIGCC 20050209) FIXME: This should really be handled fully in one place.
+                           Currently, part of this logic is in the patching code
+                           and part is in GCC. It should be all in GCC IMHO. */
+  else if (TARGET_PCREL && GET_CODE (dest) == MEM
+           && GET_CODE (XEXP (dest, 0)) == SYMBOL_REF
+           && (!strncmp(XSTR (XEXP (dest, 0), 0),"_ROM_CALL_",10)
+               || !strncmp(XSTR (XEXP (dest, 0), 0),"_RAM_CALL_",10)))
+    out = "jbsr %o0";
   else if (TARGET_PCREL)
-    out = "bsr.l %o0";
+    out = "bsr %o0";
   else if (TARGET_68020)
 #if defined(USE_GAS)
     out = "bsr.l %0@PLTPC";
@@ -1455,11 +1637,11 @@
 
 typedef enum { MOVL, SWAP, NEGW, NOTW, NOTB, MOVQ, MVS, MVZ } CONST_METHOD;
 
-static CONST_METHOD const_method (rtx);
+CONST_METHOD const_method (rtx);
 
 #define USE_MOVQ(i)	((unsigned)((i) + 128) <= 255)
 
-static CONST_METHOD
+CONST_METHOD
 const_method (rtx constant)
 {
   int i;
@@ -1561,10 +1743,15 @@
        for add and the time for shift, taking away a little more because
        sometimes move insns are needed.  */
     /* div?.w is relatively cheaper on 68000 counted in COSTS_N_INSNS terms.  */
+    /* (TIGCC 20030705) Decrease multiplication/division cost under -Os, so that
+                        muls/divs/divu gets preferred over large expansions of
+                        shifts & adds.
+                        -- Kevin Kofler */
 #define MULL_COST (TARGET_68060 ? 2 : TARGET_68040 ? 5 : (TARGET_COLDFIRE && !TARGET_5200) ? 3 : TARGET_COLDFIRE ? 10 : 13)
-#define MULW_COST (TARGET_68060 ? 2 : TARGET_68040 ? 3 : TARGET_68020 ? 8 : \
-			(TARGET_COLDFIRE && !TARGET_5200) ? 2 : 5)
-#define DIVW_COST (TARGET_68020 ? 27 : TARGET_CF_HWDIV ? 11 : 12)
+#define MULW_COST (optimize_size ? 3 : (TARGET_68060 ? 2 : TARGET_68040 ? 3 : TARGET_68020 ? 8 : \
+			(TARGET_COLDFIRE && !TARGET_5200) ? 2 : 5))
+#define DIVW_COST (optimize_size ? 3 : (TARGET_68020 ? 27 : TARGET_CF_HWDIV ? 11 : 12))
+#define UDIVW_COST (optimize_size ? 6 : (TARGET_68020 ? 27 : TARGET_CF_HWDIV ? 11 : 12))
 
     case PLUS:
       /* An lea costs about three times as much as a simple add.  */
@@ -1595,11 +1782,15 @@
         {
 	  if (GET_CODE (XEXP (x, 1)) == CONST_INT)
 	    {
+/* (TIGCC 20030705) shifts costs under -Os are instruction counts, not cycle counts -- Kevin Kofler */ \
+/* (TIGCC 20050210) lsl #2 is cheaper than 2 adds even when optimizing for speed.
+                    This ugly hack (making long shifts "cost less" than word
+                    shifts) accounts for that. */ \
 	      if (INTVAL (XEXP (x, 1)) < 16)
-	        *total = COSTS_N_INSNS (2) + INTVAL (XEXP (x, 1)) / 2;
+	        *total = COSTS_N_INSNS (2) + INTVAL (XEXP (x, 1)) / (optimize_size ? 9 : GET_MODE (x) == SImode ? 3 : 2);
 	      else
 	        /* We're using clrw + swap for these cases.  */
-	        *total = COSTS_N_INSNS (4) + (INTVAL (XEXP (x, 1)) - 16) / 2;
+	        *total = COSTS_N_INSNS (4) + (INTVAL (XEXP (x, 1)) - 16) / (optimize_size ? 9 : GET_MODE (x) == SImode ? 3 : 2);
 	    }
 	  else
 	    *total = COSTS_N_INSNS (10); /* worst case */
@@ -1632,10 +1823,10 @@
         *total = COSTS_N_INSNS (MULL_COST);
       return true;
 
+/* (TIGCC 20030705) distinguish signed vs. unsigned division */ \
+/* - ext is cheaper than the unsigned equivalent -- Kevin Kofler */ \
     case DIV:
-    case UDIV:
     case MOD:
-    case UMOD:
       if (GET_MODE (x) == QImode || GET_MODE (x) == HImode)
         *total = COSTS_N_INSNS (DIVW_COST);	/* div.w */
       else if (TARGET_CF_HWDIV)
@@ -1644,6 +1835,16 @@
 	*total = COSTS_N_INSNS (43);		/* div.l */
       return true;
 
+    case UDIV:							\
+    case UMOD:							\
+      if (GET_MODE (x) == QImode || GET_MODE (x) == HImode)
+        *total = COSTS_N_INSNS (UDIVW_COST);	/* div.w */
+      else if (TARGET_CF_HWDIV)
+        *total = COSTS_N_INSNS (18);
+      else
+	*total = COSTS_N_INSNS (43);		/* div.l */
+      return true;
+
     default:
       return false;
     }
@@ -1860,6 +2061,24 @@
   return "move%.b %1,%0";
 }
 
+static const char *
+output_move_himode_const (rtx *operands)
+{
+  if (operands[1] == const0_rtx
+      && (DATA_REG_P (operands[0])
+	  || GET_CODE (operands[0]) == MEM)
+      /* clr insns on 68000 read before writing.
+	 This isn't so on the 68010, but we have no TARGET_68010.  */
+      && ((TARGET_68020 || TARGET_5200)
+	  || !(GET_CODE (operands[0]) == MEM
+	       && MEM_VOLATILE_P (operands[0]))))
+    return "clr%.w %0";
+  else if (operands[1] == const0_rtx
+	   && ADDRESS_REG_P (operands[0]))
+    return "sub%.w %0,%0";
+  return "move%.w %1,%0";
+}
+
 const char *
 output_move_stricthi (rtx *operands)
 {
@@ -1884,6 +2103,17 @@
   return "move%.b %1,%0";
 }
 
+/* (TIGCC) Return the best assembler insn template
+   for moving operands[1] into operands[0] as a halfword.  */
+
+static const char *
+halfsinglemove_string (rtx *operands)
+{
+  if (GET_CODE (operands[1]) == CONST_INT)
+    return output_move_himode_const (operands);
+  return "move%.w %1,%0";
+}
+
 /* Return the best assembler insn template
    for moving operands[1] into operands[0] as a fullword.  */
 
@@ -1960,10 +2190,14 @@
       operands[0] = XEXP (XEXP (operands[0], 0), 0);
       if (size == 12)
         output_asm_insn ("sub%.l #12,%0", operands);
+      else if (size == 10)
+        output_asm_insn ("sub%.l #10,%0", operands);
       else
         output_asm_insn ("subq%.l #8,%0", operands);
-      if (GET_MODE (operands[1]) == XFmode)
+      if (GET_MODE (operands[0]) == XFmode)
 	operands[0] = gen_rtx_MEM (XFmode, operands[0]);
+      else if (GET_MODE (operands[0]) == BFmode)
+	operands[0] = gen_rtx_MEM (BFmode, operands[0]);
       else if (GET_MODE (operands[0]) == DFmode)
 	operands[0] = gen_rtx_MEM (DFmode, operands[0]);
       else
@@ -1975,10 +2209,14 @@
       operands[1] = XEXP (XEXP (operands[1], 0), 0);
       if (size == 12)
         output_asm_insn ("sub%.l #12,%1", operands);
+      else if (size == 10)
+        output_asm_insn ("sub%.l #10,%1", operands);
       else
         output_asm_insn ("subq%.l #8,%1", operands);
       if (GET_MODE (operands[1]) == XFmode)
 	operands[1] = gen_rtx_MEM (XFmode, operands[1]);
+      else if (GET_MODE (operands[1]) == BFmode)
+	operands[1] = gen_rtx_MEM (BFmode, operands[1]);
       else if (GET_MODE (operands[1]) == DFmode)
 	operands[1] = gen_rtx_MEM (DFmode, operands[1]);
       else
@@ -2014,7 +2252,7 @@
       else if (optype0 == OFFSOP)
 	{
 	  middlehalf[0] = adjust_address (operands[0], SImode, 4);
-	  latehalf[0] = adjust_address (operands[0], SImode, size - 4);
+	  latehalf[0] = adjust_address (operands[0], SImode, 8);
 	}
       else
 	{
@@ -2030,7 +2268,7 @@
       else if (optype1 == OFFSOP)
 	{
 	  middlehalf[1] = adjust_address (operands[1], SImode, 4);
-	  latehalf[1] = adjust_address (operands[1], SImode, size - 4);
+	  latehalf[1] = adjust_address (operands[1], SImode, 8);
 	}
       else if (optype1 == CNSTOP)
 	{
@@ -2058,8 +2296,66 @@
 	  latehalf[1] = operands[1];
 	}
     }
-  else
-    /* size is not 12: */
+  else if (size == 10)
+    {
+      if (optype0 == REGOP)
+	{
+	  latehalf[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 2);
+	  middlehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+	}
+      else if (optype0 == OFFSOP)
+	{
+	  middlehalf[0] = adjust_address (operands[0], SImode, 4);
+	  latehalf[0] = adjust_address (operands[0], SImode, 8);
+	}
+      else
+	{
+	  middlehalf[0] = operands[0];
+	  latehalf[0] = operands[0];
+	}
+
+      if (optype1 == REGOP)
+	{
+	  latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 2);
+	  middlehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
+	}
+      else if (optype1 == OFFSOP)
+	{
+	  middlehalf[1] = adjust_address (operands[1], SImode, 4);
+	  latehalf[1] = adjust_address (operands[1], SImode, 8);
+	}
+      else if (optype1 == CNSTOP)
+	{
+	  if (GET_CODE (operands[1]) == CONST_DOUBLE)
+	    {
+	      REAL_VALUE_TYPE r;
+	      long l[3];
+
+	      gcc_unreachable ();
+	      REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+	      REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
+	      operands[1] = GEN_INT (l[0]);
+	      middlehalf[1] = GEN_INT (l[1]);
+	      latehalf[1] = GEN_INT (l[2]);
+	    }
+	  else if (CONSTANT_P (operands[1]))
+	    {
+	      /* actually, no non-CONST_DOUBLE constant should ever
+		 appear here.  */
+	      gcc_unreachable ();
+	      if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 0)
+		latehalf[1] = constm1_rtx;
+	      else
+		latehalf[1] = const0_rtx;
+	    }
+	}
+      else
+	{
+	  middlehalf[1] = operands[1];
+	  latehalf[1] = operands[1];
+	}
+    }
+  else    /* size is neither 12 or 10: */
     {
       if (optype0 == REGOP)
 	latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
@@ -2084,7 +2380,16 @@
   if (optype0 == PUSHOP
       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
+  {
+    if (size==10) {
+      /* (TIGCC 20040219) The above is not quite right for size==10. What we
+         have to do here is: (1) move.w operands[1]+8,-(%sp);
+         (2) move.l operands[1]+6,-(%sp); (3) move.l operands[1]+6,-(%sp).
+         -- Kevin Kofler */
+      operands[1] = middlehalf[1] = adjust_address (operands[1], SImode, 6);
+    } else
     operands[1] = middlehalf[1] = latehalf[1];
+  }
 
   /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
      if the upper part of reg N does not appear in the MEM, arrange to
@@ -2112,6 +2417,12 @@
 	      middlehalf[1] = adjust_address (operands[1], DImode, size - 8);
 	      latehalf[1] = adjust_address (operands[1], DImode, size - 4);
 	    }
+	  else if( GET_MODE (operands[1]) == BFmode )
+	    {
+	      operands[1] = gen_rtx_MEM (BFmode, latehalf[0]);
+	      middlehalf[1] = adjust_address (operands[1], DImode, 4);
+	      latehalf[1] = adjust_address (operands[1], DImode, 8);
+	    }
 	  else
 	    {
 	      operands[1] = gen_rtx_MEM (DImode, latehalf[0]);
@@ -2141,6 +2452,30 @@
 	  output_asm_insn (singlemove_string (middlehalf), middlehalf);
 	  return "";
 	}
+      else if (size == 10
+	       && reg_overlap_mentioned_p (middlehalf[0],
+					   XEXP (operands[1], 0)))
+	{
+	  /* Check for two regs used by both source and dest.
+	     Note that this can't happen if the dest is all data regs.
+	     It can happen if the dest is d6, d7, a0.
+	     But in that case, latehalf is an addr reg, so
+	     the code at compadr does ok.  */
+
+	  if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
+	      || reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
+	    goto compadr;
+
+	  /* JRV says this can't happen: */
+	  if (addreg0 || addreg1)
+	    gcc_unreachable ();
+
+	  /* Only the middle reg conflicts; simply put it last. */
+	  output_asm_insn (singlemove_string (operands), operands);
+	  output_asm_insn (halfsinglemove_string (latehalf), latehalf);
+	  output_asm_insn (singlemove_string (middlehalf), middlehalf);
+	  return "";
+	}
       else if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0)))
 	/* If the low half of dest is mentioned in the source memory
 	   address, the arrange to emit the move late half first.  */
@@ -2164,21 +2499,24 @@
       /* Make any unoffsettable addresses point at high-numbered word.  */
       if (addreg0)
 	{
-	  if (size == 12)
+	  if (size == 12 || size == 10)
 	    output_asm_insn ("addq%.l #8,%0", &addreg0);
 	  else
 	    output_asm_insn ("addq%.l #4,%0", &addreg0);
 	}
       if (addreg1)
 	{
-	  if (size == 12)
+	  if (size == 12 || size == 10)
 	    output_asm_insn ("addq%.l #8,%0", &addreg1);
 	  else
 	    output_asm_insn ("addq%.l #4,%0", &addreg1);
 	}
 
       /* Do that word.  */
-      output_asm_insn (singlemove_string (latehalf), latehalf);
+      if (size == 10)
+        output_asm_insn (halfsinglemove_string (latehalf), latehalf);
+      else
+        output_asm_insn (singlemove_string (latehalf), latehalf);
 
       /* Undo the adds we just did.  */
       if (addreg0)
@@ -2186,7 +2524,7 @@
       if (addreg1)
 	output_asm_insn ("subq%.l #4,%0", &addreg1);
 
-      if (size == 12)
+      if (size == 12 || size == 10)
 	{
 	  output_asm_insn (singlemove_string (middlehalf), middlehalf);
 	  if (addreg0)
@@ -2204,7 +2542,7 @@
   output_asm_insn (singlemove_string (operands), operands);
 
   /* Do the middle one of the three words for long double */
-  if (size == 12)
+  if (size == 12 || size == 10)
     {
       if (addreg0)
 	output_asm_insn ("addq%.l #4,%0", &addreg0);
@@ -2221,19 +2559,22 @@
     output_asm_insn ("addq%.l #4,%0", &addreg1);
 
   /* Do that word.  */
-  output_asm_insn (singlemove_string (latehalf), latehalf);
+  if (size == 10)
+    output_asm_insn (halfsinglemove_string (latehalf), latehalf);
+  else
+    output_asm_insn (singlemove_string (latehalf), latehalf);
 
   /* Undo the adds we just did.  */
   if (addreg0)
     {
-      if (size == 12)
+      if (size == 12 || size == 10)
         output_asm_insn ("subq%.l #8,%0", &addreg0);
       else
         output_asm_insn ("subq%.l #4,%0", &addreg0);
     }
   if (addreg1)
     {
-      if (size == 12)
+      if (size == 12 || size == 10)
         output_asm_insn ("subq%.l #8,%0", &addreg1);
       else
         output_asm_insn ("subq%.l #4,%0", &addreg1);
@@ -2563,6 +2904,8 @@
 int
 floating_exact_log2 (rtx x)
 {
+gcc_unreachable();
+#if 0
   REAL_VALUE_TYPE r, r1;
   int exp;
 
@@ -2577,6 +2920,7 @@
     return exp;
 
   return 0;
+#endif /* 0 */
 }
 
 /* A C compound statement to output to stdio stream STREAM the
@@ -2623,6 +2967,8 @@
    'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
        or print pair of registers as rx:ry.
 
+(TIGCC 20040222) 'A' like 'o', but for addresses.
+
    */
 
 void
@@ -2663,6 +3009,14 @@
 		  && TARGET_PCREL);
       output_addr_const (file, XEXP (op, 0));
     }
+  else if (letter == 'A') /* (TIGCC 20040222) */
+    {
+      if (TARGET_PCREL) {
+        target_flags&=~MASK_PCREL; /* ugly hack, but works */
+        print_operand_address(file,op);
+        target_flags|=MASK_PCREL;
+      } else print_operand_address(file,op);
+    }
   else if (GET_CODE (op) == REG)
     {
       if (letter == 'R')
@@ -2675,13 +3029,24 @@
   else if (GET_CODE (op) == MEM)
     {
       output_address (XEXP (op, 0));
+      /* TIGCC Patch: This is a very bad try to implement addresses relative to a register.
+         Julien Muchembled says this should work.
+         At least it should if only one file is used.
+         (TIGCC 20040808) Added CONST. A MEM(CONST) is used for sym+const addressing. This
+                          needs to be made reg-relative too. -- Kevin Kofler  */
+      if (TARGET_REG_RELATIVE && (GET_CODE (XEXP (op, 0)) == SYMBOL_REF || GET_CODE (XEXP (op, 0)) == LABEL_REF || GET_CODE (XEXP (op, 0)) == CODE_LABEL || GET_CODE (XEXP (op, 0)) == CONST))
+        fprintf (file, "-__relation(%%%s)", TARGET_RELATION_REG);
+      else
+	{
       if (letter == 'd' && ! TARGET_68020
 	  && CONSTANT_ADDRESS_P (XEXP (op, 0))
 	  && !(GET_CODE (XEXP (op, 0)) == CONST_INT
 	       && INTVAL (XEXP (op, 0)) < 0x8000
 	       && INTVAL (XEXP (op, 0)) >= -0x8000))
 	fprintf (file, MOTOROLA ? ".l" : ":l");
+	}
     }
+#if 0
   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
     {
       REAL_VALUE_TYPE r;
@@ -2700,6 +3065,7 @@
       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
       ASM_OUTPUT_DOUBLE_OPERAND (file, r);
     }
+#endif /* 0 */
   else
     {
       /* Use `print_operand_address' instead of `output_addr_const'
@@ -3232,6 +3598,169 @@
   return "eor%.l %2,%0";
 }
 
+/* Argument-passing support functions.  */
+
+/* Initialize a variable CUM of type CUMULATIVE_ARGS
+   for a call to a function whose data type is FNTYPE.
+   For a library call, FNTYPE is 0.  */
+
+static void
+m68k_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, tree fndecl)
+{
+  cum->last_arg_reg = -1;
+  cum->regs_already_used = 0;
+  if (fntype)
+    {
+      if (lookup_attribute ("stkparm", TYPE_ATTRIBUTES (fntype)))
+	cum->num_of_regs = 0;
+      else
+	{
+	  tree ratree = lookup_attribute ("regparm", TYPE_ATTRIBUTES (fntype));
+	  if (ratree)
+	    {
+	      cum->num_of_regs = m68k_regparm ? m68k_regparm
+					      : M68K_DEFAULT_REGPARM;
+	      if (TREE_VALUE (ratree)
+		  && TREE_CODE (TREE_VALUE (ratree)) == TREE_LIST)
+		{
+		  tree num_of_regs = TREE_VALUE (TREE_VALUE (ratree));
+		  cum->num_of_regs =
+		    num_of_regs ? TREE_INT_CST_LOW (num_of_regs) :
+		      (m68k_regparm ? m68k_regparm : M68K_DEFAULT_REGPARM);
+		}
+	    }
+/* (TIGCC 20050208) Use register calling convention for local functions when
+                    possible. Partially copied from i386.c. */
+	  else if (fndecl && flag_unit_at_a_time)
+	    {
+	      struct cgraph_local_info *i = cgraph_local_info (fndecl);
+	      if (i && i->local)
+	        {
+	          cum->num_of_regs = m68k_regparm ? m68k_regparm
+	                             : M68K_DEFAULT_REGPARM;
+	        }
+	      else
+	        cum->num_of_regs = m68k_regparm;
+	    }
+	  else
+	    cum->num_of_regs = m68k_regparm;
+	}
+    }
+  else /* Libcall.  */
+    cum->num_of_regs = 0;
+
+  if (cum->num_of_regs)
+    {
+      /* If this is a vararg call, put all arguments on stack.  */
+      tree param, next_param;
+      for (param = TYPE_ARG_TYPES (fntype); param; param = next_param)
+	{
+	  next_param = TREE_CHAIN (param);
+	  if (!next_param && TREE_VALUE (param) != void_type_node)
+	    cum->num_of_regs = 0;
+	}
+    }
+
+#if ! defined (PCC_STATIC_STRUCT_RETURN) && defined (M68K_STRUCT_VALUE_REGNUM)
+  /* If return value is a structure, and we pass the buffer address in a
+     register, we can't use this register for our own purposes.  */
+  if (fntype && aggregate_value_p (TREE_TYPE (fntype), fntype))
+    cum->regs_already_used |= (1 << M68K_STRUCT_VALUE_REGNUM);
+#endif
+
+  /* (TIGCC 20060916) Same for static chain. -- Kevin Kofler */
+  if (fndecl && decl_function_context(fndecl) && !DECL_NO_STATIC_CHAIN(fndecl))
+    cum->regs_already_used |= (1 << STATIC_CHAIN_REGNUM);
+}
+
+/* Update the data in CUM to advance over an argument.  */
+
+static void
+m68k_function_arg_advance (CUMULATIVE_ARGS *cum)
+{
+  if (cum->last_arg_reg != -1)
+    {
+      int count;
+      for (count = 0; count < cum->last_arg_len; count++)
+	cum->regs_already_used |= (1 << (cum->last_arg_reg + count));
+      cum->last_arg_reg = -1;
+    }
+}
+
+/* Define where to put the arguments to a function.
+   Value is zero to push the argument on the stack,
+   or a hard register in which to store the argument.
+
+   MODE is the argument's machine mode.
+   TYPE is the data type of the argument (as a tree).
+   This is null for libcalls where that information may
+    not be available.
+   CUM is a variable of type CUMULATIVE_ARGS which gives info about
+    the preceding args and about the function being called.  */
+
+static struct rtx_def *
+m68k_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type)
+{
+  if (cum->num_of_regs)
+    {
+      int regbegin = -1, altregbegin = -1, len;
+
+      /* FIXME: The last condition below is a workaround for a bug.  */
+      if (TARGET_68881 && FLOAT_MODE_P (mode) &&
+	  GET_MODE_UNIT_SIZE (mode) <= 12 &&
+	  (GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT || mode == SCmode))
+	{
+	  regbegin = 16; /* FPx */
+	  len = GET_MODE_NUNITS (mode);
+	}
+      /* FIXME: Two last conditions below are workarounds for bugs.  */
+      else if (INTEGRAL_MODE_P (mode) && mode !=CQImode && mode != CHImode)
+	{
+	  if (POINTER_TYPE_P (type))
+	    regbegin = 8; /* Ax */
+	  else
+	    regbegin = 0; /* Dx */
+	  altregbegin = 8 - regbegin;
+	  len = (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
+	}
+
+      if (regbegin != -1)
+	{
+	  int reg;
+	  long mask;
+
+look_for_reg:
+	  mask = 1 << regbegin;
+	  for (reg = 0; reg < cum->num_of_regs; reg++, mask <<= 1)
+	    if (!(cum->regs_already_used & mask))
+	      {
+		int end;
+		for (end = reg; end < cum->num_of_regs && end < reg + len;
+		     end++, mask <<= 1)
+		  if (cum->regs_already_used & mask)
+		    break;
+		if (end == reg + len)
+		  {
+		    cum->last_arg_reg = reg + regbegin;
+		    cum->last_arg_len = len;
+		    break;
+		  }
+	      }
+
+	  if (reg == cum->num_of_regs && altregbegin != -1)
+	    {
+	      regbegin = altregbegin;
+	      altregbegin = -1;
+	      goto look_for_reg;
+	    }
+	}
+
+      if (cum->last_arg_reg != -1)
+	return gen_rtx_REG (mode, cum->last_arg_reg);
+    }
+  return 0;
+}
+
 #ifdef M68K_TARGET_COFF
 
 /* Output assembly to switch to section NAME with attribute FLAGS.  */
@@ -3241,13 +3770,28 @@
 			     tree decl ATTRIBUTE_UNUSED)
 {
   char flagchar;
-
-  if (flags & SECTION_WRITE)
+  /* (TIGCC 20040725) Constant/string merging flags for TIGCC-extended COFF.
+                      SECTION_STRINGS is abused for the unaligned flag. */
+  const char *xflags = "";
+
+  /* (TIGCC 20040619) Handle BSS sections properly with -fdata-sections.
+                      -- Kevin Kofler*/
+  if ((flags & SECTION_BSS) && !TARGET_NO_BSS)
+    flagchar = 'b';
+  /* (TIGCC 20040620) Handle rodata sections properly with -fdata-sections.
+                      -- Kevin Kofler*/
+  else if ((flags & SECTION_WRITE)
+           || (!TARGET_RODATA_TO_TEXT && !(flags & SECTION_CODE)))
     flagchar = 'd';
   else
     flagchar = 'x';
 
-  fprintf (asm_out_file, "\t.section\t%s,\"%c\"\n", name, flagchar);
+  if (flags & SECTION_MERGE)
+    xflags = (flags & SECTION_STRINGS)?"mu":"m";
+  else if (flags & SECTION_STRINGS)
+    xflags = "u";
+
+  fprintf (asm_out_file, "\t.section\t%s,\"%c%s\"\n", name, flagchar, xflags);
 }
 
 #endif /* M68K_TARGET_COFF */
@@ -3300,7 +3844,7 @@
   if (flag_pic)
     {
       if (TARGET_PCREL)
-	fmt = "bra.l %o0";
+	fmt = "bra %o0"; /* (TIGCC 20040222, 20050204) No long branches please... */
       else if ((flag_pic == 1) || TARGET_68020)
 	{
 	  if (MOTOROLA)
@@ -3375,7 +3919,10 @@
     {
 	/* Address Registers, can't hold bytes, can hold aggregate if
 	   fits in.  */
-	if (GET_MODE_SIZE (mode) == 1)
+	/* (TIGCC 20050924) We can put bytes in address registers on non-Coldfire.
+	   GCC just uses word moves where appropriate. This always worked for us.
+	   -- Kevin Kofler */
+	if (TARGET_COLDFIRE && GET_MODE_SIZE (mode) == 1)
 	  return false;
 	if (regno + GET_MODE_SIZE (mode) / 4 <= 16)
 	  return true;
@@ -3391,3 +3938,127 @@
     }
   return false;
 }
+
+/* begin-TIGCC-local (regparms): explicit register specification for parameters */
+
+/* Initialize a variable CUM of type CUMULATIVE_ARGS
+   for a call to a function whose data type is FNTYPE.
+   For a library call, FNTYPE is 0.  */
+
+void
+amigaos_init_cumulative_args(CUMULATIVE_ARGS *cum, tree fntype, tree fndecl)
+{
+  m68k_init_cumulative_args(cum, fntype, fndecl);
+
+  if (fntype)
+    cum->formal_type=TYPE_ARG_TYPES(fntype);
+  else /* Call to compiler-support function. */
+    cum->formal_type=0;
+}
+
+/* Update the data in CUM to advance over an argument.  */
+
+void
+amigaos_function_arg_advance(CUMULATIVE_ARGS *cum)
+{
+  m68k_function_arg_advance(cum);
+
+  if (cum->formal_type)
+    cum->formal_type=TREE_CHAIN((tree)cum->formal_type);
+}
+
+/* A C expression that controls whether a function argument is passed
+   in a register, and which register. */
+
+struct rtx_def *
+amigaos_function_arg(CUMULATIVE_ARGS *cum, enum machine_mode mode,
+  tree type)
+{
+  tree asmtree;
+  if (cum->formal_type && TREE_VALUE((tree)cum->formal_type)
+      && (asmtree=lookup_attribute("asm",
+			TYPE_ATTRIBUTES(TREE_VALUE((tree)cum->formal_type)))))
+    {
+      int i;
+#if 0
+      /* See c-decl.c/push_parm_decl for an explanation why this doesn't work.
+       */
+      cum->last_arg_reg=TREE_INT_CST_LOW(TREE_VALUE(TREE_VALUE(asmtree)));
+#else
+      cum->last_arg_reg=TREE_INT_CST_LOW(TREE_VALUE(asmtree));
+#endif
+      cum->last_arg_len=HARD_REGNO_NREGS(cum->last_arg_reg, mode);
+
+      for (i=0; i<cum->last_arg_len; i++)
+	if (cum->regs_already_used & (1 << (cum->last_arg_reg+i)))
+	  {
+	    error("two parameters allocated for one register");
+	    break;
+	  }
+      return gen_rtx_REG (mode, cum->last_arg_reg);
+    }
+  else
+    return (struct rtx_def *)m68k_function_arg(cum, mode, type);
+}
+
+/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible,
+   one if they are compatible, and two if they are nearly compatible
+   (which causes a warning to be generated). */
+
+int
+comp_amigaos_type_attributes(tree type1, tree type2)
+{
+  int ret;
+  if ((ret=comp_m68k_type_attributes(type1, type2))!=1)
+    return ret;
+
+  /* Functions or methods are incompatible if they specify mutually exclusive
+     ways of passing arguments. */
+  if (TREE_CODE(type1)==FUNCTION_TYPE || TREE_CODE(type1)==METHOD_TYPE)
+    {
+      tree arg1, arg2;
+      arg1=TYPE_ARG_TYPES(type1);
+      arg2=TYPE_ARG_TYPES(type2);
+      for (; arg1 && arg2; arg1=TREE_CHAIN(arg1), arg2=TREE_CHAIN(arg2))
+	if (TREE_VALUE(arg1) && TREE_VALUE(arg2))
+	  {
+	    tree asm1, asm2;
+	    asm1=lookup_attribute("asm", TYPE_ATTRIBUTES(TREE_VALUE(arg1)));
+	    asm2=lookup_attribute("asm", TYPE_ATTRIBUTES(TREE_VALUE(arg2)));
+	    if (asm1 && asm2)
+	      {
+		if (TREE_INT_CST_LOW(TREE_VALUE(asm1))!=
+		    TREE_INT_CST_LOW(TREE_VALUE(asm2)))
+		  return 0; /* Two different registers specified. */
+	      }
+	    else
+	      if (asm1 || asm2)
+		return 0; /* "asm" used in only one type. */
+	  }
+    }
+  return 1;
+}
+
+/* end-TIGCC-local (regparms) */
+
+/* (TIGCC) If TARGET_MERGE_SECTIONS is set (on by default), we need an explicit
+   '.text' or '.data' (depending on TARGET_MERGE_TO_DATA) statement at the
+   beginning of the file. */
+
+void m68k_asm_file_start(void)
+{
+	output_file_directive (asm_out_file, main_input_filename);
+	fprintf (asm_out_file, "#NO_APP\n");
+	if (TARGET_REG_RELATIVE)
+		fprintf (asm_out_file, "\t.set __relation,__ld_entry_point_plus_0x8000\n\t.xdef __ref_all___reg_relative_%s\n", TARGET_RELATION_REG);
+	fprintf (asm_out_file, (TARGET_MERGE_SECTIONS?(TARGET_MERGE_TO_DATA?"\t.data\ntigcc_compiled.:\n":"\t.text\ntigcc_compiled.:\n"):"tigcc_compiled.:\n"));
+}
+
+/* (TIGCC 20050424) Everything which is not a CONST_DOUBLE has no business of
+                    being in the constant pool. This is especially valid for
+                    expressions containing relocations. -- Kevin Kofler */
+static bool m68k_cannot_force_const_mem (rtx r)
+{
+  return (GET_CODE (r) != CONST_DOUBLE);
+}
+
diff -Naur gcc-4.1.2.orig/gcc/config/m68k/m68k.h gcc-4.1.2-src/gcc/config/m68k/m68k.h
--- gcc-4.1.2.orig/gcc/config/m68k/m68k.h	2005-07-12 01:32:01.000000000 +0200
+++ gcc-4.1.2-src/gcc/config/m68k/m68k.h	2007-02-19 02:32:34.000000000 +0100
@@ -113,6 +113,12 @@
 /* Set the default.  */
 #define INT_OP_GROUP INT_OP_DOT_WORD
 
+/* Access everything in relation to a specific register */
+#define MASK_REG_RELATIVE	(1<<30)
+#define TARGET_REG_RELATIVE	(target_flags & MASK_REG_RELATIVE)
+
+#define TARGET_DIRECTFLOAT 0 /* not supported yet */
+
 /* Compile for a CPU32.  A 68020 without bitfields is a good
    heuristic for a CPU32.  */
 #define TARGET_CPU32	(TARGET_68020 && !TARGET_BITFIELD)
@@ -126,6 +132,8 @@
 /* These are meant to be redefined in the host dependent files */
 #define SUBTARGET_OVERRIDE_OPTIONS
 
+extern char TARGET_RELATION_REG[];
+
 /* target machine storage layout */
 
 #define LONG_DOUBLE_TYPE_SIZE 80
@@ -141,7 +149,7 @@
 
 #define UNITS_PER_WORD 4
 
-#define PARM_BOUNDARY (TARGET_SHORT ? 16 : 32)
+#define PARM_BOUNDARY 16
 #define STACK_BOUNDARY 16
 #define FUNCTION_BOUNDARY 16
 #define EMPTY_FIELD_BOUNDARY 16
@@ -175,7 +183,9 @@
 #define FIRST_PSEUDO_REGISTER 25
 
 /* All m68k targets (except AmigaOS) use %a5 as the PIC register  */
-#define PIC_OFFSET_TABLE_REGNUM (flag_pic ? 13 : INVALID_REGNUM)
+/* (TIGCC 20050209) TIGCC doesn't use a PIC register, and besides this was
+                    forgetting the -mpcrel case.  */
+#define PIC_OFFSET_TABLE_REGNUM (INVALID_REGNUM)
 
 /* 1 for registers that have pervasive standard uses
    and are not available for the register allocator.
@@ -375,6 +385,9 @@
    `S' is for operands that satisfy 'm' when -mpcrel is in effect.
    `T' is for operands that satisfy 's' when -mpcrel is not in effect.
    `U' is for register offset addressing.  */
+/* (TIGCC 20040808) Under -freg-relative-an, the same restrictions on 's'/'T' as
+                    for -mpcrel apply. We can't use immediates as labels if
+                    we need to output reg-relative code. -- Kevin Kofler  */
 #define EXTRA_CONSTRAINT(OP,CODE)			\
   (((CODE) == 'S')					\
    ? (TARGET_PCREL					\
@@ -384,7 +397,7 @@
 	  || GET_CODE (XEXP (OP, 0)) == CONST))		\
    : 							\
   (((CODE) == 'T')					\
-   ? ( !TARGET_PCREL 					\
+   ? ( (!TARGET_PCREL && !TARGET_REG_RELATIVE) 					\
       && (GET_CODE (OP) == SYMBOL_REF			\
 	  || GET_CODE (OP) == LABEL_REF			\
 	  || GET_CODE (OP) == CONST))			\
@@ -486,24 +499,59 @@
 
 #define PCC_STATIC_STRUCT_RETURN
 
-/* On the m68k, all arguments are usually pushed on the stack.  */
-#define FUNCTION_ARG_REGNO_P(N) 0
-
-/* On the m68k, this is a single integer, which is a number of bytes
-   of arguments scanned so far.  */
-#define CUMULATIVE_ARGS int
-
-/* On the m68k, the offset starts at 0.  */
-#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
- ((CUM) = 0)
+/* Define this if explicit register specification for parameters
+   is supported.  */
+
+#define EXPLICIT_REGPARM
+
+#define FUNCTION_ARG_REGNO_P(N)			\
+  (((N) >= 0 && (N) < M68K_MAX_REGPARM)		\
+   || ((N) >= 8 && (N) < 8 + M68K_MAX_REGPARM)	\
+   || (TARGET_68881 && (N) >= 16 && (N) < 16 + M68K_MAX_REGPARM))
+
+/* On the m68k, this is a structure:
+   num_of_regs: number of data, address and float registers to use for
+     arguments passing (if it's 2, than pass arguments in d0, d1, a0, a1,
+     fp0 and fp1). 0 - pass everything on stack. vararg calls are
+     always passed entirely on stack.
+   regs_already_used: bitmask of the already used registers.
+   last_arg_reg: register number of the most recently passed argument.
+     -1 if passed on stack.
+   last_arg_len: number of registers used by the most recently passed
+     argument.
+   formal_type: formal type of the current argument.
+*/
+
+struct m68k_args
+{
+  int num_of_regs;
+  long regs_already_used;
+  int last_arg_reg;
+  int last_arg_len;
+  void *formal_type;
+};
+
+#define CUMULATIVE_ARGS struct m68k_args
+
+/* Max. number of data, address and float registers to be used for passing
+   integer, pointer and float arguments when TARGET_REGPARM.
+   It's 6, so d0-d5, a0-a5 and fp0-fp5 can be used.  */
+
+#define M68K_MAX_REGPARM 6  /* was 4 in the original patch */
+
+/* The default number of data, address and float registers to use when
+   user specified '-mregparm' switch, not '-mregparm=<value>' option.  */
+
+#define M68K_DEFAULT_REGPARM 2  /* was 2 in the orginial patch */
+
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
+  (amigaos_init_cumulative_args (&(CUM), (FNTYPE), (FNDECL)))
 
 #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED)	\
- ((CUM) += ((MODE) != BLKmode			\
-	    ? (GET_MODE_SIZE (MODE) + 3) & ~3	\
-	    : (int_size_in_bytes (TYPE) + 3) & ~3))
+  (amigaos_function_arg_advance (&(CUM)))
 
-/* On the m68k all args are always pushed.  */
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) 0
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+  ((struct rtx_def *)amigaos_function_arg (&(CUM), (MODE), (TYPE)))
 
 #define FUNCTION_PROFILER(FILE, LABELNO)  \
   asm_fprintf (FILE, "\tlea %LLP%d,%Ra0\n\tjsr mcount\n", (LABELNO))
@@ -639,7 +687,11 @@
 
 /* Nonzero if the constant value X is a legitimate general operand.
    It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */
-#define LEGITIMATE_CONSTANT_P(X) (GET_MODE (X) != XFmode)
+/* (TIGCC 20040808) If reg-relative, we need to reject "constants" of the #label
+                    or #label+const form. -- Kevin Kofler  */
+
+#define LEGITIMATE_CONSTANT_P(X) (!TARGET_REG_RELATIVE \
+                                  || !pcrel_address (X, VOIDmode))
 
 #ifndef REG_OK_STRICT
 #define PCREL_GENERAL_OPERAND_OK 0
@@ -950,15 +1002,19 @@
 #define ASM_OUTPUT_SKIP(FILE,SIZE)  \
   fprintf (FILE, "\t.skip %u\n", (int)(SIZE))
 
+#ifndef ASM_OUTPUT_COMMON
 #define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED)  \
 ( fputs (".comm ", (FILE)),			\
   assemble_name ((FILE), (NAME)),		\
   fprintf ((FILE), ",%u\n", (int)(ROUNDED)))
+#endif
 
+#ifndef ASM_OUTPUT_LOCAL
 #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED)  \
 ( fputs (".lcomm ", (FILE)),			\
   assemble_name ((FILE), (NAME)),		\
   fprintf ((FILE), ",%u\n", (int)(ROUNDED)))
+#endif
 
 /* Output a float value (represented as a C double) as an immediate operand.
    This macro is m68k-specific.  */
@@ -1030,4 +1086,6 @@
 
 /* Variables in m68k.c */
 extern const char *m68k_library_id_string;
+extern const char *m68k_regparm_string;
+extern int m68k_regparm;
 extern int m68k_last_compare_had_fp_operands;
diff -Naur gcc-4.1.2.orig/gcc/config/m68k/m68k.md gcc-4.1.2-src/gcc/config/m68k/m68k.md
--- gcc-4.1.2.orig/gcc/config/m68k/m68k.md	2005-11-22 21:53:08.000000000 +0100
+++ gcc-4.1.2-src/gcc/config/m68k/m68k.md	2007-02-19 02:32:34.000000000 +0100
@@ -329,20 +329,22 @@
                  (match_operand:SI 1 "general_src_operand" "mSr,mSa,KTr,Ksr,>")))]
   "!TARGET_COLDFIRE"
 {
+/* (TIGCC 20040222) This used %d0 and %d1 to force absolute addressing, which
+                    doesn't make sense and breaks -mpcrel. -- Kevin Kofler */
   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
     return "cmpm%.l %1,%0";
   if (REG_P (operands[1])
       || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
     {
       cc_status.flags |= CC_REVERSED;
-      return "cmp%.l %d0,%d1";
+      return "cmp%.l %0,%1";
     }
   if (ADDRESS_REG_P (operands[0])
       && GET_CODE (operands[1]) == CONST_INT
       && INTVAL (operands[1]) < 0x8000
       && INTVAL (operands[1]) >= -0x8000)
     return "cmp%.w %1,%0";
-  return "cmp%.l %d1,%d0";
+  return "cmp%.l %1,%0";
 })
 
 (define_insn ""
@@ -360,52 +362,62 @@
   return "cmp%.l %d1,%d0";
 })
 
+;; (TIGCC 20040808) Don't allow source-only operands as the destination in the
+;;                  compare. We need to use nonimmediate_operand, not
+;;                  nonimmediate_src_operand. Otherwise, -mpcrel outputs invalid
+;;                  assembly code. The SImode patterns already got this right.
+;; -- Kevin Kofler
+
 (define_expand "cmphi"
   [(set (cc0)
-        (compare (match_operand:HI 0 "nonimmediate_src_operand" "")
+        (compare (match_operand:HI 0 "nonimmediate_operand" "")
                  (match_operand:HI 1 "general_src_operand" "")))]
   "!TARGET_COLDFIRE"
   "m68k_last_compare_had_fp_operands = 0;")
 
 (define_insn ""
   [(set (cc0)
-        (compare (match_operand:HI 0 "nonimmediate_src_operand" "rnmS,d,n,mS,>")
+        (compare (match_operand:HI 0 "nonimmediate_operand" "rnmS,d,n,mS,>")
                  (match_operand:HI 1 "general_src_operand" "d,rnmS,mS,n,>")))]
   "!TARGET_COLDFIRE"
 {
+/* (TIGCC 20040222) This used %d0 and %d1 to force absolute addressing, which
+                    doesn't make sense and breaks -mpcrel. -- Kevin Kofler */
   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
     return "cmpm%.w %1,%0";
   if ((REG_P (operands[1]) && !ADDRESS_REG_P (operands[1]))
       || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
     {
       cc_status.flags |= CC_REVERSED;
-      return "cmp%.w %d0,%d1";
+      return "cmp%.w %0,%1";
     }
-  return "cmp%.w %d1,%d0";
+  return "cmp%.w %1,%0";
 })
 
 (define_expand "cmpqi"
   [(set (cc0)
-        (compare (match_operand:QI 0 "nonimmediate_src_operand" "")
+        (compare (match_operand:QI 0 "nonimmediate_operand" "")
                  (match_operand:QI 1 "general_src_operand" "")))]
   "!TARGET_COLDFIRE"
   "m68k_last_compare_had_fp_operands = 0;")
 
 (define_insn ""
   [(set (cc0)
-        (compare (match_operand:QI 0 "nonimmediate_src_operand" "dn,dmS,>")
+        (compare (match_operand:QI 0 "nonimmediate_operand" "dn,dmS,>")
                  (match_operand:QI 1 "general_src_operand" "dmS,nd,>")))]
   "!TARGET_COLDFIRE"
 {
+/* (TIGCC 20040222) This used %d0 and %d1 to force absolute addressing, which
+                    doesn't make sense and breaks -mpcrel. -- Kevin Kofler */
   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
     return "cmpm%.b %1,%0";
   if (REG_P (operands[1])
       || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
     {
       cc_status.flags |= CC_REVERSED;
-      return "cmp%.b %d0,%d1";
+      return "cmp%.b %0,%1";
     }
-  return "cmp%.b %d1,%d0";
+  return "cmp%.b %1,%0";
 })
 
 (define_expand "cmpdf"
@@ -662,6 +674,12 @@
 	       && symbolic_operand (XEXP (operands[0], 0), SImode))
 	operands[0] = gen_rtx_MEM (SImode,
 			       force_reg (SImode, XEXP (operands[0], 0)));
+      /* (TIGCC 20060105) Don't allow writes of a label directly to memory
+                          either. -- Kevin Kofler  */
+      else if (GET_CODE (operands[0]) == MEM
+	       && !push_operand (operands[0], SImode)
+	       && symbolic_operand (operands[1], SImode))
+	operands[1] = force_reg (SImode, operands[1]);
     }
 })
 
@@ -693,16 +711,25 @@
 
 ;; Special case of fullword move, where we need to get a non-GOT PIC
 ;; reference into an address register.
+;; (TIGCC 20040808) This is also needed for -freg-relative-an. -- Kevin Kofler
+;; (TIGCC 20060105) Make sure we have an address register or a push operand.
+;;                  -- Kevin Kofler
 (define_insn ""
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=a<")
+  [(set (match_operand:SI 0 "register_operand" "=a")
         (match_operand:SI 1 "pcrel_address" ""))]
-  "TARGET_PCREL"
+  "TARGET_PCREL || TARGET_REG_RELATIVE"
 {
-  if (push_operand (operands[0], SImode))
-    return "pea %a1";
   return "lea %a1,%0";
 })
 
+(define_insn ""
+  [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+        (match_operand:SI 0 "pcrel_address" ""))]
+  "TARGET_PCREL || TARGET_REG_RELATIVE"
+{
+  return "pea %a0";
+})
+
 (define_expand "movhi"
   [(set (match_operand:HI 0 "nonimmediate_operand" "")
 	(match_operand:HI 1 "general_operand" ""))]
@@ -775,13 +802,63 @@
   "TARGET_COLDFIRE"
   "* return output_move_strictqi (operands);")
 
+;; (TIGCC 20050210) Distinguish nonmemory_operand vs. memory_operand here, and
+;;                  optimize pushes from nonmemory_operand to word pushes. We
+;;                  can't do that for memory operands because of odd addresses.
+;;                  The distinction between register_operand and
+;;                  const_int_operand is because of paradoxical subreg
+;;                  technicalities.
+;; (TIGCC 20060801) We can accept SUBREGs with the register optimization only
+;;                  if the SUBREG_BYTE is odd.
+
 (define_expand "pushqi1"
+  [(match_operand:QI 0 "general_operand" "")]
+  "!TARGET_COLDFIRE"
+"{
+  if (const_int_operand (operands[0], QImode))
+    emit_insn (gen_pushqi1_imm (operands[0]));
+  else if (register_operand (operands[0], QImode)
+           && (GET_CODE (operands[0]) != SUBREG
+               || (SUBREG_BYTE(operands[0]) & 1)))
+    emit_insn (gen_pushqi1_reg (operands[0]));
+  else
+    emit_insn (gen_pushqi1_mem (operands[0]));
+  DONE;
+}")
+
+(define_expand "pushqi1_mem"
   [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -2)))
    (set (mem:QI (plus:SI (reg:SI SP_REG) (const_int 1)))
 	(match_operand:QI 0 "general_operand" ""))]
   "!TARGET_COLDFIRE"
   "")
 
+(define_expand "pushqi1_imm"
+  [(set (mem:HI (pre_dec:SI (reg:SI SP_REG)))
+	(match_operand:HI 0 "const_int_operand" ""))]
+  "!TARGET_COLDFIRE"
+  "")
+
+;; Yes, this is a paradoxical subreg.
+;; (TIGCC 20060801) Well, not always. We could have a true subreg, and then we
+;;                  need to adjust SUBREG_BYTE.
+;;                  SUBREG_BYTE(operands[0]) - 1 is always positive because
+;;                  SUBREG_BYTE(operands[0]) is unsigned and odd.
+(define_expand "pushqi1_reg"
+  [(set (mem:HI (pre_dec:SI (reg:SI SP_REG)))
+	(match_operand:QI 0 "register_operand" ""))]
+  "!TARGET_COLDFIRE"
+"{
+  {
+    unsigned offset = 0;
+    if (GET_CODE (operands[0]) == SUBREG) {
+      offset = SUBREG_BYTE(operands[0]) - 1;
+      operands[0] = SUBREG_REG (operands[0]);
+    }
+    operands[0] = gen_rtx_SUBREG (HImode, operands[0], offset);
+  }
+}")
+
 (define_expand "movsf"
   [(set (match_operand:SF 0 "nonimmediate_operand" "")
 	(match_operand:SF 1 "general_operand" ""))]
@@ -897,6 +974,34 @@
 ;; constants.  Most but not all have output templates that handle constants.
 ;; See also LEGITIMATE_CONSTANT_P.
 
+(define_expand "movbf"
+  ;; SMAP BCD
+  [(set (match_operand:BF 0 "nonimmediate_operand" "")
+	(match_operand:BF 1 "general_operand" ""))]
+  ""
+  "
+{
+  /* We can't rewrite operands during reload.  */
+  if (! reload_in_progress)
+    {
+      if (CONSTANT_P (operands[1]))
+        {
+          operands[1] = force_const_mem (BFmode, operands[1]);
+          if (! memory_address_p (BFmode, XEXP (operands[1], 0)))
+              operands[1] = adjust_address (operands[1], BFmode, 0);
+        }
+      if (flag_pic && TARGET_PCREL)
+        {
+          /* Don't allow writes to memory except via a register; the
+             m68k doesn't consider PC-relative addresses to be writable.  */
+          if (GET_CODE (operands[0]) == MEM
+              && symbolic_operand (XEXP (operands[0], 0), SImode))
+              operands[0] = gen_rtx_MEM (BFmode,
+                                         force_reg (SImode, XEXP (operands[0], 0)));
+        }
+    }
+}")
+ 
 (define_expand "movxf"
   [(set (match_operand:XF 0 "nonimmediate_operand" "")
 	(match_operand:XF 1 "general_operand" ""))]
@@ -963,6 +1068,46 @@
 })
 
 (define_insn ""
+  ;; SMAP BCD
+  [(set (match_operand:BF 0 "nonimmediate_operand" "=rm,rf,&rof<>")
+	(match_operand:BF 1 "nonimmediate_operand" "rf,m,rof<>"))]
+  "! TARGET_68881 && ! TARGET_COLDFIRE"
+{
+  if (FP_REG_P (operands[0]))
+    {
+      if (FP_REG_P (operands[1]))
+	return "fmove%.x %1,%0";
+      if (REG_P (operands[1]))
+	{
+	  rtx xoperands[2];
+	  xoperands[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 2);
+	  output_asm_insn ("move%.w %1,%-", xoperands);
+	  xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
+	  output_asm_insn ("move%.l %1,%-", xoperands);
+	  output_asm_insn ("move%.l %1,%-", operands);
+	  return "fmove%.x %+,%0";
+	}
+      if (GET_CODE (operands[1]) == CONST_DOUBLE)
+        return "fmove%.x %1,%0";
+      return "fmove%.x %f1,%0";
+    }
+  if (FP_REG_P (operands[1]))
+    {
+      if (REG_P (operands[0]))
+        {
+          output_asm_insn ("fmove%.x %f1,%-\;move%.l %+,%0", operands);
+          operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+          output_asm_insn ("move%.l %+,%0", operands);
+          operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
+          return "move%.w %+,%0";
+        }
+      else
+        return "fmove%.x %f1,%0";
+    }
+  return output_move_double (operands);
+})
+
+(define_insn ""
   [(set (match_operand:XF 0 "nonimmediate_operand" "=rm,rf,&rof<>")
 	(match_operand:XF 1 "nonimmediate_operand" "rf,m,rof<>"))]
   "! TARGET_68881 && ! TARGET_COLDFIRE"
@@ -1233,9 +1378,12 @@
   "TARGET_CFV4"
   "mvz%.w %1,%0")
 
+;; (TIGCC 20050210) We need to mark the register operand as earlyclobber in the
+;;                  case of memory operands to avoid having to split (see
+;;                  reg_mentioned_p below) things.
 (define_insn "zero_extendhisi2"
-  [(set (match_operand:SI 0 "register_operand" "=d")
-	(zero_extend:SI (match_operand:HI 1 "nonimmediate_src_operand" "rmS")))]
+  [(set (match_operand:SI 0 "register_operand" "=d,&d")
+	(zero_extend:SI (match_operand:HI 1 "nonimmediate_src_operand" "r,mS")))]
   ""
   "#")
 
@@ -1258,8 +1406,8 @@
   "mvz%.b %1,%0")
 
 (define_insn "zero_extendqisi2"
-  [(set (match_operand:SI 0 "register_operand" "=d")
-	(zero_extend:SI (match_operand:QI 1 "nonimmediate_src_operand" "dmS")))]
+  [(set (match_operand:SI 0 "register_operand" "=d,&d")
+	(zero_extend:SI (match_operand:QI 1 "nonimmediate_src_operand" "d,mS")))]
   ""
   "#")
 
@@ -4135,7 +4283,11 @@
       output_asm_insn (INTVAL (operands[2]) <= 8 ? "asr%.l %2,%0" :
 			"moveq %2,%1\;asr%.l %1,%0", operands);
       output_asm_insn ("mov%.l %0,%1\;smi %0", operands);
-      return INTVAL (operands[2]) >= 15 ? "ext%.w %d0" :
+/* (TIGCC 20040222) The %d0 here was a typo or thinko. It means 'force absolute
+                    addressing' in this context, not 'data register'. This
+                    doesn't make sense in a context where only data registers
+                    are allowed, so I removed it. -- Kevin Kofler */
+      return INTVAL (operands[2]) >= 15 ? "ext%.w %0" :
 	     TARGET_68020 ? "extb%.l %0" : "ext%.w %0\;ext%.l %0";
     }
 })
@@ -6320,10 +6472,19 @@
   return "rtd %0";
 })
 
+;; (TIGCC 20040222) Use jra instead of jmp here. Also don't add (%pc) under
+;;                  -mpcrel. Moreover, we need to handle extended address
+;;                  operands here. -- Kevin Kofler
+;; (TIGCC 20050204) Use plain bra for labels under -mpcrel to guarantee PC-rel
+;;                  code.
 (define_insn "indirect_jump"
-  [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
+  [(set (pc) (match_operand:SI 0 "extended_address_operand" "p"))]
   ""
-  "jmp %a0")
+{
+  return (TARGET_PCREL && GET_CODE (operands[0]) == MEM
+          && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)?
+         "bra %A0":"jra %A0";
+})
 
 ;; This should not be used unless the add/sub insns can't be.
 
@@ -6417,6 +6578,9 @@
 })
 
 ;; Speed up stack adjust followed by a fullword fixedpoint push.
+;; (TIGCC 20050211) Don't do this if pushing an immediate operand in range for
+;;                  a pea, and a stack adjust is needed anyway. That would
+;;                  generate bigger (or same size) and slower code.
 
 (define_peephole
   [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
@@ -6424,7 +6588,8 @@
    (set (match_operand:SI 1 "push_operand" "=m")
 	(match_operand:SI 2 "general_operand" "g"))]
   "INTVAL (operands[0]) >= 4
-   && ! reg_mentioned_p (stack_pointer_rtx, operands[2])"
+   && ! reg_mentioned_p (stack_pointer_rtx, operands[2])
+   && !(INTVAL (operands[0]) > 4 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) && INTVAL (operands[2]) >= -0x8000 && INTVAL (operands[2]) < 0x8000)"
 {
   if (INTVAL (operands[0]) > 4)
     {
@@ -6460,6 +6625,77 @@
   return "move%.l %2,%@";
 })
 
+;; (TIGCC 20050207) Bundle 2 immediate word pushes to the stack into 1 immediate
+;;                  longword push.
+
+(define_peephole
+  [(set (match_operand:HI 0 "push_operand" "=m")
+	(match_operand:HI 1 "const_int_operand" "n"))
+   (set (match_operand:HI 2 "push_operand" "=m")
+	(match_operand:HI 3 "const_int_operand" "n"))]
+  ""
+{
+  rtx xoperands[2];
+  xoperands[0] = operands[0];
+  xoperands[1] = GEN_INT ((INTVAL (operands[1]) & 0xFFFF) + (INTVAL (operands[3]) << 16));
+  output_asm_insn (output_move_simode_const (xoperands), xoperands);
+  CC_STATUS_INIT; /* We clobbered the CC. */
+  return "";
+})
+
+;; (TIGCC 20050210) Same as above, but with a stack adjust.
+
+(define_peephole
+  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
+				 (match_operand:SI 0 "const_int_operand" "n")))
+   (set (mem:HI (reg:SI SP_REG))
+	(match_operand:HI 1 "const_int_operand" "n"))
+   (set (match_operand:HI 2 "push_operand" "=m")
+	(match_operand:HI 3 "const_int_operand" "n"))]
+  "INTVAL (operands[0]) >= 2"
+{
+  HOST_WIDE_INT longword = (INTVAL (operands[1]) & 0xFFFF) + (INTVAL (operands[3]) << 16);
+  bool usepea = longword && longword < 0x8000 && longword >= -0x8000
+                && INTVAL (operands[0]) > 2;
+  rtx xoperands[2];
+  if (INTVAL (operands[0]) > 2)
+    {
+      xoperands[0] = stack_pointer_rtx;
+      xoperands[1] = GEN_INT (INTVAL (operands[0]) + (usepea?2:-2));
+      if (INTVAL (xoperands[1]) <= 8)
+	{
+	  if (!TARGET_COLDFIRE)
+	    output_asm_insn ("addq%.w %1,%0", xoperands);
+	  else
+	    output_asm_insn ("addq%.l %1,%0", xoperands);
+	}
+      else if (TARGET_CPU32 && INTVAL (xoperands[1]) <= 16)
+	{
+	  xoperands[1] = GEN_INT (INTVAL (xoperands[1]) - 8);
+	  output_asm_insn ("addq%.w #8,%0\;addq%.w %1,%0", xoperands);
+	}
+      else if (INTVAL (xoperands[1]) <= 0x7FFF)
+        {
+	  if (TARGET_68040)
+	    output_asm_insn ("add%.w %1,%0", xoperands);
+	  else if (MOTOROLA)
+	    output_asm_insn ("lea (%c1,%0),%0", xoperands);
+	  else
+	    output_asm_insn ("lea %0@(%c1),%0", xoperands);
+        }
+      else
+        output_asm_insn ("add%.l %1,%0", xoperands);
+    }
+  if (usepea)
+    xoperands[0] = operands[2];
+  else
+    xoperands[0] = gen_rtx_MEM (SImode, stack_pointer_rtx);
+  xoperands[1] = GEN_INT (longword);
+  output_asm_insn (output_move_simode_const (xoperands), xoperands);
+  CC_STATUS_INIT; /* We clobbered the CC. */
+  return "";
+})
+
 ;; Speed up pushing a single byte but leaving four bytes of space.
 
 (define_peephole
@@ -7092,3 +7328,166 @@
   default: gcc_unreachable ();
   }
 })
+
+;; (TIGCC 20050210) Optimize lea (4,%an),%am; move.l foo,-(%am) into
+;;                  move.l %an,%am; move.l foo,(%an)
+;; (TIGCC 20050211) Don't do this if foo is an immediate operand in range for
+;;                  a moveq (because the movsi insn won't like that).
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+        (plus:SI (match_operand:SI 1 "register_operand" "")
+            (const_int 4)))
+   (set (mem:SI (pre_dec:SI (match_dup 0)))
+        (match_operand:SI 2 "general_operand" ""))]
+  "REG_P(operands[1]) && (REGNO (operands[1]) ^ 010) < 8 && ! reg_mentioned_p (operands[0], operands[2]) && !(GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) && INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128)"
+  [(set (match_dup 0) (match_dup 1))
+   (set (mem:SI (match_dup 1)) (match_dup 2))]
+  "")
+
+;; (TIGCC 20050211) Optimize lea (4,%an),%am; move.l #foo,-(%am), foo!=0,
+;;                  -128<=foo<128 into moveq.l #foo,%dx; move.l %an,%am;
+;;                  move.l %dx,(%an) if we have a free data register to do that.
+(define_peephole2
+  [(match_scratch:SI 0 "d")
+   (set (match_operand:SI 1 "register_operand" "")
+        (plus:SI (match_operand:SI 2 "register_operand" "")
+            (const_int 4)))
+   (match_dup 0)
+   (set (mem:SI (pre_dec:SI (match_dup 1)))
+        (match_operand:SI 3 "const_int_operand" ""))]
+  "REG_P(operands[2]) && (REGNO (operands[2]) ^ 010) < 8 && INTVAL (operands[3]) && INTVAL (operands[3]) >= -128 && INTVAL (operands[3]) < 128"
+  [(set (match_dup 0) (match_dup 3))
+   (set (match_dup 1) (match_dup 2))
+   (set (mem:SI (match_dup 2)) (match_dup 0))]
+  "")
+
+;; (TIGCC 20050210) Optimize lea (2,%an),%am; move.w foo,-(%am) into
+;;                  move.l %an,%am; move.w foo,(%an)
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+        (plus:SI (match_operand:SI 1 "register_operand" "")
+            (const_int 2)))
+   (set (mem:HI (pre_dec:SI (match_dup 0)))
+        (match_operand:HI 2 "general_operand" ""))]
+  "REG_P(operands[1]) && (REGNO (operands[1]) ^ 010) < 8 && ! reg_mentioned_p (operands[0], operands[2])"
+  [(set (match_dup 0) (match_dup 1))
+   (set (mem:HI (match_dup 1)) (match_dup 2))]
+  "")
+
+;; (TIGCC 20050210) Optimize lea (1,%an),%am; move.w foo,-(%am), m!=7 into
+;;                  move.l %an,%am; move.b foo,(%an)
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+        (plus:SI (match_operand:SI 1 "register_operand" "")
+            (const_int 1)))
+   (set (mem:QI (pre_dec:SI (match_dup 0)))
+        (match_operand:QI 2 "general_operand" ""))]
+  "REG_P(operands[1]) && (REGNO (operands[1]) ^ 010) < 8 && !(REG_P(operands[0]) && REGNO (operands[0]) == STACK_POINTER_REGNUM) && ! reg_mentioned_p (operands[0], operands[2])"
+  [(set (match_dup 0) (match_dup 1))
+   (set (mem:QI (match_dup 1)) (match_dup 2))]
+  "")
+
+;; (TIGCC 20050210) Optimize lea (x,%an),%am; move.l foo,-(%am), x!=4,
+;;                  x>=-0x7ffc into lea (x-4,%an),%am; move.l foo,(%am)
+;; (TIGCC 20050211) Don't do this if foo is an immediate operand in range for
+;;                  a pea (especially not if in range for a moveq, because the
+;;                  movsi insn won't like that).
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+        (plus:SI (match_operand:SI 1 "register_operand" "")
+            (match_operand:SI 2 "const_int_operand" "")))
+   (set (mem:SI (pre_dec:SI (match_dup 0)))
+        (match_operand:SI 3 "general_operand" ""))]
+  "REG_P(operands[1]) && (REGNO (operands[1]) ^ 010) < 8 && ! reg_mentioned_p (operands[0], operands[3]) && INTVAL (operands[2]) != 4 && INTVAL (operands[2]) >= -0x7ffc && !(GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) && INTVAL (operands[3]) >= -0x8000 && INTVAL (operands[3]) < 0x8000)"
+  [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
+   (set (mem:SI (match_dup 0)) (match_dup 3))]
+  "operands[2] = GEN_INT (INTVAL (operands[2]) - 4);")
+
+;; (TIGCC 20050210) Optimize lea (x,%an),%am; move.w foo,-(%am), m!=7, x!=2,
+;;                  x>=-0x7ffe into lea (x-2,%an),%am; move.w foo,(%am)
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+        (plus:SI (match_operand:SI 1 "register_operand" "")
+            (match_operand:SI 2 "const_int_operand" "")))
+   (set (mem:HI (pre_dec:SI (match_dup 0)))
+        (match_operand:HI 3 "general_operand" ""))]
+  "REG_P(operands[1]) && (REGNO (operands[1]) ^ 010) < 8 && ! reg_mentioned_p (operands[0], operands[3]) && INTVAL (operands[2]) != 2 && INTVAL (operands[2]) >= -0x7ffe"
+  [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
+   (set (mem:HI (match_dup 0)) (match_dup 3))]
+  "operands[2] = GEN_INT (INTVAL (operands[2]) - 2);")
+
+;; (TIGCC 20050210) Optimize lea (x,%an),%am; move.b foo,-(%am), m!=7, x!=1,
+;;                  x>=-0x7fff into lea (x-1,%an),%am; move.b foo,(%am)
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+        (plus:SI (match_operand:SI 1 "register_operand" "")
+            (match_operand:SI 2 "const_int_operand" "")))
+   (set (mem:QI (pre_dec:SI (match_dup 0)))
+        (match_operand:QI 3 "general_operand" ""))]
+  "REG_P(operands[1]) && (REGNO (operands[1]) ^ 010) < 8 && !(REG_P(operands[0]) && REGNO (operands[0]) == STACK_POINTER_REGNUM) && ! reg_mentioned_p (operands[0], operands[3]) && INTVAL (operands[2]) != 1 && INTVAL (operands[2]) >= -0x7fff"
+  [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
+   (set (mem:QI (match_dup 0)) (match_dup 3))]
+  "operands[2] = GEN_INT (INTVAL (operands[2]) - 1);")
+
+;; (TIGCC 20050213) Optimize and #const1,%dn; and #const2,%dn (generated by
+;;                  zero_extend) into and #const1&const2,%dn
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+        (and:SI (match_dup 0)
+            (match_operand:SI 1 "const_int_operand" "")))
+   (set (match_dup 0)
+        (and:SI (match_dup 0)
+            (match_operand:SI 2 "const_int_operand" "")))]
+  ""
+  [(set (match_dup 0) (and:SI (match_dup 0) (match_dup 1)))]
+  "operands[1] = GEN_INT (INTVAL (operands[1]) & INTVAL (operands[2]));")
+
+(define_peephole2
+  [(set (match_operand:HI 0 "register_operand" "")
+        (and:HI (match_dup 0)
+            (match_operand:HI 1 "const_int_operand" "")))
+   (set (match_dup 0)
+        (and:HI (match_dup 0)
+            (match_operand:HI 2 "const_int_operand" "")))]
+  ""
+  [(set (match_dup 0) (and:HI (match_dup 0) (match_dup 1)))]
+  "operands[1] = GEN_INT (INTVAL (operands[1]) & INTVAL (operands[2]));")
+
+(define_peephole2
+  [(set (match_operand:QI 0 "register_operand" "")
+        (and:QI (match_dup 0)
+            (match_operand:QI 1 "const_int_operand" "")))
+   (set (match_dup 0)
+        (and:QI (match_dup 0)
+            (match_operand:QI 2 "const_int_operand" "")))]
+  ""
+  [(set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))]
+  "operands[1] = GEN_INT (INTVAL (operands[1]) & INTVAL (operands[2]));")
+
+;; (TIGCC 20050213) Optimize and.l #65535,%dn; clr.w %dn (generated by
+;;                  zero_extend) into moveq #0,%dn
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+        (and:SI (match_dup 0)
+            (const_int 65535)))
+   (set (strict_low_part (match_operand:HI 1 "register_operand" ""))
+        (const_int 0))]
+  "REG_P(operands[0]) && REG_P(operands[1]) && REGNO(operands[0]) == REGNO(operands[1])"
+  [(set (match_dup 0) (const_int 0))]
+  "")
+
+;; (TIGCC 20050213) Optimize and.w #255,%dn; clr.b %dn (generated by
+;;                  zero_extend) into clr.w %dn
+
+(define_peephole2
+  [(set (match_operand:HI 0 "register_operand" "")
+        (and:HI (match_dup 0)
+            (const_int 255)))
+   (set (strict_low_part (match_operand:QI 1 "register_operand" ""))
+        (const_int 0))]
+  "REG_P(operands[0]) && REG_P(operands[1]) && REGNO(operands[0]) == REGNO(operands[1])"
+  [(set (strict_low_part (match_dup 0)) (const_int 0))]
+  "")
+
diff -Naur gcc-4.1.2.orig/gcc/config/m68k/m68k-modes.def gcc-4.1.2-src/gcc/config/m68k/m68k-modes.def
--- gcc-4.1.2.orig/gcc/config/m68k/m68k-modes.def	2005-06-25 03:22:41.000000000 +0200
+++ gcc-4.1.2-src/gcc/config/m68k/m68k-modes.def	2007-02-19 02:32:34.000000000 +0100
@@ -18,5 +18,6 @@
 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
 Boston, MA 02110-1301, USA.  */
 
-/* 80-bit floating point (IEEE extended, in a 96-bit field) */
-FRACTIONAL_FLOAT_MODE (XF, 80, 12, ieee_extended_motorola_format);
+FLOAT_MODE (BF, 10, 0);
+FLOAT_MODE (XF, 12, 0);
+
diff -Naur gcc-4.1.2.orig/gcc/config/m68k/m68k-none.h gcc-4.1.2-src/gcc/config/m68k/m68k-none.h
--- gcc-4.1.2.orig/gcc/config/m68k/m68k-none.h	2005-06-25 03:22:41.000000000 +0200
+++ gcc-4.1.2-src/gcc/config/m68k/m68k-none.h	2007-02-19 02:32:34.000000000 +0100
@@ -18,10 +18,12 @@
 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
 Boston, MA 02110-1301, USA.  */
 
-/* Default to m68k (m68020).  */
-#ifndef TARGET_CPU_DEFAULT
-#define TARGET_CPU_DEFAULT M68K_CPU_m68k
-#endif
+/* Define the appropriate flags for the TI's architecture */
+#undef TARGET_CPU_DEFAULT
+#define TARGET_CPU_DEFAULT M68K_CPU_m68000
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT ((TARGET_CPU_DEFAULT >> 4) | MASK_SHORT | MASK_TIOS | MASK_MERGE_SECTIONS)
 
 /* These are values set by the configure script in TARGET_CPU_DEFAULT.
    They are (sequential integer + (desired value for TARGET_DEFAULT) << 4).  */
diff -Naur gcc-4.1.2.orig/gcc/config/m68k/m68k.opt gcc-4.1.2-src/gcc/config/m68k/m68k.opt
--- gcc-4.1.2.orig/gcc/config/m68k/m68k.opt	2005-06-25 03:22:41.000000000 +0200
+++ gcc-4.1.2-src/gcc/config/m68k/m68k.opt	2007-02-19 02:32:34.000000000 +0100
@@ -92,6 +92,10 @@
 Target Report RejectNegative Mask(BITFIELD)
 Use the bit-field instructions
 
+mbss
+Target Report InverseMask(NO_BSS)
+Output common/lcomm (BSS) symbols for uninitialized data
+
 mc68000
 Target RejectNegative
 Generate code for a 68000
@@ -100,6 +104,10 @@
 Target RejectNegative
 Generate code for a 68020
 
+mcoff-abslines
+Target Report Mask(COFFABSLINES)
+Use absolute line numbers for COFF debugging
+
 mcpu32
 Target RejectNegative
 Generate code for a cpu32
@@ -108,10 +116,30 @@
 Target Report Mask(ID_SHARED_LIBRARY)
 Enable ID based shared library
 
+mlong
+Target InverseMask(SHORT)
+Consider type 'int' to be 32 bits wide
+
+mmerge-sections
+Target Report Mask(MERGE_SECTIONS)
+Merge the .text and .data sections
+
+mmerge-to-data
+Target Report Mask(MERGE_TO_DATA)
+When merging sections, merge to .data rather than to .text
+
 mnobitfield
 Target RejectNegative InverseMask(BITFIELD)
 Do not use the bit-field instructions
 
+mnobss
+Target Report Mask(NO_BSS)
+Don't output common/lcomm (BSS) symbols for uninitialized data
+
+mnolong
+Target Report RejectNegative Mask(SHORT) MaskExists
+Consider type 'int' to be 16 bits wide
+
 mnortd
 Target RejectNegative InverseMask(RTD)
 Use normal calling convention
@@ -124,6 +152,18 @@
 Target Report Mask(PCREL)
 Generate pc-relative code
 
+mregparm
+Target Report Mask(REGPARM)
+Allow passing by registers
+
+mregparm=
+Target Report Joined Var(m68k_regparm_string)
+Number of register parameters of each register type
+
+mrodata-to-text
+Target Report Mask(RODATA_TO_TEXT)
+When not merging sections, put read-only data into .text rather than .data
+
 mrtd
 Target Report RejectNegative Mask(RTD)
 Use different calling convention using 'rtd'
@@ -137,7 +177,7 @@
 ID of shared library to build
 
 mshort
-Target Report RejectNegative Mask(SHORT)
+Target Report Mask(SHORT)
 Consider type 'int' to be 16 bits wide
 
 msoft-float
@@ -147,3 +187,7 @@
 mstrict-align
 Target Report Mask(STRICT_ALIGNMENT)
 Do not use unaligned memory references
+
+mtios
+Target Report Mask(TIOS)
+Enable TIOS interoperability
diff -Naur gcc-4.1.2.orig/gcc/config/m68k/m68k-protos.h gcc-4.1.2-src/gcc/config/m68k/m68k-protos.h
--- gcc-4.1.2.orig/gcc/config/m68k/m68k-protos.h	2005-07-12 01:32:01.000000000 +0200
+++ gcc-4.1.2-src/gcc/config/m68k/m68k-protos.h	2007-02-19 02:32:34.000000000 +0100
@@ -44,6 +44,13 @@
 extern int floating_exact_log2 (rtx);
 extern bool strict_low_part_peephole_ok (enum machine_mode mode, rtx first_insn, rtx target);
 
+/* begin-TIGCC-local (regparms): explicit register specification for parameters */
+void amigaos_init_cumulative_args(struct m68k_args *, tree, tree);
+void amigaos_function_arg_advance(struct m68k_args *);
+struct rtx_def *amigaos_function_arg(struct m68k_args *, enum machine_mode, tree);
+/* end-TIGCC-local (regparms) */
+void m68k_asm_file_start(void);
+
 /* Functions from m68k.c used in macros.  */
 extern int standard_68881_constant_p (rtx);
 extern void print_operand_address (FILE *, rtx);
diff -Naur gcc-4.1.2.orig/gcc/config/m68k/m68k-ti.h gcc-4.1.2-src/gcc/config/m68k/m68k-ti.h
--- gcc-4.1.2.orig/gcc/config/m68k/m68k-ti.h	1970-01-01 01:00:00.000000000 +0100
+++ gcc-4.1.2-src/gcc/config/m68k/m68k-ti.h	2007-02-19 02:32:34.000000000 +0100
@@ -0,0 +1,215 @@
+/* Definitions of target machine for GNU compiler.
+   TI-68k architecture (68000),
+   COFF object files and debugging version.
+   Derived in part from m68kemb.h and other files.
+   Copyright (C) 1994 Free Software Foundation, Inc.
+   Copyright (C) 2000 mmu_man (François Revol)
+   (Modified by Sebastian Reichelt for the Windows release of TIGCC)
+ 
+This file is part of TIGCC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Define the output of the target version */
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (MC68000 TI with COFF output)");
+
+/* Even if we compile with -mlong, we want only 16-bit alignment. */
+
+#undef PARM_BOUNDARY
+#define PARM_BOUNDARY 16
+
+/* Don't default to pcc-struct-return, so that we can return small
+   structures and unions in registers, which is slightly more
+   efficient. There are probably no TIOS routines returning structs;
+   if there are, the appropriate program will have to be compiled
+   with the "-fpcc-struct-return" option. But that option will cause
+   problems with ROM_CALLs returning a HSym, which is defined as a
+   structure in TIGCC.  */
+
+#undef DEFAULT_PCC_STRUCT_RETURN
+#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/* In order for bitfields to work on a 68000, or with -mnobitfield, we must
+   define either PCC_BITFIELD_TYPE_MATTERS or STRUCTURE_SIZE_BOUNDARY.
+   Defining STRUCTURE_SIZE_BOUNDARY results in structure packing problems,
+   so we define PCC_BITFIELD_TYPE_MATTERS.  */
+
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* Undefine PCC_STATIC_STRUCT_RETURN so that we get a re-entrant
+   calling convention (whatever that means).  */
+
+#undef PCC_STATIC_STRUCT_RETURN
+
+/* Define how to generate (in the callee) the output value of a
+   function and how to find (in the caller) the value returned by a
+   function. VALTYPE is the data type of the value (as a tree). If
+   the precise function being called is known, FUNC is its
+   FUNCTION_DECL; otherwise, FUNC is 0. When calling TIOS functions,
+   find the result in d0 or a0 as appropriate. */
+ 
+#undef FUNCTION_VALUE
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+	(((TARGET_TIOS) && (POINTER_TYPE_P (VALTYPE))) \
+	? gen_rtx_REG (TYPE_MODE (VALTYPE), 8) \
+	: LIBCALL_VALUE (TYPE_MODE (VALTYPE)))
+
+/* Define how to find a library call return value. Usually the value will be
+   in d0 (thru d1 or d2), but floats should be assumed to be returned in a
+   stack frame. This happens automatically if the specified register (d1 in
+   this case) is not a possible register for returning the value, because
+   floats take up 3 registers. Never use direct floats if d3 is clobbered
+   by function calls. */
+
+#undef LIBCALL_VALUE
+#define LIBCALL_VALUE(MODE) \
+	(((TARGET_DIRECTFLOAT) && ((MODE) == BFmode)) \
+	? gen_rtx_REG (MODE, 1) \
+	: gen_rtx_REG (MODE, 0))
+
+/* 1 if N is a possible register number for a function value. For
+   calling TIOS functions, allow a0 in addition to d0 (see above). */
+
+#undef FUNCTION_VALUE_REGNO_P
+#define FUNCTION_VALUE_REGNO_P(N) \
+	(((N) == 0) || (TARGET_TIOS && ((N) == 8)) || (TARGET_DIRECTFLOAT && ((N) == 1)))
+
+/* Define this to be true when FUNCTION_VALUE_REGNO_P is true for
+   more than one register (see above). */
+
+#undef NEEDS_UNTYPED_CALL
+#define NEEDS_UNTYPED_CALL (TARGET_TIOS || TARGET_DIRECTFLOAT)
+
+/* This says how to output an assembler line
+   to define a global common symbol. */
+
+#undef ASM_OUTPUT_COMMON
+#define ASM_OUTPUT_COMMON(FILE,NAME,SIZE,ROUNDED) \
+do { \
+	if (TARGET_NO_BSS && ((NAME) [0] != '_')) \
+	{ \
+		long i; \
+		data_section (); \
+		fputs (".globl ", (FILE)); \
+		assemble_name ((FILE), (NAME)); \
+		fputs ("\n\t.even\n", (FILE)); \
+		assemble_name ((FILE), (NAME)); \
+		fputs (":\n", (FILE)); \
+		fprintf ((FILE), "\t.space %u\n", (unsigned)(ROUNDED)); \
+		fputs ("\t.even\n", (FILE)); \
+	} \
+	else \
+	{ \
+		fputs (".comm ", (FILE)); \
+		assemble_name ((FILE), (NAME)); \
+		fprintf ((FILE), ",%u\n", (unsigned)(ROUNDED)); \
+	} \
+} while (0)
+
+/* This says how to output an assembler line
+   to define a local common symbol. */
+
+#undef ASM_OUTPUT_LOCAL
+#define ASM_OUTPUT_LOCAL(FILE,NAME,SIZE,ROUNDED) \
+do { \
+	if (TARGET_NO_BSS) \
+	{ \
+		long i; \
+		data_section (); \
+		fputs ("\t.even\n", (FILE)); \
+		assemble_name ((FILE), (NAME)); \
+		fputs (":\n", (FILE)); \
+		fprintf ((FILE), "\t.space %u\n", (unsigned)(ROUNDED)); \
+		fputs ("\t.even\n", (FILE)); \
+	} \
+	else \
+	{ \
+		fputs (".lcomm ", (FILE)); \
+		assemble_name ((FILE), (NAME)); \
+		fprintf ((FILE), ",%u\n", (unsigned)(ROUNDED)); \
+	} \
+} while (0)
+
+/* If TARGET_MERGE_SECTIONS is set (on by default): if TARGET_MERGE_TO_DATA is
+   set, only use data sections, otherwise only use text sections. Both code and
+   data in RAM programs on a TI-89/92+/V200 are always writable; that's why it
+   does not make sense to have different data and text sections.
+   Those cannot be set to an empty string, since a number may follow, etc.
+   Anyway, better more than less. */
+
+#undef TEXT_SECTION_ASM_OP
+#define TEXT_SECTION_ASM_OP ((TARGET_MERGE_SECTIONS && TARGET_MERGE_TO_DATA)? \
+                             "\t.data":"\t.text")
+
+#undef DATA_SECTION_ASM_OP
+#define DATA_SECTION_ASM_OP ((TARGET_MERGE_SECTIONS && !TARGET_MERGE_TO_DATA)? \
+                             "\t.text":"\t.data")
+
+/* If TARGET_NO_BSS is set (off by default), use the data section here.
+   Otherwise use the BSS section. */
+
+#undef BSS_SECTION_ASM_OP
+#define BSS_SECTION_ASM_OP (TARGET_NO_BSS?DATA_SECTION_ASM_OP:"\t.section .bss")
+
+/* When not merging sections, put read-only data into .data unless
+   TARGET_RODATA_TO_TEXT is set. But jump tables do NOT qualify for going into
+   the data section! */
+#define READONLY_DATA_SECTION() (TARGET_RODATA_TO_TEXT ? text_section() \
+                                                       : data_section())
+#define JUMP_TABLES_IN_TEXT_SECTION 1
+
+/* Define "__INT_SHORT__" if short ints are set, e.g. if the "-mlong" switch
+   is not used. This is necessary for the TIGCC Library, since INT_MAX and
+   others need to be constants. */
+
+#undef CPP_SUBTARGET_SPEC
+#if (defined(__CYGWIN__) || defined(__WIN32__))
+#define CPP_SUBTARGET_SPEC "-D__TIGCC_ENV__ -D__TIGCC_WIN_ENV__ %{!mlong:%{!mnoshort:%{!mno-short:-D__INT_SHORT__ }}}"
+#else
+#define CPP_SUBTARGET_SPEC "-D__TIGCC_ENV__ %{!mlong:%{!mnoshort:%{!mno-short:-D__INT_SHORT__ }}}"
+#endif
+#undef CPP_SPEC
+#define CPP_SPEC CPP_SUBTARGET_SPEC
+
+/* Trampolines are code on the stack, so we need to add 0x40000 to their address
+   for it to work on a TI-89/92+/V200 HW2. On HW3, we should NOT add that
+   address. Moreover, EXECUTE_IN_GHOST_SPACE is required for it to work
+   correctly. Therefore, I am emitting a libcall and letting TIGCCLIB worry
+   about the details.
+   (code partially lifted from gcc/config/sh/sh.h) */
+#define TRAMPOLINE_ADJUST_ADDRESS(TRAMP) do \
+{ \
+  (TRAMP) = expand_simple_binop (Pmode, PLUS, (TRAMP), \
+                                 emit_library_call_value (gen_rtx_SYMBOL_REF (\
+                                                           Pmode, \
+                                                           "__trampoline_offset"), \
+                                                          NULL_RTX, LCT_CONST, \
+                                                          Pmode, 0), \
+                                 gen_reg_rtx (Pmode), 0, \
+                                 OPTAB_LIB_WIDEN); \
+} while (0)
+
+/* We want -fomit-frame-pointer by default. */
+#define CAN_DEBUG_WITHOUT_FP
+
+/* We want DWARF2 debugging and unwinding information */
+#define DWARF2_DEBUGGING_INFO 1
+#define DWARF2_ASM_LINE_DEBUG_INFO 1
+#define DWARF2_UNWIND_INFO 1
+
+/* end of m68k-ti.h */
diff -Naur gcc-4.1.2.orig/gcc/config/m68k/predicates.md gcc-4.1.2-src/gcc/config/m68k/predicates.md
--- gcc-4.1.2.orig/gcc/config/m68k/predicates.md	2005-06-25 03:22:41.000000000 +0200
+++ gcc-4.1.2-src/gcc/config/m68k/predicates.md	2007-02-19 02:32:34.000000000 +0100
@@ -88,7 +88,7 @@
 ;; hosted on 64-bit machines.
 
 (define_predicate "const_uint32_operand"
-  (match_code "const_int,const_double")
+  (match_code "const_int")
 {
   /* It doesn't make sense to ask this question with a mode that is
      not larger than 32 bits.  */
@@ -101,7 +101,7 @@
 	  && (INTVAL (op) >= 0 && INTVAL (op) <= 0xffffffffL));
 #else
   return (GET_CODE (op) == CONST_INT
-	  || (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_HIGH (op) == 0));
+	  && INTVAL (op) >= 0);
 #endif
 })
 
@@ -194,3 +194,13 @@
 {
   return MEM_P (op) && GET_CODE (XEXP (op, 0)) == PRE_DEC;
 })
+
+;; (TIGCC 20040222) This predicate is used to allow straight labels in the
+;;                  indirect_jump pattern. -- Kevin Kofler
+(define_predicate "extended_address_operand"
+  (match_code "const_int,const_double,const,symbol_ref,label_ref,subreg,reg,mem,plus,minus,mult")
+{
+  if (TARGET_PCREL && CONSTANT_ADDRESS_P (op))
+    return 1;
+  return address_operand (op, mode);
+})
diff -Naur gcc-4.1.2.orig/gcc/config/smapbcd.h gcc-4.1.2-src/gcc/config/smapbcd.h
--- gcc-4.1.2.orig/gcc/config/smapbcd.h	1970-01-01 01:00:00.000000000 +0100
+++ gcc-4.1.2-src/gcc/config/smapbcd.h	2007-02-19 02:32:34.000000000 +0100
@@ -0,0 +1,369 @@
+/* Definitions for SMAP II BCD support in the GNU C Compiler.
+   These macros implement software BCD floating point support;
+   primary use will be TIGCC.
+   Copyright (C) 1994 Free Software Foundation, Inc.
+   Copyright (C) 2000 Sebastian Reichelt
+   Copyright (C) 2003-2005 Kevin Kofler
+
+This file is part of TIGCC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#undef TARGET_FLOAT_FORMAT
+#define	TARGET_FLOAT_FORMAT SMAP_BCD_FLOAT_FORMAT
+
+#ifndef __SMAP_BCD_FLOAT
+#define __SMAP_BCD_FLOAT
+
+typedef struct real_value smap_bcd_float;
+
+#endif
+
+#undef REAL_VALUE_TYPE
+#define REAL_VALUE_TYPE smap_bcd_float
+
+#undef FLOAT_TYPE_SIZE
+#undef DOUBLE_TYPE_SIZE
+#undef LONG_DOUBLE_TYPE_SIZE
+
+/* We have to define a special mode for this; one that handles 10 byte
+   floats. There have to be a lot of changes to other files; due to the
+   fact that they are so countless, it would be too hard to make them
+   compatible with a general-purpose GCC. */
+#define FLOAT_TYPE_SIZE 80
+#define DOUBLE_TYPE_SIZE 80
+#define LONG_DOUBLE_TYPE_SIZE 80
+
+#ifndef REAL_IS_NOT_DOUBLE
+#define REAL_IS_NOT_DOUBLE
+#endif
+
+#define ZERO (__extension__(smap_bcd_float){0x4000,0})
+#define UNSIGNED_ZERO (__extension__(smap_bcd_float){0x4000,0})
+#define POSITIVE_ZERO (__extension__(smap_bcd_float){0,0})
+#define NEGATIVE_ZERO (__extension__(smap_bcd_float){0x8000,0})
+
+#define UNSIGNED_INF (__extension__(smap_bcd_float){0x7FFF,0xAA00CC0000000000ull})
+#define POSITIVE_INF (__extension__(smap_bcd_float){0x7FFF,0xAA00BB0000000000ull})
+#define NEGATIVE_INF (__extension__(smap_bcd_float){0xFFFF,0xAA00BB0000000000ull})
+
+#define NAN (__extension__(smap_bcd_float){0x7FFF,0xAA00000000000000ull})
+
+#ifndef REAL_INFINITY
+#define REAL_INFINITY
+#endif
+
+#undef REAL_VALUE_ISNAN
+#define REAL_VALUE_ISNAN(x) \
+	(REAL_VALUES_IDENTICAL (x, NAN))
+
+#undef REAL_VALUE_ISINF
+#define REAL_VALUE_ISINF(x) \
+	((REAL_VALUES_IDENTICAL (x, POSITIVE_INF)) \
+	|| (REAL_VALUES_IDENTICAL (x, NEGATIVE_INF)) \
+	|| (REAL_VALUES_IDENTICAL (x, UNSIGNED_INF)))
+
+#define REAL_VALUE_ISNANUINF(x) \
+	((REAL_VALUE_ISNAN (x)) \
+	|| (REAL_VALUES_IDENTICAL (x, UNSIGNED_INF)))
+
+#define REAL_VALUE_ISFINITE(x) \
+	(!(REAL_VALUE_ISNAN (x)) \
+	&& !(REAL_VALUE_ISINF (x)))
+
+#define REAL_VALUE_ISZERO(x) \
+	(!((x).mantissa))
+
+#undef REAL_VALUE_MINUS_ZERO
+#define REAL_VALUE_MINUS_ZERO(x) \
+	(REAL_VALUES_IDENTICAL (x, NEGATIVE_ZERO))
+
+#define REAL_VALUE_ISPOSITIVE(x) \
+	(!(REAL_VALUE_ISNANUINF (x)) \
+	&& ((x).exponent < 0x8000) \
+	&& !(REAL_VALUE_ISZERO (x)))
+
+#define REAL_VALUE_ISNEGATIVE(x) \
+	(!(REAL_VALUE_ISNANUINF (x)) \
+	&& ((x).exponent >= 0x8000) \
+	&& !(REAL_VALUE_ISZERO (x)))
+
+#undef REAL_VALUE_POSITIVE
+#define REAL_VALUE_POSITIVE(x) \
+	(REAL_VALUE_ISPOSITIVE (x))
+
+#undef REAL_VALUE_NEGATIVE
+#define REAL_VALUE_NEGATIVE(x) \
+	(REAL_VALUE_ISNEGATIVE (x))
+
+#define real_isneg(x) \
+	(REAL_VALUE_ISNEGATIVE (*(x)))
+
+#undef REAL_VALUES_IDENTICAL
+#define REAL_VALUES_IDENTICAL(x, y) \
+	((x).exponent == (y).exponent && (x).mantissa == (y).mantissa)
+
+#undef REAL_VALUES_EQUAL
+#define REAL_VALUES_EQUAL(x,y) \
+	(((REAL_VALUES_IDENTICAL (x, y)) \
+	&& !REAL_VALUE_ISNANUINF (x) \
+	&& !REAL_VALUE_ISNANUINF (y)) \
+	|| (REAL_VALUE_ISZERO (x) \
+	&& REAL_VALUE_ISZERO (y)))
+
+#undef REAL_VALUES_LESS
+#define REAL_VALUES_LESS(x,y) \
+__extension__ ({ \
+	register int result = 0; \
+	if (REAL_VALUE_ISNANUINF (x) \
+		|| REAL_VALUE_ISNANUINF (y) \
+		|| REAL_VALUES_EQUAL (x, y) \
+		|| (REAL_VALUE_ISPOSITIVE (x) && !(REAL_VALUE_ISPOSITIVE (y))) \
+		|| (!(REAL_VALUE_ISNEGATIVE (x)) && REAL_VALUE_ISNEGATIVE (y))) \
+		result = 0; \
+	else if ((REAL_VALUE_ISNEGATIVE (x) && !(REAL_VALUE_ISNEGATIVE (y))) \
+		|| (!(REAL_VALUE_ISPOSITIVE (x)) && REAL_VALUE_ISPOSITIVE (y))) \
+		result = 1; \
+	else \
+	{ \
+		if ((x).exponent == (y).exponent) \
+		{ \
+			if (REAL_VALUE_ISNEGATIVE (x)) \
+				result = ((x).mantissa > (y).mantissa); \
+			else \
+				result = ((x).mantissa < (y).mantissa); \
+		} \
+		else \
+		{ \
+			if (REAL_VALUE_ISNEGATIVE (x)) \
+				result = ((x).exponent > (y).exponent); \
+			else \
+				result = ((x).exponent < (y).exponent); \
+		} \
+	} \
+	result; \
+})
+
+#undef REAL_VALUE_LDEXP
+#define REAL_VALUE_LDEXP(x,tempscale) \
+__extension__ ({ \
+	REAL_VALUE_TYPE __tempx = x; \
+	int scale; \
+	unsigned long long pmul; \
+	signed short carry, help; \
+	if (REAL_VALUE_ISFINITE (__tempx)) \
+	{ \
+		if (tempscale > 0) \
+			for (scale = 0; scale < tempscale; scale++) \
+			{ \
+				if (__tempx.mantissa >= 0x5000000000000000ull) \
+				{ \
+					__tempx.mantissa /= 0x10; \
+					__tempx.exponent++; \
+				} \
+				carry = 0; \
+				for (pmul = 1; 1; pmul *= 0x10) \
+				{ \
+					help = (__tempx.mantissa / pmul) & 0xF; \
+					__tempx.mantissa -= ((unsigned long long) help) * pmul; \
+					help *= 2; \
+					help += carry; \
+					carry = help / 10; \
+					__tempx.mantissa += ((unsigned long long) (help % 10)) * pmul; \
+					if (pmul >= 0x1000000000000000ull) \
+						break; \
+				} \
+			} \
+		else if (tempscale < 0) \
+			for (scale = 0; scale > tempscale; scale--) \
+			{ \
+				carry = 0; \
+				for (pmul = 0x1000000000000000ull; pmul > 0; pmul /= 0x10) \
+				{ \
+					help = (__tempx.mantissa / pmul) & 0xF; \
+					__tempx.mantissa -= ((unsigned long long) help) * pmul; \
+					help += carry; \
+					__tempx.mantissa += ((unsigned long long) (help / 2)) * pmul; \
+					carry = (help % 2) * 10; \
+				} \
+				if (__tempx.mantissa < 0x1000000000000000ull) \
+				{ \
+					__tempx.mantissa *= 0x10; \
+					__tempx.mantissa += carry / 2; \
+					__tempx.exponent--; \
+				} \
+			} \
+	} \
+	__tempx; \
+})
+
+#undef REAL_VALUE_FIX
+#define REAL_VALUE_FIX(x) \
+	((REAL_VALUE_ISNEGATIVE (x)) \
+	? (-(REAL_VALUE_UNSIGNED_FIX (REAL_VALUE_NEGATE (x)))) \
+	: (REAL_VALUE_UNSIGNED_FIX (x)))
+
+#undef REAL_VALUE_UNSIGNED_FIX
+#define REAL_VALUE_UNSIGNED_FIX(x) \
+__extension__ ({ \
+	register unsigned int r = 0; \
+	signed char i; \
+	unsigned long long mpmul = 0x1000000000000000ull; \
+	if (((x.exponent & 0x7FFF) >= 0x4000) && ((x.exponent & 0x7FFF) < 0x4016)) \
+	{ \
+		for (i = 0; i <= (x.exponent & 0x7FFF) - 0x4000; i++) \
+			if (mpmul) \
+			{ \
+				r *= 10; \
+				r += (x.mantissa / mpmul) & 0xF; \
+				mpmul /= 0x10; \
+			} \
+	} \
+	r; \
+})
+
+#undef REAL_VALUE_RNDZINT
+#define REAL_VALUE_RNDZINT(x) \
+__extension__ ({ \
+	REAL_VALUE_TYPE r = ZERO; \
+	signed char i; \
+	unsigned long long mpmul = 0x1000000000000000ull; \
+	r.exponent = (x).exponent; \
+	if (((r.exponent & 0x7FFF) >= 0x4000) && ((r.exponent & 0x7FFF) < 0x4016)) \
+	{ \
+		for (i = 0; i <= (r.exponent & 0x7FFF) - 0x4000; i++) \
+			if (mpmul) \
+			{ \
+				r.mantissa += x.mantissa & (0xF * mpmul); \
+				mpmul /= 0x10; \
+			} \
+	} \
+	r; \
+})
+
+#undef REAL_VALUE_UNSIGNED_RNDZINT
+#define REAL_VALUE_UNSIGNED_RNDZINT(x) \
+	((REAL_VALUE_ISPOSITIVE (x)) \
+	? (REAL_VALUE_RNDZINT (x)) \
+	: (ZERO))
+
+#undef REAL_VALUE_ATOF
+#define REAL_VALUE_ATOF(string,mode) \
+	real_from_string2((string), (mode))
+
+#undef REAL_ARITHMETIC
+#define REAL_ARITHMETIC(value, code, d1, d2) \
+	real_arithmetic (&(value), (code), &(d1), &(d2))
+
+#undef REAL_VALUE_NEGATE
+#define REAL_VALUE_NEGATE(x) \
+__extension__ ({ \
+	REAL_VALUE_TYPE __tempx = x; \
+	if ((!(REAL_VALUE_ISNANUINF (__tempx))) && ((__tempx.mantissa) || (__tempx.exponent != 0x4000))) \
+		__tempx.exponent ^= 0x8000; \
+	__tempx; \
+})
+
+#undef REAL_VALUE_TRUNCATE
+#define REAL_VALUE_TRUNCATE(mode,x) \
+	(x)
+
+#define real_convert(r,mode,x) \
+	(*(r)=*(x))
+
+#define REAL_VALUE_TO_INT(lo, hi, r) real_to_integer2 ((lo), (hi), &(r))
+
+#define REAL_VALUE_FROM_INT(d, lo, hi, mode) \
+	real_from_integer (&(d), (mode), (lo), (hi), 0)
+
+#define REAL_VALUE_FROM_UNSIGNED_INT(d, lo, hi, mode) \
+	real_from_integer (&(d), (mode), (lo), (hi), 1)
+
+#undef REAL_VALUE_TO_TARGET_SINGLE
+#define REAL_VALUE_TO_TARGET_SINGLE(IN, OUT) \
+	gcc_unreachable();
+
+#undef REAL_VALUE_TO_TARGET_DOUBLE
+#define REAL_VALUE_TO_TARGET_DOUBLE(IN, OUT) \
+	gcc_unreachable();
+
+#undef REAL_VALUE_TO_TARGET_LONG_DOUBLE
+#define REAL_VALUE_TO_TARGET_LONG_DOUBLE(IN, OUT) \
+do { \
+	REAL_VALUE_TYPE f = (IN); \
+	(OUT)[0] = f.exponent * 0x10000 + ((unsigned short) (f.mantissa / 0x1000000000000ull)), (OUT)[1] = (unsigned long) (f.mantissa / 0x10000), (OUT)[2] = ((unsigned short) (f.mantissa)) * 0x10000; \
+} while (0)
+
+#undef REAL_VALUE_TO_TARGET_SMAP_BCD
+#define REAL_VALUE_TO_TARGET_SMAP_BCD(IN, OUT) \
+do { \
+	REAL_VALUE_TYPE f = (IN); \
+	(OUT)[0] = f.exponent, (OUT)[1] = (unsigned long) (f.mantissa / 0x100000000ull), (OUT)[2] = (unsigned long) (f.mantissa); \
+} while (0)
+
+#define REAL_VALUE_TO_STRING(IN, OUT) \
+do { \
+	REAL_VALUE_TYPE f = (IN); \
+	if (REAL_VALUE_ISNAN (f)) \
+		sprintf ((OUT), "NaN"); \
+	else if (REAL_VALUES_IDENTICAL (f, UNSIGNED_INF)) \
+		sprintf ((OUT), "Inf"); \
+	else if (REAL_VALUES_IDENTICAL (f, POSITIVE_INF)) \
+		sprintf ((OUT), "+Inf"); \
+	else if (REAL_VALUES_IDENTICAL (f, NEGATIVE_INF)) \
+		sprintf ((OUT), "-Inf"); \
+	else if (REAL_VALUES_IDENTICAL (f, UNSIGNED_ZERO)) \
+		sprintf ((OUT), "0.0"); \
+	else if (REAL_VALUES_IDENTICAL (f, POSITIVE_ZERO)) \
+		sprintf ((OUT), "+0.0"); \
+	else if (REAL_VALUES_IDENTICAL (f, NEGATIVE_ZERO)) \
+		sprintf ((OUT), "-0.0"); \
+	else \
+	{ \
+		long exp; \
+		int neg = REAL_VALUE_ISNEGATIVE (f); \
+		if (neg) \
+			exp = f.exponent - 0xC000; \
+		else \
+			exp = f.exponent - 0x4000; \
+		sprintf ((OUT), "%s%lx.%07lx%08lxe%d", neg ? "-" : "", (unsigned long) (f.mantissa >> 60), (unsigned long) (f.mantissa >> 32) & 0x0ffffffful, (unsigned long) (f.mantissa), (int) (exp)); \
+	} \
+} while (0)
+
+#define REAL_VALUE_ABS(x) ((REAL_VALUE_ISNEGATIVE((x))\
+                            || REAL_VALUE_MINUS_ZERO((x))\
+                            || REAL_VALUES_IDENTICAL ((x), NEGATIVE_INF))?\
+                           REAL_VALUE_NEGATE((x)):(x))
+
+/* WARNING: This is the number of bits we can represent, not the true size of
+            the mantissa. */
+#define significand_size(dummy) (53)
+
+#undef MODE_HAS_NANS
+#define MODE_HAS_NANS(MODE) ((MODE)==BFmode)
+
+#undef MODE_HAS_INFINITIES
+#define MODE_HAS_INFINITIES(MODE) ((MODE)==BFmode)
+
+/* FIXME: GCC expects this to mean that there is only 0 and -0. We actually have
+          0, +0 and -0. This allows a few optimizations GCC is too cautious to
+          do in the presence of signed zeros. */
+#undef MODE_HAS_SIGNED_ZEROS
+#define MODE_HAS_SIGNED_ZEROS(MODE) ((MODE)==BFmode)
+
+#define REAL_MODE_FORMAT_COMPOSITE_P(dummy) (0)
+
+/* end of smapbcd.h */
diff -Naur gcc-4.1.2.orig/gcc/config.gcc gcc-4.1.2-src/gcc/config.gcc
--- gcc-4.1.2.orig/gcc/config.gcc	2006-10-16 01:12:23.000000000 +0200
+++ gcc-4.1.2-src/gcc/config.gcc	2007-02-19 02:32:34.000000000 +0100
@@ -1381,7 +1381,7 @@
 m68k-*-coff*)
 	tmake_file=m68k/t-m68kbare
 	tm_defines="MOTOROLA USE_GAS"
-	tm_file="m68k/m68k.h m68k/m68k-none.h m68k/m68kemb.h dbxcoff.h m68k/coff.h dbx.h"
+	tm_file="m68k/m68k.h m68k/m68k-none.h dbxcoff.h m68k/coff.h smapbcd.h m68k/m68k-ti.h dbx.h"
 	use_fixproto=yes
 	;;
 m68020-*-elf* | m68k-*-elf*)
diff -Naur gcc-4.1.2.orig/gcc/convert.c gcc-4.1.2-src/gcc/convert.c
--- gcc-4.1.2.orig/gcc/convert.c	2006-11-13 11:18:57.000000000 +0100
+++ gcc-4.1.2-src/gcc/convert.c	2007-02-19 02:32:34.000000000 +0100
@@ -73,6 +73,9 @@
 {
   tree sub, expt, subt;
 
+/* (TIGCC 20050205) We do not implement exact_real_truncate and there is no
+                    narrower float mode anyway. -- Kevin Kofler */
+#if 0
   /*  For floating point constant look up the narrowest type that can hold
       it properly and handle it like (type)(narrowest_type)constant.
       This way we can optimize for instance a=a*2.0 where "a" is float
@@ -93,6 +96,7 @@
       if (type)
 	return build_real (type, real_value_truncate (TYPE_MODE (type), orig));
     }
+#endif /* 0 */
 
   if (TREE_CODE (exp) != NOP_EXPR
       && TREE_CODE (exp) != CONVERT_EXPR)
diff -Naur gcc-4.1.2.orig/gcc/c.opt gcc-4.1.2-src/gcc/c.opt
--- gcc-4.1.2.orig/gcc/c.opt	2006-01-26 20:06:06.000000000 +0100
+++ gcc-4.1.2-src/gcc/c.opt	2007-02-19 02:32:34.000000000 +0100
@@ -446,6 +446,10 @@
 C ObjC C++ ObjC++
 Recognize the \"asm\" keyword
 
+fauto-octals
+C ObjC C++ ObjC++
+Numbers starting with zero should be octal (default on).
+
 fbuiltin
 C ObjC C++ ObjC++
 Recognize built-in functions
diff -Naur gcc-4.1.2.orig/gcc/c-opts.c gcc-4.1.2-src/gcc/c-opts.c
--- gcc-4.1.2.orig/gcc/c-opts.c	2007-01-05 16:55:45.000000000 +0100
+++ gcc-4.1.2-src/gcc/c-opts.c	2007-02-19 02:32:34.000000000 +0100
@@ -222,6 +222,9 @@
      before passing on command-line options to cpplib.  */
   cpp_opts->warn_dollars = 0;
 
+  /* (TIGCC 20050217) Enable -fms-extensions by default. */
+  flag_ms_extensions = 1;
+
   flag_const_strings = c_dialect_cxx ();
   flag_exceptions = c_dialect_cxx ();
   warn_pointer_arith = c_dialect_cxx ();
@@ -323,7 +326,9 @@
 	    error ("-I- specified twice");
 	  quote_chain_split = true;
 	  split_quote_chain ();
+#if 0 /* (TIGCC 20050206) */
 	  inform ("obsolete option -I- used, please use -iquote instead");
+#endif /* 0 */
 	}
       break;
 
@@ -418,8 +423,10 @@
       cpp_opts->warn_num_sign_change = value;
       cpp_opts->warn_multichar = value;	/* Was C++ only.  */
 
+#if 0 /* (TIGCC 20060430) */
       if (warn_pointer_sign == -1)
 	warn_pointer_sign = 1;
+#endif /* 0 */
       break;
 
     case OPT_Wcomment:
@@ -881,6 +888,8 @@
     case OPT_pedantic:
       cpp_opts->pedantic = 1;
       cpp_opts->warn_endif_labels = 1;
+      /* (TIGCC 20050217) No Microsoft extensions if -pedantic. */
+      flag_ms_extensions = 0;
       if (warn_pointer_sign == -1)
 	warn_pointer_sign = 1;
       break;
@@ -949,6 +958,10 @@
     case OPT_v:
       verbose = true;
       break;
+
+    case OPT_fauto_octals:
+      cpp_opts->no_auto_octals = !value;
+      break;
     }
 
   return result;
@@ -1029,10 +1042,12 @@
 	       "-Wformat-security ignored without -Wformat");
     }
 
+#if 0 /* (TIGCC 20050306) Disable as we don't have these libcalls. */
   /* C99 requires special handling of complex multiplication and division;
      -ffast-math and -fcx-limited-range are handled in process_options.  */
   if (flag_isoc99)
     flag_complex_method = 2;
+#endif /* 0 */
 
   if (flag_preprocess_only)
     {
diff -Naur gcc-4.1.2.orig/gcc/c-parser.c gcc-4.1.2-src/gcc/c-parser.c
--- gcc-4.1.2.orig/gcc/c-parser.c	2006-08-15 18:55:25.000000000 +0200
+++ gcc-4.1.2-src/gcc/c-parser.c	2007-02-19 02:32:34.000000000 +0100
@@ -911,14 +911,14 @@
 						      struct c_expr *);
 static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *);
 static struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *);
-static struct c_expr c_parser_unary_expression (c_parser *);
+static struct c_expr c_parser_unary_expression (c_parser *, bool in_cast);
 static struct c_expr c_parser_sizeof_expression (c_parser *);
 static struct c_expr c_parser_alignof_expression (c_parser *);
-static struct c_expr c_parser_postfix_expression (c_parser *);
+static struct c_expr c_parser_postfix_expression (c_parser *, bool in_cast);
 static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *,
 								   struct c_type_name *);
 static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
-								struct c_expr);
+								struct c_expr, bool in_cast);
 static struct c_expr c_parser_expression (c_parser *);
 static struct c_expr c_parser_expression_conv (c_parser *);
 static tree c_parser_expr_list (c_parser *, bool);
@@ -2527,6 +2527,7 @@
   struct c_declspecs *specs;
   struct c_declarator *declarator;
   tree prefix_attrs;
+  tree maybeasm = NULL_TREE;
   tree postfix_attrs = NULL_TREE;
   bool dummy = false;
   if (!c_parser_next_token_starts_declspecs (parser))
@@ -2556,10 +2557,14 @@
       c_parser_skip_until_found (parser, CPP_COMMA, NULL);
       return NULL;
     }
+  /* (TIGCC 20051221) Register parameter support. We accept an ASM
+     at this place to specify a register for the parameter. */
+  if (c_parser_next_token_is_keyword (parser, RID_ASM))
+    maybeasm = c_parser_simple_asm_expr (parser);
   if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
     postfix_attrs = c_parser_attributes (parser);
   return build_c_parm (specs, chainon (postfix_attrs, prefix_attrs),
-		       declarator);
+		       declarator, maybeasm);
 }
 
 /* Parse a string literal in an asm expression.  It should not be
@@ -3317,8 +3322,8 @@
 
       parser->error = false;
     }
-  if (last_label)
-    error ("label at end of compound statement");
+  if (last_label && pedantic)
+    pedwarn ("ISO C doesn't allow labels at the end of compound statements");
   c_parser_consume_token (parser);
 }
 
@@ -4463,11 +4468,8 @@
 */
 
 static struct c_expr
-c_parser_cast_expression (c_parser *parser, struct c_expr *after)
+c_parser_cast_expression_1 (c_parser *parser, bool in_cast)
 {
-  gcc_assert (!after || c_dialect_objc ());
-  if (after)
-    return c_parser_postfix_expression_after_primary (parser, *after);
   /* If the expression begins with a parenthesized type name, it may
      be either a cast or a compound literal; we need to see whether
      the next character is '{' to tell the difference.  If not, it is
@@ -4490,14 +4492,28 @@
       if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
 	return c_parser_postfix_expression_after_paren_type (parser,
 							     type_name);
-      expr = c_parser_cast_expression (parser, NULL);
+      expr = c_parser_cast_expression_1 (parser, 1);
       expr = default_function_array_conversion (expr);
       ret.value = c_cast_expr (type_name, expr.value);
       ret.original_code = ERROR_MARK;
       return ret;
     }
   else
-    return c_parser_unary_expression (parser);
+    return c_parser_unary_expression (parser, in_cast);
+}
+
+/* (TIGCC 20051222) Postfix operators apply to casts too. */
+static struct c_expr
+c_parser_cast_expression (c_parser *parser, struct c_expr *after)
+{
+  gcc_assert (!after || c_dialect_objc ());
+  if (after)
+    return c_parser_postfix_expression_after_primary (parser, *after, 0);
+  /* Allow all postfix operators, not just ++ and --. Those with higher
+     priority than casts will already have been parsed first, unless they
+     come after ++ and --, in which case they need to be parsed here. */
+  return c_parser_postfix_expression_after_primary (parser,
+           c_parser_cast_expression_1 (parser, 0), 0);
 }
 
 /* Parse an unary expression (C90 6.3.3, C99 6.5.3).
@@ -4528,7 +4544,7 @@
    given later.  */
 
 static struct c_expr
-c_parser_unary_expression (c_parser *parser)
+c_parser_unary_expression (c_parser *parser, bool in_cast)
 {
   int ext;
   struct c_expr ret, op;
@@ -4618,10 +4634,10 @@
 	  op = default_function_array_conversion (op);
 	  return parser_build_unary_op (IMAGPART_EXPR, op);
 	default:
-	  return c_parser_postfix_expression (parser);
+	  return c_parser_postfix_expression (parser, in_cast);
 	}
     default:
-      return c_parser_postfix_expression (parser);
+      return c_parser_postfix_expression (parser, in_cast);
     }
 }
 
@@ -4666,7 +4682,7 @@
     }
   else
     {
-      expr = c_parser_unary_expression (parser);
+      expr = c_parser_unary_expression (parser, 0);
     sizeof_expr:
       skip_evaluation--;
       in_sizeof--;
@@ -4722,7 +4738,7 @@
   else
     {
       struct c_expr ret;
-      expr = c_parser_unary_expression (parser);
+      expr = c_parser_unary_expression (parser, 0);
     alignof_expr:
       skip_evaluation--;
       in_alignof--;
@@ -4786,7 +4802,7 @@
 */
 
 static struct c_expr
-c_parser_postfix_expression (c_parser *parser)
+c_parser_postfix_expression (c_parser *parser, bool in_cast)
 {
   struct c_expr expr, e1, e2, e3;
   struct c_type_name *t1, *t2;
@@ -5183,7 +5199,7 @@
       expr.original_code = ERROR_MARK;
       break;
     }
-  return c_parser_postfix_expression_after_primary (parser, expr);
+  return c_parser_postfix_expression_after_primary (parser, expr, in_cast);
 }
 
 /* Parse a postfix expression after a parenthesized type name: the
@@ -5216,7 +5232,7 @@
     pedwarn ("ISO C90 forbids compound literals");
   expr.value = build_compound_literal (type, init.value);
   expr.original_code = ERROR_MARK;
-  return c_parser_postfix_expression_after_primary (parser, expr);
+  return c_parser_postfix_expression_after_primary (parser, expr, 0);
 }
 
 /* Parse a postfix expression after the initial primary or compound
@@ -5224,7 +5240,8 @@
 
 static struct c_expr
 c_parser_postfix_expression_after_primary (c_parser *parser,
-					   struct c_expr expr)
+					   struct c_expr expr,
+					   bool in_cast)
 {
   tree ident, idx, exprlist;
   while (true)
@@ -5288,6 +5305,9 @@
 	  expr.original_code = ERROR_MARK;
 	  break;
 	case CPP_PLUS_PLUS:
+	  /* (TIGCC 20051222) Postincrement has lower priority than casts. */
+	  if (in_cast)
+	    return expr;
 	  /* Postincrement.  */
 	  c_parser_consume_token (parser);
 	  expr = default_function_array_conversion (expr);
@@ -5295,6 +5315,9 @@
 	  expr.original_code = ERROR_MARK;
 	  break;
 	case CPP_MINUS_MINUS:
+	  /* (TIGCC 20051222) Postdecrement has lower priority than casts. */
+	  if (in_cast)
+	    return expr;
 	  /* Postdecrement.  */
 	  c_parser_consume_token (parser);
 	  expr = default_function_array_conversion (expr);
diff -Naur gcc-4.1.2.orig/gcc/cppdefault.c gcc-4.1.2-src/gcc/cppdefault.c
--- gcc-4.1.2.orig/gcc/cppdefault.c	2005-06-25 04:02:01.000000000 +0200
+++ gcc-4.1.2-src/gcc/cppdefault.c	2007-02-19 02:32:34.000000000 +0100
@@ -46,6 +46,7 @@
 = INCLUDE_DEFAULTS;
 #else
 = {
+#if 0 /* (TIGCC 20040104) Don't hardcode any prefix at compile time. */
 #ifdef GPLUSPLUS_INCLUDE_DIR
     /* Pick up GNU C++ generic include files.  */
     { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1, 0 },
@@ -85,11 +86,12 @@
     /* /usr/include comes dead last.  */
     { STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0, 1 },
 #endif
+#endif /* 0 */
     { 0, 0, 0, 0, 0 }
   };
 #endif /* no INCLUDE_DEFAULTS */
 
-#ifdef GCC_INCLUDE_DIR
+#if 0 /* (TIGCC 20040104) Don't hardcode any prefix at compile time. */
 const char cpp_GCC_INCLUDE_DIR[] = GCC_INCLUDE_DIR;
 const size_t cpp_GCC_INCLUDE_DIR_len = sizeof GCC_INCLUDE_DIR - 8;
 #else
diff -Naur gcc-4.1.2.orig/gcc/c-ppoutput.c gcc-4.1.2-src/gcc/c-ppoutput.c
--- gcc-4.1.2.orig/gcc/c-ppoutput.c	2005-10-14 16:56:45.000000000 +0200
+++ gcc-4.1.2-src/gcc/c-ppoutput.c	2007-02-19 02:32:34.000000000 +0100
@@ -174,7 +174,8 @@
       print.prev = token;
       cpp_output_token (token, print.outf);
 
-      if (token->type == CPP_COMMENT)
+      if (token->type == CPP_STRING || token->type == CPP_WSTRING
+	  || token->type == CPP_COMMENT)
 	account_for_newlines (token->val.str.text, token->val.str.len);
     }
 }
diff -Naur gcc-4.1.2.orig/gcc/c-pretty-print.c gcc-4.1.2-src/gcc/c-pretty-print.c
--- gcc-4.1.2.orig/gcc/c-pretty-print.c	2006-08-26 00:47:00.000000000 +0200
+++ gcc-4.1.2-src/gcc/c-pretty-print.c	2007-02-19 02:32:34.000000000 +0100
@@ -913,8 +913,7 @@
 static void
 pp_c_floating_constant (c_pretty_printer *pp, tree r)
 {
-  real_to_decimal (pp_buffer (pp)->digit_buffer, &TREE_REAL_CST (r),
-		   sizeof (pp_buffer (pp)->digit_buffer), 0, 1);
+  REAL_VALUE_TO_STRING (TREE_REAL_CST (r), pp_buffer (pp)->digit_buffer);
   pp_string (pp, pp_buffer(pp)->digit_buffer);
   if (TREE_TYPE (r) == float_type_node)
     pp_character (pp, 'f');
@@ -1957,6 +1956,17 @@
       pp_postfix_expression (pp, TREE_OPERAND (e, 1));
       break;
 
+    /* (TIGCC 20050210) Get pp_c_expression to print statement expressions
+                        correctly. We only print the last statement of a list,
+                        because that's the result of the statement expression. */
+    case BIND_EXPR:
+      pp_c_expression (pp, BIND_EXPR_BODY (e));
+      break;
+
+    case STATEMENT_LIST:
+      pp_c_expression (pp, STATEMENT_LIST_TAIL (e)->stmt);
+      break;
+
     default:
       pp_unsupported_tree (pp, e);
       break;
diff -Naur gcc-4.1.2.orig/gcc/c-tree.h gcc-4.1.2-src/gcc/c-tree.h
--- gcc-4.1.2.orig/gcc/c-tree.h	2005-11-19 00:40:29.000000000 +0100
+++ gcc-4.1.2-src/gcc/c-tree.h	2007-02-19 02:32:34.000000000 +0100
@@ -353,6 +353,8 @@
   tree attrs;
   /* The declarator.  */
   struct c_declarator *declarator;
+  /* (TIGCC 20050203) The asmspec.  */
+  tree asmspec;
 };
 
 /* Save and restore the variables in this file and elsewhere
@@ -431,6 +433,7 @@
 extern tree pushdecl (tree);
 extern void c_expand_body (tree);
 
+extern void c_insert_default_attributes (tree);
 extern void c_init_decl_processing (void);
 extern void c_dup_lang_specific_decl (tree);
 extern void c_print_identifier (FILE *, tree, int);
@@ -478,7 +481,7 @@
 extern struct c_typespec parser_xref_tag (enum tree_code, tree);
 extern int c_expand_decl (tree);
 extern struct c_parm *build_c_parm (struct c_declspecs *, tree,
-				    struct c_declarator *);
+				    struct c_declarator *, tree /* (TIGCC 20050203) */);
 extern struct c_declarator *build_attrs_declarator (tree,
 						    struct c_declarator *);
 extern struct c_declarator *build_function_declarator (struct c_arg_info *,
diff -Naur gcc-4.1.2.orig/gcc/c-typeck.c gcc-4.1.2-src/gcc/c-typeck.c
--- gcc-4.1.2.orig/gcc/c-typeck.c	2006-10-25 10:11:26.000000000 +0200
+++ gcc-4.1.2-src/gcc/c-typeck.c	2007-02-19 03:40:55.000000000 +0100
@@ -83,6 +83,8 @@
 static tree lookup_field (tree, tree);
 static tree convert_arguments (tree, tree, tree, tree);
 static tree pointer_diff (tree, tree);
+static tree unary_complex_lvalue (enum tree_code, tree, int);
+static void pedantic_lvalue_warning (enum tree_code);
 static tree convert_for_assignment (tree, tree, enum impl_conv, tree, tree,
 				    int);
 static tree valid_compound_expr_initializer (tree, tree);
@@ -2168,6 +2170,7 @@
   /* fntype now gets the type of function pointed to.  */
   fntype = TREE_TYPE (fntype);
 
+#if 0
   /* Check that the function is called through a compatible prototype.
      If it is not, replace the call by a trap, wrapped up in a compound
      expression if necessary.  This has the nice side-effect to prevent
@@ -2206,6 +2209,7 @@
 	  return build2 (COMPOUND_EXPR, return_type, trap, rhs);
 	}
     }
+#endif /* 0 */
 
   /* Convert the parameters to the types declared in the
      function prototype, or apply default promotions.  */
@@ -2780,6 +2784,12 @@
     case POSTINCREMENT_EXPR:
     case PREDECREMENT_EXPR:
     case POSTDECREMENT_EXPR:
+      /* Handle complex lvalues (when permitted)
+	 by reduction to simpler cases.  */
+
+      val = unary_complex_lvalue (code, arg, 0);
+      if (val != 0)
+	return val;
 
       /* Increment or decrement the real part of the value,
 	 and don't change the imaginary part.  */
@@ -2848,6 +2858,57 @@
 
 	inc = convert (argtype, inc);
 
+	/* Handle incrementing a cast-expression.  */
+
+	while (1)
+	  switch (TREE_CODE (arg))
+	    {
+	    case NOP_EXPR:
+	    case CONVERT_EXPR:
+	    case FLOAT_EXPR:
+	    case FIX_TRUNC_EXPR:
+	    case FIX_FLOOR_EXPR:
+	    case FIX_ROUND_EXPR:
+	    case FIX_CEIL_EXPR:
+	      pedantic_lvalue_warning (CONVERT_EXPR);
+	      /* If the real type has the same machine representation
+		 as the type it is cast to, we can make better output
+		 by adding directly to the inside of the cast.  */
+	      if ((TREE_CODE (TREE_TYPE (arg))
+		   == TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 0))))
+		  && (TYPE_MODE (TREE_TYPE (arg))
+		      == TYPE_MODE (TREE_TYPE (TREE_OPERAND (arg, 0)))))
+		arg = TREE_OPERAND (arg, 0);
+	      else
+		{
+		  tree incremented, modify, value;
+		  if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
+		    value = boolean_increment (code, arg);
+		  else
+		    {
+		      arg = stabilize_reference (arg);
+		      if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
+			value = arg;
+		      else
+			value = save_expr (arg);
+		      incremented = build (((code == PREINCREMENT_EXPR
+					     || code == POSTINCREMENT_EXPR)
+					    ? PLUS_EXPR : MINUS_EXPR),
+					   argtype, value, inc);
+		      TREE_SIDE_EFFECTS (incremented) = 1;
+		      modify = build_modify_expr (arg, NOP_EXPR, incremented);
+		      value = build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value);
+		    }
+		  TREE_USED (value) = 1;
+		  return value;
+		}
+	      break;
+
+	    default:
+	      goto give_up;
+	    }
+      give_up:
+
 	/* Complain about anything else that is not a true lvalue.  */
 	if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
 				    || code == POSTINCREMENT_EXPR)
@@ -2898,6 +2959,12 @@
 				  TREE_OPERAND (arg, 1), 1);
 	}
 
+      /* Handle complex lvalues (when permitted)
+	 by reduction to simpler cases.  */
+      val = unary_complex_lvalue (code, arg, flag);
+      if (val != 0)
+	return val;
+
       /* Anything not already handled and not a true memory reference
 	 or a non-lvalue array is an error.  */
       else if (typecode != FUNCTION_TYPE && !flag
@@ -2988,6 +3055,69 @@
     }
 }
 
+/* Apply unary lvalue-demanding operator CODE to the expression ARG
+   for certain kinds of expressions which are not really lvalues
+   but which we can accept as lvalues.  If FLAG is nonzero, then
+   non-lvalues are OK since we may be converting a non-lvalue array to
+   a pointer in C99.
+
+   If ARG is not a kind of expression we can handle, return zero.  */
+
+static tree
+unary_complex_lvalue (enum tree_code code, tree arg, int flag)
+{
+  /* Handle (a, b) used as an "lvalue".  */
+  if (TREE_CODE (arg) == COMPOUND_EXPR)
+    {
+      tree real_result = build_unary_op (code, TREE_OPERAND (arg, 1), 0);
+
+      /* If this returns a function type, it isn't really being used as
+	 an lvalue, so don't issue a warning about it.  */
+      if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE && !flag)
+	pedantic_lvalue_warning (COMPOUND_EXPR);
+
+      return build (COMPOUND_EXPR, TREE_TYPE (real_result),
+		    TREE_OPERAND (arg, 0), real_result);
+    }
+
+  /* Handle (a ? b : c) used as an "lvalue".  */
+  if (TREE_CODE (arg) == COND_EXPR)
+    {
+      if (!flag)
+	pedantic_lvalue_warning (COND_EXPR);
+      if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE && !flag)
+	pedantic_lvalue_warning (COMPOUND_EXPR);
+
+      return (build_conditional_expr
+	      (TREE_OPERAND (arg, 0),
+	       build_unary_op (code, TREE_OPERAND (arg, 1), flag),
+	       build_unary_op (code, TREE_OPERAND (arg, 2), flag)));
+    }
+
+  return 0;
+}
+
+/* If pedantic, warn about improper lvalue.   CODE is either COND_EXPR
+   COMPOUND_EXPR, or CONVERT_EXPR (for casts).  */
+
+static void
+pedantic_lvalue_warning (enum tree_code code)
+{
+  if (pedantic)
+    switch (code)
+      {
+      case COND_EXPR:
+	pedwarn ("ISO C forbids use of conditional expressions as lvalues");
+	break;
+      case COMPOUND_EXPR:
+	pedwarn ("ISO C forbids use of compound expressions as lvalues");
+	break;
+      default:
+	pedwarn ("ISO C forbids use of cast expressions as lvalues");
+	break;
+      }
+}
+  
 /* Give an error for storing in something that is 'const'.  */
 
 static void
@@ -3504,8 +3634,8 @@
 	}
     }
 
-  /* Don't let a cast be an lvalue.  */
-  if (value == expr)
+  /* If pedantic, don't let a cast be an lvalue.  */
+  if (value == expr && pedantic)
     value = non_lvalue (value);
 
   return value;
@@ -3549,22 +3679,103 @@
   if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
     return error_mark_node;
 
-  if (!lvalue_or_else (lhs, lv_assign))
-    return error_mark_node;
-
   STRIP_TYPE_NOPS (rhs);
 
   newrhs = rhs;
 
+  /* Handle control structure constructs used as "lvalues".  */
+
+  switch (TREE_CODE (lhs))
+    {
+      /* Handle (a, b) used as an "lvalue".  */
+    case COMPOUND_EXPR:
+      pedantic_lvalue_warning (COMPOUND_EXPR);
+      newrhs = build_modify_expr (TREE_OPERAND (lhs, 1), modifycode, rhs);
+      if (TREE_CODE (newrhs) == ERROR_MARK)
+	return error_mark_node;
+      return build (COMPOUND_EXPR, lhstype,
+		    TREE_OPERAND (lhs, 0), newrhs);
+
+      /* Handle (a ? b : c) used as an "lvalue".  */
+    case COND_EXPR:
+      pedantic_lvalue_warning (COND_EXPR);
+      rhs = save_expr (rhs);
+      {
+	/* Produce (a ? (b = rhs) : (c = rhs))
+	   except that the RHS goes through a save-expr
+	   so the code to compute it is only emitted once.  */
+	tree cond
+	  = build_conditional_expr (TREE_OPERAND (lhs, 0),
+				    build_modify_expr (TREE_OPERAND (lhs, 1),
+						       modifycode, rhs),
+				    build_modify_expr (TREE_OPERAND (lhs, 2),
+						       modifycode, rhs));
+	if (TREE_CODE (cond) == ERROR_MARK)
+	  return cond;
+	/* Make sure the code to compute the rhs comes out
+	   before the split.  */
+	return build (COMPOUND_EXPR, TREE_TYPE (lhs),
+		      /* But cast it to void to avoid an "unused" error.  */
+		      convert (void_type_node, rhs), cond);
+      }
+    default:
+      break;
+    }
+
   /* If a binary op has been requested, combine the old LHS value with the RHS
      producing the value we should actually store into the LHS.  */
+  /* (TIGCC 20070219) Don't do this for FUNCTION_TYPE, as this would trip over
+                      a gcc_assert in default_conversion. An error is later
+                      produced in lvalue_or_else. See PR 27721. */
 
-  if (modifycode != NOP_EXPR)
+  if (modifycode != NOP_EXPR && TREE_CODE (TREE_TYPE (lhs)) != FUNCTION_TYPE)
     {
       lhs = stabilize_reference (lhs);
       newrhs = build_binary_op (modifycode, lhs, rhs, 1);
     }
 
+  /* Handle a cast used as an "lvalue".
+     We have already performed any binary operator using the value as cast.
+     Now convert the result to the cast type of the lhs,
+     and then true type of the lhs and store it there;
+     then convert result back to the cast type to be the value
+     of the assignment.  */
+
+  switch (TREE_CODE (lhs))
+    {
+    case NOP_EXPR:
+    case CONVERT_EXPR:
+    case FLOAT_EXPR:
+    case FIX_TRUNC_EXPR:
+    case FIX_FLOOR_EXPR:
+    case FIX_ROUND_EXPR:
+    case FIX_CEIL_EXPR:
+      {
+	struct c_expr newrhs_expr;
+	tree inner_lhs = TREE_OPERAND (lhs, 0);
+	tree result;
+	newrhs_expr.value = newrhs;
+	newrhs_expr = default_function_array_conversion (newrhs_expr);
+	newrhs = newrhs_expr.value;
+	result = build_modify_expr (inner_lhs, NOP_EXPR,
+				    convert (TREE_TYPE (inner_lhs),
+					     convert (lhstype, newrhs)));
+	if (TREE_CODE (result) == ERROR_MARK)
+	  return result;
+	pedantic_lvalue_warning (CONVERT_EXPR);
+	return convert (TREE_TYPE (lhs), result);
+      }
+
+    default:
+      break;
+    }
+
+  /* Now we have handled acceptable kinds of LHS that are not truly lvalues.
+     Reject anything strange now.  */
+
+  if (!lvalue_or_else (lhs, lv_assign))
+    return error_mark_node;
+
   /* Give an error for storing in something that is 'const'.  */
 
   if (TREE_READONLY (lhs) || TYPE_READONLY (lhstype)
@@ -4359,10 +4570,11 @@
 {
   char *ofwhat;
 
-  error ("%s", _(msgid));
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
-    error ("(near initialization for %qs)", ofwhat);
+    error ("%s (near initialization for %qs)", _(msgid), ofwhat);
+  else
+    error ("%s", _(msgid));
 }
 
 /* Issue a pedantic warning for a bad initializer component.
@@ -4374,10 +4586,11 @@
 {
   char *ofwhat;
 
-  pedwarn ("%s", _(msgid));
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
-    pedwarn ("(near initialization for %qs)", ofwhat);
+    pedwarn ("%s (near initialization for %qs)", _(msgid), ofwhat);
+  else
+    pedwarn ("%s", _(msgid));
 }
 
 /* Issue a warning for a bad initializer component.
@@ -4389,10 +4602,11 @@
 {
   char *ofwhat;
 
-  warning (0, "%s", _(msgid));
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
-    warning (0, "(near initialization for %qs)", ofwhat);
+    warning (0, "%s (near initialization for %qs)", _(msgid), ofwhat);
+  else
+    warning (0, "%s", _(msgid));
 }
 
 /* If TYPE is an array type and EXPR is a parenthesized string
diff -Naur gcc-4.1.2.orig/gcc/diagnostic.c gcc-4.1.2-src/gcc/diagnostic.c
--- gcc-4.1.2.orig/gcc/diagnostic.c	2005-11-04 00:08:18.000000000 +0100
+++ gcc-4.1.2-src/gcc/diagnostic.c	2007-02-19 02:32:34.000000000 +0100
@@ -252,9 +252,8 @@
       if (context->abort_on_error)
 	real_abort ();
 
-      fnotice (stderr, "Please submit a full bug report,\n"
-	       "with preprocessed source if appropriate.\n"
-	       "See %s for instructions.\n", bug_report_url);
+      fnotice (stderr, "Please fill out a bug report form at %s.\n",
+               bug_report_url);
       exit (FATAL_EXIT_CODE);
 
     case DK_FATAL:
diff -Naur gcc-4.1.2.orig/gcc/dwarf2.h gcc-4.1.2-src/gcc/dwarf2.h
--- gcc-4.1.2.orig/gcc/dwarf2.h	2005-06-25 04:02:01.000000000 +0200
+++ gcc-4.1.2-src/gcc/dwarf2.h	2007-02-19 02:32:34.000000000 +0100
@@ -352,6 +352,7 @@
     DW_AT_body_begin = 0x2105,
     DW_AT_body_end   = 0x2106,
     DW_AT_GNU_vector = 0x2107,
+    DW_AT_regparm_location = 0x2120,
     /* VMS extensions.  */
     DW_AT_VMS_rtnbeg_pd_address = 0x2201,
     /* UPC extension.  */
diff -Naur gcc-4.1.2.orig/gcc/dwarf2out.c gcc-4.1.2-src/gcc/dwarf2out.c
--- gcc-4.1.2.orig/gcc/dwarf2out.c	2006-12-27 23:23:55.000000000 +0100
+++ gcc-4.1.2-src/gcc/dwarf2out.c	2007-02-19 02:32:34.000000000 +0100
@@ -2182,8 +2182,11 @@
      emit any EH unwind information.  Note that if exceptions aren't
      enabled, we won't have collected nothrow information, and if we
      asked for asynchronous tables, we always want this info.  */
+  /* (TIGCC 20050507) We want unwinding tables for debugging purposes only,
+     so we don't want an .eh_frame section we didn't ask for. */
   if (for_eh)
     {
+#if 0
       bool any_eh_needed = !flag_exceptions || flag_asynchronous_unwind_tables;
 
       for (i = 0; i < fde_table_in_use; i++)
@@ -2196,6 +2199,7 @@
 	  any_eh_needed = true;
 
       if (! any_eh_needed)
+#endif /* 0 */
 	return;
     }
 
@@ -4176,7 +4180,7 @@
 static void decls_for_scope (tree, dw_die_ref, int);
 static int is_redundant_typedef (tree);
 static void gen_namespace_die (tree);
-static void gen_decl_die (tree, dw_die_ref);
+static dw_die_ref gen_decl_die (tree, dw_die_ref);
 static dw_die_ref force_decl_die (tree);
 static dw_die_ref force_type_die (tree);
 static dw_die_ref setup_namespace_context (tree, dw_die_ref);
@@ -4677,6 +4681,8 @@
       return "DW_AT_body_end";
     case DW_AT_GNU_vector:
       return "DW_AT_GNU_vector";
+    case DW_AT_regparm_location:
+      return "DW_AT_regparm_location";
 
     case DW_AT_VMS_rtnbeg_pd_address:
       return "DW_AT_VMS_rtnbeg_pd_address";
@@ -9779,14 +9785,7 @@
   int i;
 
   REAL_VALUE_FROM_CONST_DOUBLE (rv, rtl);
-  real_to_target (val, &rv, GET_MODE (rtl));
-
-  /* real_to_target puts 32-bit pieces in each long.  Pack them.  */
-  for (i = 0; i < GET_MODE_SIZE (GET_MODE (rtl)) / 4; i++)
-    {
-      insert_int (val[i], 4, array);
-      array += 4;
-    }
+  REAL_VALUE_TO_TARGET_SMAP_BCD (rv, array);
 }
 
 /* Attach a DW_AT_const_value attribute for a variable or a parameter which
@@ -9825,7 +9824,7 @@
 	    unsigned char *array = ggc_alloc (length);
 
 	    insert_float (rtl, array);
-	    add_AT_vec (die, DW_AT_const_value, length / 4, 4, array);
+	    add_AT_vec (die, DW_AT_const_value, 1, length, array); /* (TIGCC 20050403) */
 	  }
 	else
 	  {
@@ -11370,6 +11369,10 @@
    DW_TAG_unspecified_parameters DIE) to represent the types of the formal
    parameters as specified in some function type specification (except for
    those which appear as part of a function *definition*).  */
+/* (TIGCC 20050409) We also want to generate DW_AT_regparm_location
+   information for register parameters so GDB can call the function
+   correctly. We don't use DW_AT_location in order not to conflict with
+   the location list support. */
 
 static void
 gen_formal_types_die (tree function_or_method_type, dw_die_ref context_die)
@@ -11378,15 +11381,21 @@
   tree formal_type = NULL;
   tree first_parm_type;
   tree arg;
+  tree function_or_method_decl = NULL_TREE;
+  CUMULATIVE_ARGS cum;
 
   if (TREE_CODE (function_or_method_type) == FUNCTION_DECL)
     {
+      function_or_method_decl = function_or_method_type;
       arg = DECL_ARGUMENTS (function_or_method_type);
       function_or_method_type = TREE_TYPE (function_or_method_type);
     }
   else
     arg = NULL_TREE;
 
+  if (function_or_method_decl)
+    INIT_CUMULATIVE_ARGS (cum, function_or_method_type, NULL, function_or_method_decl, 0);
+
   first_parm_type = TYPE_ARG_TYPES (function_or_method_type);
 
   /* Make our first pass over the list of formal parameter types and output a
@@ -11406,6 +11415,17 @@
 	  || (arg && DECL_ARTIFICIAL (arg)))
 	add_AT_flag (parm_die, DW_AT_artificial, 1);
 
+      if (function_or_method_decl)
+        {
+          rtx argrtx = FUNCTION_ARG(cum, TYPE_MODE (formal_type), formal_type, 0);
+          if (argrtx && GET_CODE (argrtx) == REG && REGNO (argrtx) < FIRST_PSEUDO_REGISTER)
+            {
+              add_AT_location_description (parm_die, DW_AT_regparm_location, reg_loc_descriptor (argrtx));
+            }
+
+          FUNCTION_ARG_ADVANCE(cum, 0, 0, 0);
+        }
+
       link = TREE_CHAIN (link);
       if (arg)
 	arg = TREE_CHAIN (arg);
@@ -11509,6 +11529,10 @@
 
 /* Generate a DIE to represent a declared function (either file-scope or
    block-local).  */
+/* (TIGCC 20050409) We also want to generate DW_AT_regparm_location
+   information for register parameters so GDB can call the function
+   correctly. We don't use DW_AT_location in order not to conflict with
+   the location list support. */
 
 static void
 gen_subprogram_die (tree decl, dw_die_ref context_die)
@@ -11521,6 +11545,7 @@
   dw_die_ref old_die = lookup_decl_die (decl);
   int declaration = (current_function_decl != decl
 		     || class_or_namespace_scope_p (context_die));
+  CUMULATIVE_ARGS cum;
 
   /* It is possible to have both DECL_ABSTRACT and DECLARATION be true if we
      started to generate the abstract instance of an inline, decided to output
@@ -11759,6 +11784,8 @@
       tree arg_decls = DECL_ARGUMENTS (decl);
       tree parm;
 
+      INIT_CUMULATIVE_ARGS (cum, TREE_TYPE (decl), NULL, decl, 0);
+
       /* When generating DIEs, generate the unspecified_parameters DIE
 	 instead if we come across the arg "__builtin_va_alist" */
       for (parm = arg_decls; parm; parm = TREE_CHAIN (parm))
@@ -11769,7 +11796,16 @@
 			    "__builtin_va_alist"))
 	      gen_unspecified_parameters_die (parm, subr_die);
 	    else
-	      gen_decl_die (parm, subr_die);
+	      {
+	        dw_die_ref parm_die = gen_decl_die (parm, subr_die);
+	        rtx argrtx = FUNCTION_ARG(cum, TYPE_MODE (TREE_TYPE (parm)), TREE_TYPE (parm), 0);
+	        if (parm_die && argrtx && GET_CODE (argrtx) == REG && REGNO (argrtx) < FIRST_PSEUDO_REGISTER)
+	          {
+	            add_AT_location_description (parm_die, DW_AT_regparm_location, reg_loc_descriptor (argrtx));
+	          }
+	      }
+
+	    FUNCTION_ARG_ADVANCE(cum, 0, 0, 0);
 	  }
 
       /* Decide whether we need an unspecified_parameters DIE at the end.
@@ -13002,14 +13038,15 @@
 }
 
 /* Generate Dwarf debug information for a decl described by DECL.  */
+/* (TIGCC 20050409) Return the DIE for the parameter case. */
 
-static void
+static dw_die_ref
 gen_decl_die (tree decl, dw_die_ref context_die)
 {
   tree origin;
 
   if (DECL_P (decl) && DECL_IGNORED_P (decl))
-    return;
+    return NULL;
 
   switch (TREE_CODE (decl))
     {
@@ -13152,8 +13189,7 @@
 
     case PARM_DECL:
       gen_type_die (TREE_TYPE (decl), context_die);
-      gen_formal_parameter_die (decl, context_die);
-      break;
+      return gen_formal_parameter_die (decl, context_die);
 
     case NAMESPACE_DECL:
       gen_namespace_die (decl);
@@ -13164,6 +13200,8 @@
       gcc_assert ((int)TREE_CODE (decl) > NUM_TREE_CODES);
       break;
     }
+
+    return NULL;
 }
 
 /* Add Ada "use" clause information for SGI Workshop debugger.  */
@@ -13486,9 +13524,12 @@
      unused debug types, then we must emit .file here.  If we are eliminating
      unused debug types, then this will be done by the maybe_emit_file call in
      prune_unused_types_walk_attribs.  */
+  /* (TIGCC 20051220) Don't return the result of maybe_emit_file, it will cause
+                      maybe_emit_file to be called twice on the same fileno.
+                      -- Kevin Kofler */
 
   if (DWARF2_ASM_LINE_DEBUG_INFO && ! flag_eliminate_unused_debug_types)
-    return maybe_emit_file (i);
+    /*return*/ maybe_emit_file (i);
 
   return i;
 }
@@ -13611,7 +13652,10 @@
   if (debug_info_level >= DINFO_LEVEL_NORMAL
       && line != 0)
     {
-      current_function_section (current_function_decl);
+      /* (TIGCC 20050424) We also get called for top-level ASM with no
+                          current_function_decl, so don't crash in that case. */
+      if (current_function_decl)
+        current_function_section (current_function_decl);
 
       /* If requested, emit something human-readable.  */
       if (flag_debug_asm)
@@ -13631,10 +13675,10 @@
 	  line_info_table_in_use++;
 
 	  /* Indicate that multiple line number tables exist.  */
-	  if (DECL_SECTION_NAME (current_function_decl))
+	  if (current_function_decl && DECL_SECTION_NAME (current_function_decl))
 	    separate_line_info_table_in_use++;
 	}
-      else if (DECL_SECTION_NAME (current_function_decl))
+      else if (current_function_decl && DECL_SECTION_NAME (current_function_decl))
 	{
 	  dw_separate_line_info_ref line_info;
 	  targetm.asm_out.internal_label (asm_out_file, SEPARATE_LINE_CODE_LABEL,
diff -Naur gcc-4.1.2.orig/gcc/emit-rtl.c gcc-4.1.2-src/gcc/emit-rtl.c
--- gcc-4.1.2.orig/gcc/emit-rtl.c	2006-01-03 23:37:46.000000000 +0100
+++ gcc-4.1.2-src/gcc/emit-rtl.c	2007-02-19 02:32:34.000000000 +0100
@@ -104,8 +104,10 @@
 REAL_VALUE_TYPE dconstm2;
 REAL_VALUE_TYPE dconsthalf;
 REAL_VALUE_TYPE dconstthird;
+#if 0
 REAL_VALUE_TYPE dconstpi;
 REAL_VALUE_TYPE dconste;
+#endif /* 0 */
 
 /* All references to the following fixed hard registers go through
    these unique rtl objects.  On machines where the frame-pointer and
@@ -240,8 +242,8 @@
     return (CONST_DOUBLE_LOW (a) == CONST_DOUBLE_LOW (b)
 	    && CONST_DOUBLE_HIGH (a) == CONST_DOUBLE_HIGH (b));
   else
-    return real_identical (CONST_DOUBLE_REAL_VALUE (a),
-			   CONST_DOUBLE_REAL_VALUE (b));
+    return REAL_VALUES_IDENTICAL (*CONST_DOUBLE_REAL_VALUE (a),
+			   *CONST_DOUBLE_REAL_VALUE (b));
 }
 
 /* Returns a hash code for X (which is a really a mem_attrs *).  */
@@ -1334,10 +1336,62 @@
       && (GET_MODE_SIZE (mode) < UNITS_PER_WORD))
     return 0;
 
-  /* If we want a word outside OP, return zero.  */
+  /* If we want a word outside OP, return zero, except for special BFmode cases.  */
   if (mode != BLKmode
       && (offset + 1) * UNITS_PER_WORD > GET_MODE_SIZE (mode))
+  {
+  if (mode == BFmode)
+  {
+   if (GET_CODE (op) == MEM)
+    {
+      rtx addr = plus_constant (XEXP (op, 0), offset * UNITS_PER_WORD);
+      rtx new;
+
+      if (validate_address)
+	{
+	  if (reload_completed)
+	    {
+	      if (! strict_memory_address_p (HImode, addr))
+		return 0;
+	    }
+	  else
+	    addr = memory_address (HImode, addr);
+	}
+
+      new = gen_rtx_MEM (HImode, addr);
+
+      MEM_COPY_ATTRIBUTES (new, op);
+      MEM_READONLY_P (new) = MEM_READONLY_P (op);
+
+      return new;
+    }
+  else if (REG_P (op))
+    {
+      if (REGNO (op) < FIRST_PSEUDO_REGISTER
+	  && REGNO (op) + offset >= FIRST_PSEUDO_REGISTER)
+	return 0;
+
+      if (REGNO (op) < FIRST_PSEUDO_REGISTER
+	  && (! HARD_REGNO_MODE_OK (REGNO (op), HImode)
+	      || ! HARD_REGNO_MODE_OK (REGNO (op) + offset, HImode)))
+	return 0;
+      else if (REGNO (op) >= FIRST_PSEUDO_REGISTER
+	       || (REG_FUNCTION_VALUE_P (op))
+	       || op == frame_pointer_rtx
+#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
+	       || op == arg_pointer_rtx
+#endif
+	       || op == stack_pointer_rtx)
+	return gen_rtx_SUBREG (HImode, op, offset);
+      else
+	return gen_rtx_REG (HImode, REGNO (op) + offset);
+    }
+  else if (GET_CODE (op) == SUBREG)
+    return gen_rtx_SUBREG (HImode, SUBREG_REG (op), offset + SUBREG_BYTE (op) / UNITS_PER_WORD);
+  }
+  else
     return const0_rtx;
+  }
 
   /* Form a new MEM at the requested address.  */
   if (MEM_P (op))
@@ -5310,17 +5364,17 @@
   REAL_VALUE_FROM_INT (dconstm1, -1, -1, double_mode);
   REAL_VALUE_FROM_INT (dconstm2, -2, -1, double_mode);
 
-  dconsthalf = dconst1;
-  SET_REAL_EXP (&dconsthalf, REAL_EXP (&dconsthalf) - 1);
-
+  real_arithmetic (&dconsthalf, RDIV_EXPR, &dconst1, &dconst2);
   real_arithmetic (&dconstthird, RDIV_EXPR, &dconst1, &dconst3);
 
+#if 0
   /* Initialize mathematical constants for constant folding builtins.
      These constants need to be given to at least 160 bits precision.  */
   real_from_string (&dconstpi,
     "3.1415926535897932384626433832795028841971693993751058209749445923078");
   real_from_string (&dconste,
     "2.7182818284590452353602874713526624977572470936999595749669676277241");
+#endif /* 0 */
 
   for (i = 0; i < (int) ARRAY_SIZE (const_tiny_rtx); i++)
     {
diff -Naur gcc-4.1.2.orig/gcc/explow.c gcc-4.1.2-src/gcc/explow.c
--- gcc-4.1.2.orig/gcc/explow.c	2005-08-02 22:39:24.000000000 +0200
+++ gcc-4.1.2-src/gcc/explow.c	2007-02-19 02:32:34.000000000 +0100
@@ -569,6 +569,10 @@
 {
   rtx temp = gen_reg_rtx (mode);
 
+  if (GET_MODE (x) == BFmode && mode != BFmode)
+    convert_move (x, temp, 0);
+  else
+  {
   /* If not an operand, must be an address with PLUS and MULT so
      do the computation.  */
   if (! general_operand (x, VOIDmode))
@@ -577,6 +581,7 @@
   gcc_assert (GET_MODE (x) == mode || GET_MODE (x) == VOIDmode);
   if (x != temp)
     emit_move_insn (temp, x);
+  }
   return temp;
 }
 
diff -Naur gcc-4.1.2.orig/gcc/expr.c gcc-4.1.2-src/gcc/expr.c
--- gcc-4.1.2.orig/gcc/expr.c	2006-11-02 18:18:52.000000000 +0100
+++ gcc-4.1.2-src/gcc/expr.c	2007-02-19 02:32:34.000000000 +0100
@@ -748,7 +748,7 @@
   if (GET_MODE (x) != VOIDmode)
     oldmode = GET_MODE (x);
 
-  if (mode == oldmode)
+  if (mode == oldmode || oldmode == BFmode)
     return x;
 
   /* There is one case that we must handle specially: If we are converting
@@ -1351,6 +1351,7 @@
   dst_tree = make_tree (ptr_type_node, dst_addr);
   src_tree = make_tree (ptr_type_node, src_addr);
 
+#if 0
   size_mode = TYPE_MODE (sizetype);
 
   size = convert_to_mode (size_mode, size, 1);
@@ -1360,8 +1361,8 @@
      memcpy in this context.  This could be a user call to memcpy and
      the user may wish to examine the return value from memcpy.  For
      targets where libcalls and normal calls have different conventions
-     for returning pointers, we could end up generating incorrect code.  */
-
+     for returning pointers, we could end up generating incorrect code.
+     (TIGCC 20050205) NO, the "incorrect" code is actually correct for us!  */
   size_tree = make_tree (sizetype, size);
 
   fn = emit_block_move_libcall_fn (true);
@@ -1376,6 +1377,14 @@
   CALL_EXPR_TAILCALL (call_expr) = tailcall;
 
   retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
+#endif /* 0 */
+
+  retval = emit_library_call_value (memcpy_libfunc, NULL_RTX, LCT_NORMAL,
+                                    VOIDmode, 3, dst_addr, Pmode,
+                                    src_addr, Pmode,
+                                    convert_to_mode (TYPE_MODE (sizetype),
+                                                     size, TYPE_UNSIGNED (sizetype)),
+                                    TYPE_MODE (sizetype));
 
   return retval;
 }
@@ -2500,6 +2509,7 @@
 
   object = copy_to_mode_reg (Pmode, XEXP (object, 0));
 
+#if 0
   size_mode = TYPE_MODE (sizetype);
   size = convert_to_mode (size_mode, size, 1);
   size = copy_to_mode_reg (size_mode, size);
@@ -2508,7 +2518,8 @@
      memset in this context.  This could be a user call to memset and
      the user may wish to examine the return value from memset.  For
      targets where libcalls and normal calls have different conventions
-     for returning pointers, we could end up generating incorrect code.  */
+     for returning pointers, we could end up generating incorrect code.
+     (TIGCC 20050205) NO, the "incorrect" code is actually correct for us!  */
 
   object_tree = make_tree (ptr_type_node, object);
   size_tree = make_tree (sizetype, size);
@@ -2525,6 +2536,15 @@
   CALL_EXPR_TAILCALL (call_expr) = tailcall;
 
   retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
+#endif /* 0 */
+
+  /* Note: Our memset libcall expects a short integer zero even with -mlong.  */
+  retval = emit_library_call_value (memset_libfunc, NULL_RTX, LCT_NORMAL,
+                                    VOIDmode, 3, object, Pmode,
+                                    const0_rtx, TYPE_MODE (short_integer_type_node),
+                                    convert_to_mode (TYPE_MODE (sizetype),
+                                                     size, TYPE_UNSIGNED (sizetype)),
+                                    TYPE_MODE (sizetype));
 
   return retval;
 }
@@ -2543,8 +2563,10 @@
       tree fn, args;
 
       fn = get_identifier ("memset");
+      /* TIGCC Patch: The memset libcall expects a short integer zero even with
+         -mlong.  */
       args = build_function_type_list (ptr_type_node, ptr_type_node,
-				       integer_type_node, sizetype,
+				       short_integer_type_node, sizetype,
 				       NULL_TREE);
 
       fn = build_decl (FUNCTION_DECL, fn, args);
@@ -2954,14 +2976,21 @@
   if (push_operand (x, mode))
     return emit_move_complex_push (mode, x, y);
 
+  /* For memory to memory moves, optimal behavior can be had with the
+     existing block move logic.  */
+  /* (TIGCC 20050323) ... and this is indeed the case for our target, despite
+     claims to the contrary in PR rtl-optimization/20306. -- Kevin Kofler  */
+  if (MEM_P (x) && MEM_P (y))
+    {
+      emit_block_move (x, y, GEN_INT (GET_MODE_SIZE (mode)),
+		       BLOCK_OP_NO_LIBCALL);
+      return get_last_insn ();
+    }
+
   /* See if we can coerce the target into moving both values at once.  */
 
-  /* Move floating point as parts.  */
-  if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
-      && mov_optab->handlers[GET_MODE_INNER (mode)].insn_code != CODE_FOR_nothing)
-    try_int = false;
   /* Not possible if the values are inherently not adjacent.  */
-  else if (GET_CODE (x) == CONCAT || GET_CODE (y) == CONCAT)
+  if (GET_CODE (x) == CONCAT || GET_CODE (y) == CONCAT)
     try_int = false;
   /* Is possible if both are registers (or subregs of registers).  */
   else if (register_operand (x, mode) && register_operand (y, mode))
@@ -2979,18 +3008,7 @@
 
   if (try_int)
     {
-      rtx ret;
-
-      /* For memory to memory moves, optimal behavior can be had with the
-	 existing block move logic.  */
-      if (MEM_P (x) && MEM_P (y))
-	{
-	  emit_block_move (x, y, GEN_INT (GET_MODE_SIZE (mode)),
-			   BLOCK_OP_NO_LIBCALL);
-	  return get_last_insn ();
-	}
-
-      ret = emit_move_via_integer (mode, x, y, true);
+      rtx ret = emit_move_via_integer (mode, x, y, true);
       if (ret)
 	return ret;
     }
@@ -3230,6 +3248,9 @@
   else
     oldcost = rtx_cost (force_const_mem (dstmode, y), SET);
 
+/* (TIGCC) We do not implement exact_real_truncate and there is no narrower
+           float mode anyway. -- Kevin Kofler */
+#if 0
   for (srcmode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_srcmode));
        srcmode != orig_srcmode;
        srcmode = GET_MODE_WIDER_MODE (srcmode))
@@ -3279,6 +3300,7 @@
 
       return last_insn;
     }
+#endif /* 0 */
 
   return NULL_RTX;
 }
diff -Naur gcc-4.1.2.orig/gcc/final.c gcc-4.1.2-src/gcc/final.c
--- gcc-4.1.2.orig/gcc/final.c	2005-12-20 05:51:27.000000000 +0100
+++ gcc-4.1.2-src/gcc/final.c	2007-02-19 02:32:34.000000000 +0100
@@ -3091,11 +3091,23 @@
 	    else if (letter == 'l')
 	      output_asm_label (operands[opnum]);
 	    else if (letter == 'a')
+	    {
 	      output_address (operands[opnum]);
+	      /* TIGCC Patch: This is a very bad try to implement addresses
+	         relative to a register.  See m68k.c
+	         (TIGCC 20040808) Added CONST here (and below) too. -- Kevin Kofler  */
+	      if (TARGET_REG_RELATIVE && (GET_CODE (operands[opnum]) == SYMBOL_REF || GET_CODE (operands[opnum]) == LABEL_REF || GET_CODE (operands[opnum]) == CODE_LABEL || GET_CODE (operands[opnum]) == CONST))
+		fprintf (asm_out_file, "-__relation(%%%s)", TARGET_RELATION_REG);
+	    }
 	    else if (letter == 'c')
 	      {
 		if (CONSTANT_ADDRESS_P (operands[opnum]))
+		{
 		  output_addr_const (asm_out_file, operands[opnum]);
+		  /* TIGCC Patch: See above  */
+		  if (TARGET_REG_RELATIVE && (GET_CODE (operands[opnum]) == SYMBOL_REF || GET_CODE (operands[opnum]) == LABEL_REF || GET_CODE (operands[opnum]) == CODE_LABEL || GET_CODE (operands[opnum]) == CONST))
+		    fprintf (asm_out_file, "-__relation(%%%s)", TARGET_RELATION_REG);
+		}
 		else
 		  output_operand (operands[opnum], 'c');
 	      }
@@ -3108,6 +3120,9 @@
 		  {
 		    putc ('-', asm_out_file);
 		    output_addr_const (asm_out_file, operands[opnum]);
+		    /* TIGCC Patch: See above */
+		    if (TARGET_REG_RELATIVE && (GET_CODE (operands[opnum]) == SYMBOL_REF || GET_CODE (operands[opnum]) == LABEL_REF || GET_CODE (operands[opnum]) == CODE_LABEL))
+		      fprintf (asm_out_file, "-__relation(%%%s)", TARGET_RELATION_REG);
 		  }
 	      }
 	    else
@@ -3619,6 +3634,8 @@
     }
   else
     {
+      gcc_unreachable ();
+#if 0
       REAL_VALUE_TYPE r;
       long l[2];
       REAL_VALUE_FROM_CONST_DOUBLE (r, value);
@@ -3647,6 +3664,7 @@
 
       *first = GEN_INT (l[0]);
       *second = GEN_INT (l[1]);
+#endif /* 0 */
     }
 }
 
diff -Naur gcc-4.1.2.orig/gcc/flags.h gcc-4.1.2-src/gcc/flags.h
--- gcc-4.1.2.orig/gcc/flags.h	2005-06-29 05:01:27.000000000 +0200
+++ gcc-4.1.2-src/gcc/flags.h	2007-02-19 02:32:34.000000000 +0100
@@ -287,4 +287,10 @@
 #define HONOR_SIGN_DEPENDENT_ROUNDING(MODE) \
   (MODE_HAS_SIGN_DEPENDENT_ROUNDING (MODE) && flag_rounding_math)
 
+/* (TIGCC) Make compound literals (cast constructors) global for backwards compatibility.  */
+extern int flag_global_compound_literals;
+
+/* (TIGCC 20040727) When merging constants, also merge constant pools.  */
+extern int flag_merge_constant_pools;
+
 #endif /* ! GCC_FLAGS_H */
diff -Naur gcc-4.1.2.orig/gcc/fold-const.c gcc-4.1.2-src/gcc/fold-const.c
--- gcc-4.1.2.orig/gcc/fold-const.c	2007-01-03 09:15:24.000000000 +0100
+++ gcc-4.1.2-src/gcc/fold-const.c	2007-02-19 02:32:34.000000000 +0100
@@ -1569,7 +1569,7 @@
       if ((flag_rounding_math
 	   || (REAL_MODE_FORMAT_COMPOSITE_P (mode)
 	       && !flag_unsafe_math_optimizations))
-	  && (inexact || !real_identical (&result, &value)))
+	  && (inexact || !REAL_VALUES_IDENTICAL (result, value)))
 	return NULL_TREE;
 
       t = build_real (type, result);
@@ -1776,6 +1776,7 @@
      FP-to-integer conversion is unspecified upon overflow.  */
 
   HOST_WIDE_INT high, low;
+#if 0
   REAL_VALUE_TYPE r;
   REAL_VALUE_TYPE x = TREE_REAL_CST (arg1);
 
@@ -1800,9 +1801,12 @@
     default:
       gcc_unreachable ();
     }
+#else
+  REAL_VALUE_TYPE r = TREE_REAL_CST (arg1);
+#endif /* 0 */
 
   /* If R is NaN, return zero and show we have an overflow.  */
-  if (REAL_VALUE_ISNAN (r))
+  if (REAL_VALUE_ISNANUINF (r))
     {
       overflow = 1;
       high = 0;
@@ -2111,7 +2115,7 @@
 /* When pedantic, return an expr equal to X but certainly not valid as a
    pedantic lvalue.  Otherwise, return X.  */
 
-static tree
+tree
 pedantic_non_lvalue (tree x)
 {
   if (pedantic_lvalues)
@@ -5717,6 +5721,10 @@
   if (!HONOR_SIGNED_ZEROS (TYPE_MODE (type)))
     return true;
 
+  /* (TIGCC 20050210) This is invalid independently of the rounding mode and the
+                      type of the zero for 3-sign-zeros. */
+  return false;
+
   /* Treat x + -0 as x - 0 and x - -0 as x + 0.  */
   if (TREE_CODE (addend) == REAL_CST
       && REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (addend)))
@@ -5902,6 +5910,7 @@
 	}
       break;
 
+#if 0 /* (TIGCC 20050205) */
     case EQ_EXPR:
     case GE_EXPR:
       /* x == +Inf and x >= +Inf are always equal to x > DBL_MAX.  */
@@ -5930,6 +5939,7 @@
       temp = fold_build2 (neg ? LT_EXPR : GT_EXPR, type,
 			  arg0, build_real (TREE_TYPE (arg0), max));
       return fold_build1 (TRUTH_NOT_EXPR, type, temp);
+#endif /* 0 */
 
     default:
       break;
@@ -7025,6 +7035,21 @@
     } /* switch (code) */
 }
 
+/* Return 1 if EXPR is the real constant UNSIGNED_ZERO.  */
+
+static int
+real_uzerop (tree expr)
+{
+  STRIP_NOPS (expr);
+
+  return ((TREE_CODE (expr) == REAL_CST
+	   && ! TREE_CONSTANT_OVERFLOW (expr)
+	   && REAL_VALUES_IDENTICAL (TREE_REAL_CST (expr), UNSIGNED_ZERO))
+	  || (TREE_CODE (expr) == COMPLEX_CST
+	      && real_uzerop (TREE_REALPART (expr))
+	      && real_uzerop (TREE_IMAGPART (expr))));
+}
+
 /* Fold a binary expression of code CODE and type TYPE with operands
    OP0 and OP1.  Return the folded expression if folding is
    successful.  Otherwise, return NULL_TREE.  */
@@ -7847,8 +7872,11 @@
 	     when x is NaN, since x * 0 is also NaN.  Nor are they the
 	     same in modes with signed zeros, since multiplying a
 	     negative value by 0 gives -0, not +0.  */
+	  /* (TIGCC 20050210) We can do this for UNSIGNED_ZERO even when honoring
+	                      signed zeros. */
 	  if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0)))
-	      && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0)))
+	      && (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0)))
+	          || real_uzerop (arg1))
 	      && real_zerop (arg1))
 	    return omit_one_operand (type, arg1, arg0);
 	  /* In IEEE floating point, x*1 is not equivalent to x for snans.  */
@@ -9065,7 +9093,7 @@
 				  build_real (TREE_TYPE (arg1), dconst0));
 
 	    /* x != NaN is always true, other ops are always false.  */
-	    if (REAL_VALUE_ISNAN (cst)
+	    if (REAL_VALUE_ISNANUINF (cst)
 		&& ! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1))))
 	      {
 		tem = (code == NE_EXPR) ? integer_one_node : integer_zero_node;
@@ -9839,7 +9867,7 @@
 
       /* If the first operand is NaN, the result is constant.  */
       if (TREE_CODE (arg0) == REAL_CST
-	  && REAL_VALUE_ISNAN (TREE_REAL_CST (arg0))
+	  && REAL_VALUE_ISNANUINF (TREE_REAL_CST (arg0))
 	  && (code != LTGT_EXPR || ! flag_trapping_math))
 	{
 	  t1 = (code == ORDERED_EXPR || code == LTGT_EXPR)
@@ -9850,7 +9878,7 @@
 
       /* If the second operand is NaN, the result is constant.  */
       if (TREE_CODE (arg1) == REAL_CST
-	  && REAL_VALUE_ISNAN (TREE_REAL_CST (arg1))
+	  && REAL_VALUE_ISNANUINF (TREE_REAL_CST (arg1))
 	  && (code != LTGT_EXPR || ! flag_trapping_math))
 	{
 	  t1 = (code == ORDERED_EXPR || code == LTGT_EXPR)
@@ -9888,12 +9916,12 @@
     case COMPOUND_EXPR:
       /* When pedantic, a compound expression can be neither an lvalue
 	 nor an integer constant expression.  */
-      if (TREE_SIDE_EFFECTS (arg0) || TREE_CONSTANT (arg1))
+      if (TREE_SIDE_EFFECTS (arg0) || pedantic)
 	return NULL_TREE;
       /* Don't let (0, 0) be null pointer constant.  */
-      tem = integer_zerop (arg1) ? build1 (NOP_EXPR, type, arg1)
-				 : fold_convert (type, arg1);
-      return pedantic_non_lvalue (tem);
+      if (integer_zerop (arg1))
+	return build1 (NOP_EXPR, type, arg1);
+      return convert (type, arg1);
 
     case COMPLEX_EXPR:
       if (wins)
@@ -11355,7 +11383,11 @@
       }
 
     case REAL_CST:
-      t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
+	    {
+	      REAL_VALUE_TYPE x = TREE_REAL_CST (arg0);
+	      x = REAL_VALUE_NEGATE (x);
+	      t = build_real (type, x);
+	    }
       break;
 
     default:
@@ -11401,10 +11433,14 @@
       break;
 
     case REAL_CST:
-      if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg0)))
-	t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
-      else
-	t =  arg0;
+  	    {
+	      REAL_VALUE_TYPE x = TREE_REAL_CST (arg0);
+	      if (REAL_VALUE_NEGATIVE (x))
+		t = build_real (type,
+				REAL_VALUE_NEGATE (x));
+	      else
+		t =  arg0;
+	    }
       break;
 
     default:
@@ -11452,7 +11488,7 @@
       const REAL_VALUE_TYPE *c1 = TREE_REAL_CST_PTR (op1);
 
       /* Handle the cases where either operand is a NaN.  */
-      if (real_isnan (c0) || real_isnan (c1))
+      if (REAL_VALUE_ISNANUINF (*c0) || REAL_VALUE_ISNANUINF (*c1))
 	{
 	  switch (code)
 	    {
diff -Naur gcc-4.1.2.orig/gcc/function.c gcc-4.1.2-src/gcc/function.c
--- gcc-4.1.2.orig/gcc/function.c	2006-11-28 13:01:45.000000000 +0100
+++ gcc-4.1.2-src/gcc/function.c	2007-02-19 02:32:34.000000000 +0100
@@ -5592,3 +5592,28 @@
 
 
 #include "gt-function.h"
+
+/* begin-TIGCC-local (regparms): explicit register specification for parameters */
+/* Return 1 if an argument for the current function was passed in
+   register REGNO.  */
+
+int
+function_arg_regno_p (int regno)
+{
+  tree parm = DECL_ARGUMENTS (current_function_decl);
+  for (; parm; parm = TREE_CHAIN (parm))
+    {
+      rtx incoming = DECL_INCOMING_RTL (parm);
+      if (GET_CODE (incoming) == REG)
+	{
+	  int incoming_reg;
+	  incoming_reg = REGNO (incoming);
+	  if (regno >= incoming_reg &&
+	      regno < incoming_reg + HARD_REGNO_NREGS (incoming_reg,
+						       GET_MODE (incoming)))
+	    return 1;
+	}
+    }
+  return 0;
+}
+/* end-TIGCC-local (regparms) */
diff -Naur gcc-4.1.2.orig/gcc/function.h gcc-4.1.2-src/gcc/function.h
--- gcc-4.1.2.orig/gcc/function.h	2005-08-19 23:16:20.000000000 +0200
+++ gcc-4.1.2-src/gcc/function.h	2007-02-19 02:32:34.000000000 +0100
@@ -574,4 +574,10 @@
 extern bool reference_callee_copied (CUMULATIVE_ARGS *, enum machine_mode,
 				     tree, bool);
 
+/* begin-TIGCC-local (regparms): explicit register specification for parameters */
+/* Return 1 if an argument for the current function was passed in
+   register REGNO.  */
+int function_arg_regno_p (int regno);
+/* end-TIGCC-local (regparms) */
+
 #endif  /* GCC_FUNCTION_H */
diff -Naur gcc-4.1.2.orig/gcc/gcc.c gcc-4.1.2-src/gcc/gcc.c
--- gcc-4.1.2.orig/gcc/gcc.c	2006-11-07 15:26:21.000000000 +0100
+++ gcc-4.1.2-src/gcc/gcc.c	2007-02-19 02:32:34.000000000 +0100
@@ -1458,6 +1458,7 @@
 #define MD_STARTFILE_PREFIX_1 ""
 #endif
 
+#if 0 /* (TIGCC 20040104) Don't hardcode any prefix at compile time. */
 static const char *const standard_exec_prefix = STANDARD_EXEC_PREFIX;
 static const char *const standard_exec_prefix_1 = "/usr/libexec/gcc/";
 static const char *const standard_exec_prefix_2 = "/usr/lib/gcc/";
@@ -1475,6 +1476,7 @@
 static const char *tooldir_prefix;
 
 static const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX;
+#endif /* 0 */
 
 static const char *standard_libexec_prefix = STANDARD_LIBEXEC_PREFIX;
 
@@ -1546,6 +1548,7 @@
   INIT_STATIC_SPEC ("multilib_options",		&multilib_options),
   INIT_STATIC_SPEC ("linker",			&linker_name_spec),
   INIT_STATIC_SPEC ("link_libgcc",		&link_libgcc_spec),
+#if 0 /* (TIGCC 20040104) Don't hardcode any prefix at compile time. */
   INIT_STATIC_SPEC ("md_exec_prefix",		&md_exec_prefix),
   INIT_STATIC_SPEC ("md_startfile_prefix",	&md_startfile_prefix),
   INIT_STATIC_SPEC ("md_startfile_prefix_1",	&md_startfile_prefix_1),
@@ -1553,6 +1556,7 @@
   INIT_STATIC_SPEC ("sysroot_spec",             &sysroot_spec),
   INIT_STATIC_SPEC ("sysroot_suffix_spec",	&sysroot_suffix_spec),
   INIT_STATIC_SPEC ("sysroot_hdrs_suffix_spec",	&sysroot_hdrs_suffix_spec),
+#endif /* 0 */
 };
 
 #ifdef EXTRA_SPECS		/* additional specs needed */
@@ -2437,11 +2441,21 @@
       if (stat (name, &st) < 0
 	  || S_ISDIR (st.st_mode))
 	return -1;
+
+#ifdef _WIN32
+/* (TIGCC 20070209) Vista's MSVCRT.DLL doesn't like X_OK, so translate to R_OK. */
+      return access (name, R_OK);
+#endif
     }
 
   return access (name, mode);
 }
 
+#ifdef _WIN32
+#undef access
+#define access access_check
+#endif
+
 /* Search for NAME using the prefix list PREFIXES.  MODE is passed to
    access to check permissions.
    Return 0 if not found, otherwise return its name, allocated with malloc.  */
@@ -3149,7 +3163,9 @@
 process_command (int argc, const char **argv)
 {
   int i;
+#if 0 /* (TIGCC 20040104) Don't use environment variables. */
   const char *temp;
+#endif /* 0 */
   char *temp1;
   const char *spec_lang = 0;
   int last_language_n_infiles;
@@ -3159,7 +3175,9 @@
   int j;
 #endif
 
+#if 0 /* (TIGCC 20040104) Don't use environment variables. */
   GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX");
+#endif /* 0 */
 
   n_switches = 0;
   n_infiles = 0;
@@ -3241,7 +3259,7 @@
      see if we can create it from the pathname specified in argv[0].  */
 
   gcc_libexec_prefix = standard_libexec_prefix;
-#ifndef VMS
+#if 0
   /* FIXME: make_relative_prefix doesn't yet work for VMS.  */
   if (!gcc_exec_prefix)
     {
@@ -3260,6 +3278,7 @@
 #else
 #endif
 
+#if 0 /* (TIGCC 20040104) Don't use environment variables. */
   if (gcc_exec_prefix)
     {
       int len = strlen (gcc_exec_prefix);
@@ -3383,6 +3402,7 @@
 	    endp++;
 	}
     }
+#endif /* 0 */
 
   /* Convert new-style -- options to old-style.  */
   translate_options (&argc, (const char *const **) &argv);
@@ -3810,6 +3830,7 @@
 
   /* Set up the search paths before we go looking for config files.  */
 
+#if 0 /* (TIGCC 20040104) Don't hardcode any prefix at compile time. */
   /* These come before the md prefixes so that we will find gcc's subcommands
      (such as cpp) rather than those of the host system.  */
   /* Use 2 as fourth arg meaning try just the machine as a suffix,
@@ -3871,6 +3892,7 @@
   add_prefix (&startfile_prefixes,
 	      concat (tooldir_prefix, "lib", dir_separator_str, NULL),
 	      "BINUTILS", PREFIX_PRIORITY_LAST, 0, 1);
+#endif /* 0 */
 
 #if defined(TARGET_SYSTEM_ROOT_RELOCATABLE) && !defined(VMS)
   /* If the normal TARGET_SYSTEM_ROOT is inside of $exec_prefix,
@@ -6149,6 +6171,7 @@
   else
     init_spec ();
 
+#if 0
   /* We need to check standard_exec_prefix/just_machine_suffix/specs
      for any override of as, ld and libraries.  */
   specs_file = alloca (strlen (standard_exec_prefix)
@@ -6182,7 +6205,9 @@
 		      PREFIX_PRIORITY_LAST, 0, 0);
 	}
     }
+#endif /* 0 */
 
+#if 0 /* (TIGCC 20040104) Don't hardcode any prefix at compile time. */
   /* Process sysroot_suffix_spec.  */
   if (*sysroot_suffix_spec != 0
       && do_spec_2 (sysroot_suffix_spec) == 0)
@@ -6272,6 +6297,7 @@
 			      standard_startfile_prefix_2, "BINUTILS",
 			      PREFIX_PRIORITY_LAST, 0, 1);
     }
+#endif /* 0 */
 
   /* Process any user specified specs in the order given on the command
      line.  */
@@ -6282,10 +6308,12 @@
       read_specs (filename ? filename : uptr->filename, FALSE);
     }
 
+#if 0 /* (TIGCC 20040104) Don't use environment variables. */
   /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake.  */
   if (gcc_exec_prefix)
     gcc_exec_prefix = concat (gcc_exec_prefix, spec_machine, dir_separator_str,
 			      spec_version, dir_separator_str, NULL);
+#endif /* 0 */
 
   /* Now we have the specs.
      Set the `valid' bits for switches that match anything in any spec.  */
@@ -6306,7 +6334,8 @@
 
   if (print_search_dirs)
     {
-      printf (_("install: %s%s\n"), standard_exec_prefix, machine_suffix);
+/* (TIGCC 20040104) Don't hardcode any prefix at compile time. */
+      printf (_("install: relocatable TIGCC installation\n"));
       printf (_("programs: %s\n"), build_search_list (&exec_prefixes, "", 0));
       printf (_("libraries: %s\n"), build_search_list (&startfile_prefixes, "", 0));
       return (0);
diff -Naur gcc-4.1.2.orig/gcc/gcse.c gcc-4.1.2-src/gcc/gcse.c
--- gcc-4.1.2.orig/gcc/gcse.c	2006-01-16 10:37:10.000000000 +0100
+++ gcc-4.1.2-src/gcc/gcse.c	2007-02-19 02:32:34.000000000 +0100
@@ -3053,11 +3053,14 @@
   rtx newreg = NULL, newcnst = NULL;
 
   /* Rule out USE instructions and ASM statements as we don't want to
-     change the hard registers mentioned.  */
+     change the hard registers mentioned.
+     (TIGCC) The same thing goes for global register variables. CalcRogue gets
+             miscompiled without this patch.  */
   if (REG_P (x)
       && (REGNO (x) >= FIRST_PSEUDO_REGISTER
           || (GET_CODE (PATTERN (insn)) != USE
-	      && asm_noperands (PATTERN (insn)) < 0)))
+	      && asm_noperands (PATTERN (insn)) < 0
+	      && ! global_regs[REGNO (x)])))
     {
       cselib_val *val = cselib_lookup (x, GET_MODE (x), 0);
       struct elt_loc_list *l;
diff -Naur gcc-4.1.2.orig/gcc/genmodes.c gcc-4.1.2-src/gcc/genmodes.c
--- gcc-4.1.2.orig/gcc/genmodes.c	2005-06-25 04:02:01.000000000 +0200
+++ gcc-4.1.2-src/gcc/genmodes.c	2007-02-19 02:32:34.000000000 +0100
@@ -1068,6 +1068,7 @@
 static void
 emit_real_format_for_mode (void)
 {
+#if 0
   struct mode_data *m;
 
   /* The entities pointed to by this table are constant, whether
@@ -1093,6 +1094,7 @@
       tagged_printf ("&%s", m->format, m->name);
 
   print_closer ();
+#endif /* 0 */
 }
 
 static void
@@ -1177,10 +1179,12 @@
 	}
     }
       
+#if 0
   /* Real mode formats don't have to propagate anywhere.  */
   for (a = adj_format; a; a = a->next)
     printf ("\n  /* %s:%d */\n  REAL_MODE_FORMAT (%smode) = %s;\n",
 	    a->file, a->line, a->mode->name, a->adjustment);
+#endif /* 0 */
 
   puts ("}");
 }
diff -Naur gcc-4.1.2.orig/gcc/gimplify.c gcc-4.1.2-src/gcc/gimplify.c
--- gcc-4.1.2.orig/gcc/gimplify.c	2006-11-19 17:15:47.000000000 +0100
+++ gcc-4.1.2-src/gcc/gimplify.c	2007-04-17 16:41:54.000000000 +0200
@@ -1904,6 +1904,7 @@
   /* There is a sequence point before the call, so any side effects in
      the calling expression must occur before the actual call.  Force
      gimplify_expr to use an internal post queue.  */
+  if (!flag_no_function_cse)
   ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, NULL,
 		       is_gimple_call_addr, fb_rvalue);
 
@@ -1922,6 +1923,12 @@
   if (PUSH_ARGS_REVERSED)
     TREE_OPERAND (*expr_p, 1) = nreverse (TREE_OPERAND (*expr_p, 1));
 
+  /* (TIGCC 20050206) Gimplify the function expression only after the arguments
+                      if -fno-function-cse. */
+  if (flag_no_function_cse)
+  ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, NULL,
+		       is_gimple_call_addr, fb_rvalue);
+
   /* Try this again in case gimplification exposed something.  */
   if (ret != GS_ERROR)
     {
@@ -4234,11 +4241,15 @@
 	      break;
 	    }
 
-	  if (VOID_TYPE_P (TREE_TYPE (*expr_p))
-	      || fallback == fb_none)
+	  if ((VOID_TYPE_P (TREE_TYPE (*expr_p))
+	       || fallback == fb_none)
+	      && ! TREE_CODE (TREE_OPERAND (*expr_p, 0)) == CALL_EXPR)
 	    {
 	      /* Just strip a conversion to void (or in void context) and
 		 try again.  */
+	      /* (TIGCC 20070417) But not for function calls, so
+	         warn_unused_result doesn't warn if they're cast to void.
+	         (Patch by Richard Guenther from PR 25509.) */
 	      *expr_p = TREE_OPERAND (*expr_p, 0);
 	      break;
 	    }
diff -Naur gcc-4.1.2.orig/gcc/ifcvt.c gcc-4.1.2-src/gcc/ifcvt.c
--- gcc-4.1.2.orig/gcc/ifcvt.c	2006-11-15 09:11:59.000000000 +0100
+++ gcc-4.1.2-src/gcc/ifcvt.c	2007-02-19 02:32:34.000000000 +0100
@@ -2057,6 +2057,16 @@
   if (MEM_P (op))
     return ! side_effects_p (XEXP (op, 0));
 
+  /* (TIGCC 20040925) Can't if-convert global register variables.
+                      -- Kevin Kofler */
+  if (GET_CODE (op) == REG)
+    {
+      int regno;
+      regno = REGNO (op);
+      if (regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
+        return FALSE;
+    }
+
   if (side_effects_p (op))
     return FALSE;
 
@@ -3396,6 +3406,21 @@
 		 TEST range.  */
 	      if (for_each_rtx (&PATTERN (insn), find_memory, NULL))
 		return FALSE;
+
+	      /* (TIGCC 20040925) Can't if-convert global register variables.
+	                          -- Kevin Kofler */
+	      if (GET_CODE (PATTERN (insn)) == SET)
+            {
+              rtx dest;
+              dest = SET_DEST (PATTERN (insn));
+              if (GET_CODE (dest) == REG)
+                {
+                  int regno;
+                  regno = REGNO (dest);
+                  if (regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
+                    return FALSE;
+                }
+            }
 	    }
 	  if (insn == end)
 	    break;
diff -Naur gcc-4.1.2.orig/gcc/langhooks-def.h gcc-4.1.2-src/gcc/langhooks-def.h
--- gcc-4.1.2.orig/gcc/langhooks-def.h	2005-11-19 00:40:29.000000000 +0100
+++ gcc-4.1.2-src/gcc/langhooks-def.h	2007-02-19 02:32:34.000000000 +0100
@@ -107,6 +107,7 @@
 #define LANG_HOOKS_SAFE_FROM_P		lhd_safe_from_p
 #define LANG_HOOKS_FINISH_INCOMPLETE_DECL lhd_do_nothing_t
 #define LANG_HOOKS_STATICP		lhd_staticp
+#define LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES lhd_do_nothing_t
 #define LANG_HOOKS_DUP_LANG_SPECIFIC_DECL lhd_do_nothing_t
 #define LANG_HOOKS_SET_DECL_ASSEMBLER_NAME lhd_set_decl_assembler_name
 #define LANG_HOOKS_CAN_USE_BIT_FIELDS_P lhd_can_use_bit_fields_p
@@ -272,6 +273,7 @@
   LANG_HOOKS_EXPAND_CONSTANT, \
   LANG_HOOKS_EXPAND_EXPR, \
   LANG_HOOKS_EXPAND_DECL, \
+  LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES, \
   LANG_HOOKS_SAFE_FROM_P, \
   LANG_HOOKS_FINISH_INCOMPLETE_DECL, \
   LANG_HOOKS_MARK_ADDRESSABLE, \
diff -Naur gcc-4.1.2.orig/gcc/langhooks.h gcc-4.1.2-src/gcc/langhooks.h
--- gcc-4.1.2.orig/gcc/langhooks.h	2005-11-19 00:40:29.000000000 +0100
+++ gcc-4.1.2-src/gcc/langhooks.h	2007-02-19 02:32:34.000000000 +0100
@@ -283,6 +283,10 @@
      1 if handled, 0 otherwise.  */
   int (*expand_decl) (tree);
 
+  /* Possibly apply default attributes to a function (represented by
+     a FUNCTION_DECL).  */
+  void (*insert_default_attributes) PARAMS ((tree));
+
   /* Hook called by safe_from_p for language-specific tree codes.  It is
      up to the language front-end to install a hook if it has any such
      codes that safe_from_p needs to know about.  Since same_from_p will
diff -Naur gcc-4.1.2.orig/gcc/loop.c gcc-4.1.2-src/gcc/loop.c
--- gcc-4.1.2.orig/gcc/loop.c	2006-11-01 13:11:18.000000000 +0100
+++ gcc-4.1.2-src/gcc/loop.c	2007-02-19 02:32:34.000000000 +0100
@@ -1297,6 +1297,13 @@
 		      && REGNO_LAST_UID (regno) == INSN_UID (user)
 		      && regs->array[regno].set_in_loop == 1
 		      && GET_CODE (SET_SRC (set)) != ASM_OPERANDS
+		      /* (TIGCC 20050206) Patch by Ian Lance Taylor regarding using hard
+		                          register variables as an asm input
+		         See http://gcc.gnu.org/ml/gcc/2004-05/msg00678.html */
+		      && (regno >= FIRST_PSEUDO_REGISTER
+			  || asm_noperands (PATTERN (regs->array[regno]
+						     .single_usage))
+			  < 0)
 		      && ! side_effects_p (SET_SRC (set))
 		      && ! find_reg_note (p, REG_RETVAL, NULL_RTX)
 		      && (!SMALL_REGISTER_CLASSES
diff -Naur gcc-4.1.2.orig/gcc/machmode.def gcc-4.1.2-src/gcc/machmode.def
--- gcc-4.1.2.orig/gcc/machmode.def	2005-06-25 04:02:01.000000000 +0200
+++ gcc-4.1.2-src/gcc/machmode.def	2007-02-19 02:32:34.000000000 +0100
@@ -170,8 +170,8 @@
    These are the IEEE mappings.  They can be overridden with
    RESET_FLOAT_FORMAT or at runtime (in OVERRIDE_OPTIONS).  */
 
-FLOAT_MODE (SF, 4, ieee_single_format);
-FLOAT_MODE (DF, 8, ieee_double_format);
+FLOAT_MODE (SF, 4, 0);
+FLOAT_MODE (DF, 8, 0);
 
 /* Basic CC modes.
    FIXME define this only for targets that need it.  */
diff -Naur gcc-4.1.2.orig/gcc/optabs.c gcc-4.1.2-src/gcc/optabs.c
--- gcc-4.1.2.orig/gcc/optabs.c	2006-07-26 15:32:01.000000000 +0200
+++ gcc-4.1.2-src/gcc/optabs.c	2007-02-19 02:32:34.000000000 +0100
@@ -1741,7 +1741,7 @@
   /* Look for a wider mode of the same class for which it appears we can do
      the operation.  */
 
-  if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
+  if (class == MODE_INT)
     {
       for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
 	   wider_mode = GET_MODE_WIDER_MODE (wider_mode))
@@ -2037,7 +2037,7 @@
 
   /* It can't be done in this mode.  Can we do it in a wider mode?  */
 
-  if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
+  if (class == MODE_INT)
     {
       for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
 	   wider_mode = GET_MODE_WIDER_MODE (wider_mode))
@@ -2205,6 +2205,7 @@
   return 0;
 }
 
+#if 0 /* (TIGCC 20050216) */
 /* Extract the OMODE lowpart from VAL, which has IMODE.  Under certain
    conditions, VAL may already be a SUBREG against which we cannot generate
    a further SUBREG.  In this case, we expect forcing the value into a
@@ -2329,6 +2330,7 @@
 
   return target;
 }
+#endif /* 0 */
 
 /* Generate code to perform an operation specified by UNOPTAB
    on operand OP0, with result having machine-mode MODE.
@@ -2406,7 +2408,7 @@
 	goto try_libcall;
     }
 
-  if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
+  if (class == MODE_INT)
     for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
 	 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
       {
@@ -2482,13 +2484,16 @@
 
   if (unoptab->code == NEG)
     {
+#if 0
       /* Try negating floating point values by flipping the sign bit.  */
+      /* (TIGCC 20050205) Don't. We have unsigned zero and infinity.  */
       if (class == MODE_FLOAT)
 	{
 	  temp = expand_absneg_bit (NEG, mode, op0, target);
 	  if (temp)
 	    return temp;
 	}
+#endif /* 0 */
 
       /* If there is no negation pattern, and we have no negative zero,
 	 try subtracting from zero.  */
@@ -2545,7 +2550,7 @@
 
   /* It can't be done in this mode.  Can we do it in a wider mode?  */
 
-  if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
+  if (class == MODE_INT)
     {
       for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
 	   wider_mode = GET_MODE_WIDER_MODE (wider_mode))
@@ -2634,13 +2639,16 @@
   if (temp != 0)
     return temp;
 
+#if 0
   /* For floating point modes, try clearing the sign bit.  */
+  /* (TIGCC 20050205) Don't. We have unsigned zero and infinity.  */
   if (GET_MODE_CLASS (mode) == MODE_FLOAT)
     {
       temp = expand_absneg_bit (ABS, mode, op0, target);
       if (temp)
 	return temp;
     }
+#endif /* 0 */
 
   /* If we have a MAX insn, we can do this as MAX (x, -x).  */
   if (smax_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing
@@ -2733,6 +2741,7 @@
   return target;
 }
 
+#if 0
 /* A subroutine of expand_copysign, perform the copysign operation using the
    abs and neg primitives advertised to exist on the target.  The assumption
    is that we have a split register file, and leaving op0 in fp registers,
@@ -2965,6 +2974,7 @@
   return expand_copysign_bit (mode, op0, op1, target,
 			      fmt->signbit_rw, op0_is_abs);
 }
+#endif /* 0 */
 
 /* Generate an instruction whose insn-code is INSN_CODE,
    with two operands: an output TARGET and an input OP0.
@@ -4351,6 +4361,7 @@
 	  }
       }
 
+#if 0
   /* Unsigned integer, and no way to convert directly.
      Convert as signed, then conditionally adjust the result.  */
   if (unsignedp)
@@ -4455,6 +4466,7 @@
       emit_label (label);
       goto done;
     }
+#endif /* 0 */
 
   /* No hardware instruction available; call a library routine.  */
     {
@@ -4545,6 +4557,7 @@
 	  }
       }
 
+#if 0
   /* For an unsigned conversion, there is one more way to do it.
      If we have a signed conversion, we generate code that compares
      the real value to the largest representable positive number.  If if
@@ -4628,6 +4641,7 @@
 
 	  return;
 	}
+#endif /* 0 */
 
   /* We can't do it with an insn, so use a library call.  But first ensure
      that the mode of TO is at least as wide as SImode, since those are the
@@ -5231,6 +5245,9 @@
   /* Conversions.  */
   init_interclass_conv_libfuncs (sfloat_optab, "float",
 				 MODE_INT, MODE_FLOAT);
+  /* (TIGCC 20050208) Someone forgot this one... */
+  init_interclass_conv_libfuncs (ufloat_optab, "floatuns",
+				 MODE_INT, MODE_FLOAT);
   init_interclass_conv_libfuncs (sfix_optab, "fix",
 				 MODE_FLOAT, MODE_INT);
   init_interclass_conv_libfuncs (ufix_optab, "fixuns",
diff -Naur gcc-4.1.2.orig/gcc/opts.c gcc-4.1.2-src/gcc/opts.c
--- gcc-4.1.2.orig/gcc/opts.c	2006-05-17 20:38:58.000000000 +0200
+++ gcc-4.1.2-src/gcc/opts.c	2007-02-19 02:32:34.000000000 +0100
@@ -570,7 +570,12 @@
 #endif
       flag_regmove = 1;
       flag_strict_aliasing = 1;
+#if 0 /* (TIGCC 20050213) Null pointer dereferences won't necessarily trigger
+         a trap. When reading, they definitely won't. When writing, they will
+         only when the variable being dereferenced is a scalar or a small
+         enough structure. */
       flag_delete_null_pointer_checks = 1;
+#endif
       flag_reorder_blocks = 1;
       flag_reorder_functions = 1;
       flag_tree_store_ccp = 1;
@@ -589,6 +594,10 @@
       flag_inline_functions = 1;
       flag_unswitch_loops = 1;
       flag_gcse_after_reload = 1;
+      /* (TIGCC 20050217) Halve maximum inline insns under -O3. Use -O4 to
+                          override this. */
+      if (optimize == 3)
+        set_param_value ("max-inline-insns-auto", 60);
     }
 
   if (optimize < 2 || optimize_size)
@@ -609,12 +618,17 @@
       flag_reorder_blocks_and_partition = 0;
     }
 
-  if (optimize_size)
+  /* (TIGCC 20050217) Do this at -O2 as well, as it improves both size and speed. */
+  if (optimize == 2 || optimize_size)
     {
       /* Inlining of very small functions usually reduces total size.  */
-      set_param_value ("max-inline-insns-single", 5);
       set_param_value ("max-inline-insns-auto", 5);
       flag_inline_functions = 1;
+    }
+  if (optimize_size)
+    {
+      /* Inlining of very small functions usually reduces total size.  */
+      set_param_value ("max-inline-insns-single", 5);
 
       /* We want to crossjump as much as possible.  */
       set_param_value ("min-crossjump-insns", 1);
@@ -645,6 +659,11 @@
   if (flag_pic && !flag_pie)
     flag_shlib = 1;
 
+  /* TIGCC Patch: Register d2 is used by the TIOS calling convention.
+     See "call-used-" further down in this file. */
+  if (TARGET_TIOS)
+    fix_register ("d2", 0, 1);
+
   if (flag_no_inline == 2)
     flag_no_inline = 0;
   else
@@ -922,6 +941,12 @@
       flag_profile_values_set = true;
       break;
 
+    case OPT_freg_relative_:
+      fix_register (arg, 1, 1);
+      target_flags |= MASK_REG_RELATIVE;
+      strcpy (TARGET_RELATION_REG, arg);
+      break;
+
     case OPT_fvisibility_:
       {
         if (!strcmp(arg, "default"))
diff -Naur gcc-4.1.2.orig/gcc/output.h gcc-4.1.2-src/gcc/output.h
--- gcc-4.1.2.orig/gcc/output.h	2005-10-26 09:03:30.000000000 +0200
+++ gcc-4.1.2-src/gcc/output.h	2007-02-19 02:32:34.000000000 +0100
@@ -334,7 +334,7 @@
 #define assemble_aligned_integer(SIZE, VALUE) \
   assemble_integer (VALUE, SIZE, (SIZE) * BITS_PER_UNIT, 1)
 
-#ifdef REAL_VALUE_TYPE_SIZE
+#ifdef REAL_WIDTH /* (TIGCC 20050205) */
 /* Assemble the floating-point constant D into an object of size MODE.  */
 extern void assemble_real (REAL_VALUE_TYPE, enum machine_mode, unsigned);
 #endif
diff -Naur gcc-4.1.2.orig/gcc/postreload.c gcc-4.1.2-src/gcc/postreload.c
--- gcc-4.1.2.orig/gcc/postreload.c	2005-11-18 14:14:39.000000000 +0100
+++ gcc-4.1.2-src/gcc/postreload.c	2007-02-19 02:32:34.000000000 +0100
@@ -1189,6 +1189,9 @@
        && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (OUTMODE), \
 				 GET_MODE_BITSIZE (INMODE))))
 
+/* (TIGCC 20050213) Declare this target-dependent function. */
+int const_method (rtx);
+
 static void
 reload_cse_move2add (rtx first)
 {
@@ -1276,11 +1279,17 @@
 			   && narrow_mode != GET_MODE (reg);
 			   narrow_mode = GET_MODE_WIDER_MODE (narrow_mode))
 			{
-			  if (have_insn_for (STRICT_LOW_PART, narrow_mode)
+			  /* (TIGCC 20050213) Don't do this for QImode. Byte moves aren't
+			      any cheaper than word moves, they just kill chances to use a
+			      moveq. Also don't turn long moves which can be done using
+			      moveq into word moves. */
+			  if (narrow_mode != QImode
+			      && have_insn_for (STRICT_LOW_PART, narrow_mode)
 			      && ((reg_offset[regno]
 				   & ~GET_MODE_MASK (narrow_mode))
 				  == (INTVAL (src)
-				      & ~GET_MODE_MASK (narrow_mode))))
+				      & ~GET_MODE_MASK (narrow_mode)))
+			      && (GET_MODE (reg) != SImode || const_method (src)))
 			    {
 			      rtx narrow_reg = gen_rtx_REG (narrow_mode,
 							    REGNO (reg));
diff -Naur gcc-4.1.2.orig/gcc/print-rtl.c gcc-4.1.2-src/gcc/print-rtl.c
--- gcc-4.1.2.orig/gcc/print-rtl.c	2005-08-16 02:13:53.000000000 +0200
+++ gcc-4.1.2-src/gcc/print-rtl.c	2007-02-19 02:32:34.000000000 +0100
@@ -586,6 +586,9 @@
 	{
 	  char s[60];
 
+	  REAL_VALUE_TO_STRING (*CONST_DOUBLE_REAL_VALUE (in_rtx), s);
+	  fprintf (outfile, " %s", s);
+#if 0
 	  real_to_decimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx),
 			   sizeof (s), 0, 1);
 	  fprintf (outfile, " %s", s);
@@ -593,6 +596,7 @@
 	  real_to_hexadecimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx),
 			       sizeof (s), 0, 1);
 	  fprintf (outfile, " [%s]", s);
+#endif /* 0 */
 	}
       break;
 #endif
diff -Naur gcc-4.1.2.orig/gcc/print-tree.c gcc-4.1.2-src/gcc/print-tree.c
--- gcc-4.1.2.orig/gcc/print-tree.c	2005-10-13 01:34:09.000000000 +0200
+++ gcc-4.1.2-src/gcc/print-tree.c	2007-02-19 02:32:34.000000000 +0100
@@ -134,7 +134,7 @@
       else
 	{
 	  char string[60];
-	  real_to_decimal (string, &d, sizeof (string), 0, 1);
+	  REAL_VALUE_TO_STRING (d, string);
 	  fprintf (file, " %s", string);
 	}
     }
@@ -680,7 +680,7 @@
 	    else
 	      {
 		char string[64];
-		real_to_decimal (string, &d, sizeof (string), 0, 1);
+		REAL_VALUE_TO_STRING (d, string);
 		fprintf (file, " %s", string);
 	      }
 	  }
diff -Naur gcc-4.1.2.orig/gcc/real.c gcc-4.1.2-src/gcc/real.c
--- gcc-4.1.2.orig/gcc/real.c	2005-09-19 19:01:40.000000000 +0200
+++ gcc-4.1.2-src/gcc/real.c	2007-02-19 02:32:34.000000000 +0100
@@ -72,6 +72,7 @@
    adjust the significand to match.  */
 
 
+#if 0
 /* Used to classify two numbers simultaneously.  */
 #define CLASS2(A, B)  ((A) << 2 | (B))
 
@@ -122,7 +123,9 @@
 static void times_pten (REAL_VALUE_TYPE *, int);
 
 static void round_for_format (const struct real_format *, REAL_VALUE_TYPE *);
+#endif /* 0 */
 
+#if 0
 /* Initialize R with a positive zero.  */
 
 static inline void
@@ -973,6 +976,614 @@
       gcc_unreachable ();
     }
 }
+#endif /* 0 */
+
+/* Add 1 unit in the last place to a positive SMAP II BCD float. */
+static void bcdpadd1ulp(smap_bcd_float *op)
+{
+  int i;
+  op->mantissa++; /* This will give a digit of 10 in some cases. */
+  for (i=0;i<60;i+=4) { /* for each digit except the first one */
+    int d=(op->mantissa>>i)&15;
+    if (d<10) /* if the digit is <10, we're done */
+      break;
+    op->mantissa += 6ull<<i; /* subtract 10 from the digit, add 1 to the next digit */
+  }
+  /* Now, we should have a carry only in one case: the mantissa was
+     9999999999999999. So now, we have A000000000000000, where A is 10 in a
+     single digit. We can safely truncate the last digit because it is 0 (so
+     there is no risk of double-rounding here). */
+  if (op->mantissa >= 0xA000000000000000ull) { /* if we have a carry */
+    gcc_assert (op->mantissa == 0xA000000000000000ull); /* sanity check */
+    op->mantissa = 0x1000000000000000ull; /* A -> 10, drop the last digit */
+    op->exponent++; /* adjust the exponent */
+    if (op->exponent > 0x4000+16383) /* exponent too large, overflow to +infinity */
+      *op = POSITIVE_INF;
+  }
+}
+
+/* Add 2 positive SMAP II BCD floats. */
+static smap_bcd_float bcdppadd(smap_bcd_float op0, smap_bcd_float op1)
+{
+  int lastdigit=0;
+
+  if (op0.exponent < op1.exponent) {
+    /* If op0 does not contribute to the result, avoid shift count overflow by
+       returning op1 immediately. */
+    if (op1.exponent-op0.exponent>16) return op1;
+    /* Adjust op0 exponent to fit op1. */
+    op0.mantissa >>= ((op1.exponent-op0.exponent-1)<<2);
+    lastdigit = (op0.mantissa&15); /* save the last digit of op0 */
+    op0.mantissa >>= 4; /* drop the last digit of op0 */
+    op0.exponent = op1.exponent; /* adjust the exponent of op0 */
+  } else if (op1.exponent < op0.exponent) {
+    /* If op1 does not contribute to the result, avoid shift count overflow by
+       returning op0 immediately. */
+    if (op0.exponent-op1.exponent>16) return op0;
+    /* Adjust op1 exponent to fit op0. */
+    op1.mantissa >>= ((op0.exponent-op1.exponent-1)<<2);
+    lastdigit = (op1.mantissa&15); /* save the last digit of op1 */
+    op1.mantissa >>= 4; /* drop the last digit of op1 */
+    op1.exponent = op0.exponent; /* adjust the exponent of op1 */
+  }
+
+  /* Now do the addition in the BCD-coded mantissa. */
+  {
+    int i,d,carry=0;
+    smap_bcd_float result={0,0};result.exponent=op0.exponent;
+    for (i=0;i<64;i+=4) { /* for each digit */
+      d = (op0.mantissa&15)+(op1.mantissa&15)+carry;
+      carry = (d>=10); /* handle carry */
+      if (carry) d -= 10;
+      /* We are done with this digit of the mantissa. */
+      op0.mantissa >>= 4;
+      op1.mantissa >>= 4;
+      /* Store it into the resulting mantissa. */
+      result.mantissa += ((unsigned long long)d)<<i;
+    }
+    if (carry) { /* The mantissa overflowed, so we need to adjust the exponent. */
+      lastdigit = (result.mantissa&15); /* save the last digit of result,
+                                           dropping the previously saved last
+                                           digit */
+      result.mantissa >>= 4; /* drop the last digit of result */
+      result.exponent++; /* adjust the exponent of result */
+      if (result.exponent > 0x4000+16383) /* exponent too large, overflow to */
+        return POSITIVE_INF;              /* +infinity */
+      /* prepend the first digit */
+      result.mantissa += ((unsigned long long)carry)<<60;
+    }
+    if (lastdigit>=5) /* now do the correct rounding */
+      bcdpadd1ulp(&result);
+    return result;
+  }
+}
+
+/* Subtract 2 positive SMAP II BCD floats. */
+static smap_bcd_float bcdppsub(smap_bcd_float op0, smap_bcd_float op1)
+{
+  unsigned long long lastdigits=0;
+
+  if (REAL_VALUES_LESS(op0,op1)) /* if op0<op1, subtract the other way round */
+    return REAL_VALUE_NEGATE(bcdppsub(op1,op0));
+  else if (REAL_VALUES_IDENTICAL(op0,op1)) /* if op0=op1, return unsigned 0 */
+    return UNSIGNED_ZERO;
+
+  /* Now, we can assume op0>op1. */
+  if (op1.exponent < op0.exponent) {
+    /* If op1 does not contribute to the result, avoid shift count overflow by
+       returning op0 immediately. */
+    if (op0.exponent-op1.exponent>16) return op0;
+    /* Adjust op1 exponent to fit op0.
+       Save all dropped digits, so we can round correctly. */
+    lastdigits = op1.mantissa << (64-((op0.exponent-op1.exponent)<<2));
+    if (op0.exponent-op1.exponent==16)
+      op1.mantissa = 0; /* special-cased because shifts by 64 aren't allowed */
+    else
+      op1.mantissa >>= ((op0.exponent-op1.exponent)<<2);
+    op1.exponent = op0.exponent; /* adjust the exponent of op1 */
+  }
+
+  /* Now do the subtraction in the BCD-coded mantissa. */
+  {
+    int i,d,carry=0;
+    smap_bcd_float result={0,0};result.exponent=op0.exponent;
+    for (i=0;i<64;i+=4) { /* for each digit */
+      d = (op0.mantissa&15)-((op1.mantissa&15)+carry);
+      carry = (d<0); /* handle carry */
+      if (carry) d += 10;
+      /* We are done with this digit of the mantissa. */
+      op0.mantissa >>= 4;
+      op1.mantissa >>= 4;
+      /* Store it into the resulting mantissa. */
+      result.mantissa += ((unsigned long long)d)<<i;
+    }
+    gcc_assert (!carry); /* Carry should be 0 here! */
+    /* Normalize and return the result (which is always positive here, since we
+       assumed op1>op0). Handle rounding and extra digits during normalization.
+       */
+    while ((result.mantissa<0x1000000000000000ull)
+           || ((result.mantissa==0x1000000000000000ull)
+              && ((lastdigits>0x5000000000000000ull)
+                 || ((lastdigits>0x500000000000000ull)
+                     && (result.exponent>0x4000-16383))))) {
+    /* while mantissa<1 */
+      int c = (result.mantissa==0x1000000000000000ull); /* used by the sanity
+                                                           check below */
+      result.exponent--; /* decrease exponent by 1 */
+      if (result.exponent<0x4000-16383) /* exponent too small, underflow to +0 */
+        return POSITIVE_ZERO;
+      result.mantissa <<= 4; /* left-shift mantissa */
+      carry = !!(lastdigits>>60);
+      result.mantissa -= (lastdigits>>60)+(carry*6); /* Subtract extra digit. If
+        there is a carry, add 10 to the digit, subtract 1 from the next digit.
+        This can give digits of 15 in some cases. */
+      for (i=4;i<64;i+=4) { /* for each digit except the last one */
+        int d=(result.mantissa>>i)&15;
+        if (d<10) /* if the digit is <10, we're done */
+          break;
+        result.mantissa -= 6ull<<i; /* add 10 to the digit, subtract 1 from the
+                                       next digit */
+        /* There should be no carry in the first digit except if the mantissa
+           was exactly 1. */
+        gcc_assert (c || result.mantissa<0xA000000000000000ull);
+      }
+      lastdigits <<= 4; /* We handled an extra digit. */
+    }
+    /* Now do the rounding. */
+    if (lastdigits>0x5000000000000000ull) {
+      int c = !result.mantissa; /* used by the sanity check below */
+      /* This corner case should have been handled above. */
+      gcc_assert (result.mantissa!=0x1000000000000000ull);
+      result.mantissa--; /* Subtract 1. This can give digits of 15 in some cases. */
+      for (i=0;i<64;i+=4) { /* for each digit */
+        int d=(result.mantissa>>i)&15;
+        if (d<10) /* if the digit is <10, we're done */
+          break;
+        result.mantissa -= 6ull<<i; /* add 10 to the digit, subtract 1 from the
+                                       next digit */
+        /* There should be no carry in the first digit except if the mantissa was
+           0 (which actually means 10^16 here). */
+        gcc_assert (c || result.mantissa<0xA000000000000000ull);
+      }
+    }
+    return result;
+  }
+}
+
+/* Add 2 SMAP II BCD floats. */
+static smap_bcd_float bcdadd(smap_bcd_float op0, smap_bcd_float op1)
+{
+  if (REAL_VALUE_ISNAN(op0) || REAL_VALUE_ISNAN(op1)) /* keep NAN */
+    return NAN;
+  else if (REAL_VALUE_ISINF(op0) && REAL_VALUE_ISINF(op1)) { /* both operands
+                                                                are infinity */
+    if (!REAL_VALUES_IDENTICAL(op0,op1)
+        || REAL_VALUES_IDENTICAL(op0,UNSIGNED_INF)) /* differing signs or both
+                                                       unsigned yield NAN */
+      return NAN;
+    else /* both positive or both negative */
+      return op0;
+  } else if (REAL_VALUE_ISINF(op0)) /* op0=inf, so op0+op1=inf+op1=inf=op0 */
+    return op0;
+  else if (REAL_VALUE_ISINF(op1)) /* op1=inf, so op0+op1=op0+inf=inf=op1 */
+    return op1;
+  else if (REAL_VALUE_ISZERO(op0) && REAL_VALUE_ISZERO(op1)) { /* both operands
+                                                                  are 0 */
+    if (REAL_VALUES_IDENTICAL(op0,op1)) /* both positive, both negative or both
+                                           unsigned */
+      return op0;
+    else /* differing signs yield unsigned zero */
+      return UNSIGNED_ZERO;
+  } else if (REAL_VALUE_ISZERO(op0)) /* op0=0, so op0+op1=0+op1=op1 */
+    return op1;
+  else if (REAL_VALUE_ISZERO(op1)) /* op1=0, so op0+op1=op0+0=op0 */
+    return op0;
+  else if (REAL_VALUE_ISPOSITIVE(op0) && REAL_VALUE_ISPOSITIVE(op1))
+    return bcdppadd(op0,op1);
+  else if (REAL_VALUE_ISPOSITIVE(op0)) /* and op1 negative */
+    return bcdppsub(op0,REAL_VALUE_NEGATE(op1));
+  else if (REAL_VALUE_ISPOSITIVE(op1)) /* and op0 negative */
+    return bcdppsub(op1,REAL_VALUE_NEGATE(op0));
+  else /* both negative */
+    return REAL_VALUE_NEGATE(bcdppadd(REAL_VALUE_NEGATE(op0),
+                                      REAL_VALUE_NEGATE(op1)));
+}
+
+/* Subtract 2 SMAP II BCD floats. */
+static smap_bcd_float bcdsub(smap_bcd_float op0, smap_bcd_float op1)
+{
+  return bcdadd(op0,REAL_VALUE_NEGATE(op1));
+}
+
+/* Multiply 2 positive SMAP II BCD floats. */
+static smap_bcd_float bcdppmul(smap_bcd_float op0, smap_bcd_float op1)
+{
+  /* Compute the result in 2 binary parts. The upper 16 decimal digits and the
+     lower ones. */
+  unsigned long long resulth=0, resultl=0;
+  int i,j,k,d0,d1,d32,exponent;
+  unsigned long long factor=1ull;
+  for (i=0;i<64;i+=4,factor*=10ull) { /* for each result digit <16 */
+    for (j=0;j<64;j+=4) { /* for each digit of op0 */
+      k = i-j; /* corresponding op1 digit */
+      if (k<0 || k>=64) continue; /* digit out of range */
+      d0 = (op0.mantissa>>j)&15; /* jth digit of op0 */
+      d1 = (op1.mantissa>>k)&15; /* kth digit of op0 */
+      resultl += (unsigned long long)(d0*d1)*factor;
+      while (resultl>=10000000000000000ull/*10^16*/) { /* carry into resulth */
+        resultl -= 10000000000000000ull/*10^16*/;
+        resulth++;
+      }
+    }
+  }
+  for (factor=1ull;i<128;i+=4,factor*=10ull) { /* for each result digit >=16 */
+    for (j=0;j<64;j+=4) { /* for each digit of op0 */
+      k = i-j; /* corresponding op1 digit */
+      if (k<0 || k>=64) continue; /* digit out of range */
+      d0 = (op0.mantissa>>j)&15; /* jth digit of op0 */
+      d1 = (op1.mantissa>>k)&15; /* kth digit of op0 */
+      resulth += (unsigned long long)(d0*d1)*factor;
+    }
+  }
+
+  /* resultl should always be <10^16 */
+  gcc_assert (resultl<10000000000000000ull);
+
+  /* Because of normalization, the result has either 31 or 32 digits. */
+  d32 = (resulth>=1000000000000000ull/*10^15*/
+         || (resulth==999999999999999ull/*10^15-1*/
+             && resultl>=9500000000000000ull/*9.5*10^15*/));
+  if (!d32) { /* if we have only 15 digits in resulth, take one from resultl */
+    resulth = resulth*10ull+resultl/1000000000000000ull/*10^15*/;
+    resultl = (resultl%1000000000000000ull/*10^15*/)*10ull;
+  }
+  if (resultl>=5000000000000000ull/*5*10^15*/) /* round resultl into resulth */
+    resulth++;
+
+  /* Now compute the exponent. */
+  exponent=op0.exponent+op1.exponent-0x4000+d32;
+  if (exponent>0x4000+16383) /* exponent too large, overflow to +infinity */
+    return POSITIVE_INF;
+  if (exponent<0x4000-16383) /* exponent too small, underflow to +0 */
+    return POSITIVE_ZERO;
+
+  /* Now convert resulth into a BCD mantissa. */
+  {
+    unsigned long long d;
+    smap_bcd_float result={0,0};result.exponent=exponent;
+    for (i=0;i<64;i+=4) { /* for each digit */
+      d = resulth%10ull; /* Extract the digit. */
+      resulth /= 10ull; /* We are done with this digit of the mantissa. */
+      result.mantissa += d<<i; /* Store it into the resulting mantissa. */
+    }
+    return result;
+  }
+}
+
+/* Multiply 2 SMAP II BCD floats. */
+static smap_bcd_float bcdmul(smap_bcd_float op0, smap_bcd_float op1)
+{
+  if (REAL_VALUE_ISNAN(op0) || REAL_VALUE_ISNAN(op1)
+      || (REAL_VALUE_ISINF(op0) && REAL_VALUE_ISZERO(op1))
+      || (REAL_VALUE_ISZERO(op0) && REAL_VALUE_ISINF(op1))) /* keep NAN,
+                                                               0*inf=NAN */
+    return NAN;
+  else if (REAL_VALUES_IDENTICAL(op0,UNSIGNED_INF)
+           || REAL_VALUES_IDENTICAL(op1,UNSIGNED_INF)) /* unsigned inf * non-0 =
+                                                          unsigned inf */
+    return UNSIGNED_INF;
+  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_INF)
+            && REAL_VALUES_IDENTICAL(op1,POSITIVE_INF)) /* +inf * +inf = +inf */
+           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_INF)
+               && REAL_VALUES_IDENTICAL(op1,NEGATIVE_INF))) /* -inf * -inf = +inf */
+    return POSITIVE_INF;
+  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_INF)
+            && REAL_VALUES_IDENTICAL(op1,NEGATIVE_INF)) /* +inf * -inf = -inf */
+           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_INF)
+               && REAL_VALUES_IDENTICAL(op1,POSITIVE_INF))) /* -inf * +inf = -inf */
+    return NEGATIVE_INF;
+  /* Now we can assume that at least 1 value is finite, and that we don't have
+     an unsigned infinity, a NAN or an inf*0 indeterminate form. */
+  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_INF)
+            && REAL_VALUE_ISPOSITIVE(op1)) /* +inf * +finite = +inf */
+           || (REAL_VALUE_ISPOSITIVE(op0)
+               && REAL_VALUES_IDENTICAL(op1,POSITIVE_INF)) /* +finite * +inf = +inf */
+           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_INF)
+               && REAL_VALUE_ISNEGATIVE(op1)) /* -inf * -finite = +inf */
+           || (REAL_VALUE_ISNEGATIVE(op0)
+               && REAL_VALUES_IDENTICAL(op1,NEGATIVE_INF))) /* -finite * -inf = +inf */
+    return POSITIVE_INF;
+  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_INF)
+            && REAL_VALUE_ISNEGATIVE(op1)) /* +inf * -finite = -inf */
+           || (REAL_VALUE_ISPOSITIVE(op0)
+               && REAL_VALUES_IDENTICAL(op1,NEGATIVE_INF)) /* +finite * -inf = -inf */
+           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_INF)
+               && REAL_VALUE_ISPOSITIVE(op1)) /* -inf * +finite = -inf */
+           || (REAL_VALUE_ISNEGATIVE(op0)
+               && REAL_VALUES_IDENTICAL(op1,POSITIVE_INF))) /* -finite * +inf = -inf */
+    return NEGATIVE_INF;
+  /* Now we can assume that both values are finite. */
+  else if (REAL_VALUES_IDENTICAL(op0,UNSIGNED_ZERO)
+           || REAL_VALUES_IDENTICAL(op1,UNSIGNED_ZERO)) /* unsigned 0 * finite =
+                                                           unsigned 0 */
+    return UNSIGNED_ZERO;
+  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_ZERO)
+            && REAL_VALUES_IDENTICAL(op1,POSITIVE_ZERO)) /* +0 * +0 = +0 */
+           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_ZERO)
+               && REAL_VALUES_IDENTICAL(op1,NEGATIVE_ZERO))) /* -0 * -0 = +0 */
+    return POSITIVE_ZERO;
+  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_ZERO)
+            && REAL_VALUES_IDENTICAL(op1,NEGATIVE_ZERO)) /* +0 * -0 = -0 */
+           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_ZERO)
+               && REAL_VALUES_IDENTICAL(op1,POSITIVE_ZERO))) /* -0 * +0 = -0 */
+    return NEGATIVE_ZERO;
+  /* Now we can assume that both values are finite, at least 1 value is non-0,
+     and that we don't have an unsigned 0. */
+  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_ZERO)
+            && REAL_VALUE_ISPOSITIVE(op1)) /* +0 * +finite = +0 */
+           || (REAL_VALUE_ISPOSITIVE(op0)
+               && REAL_VALUES_IDENTICAL(op1,POSITIVE_ZERO)) /* +finite * +0 = +0 */
+           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_ZERO)
+               && REAL_VALUE_ISNEGATIVE(op1)) /* -0 * -finite = +0 */
+           || (REAL_VALUE_ISNEGATIVE(op0)
+               && REAL_VALUES_IDENTICAL(op1,NEGATIVE_ZERO))) /* -finite * -0 = +0 */
+    return POSITIVE_ZERO;
+  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_ZERO)
+            && REAL_VALUE_ISNEGATIVE(op1)) /* +0 * -finite = -0 */
+           || (REAL_VALUE_ISPOSITIVE(op0)
+               && REAL_VALUES_IDENTICAL(op1,NEGATIVE_ZERO)) /* +finite * -0 = -0 */
+           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_ZERO)
+               && REAL_VALUE_ISPOSITIVE(op1)) /* -0 * +finite = -0 */
+           || (REAL_VALUE_ISNEGATIVE(op0)
+               && REAL_VALUES_IDENTICAL(op1,POSITIVE_ZERO))) /* -finite * +0 = -0 */
+    return NEGATIVE_ZERO;
+  /* Now we can assume that both values are finite and non-0. */
+  else if (REAL_VALUE_ISPOSITIVE(op0) && REAL_VALUE_ISPOSITIVE(op1))
+    return bcdppmul(op0,op1);
+  else if (REAL_VALUE_ISPOSITIVE(op0)) /* and op1 negative */
+    return REAL_VALUE_NEGATE(bcdppmul(op0,REAL_VALUE_NEGATE(op1)));
+  else if (REAL_VALUE_ISPOSITIVE(op1)) /* and op0 negative */
+    return REAL_VALUE_NEGATE(bcdppmul(REAL_VALUE_NEGATE(op0),op1));
+  else /* both negative */
+    return bcdppmul(REAL_VALUE_NEGATE(op0),REAL_VALUE_NEGATE(op1));
+}
+
+/* Divide 2 positive SMAP II BCD floats. Indicate if the computed result was exact. */
+static smap_bcd_float bcdppdiv(smap_bcd_float op0, smap_bcd_float op1, int *exactresult)
+{
+  /* The dividend is represented multiplied by 10^16, and in 2 binary parts. The
+     upper 64 bits and the lower ones. The divisor is represented in binary, in
+     2 parts to allow shifting. Compute the result mantissa in binary. */
+  unsigned long long dividendh, dividendl=0, divisorh, divisorl=0, resultm=0;
+  int i,d17,exponent;
+  unsigned long long factor=1ull;
+  /* Convert the mantissa of op0 to binary. */
+  for (i=0;i<64;i+=4,factor*=10ull) /* for each digit of op0 */
+    dividendl += (unsigned long long)((op0.mantissa>>i)&15)*factor;
+  /* Multiply the dividend with 10^16. */
+  dividendh = dividendl>>48; /* multiply first 16 bits with 2^16 */
+  dividendh *= 152587890625ull; /* and with 5^16 */
+  dividendl &= 0xFFFFFFFFFFFFull; /* remove them from dividendl */
+  dividendl *= 15625ull; /* multiply the remaining 48 bits with 5^6
+                            we still have to multiply them by 2^16*5^10 */
+  dividendh += (dividendl>>48)*9765625ull; /* multiply first 16 bits with 2^16*5^10 */
+  dividendl &= 0xFFFFFFFFFFFFull; /* remove them from dividendl */
+  dividendl *= 15625ull; /* multiply the remaining 48 bits with 5^6
+                            we still have to multiply them by 2^16*5^4 */
+  dividendh += (dividendl>>48)*625ull; /* multiply first 16 bits with 2^16*5^4 */
+  dividendl &= 0xFFFFFFFFFFFFull; /* remove them from dividendl */
+  dividendl *= 625ull; /* multiply the remaining 48 bits with 5^4
+                          we still have to multiply them by 2^16 */
+  dividendh += dividendl>>48; /* multiply first 16 bits with 2^16 */
+  dividendl <<= 16; /* multiply the remaining 48 bits with 2^16 */
+  /* Convert the mantissa of op1 to binary. */
+  for (i=0,factor=1ull;i<64;i+=4,factor*=10ull) /* for each digit of op1 */
+    divisorl += (unsigned long long)((op1.mantissa>>i)&15)*factor;
+  /* Multiply the divisor with 2^56. We know that, due to normalization, the
+     result is always <10^17, which is smaller than 2^57, so we don't have to go
+     through the full 128-bit division. */
+  divisorh = divisorl>>(64-56);
+  divisorl <<= 56;
+  /* Now do the 128-bit division. */
+  for (i=56;i>=0;i--) {
+    /* Shift the result to the left. */
+    resultm <<= 1;
+    /* Check if the divisor fits into the dividend. */
+    if (divisorh<dividendh || (divisorh==dividendh && divisorl<=dividendl)) {
+      /* Add 1 to the result. */
+      resultm++;
+      /* Subtract the divisor from the dividend. */
+      if (dividendl<divisorl) /* handle carry, use unsigned wraparound overflow */
+        dividendh--;
+      dividendl -= divisorl; /* now do the subtraction */
+      dividendh -= divisorh;
+    }
+    if (i) {
+      /* Shift the divisor to the right. */
+      divisorl = ((divisorh&1)<<63)+(divisorl>>1);
+      divisorh >>= 1;
+    }
+  }
+  /* dividendl now contains the remainder. It is always smaller than the
+     divisor, so it always fits into 64 bits. divisorl now contains the original
+     divisor. */
+
+  if (exactresult)
+    *exactresult = !dividendl; /* if there is a remainder, the result sure is
+                                  not exact, otherwise, let's assume it is for
+                                  a moment */
+
+  /* Because of normalization, the result has either 16 or 17 digits. */
+  d17 = (resultm>=10000000000000000ull/*10^16*/
+         || (resultm==9999999999999999ull/*10^16-1*/
+             && (dividendl<<1)>=divisorl) /* 2r>=d <=> r>=d/2 */);
+  if (d17) { /* if we have 17 digits in the result, drop one */
+    if (exactresult && (resultm%10ull)) /* if we are about to drop a non-0
+                                           digit, the result is not exact
+                                           anymore */
+      *exactresult = 0;
+    resultm = (resultm+5ull)/10ull; /* add 5 for correct rounding */
+  } else {
+    if ((dividendl<<1)>=divisorl /* r>=d/2 */) /* round remainder into result */
+      resultm++;
+  }
+
+  /* Now compute the exponent. */
+  exponent=op0.exponent-op1.exponent+0x4000-(!d17);
+  if (exactresult && (exponent>0x4000+16383 || exponent<0x4000-16383))
+    /* if we overflowed, the result is not exact anymore */
+    *exactresult = 0;
+  if (exponent>0x4000+16383) /* exponent too large, overflow to +infinity */
+    return POSITIVE_INF;
+  if (exponent<0x4000-16383) /* exponent too small, underflow to +0 */
+    return POSITIVE_ZERO;
+
+  /* Now convert resulth into a BCD mantissa. */
+  {
+    unsigned long long d;
+    smap_bcd_float result={0,0};result.exponent=exponent;
+    for (i=0;i<64;i+=4) { /* for each digit */
+      d = resultm%10ull; /* Extract the digit. */
+      resultm /= 10ull; /* We are done with this digit of the mantissa. */
+      result.mantissa += d<<i; /* Store it into the resulting mantissa. */
+    }
+    return result;
+  }
+}
+
+/* Divide 2 SMAP II BCD floats. Indicate if the computed result was exact. */
+static smap_bcd_float bcddiv(smap_bcd_float op0, smap_bcd_float op1, int *exactresult)
+{
+  if (exactresult) *exactresult=1; /* special cases are all exact */
+  if (REAL_VALUE_ISNAN(op0) || REAL_VALUE_ISNAN(op1)
+      || (REAL_VALUE_ISINF(op0) && REAL_VALUE_ISINF(op1))
+      || (REAL_VALUE_ISZERO(op0) && REAL_VALUE_ISZERO(op1))) /* keep NAN,
+                                                                0/0=inf/inf=NAN */
+    return NAN;
+  else if (REAL_VALUES_IDENTICAL(op0,UNSIGNED_INF)
+           || REAL_VALUES_IDENTICAL(op1,UNSIGNED_ZERO)) /* unsigned inf / finite
+                                          = non-0 / unsigned 0 = unsigned inf */
+    return UNSIGNED_INF;
+  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_INF)
+            && REAL_VALUES_IDENTICAL(op1,POSITIVE_ZERO)) /* +inf / +0 = +inf */
+           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_INF)
+               && REAL_VALUES_IDENTICAL(op1,NEGATIVE_ZERO))) /* -inf / -0 = +inf */
+    return POSITIVE_INF;
+  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_INF)
+            && REAL_VALUES_IDENTICAL(op1,NEGATIVE_ZERO)) /* +inf / -0 = -inf */
+           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_INF)
+               && REAL_VALUES_IDENTICAL(op1,POSITIVE_ZERO))) /* -inf / +0 = -inf */
+    return NEGATIVE_INF;
+  /* Now we can assume that at least 1 of op0 and 1/op1 is finite, and that we
+     don't have op0 = unsigned inf, op1 = unsigned 0, a NAN or an inf/inf or 0/0
+     indeterminate form. */
+  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_INF)
+            && REAL_VALUE_ISPOSITIVE(op1)) /* +inf / +non-0 = +inf */
+           || (REAL_VALUE_ISPOSITIVE(op0)
+               && REAL_VALUES_IDENTICAL(op1,POSITIVE_ZERO)) /* +finite / +0 = +inf */
+           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_INF)
+               && REAL_VALUE_ISNEGATIVE(op1)) /* -inf / -non-0 = +inf */
+           || (REAL_VALUE_ISNEGATIVE(op0)
+               && REAL_VALUES_IDENTICAL(op1,NEGATIVE_ZERO))) /* -finite / -0 = +inf */
+    return POSITIVE_INF;
+  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_INF)
+            && REAL_VALUE_ISNEGATIVE(op1)) /* +inf / -non-0 = -inf */
+           || (REAL_VALUE_ISPOSITIVE(op0)
+               && REAL_VALUES_IDENTICAL(op1,NEGATIVE_ZERO)) /* +finite / -0 = -inf */
+           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_INF)
+               && REAL_VALUE_ISPOSITIVE(op1)) /* -inf / +non-0 = -inf */
+           || (REAL_VALUE_ISNEGATIVE(op0)
+               && REAL_VALUES_IDENTICAL(op1,POSITIVE_ZERO))) /* -finite / +0 = -inf */
+    return NEGATIVE_INF;
+  /* Now we can assume that both of op0 and 1/op1 are finite. */
+  else if (REAL_VALUES_IDENTICAL(op0,UNSIGNED_ZERO)
+           || REAL_VALUES_IDENTICAL(op1,UNSIGNED_INF)) /* unsigned 0 / non-0 =
+                                           finite / unsigned inf = unsigned 0 */
+    return UNSIGNED_ZERO;
+  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_ZERO)
+            && REAL_VALUES_IDENTICAL(op1,POSITIVE_INF)) /* +0 / +inf = +0 */
+           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_ZERO)
+               && REAL_VALUES_IDENTICAL(op1,NEGATIVE_INF))) /* -0 / -inf = +0 */
+    return POSITIVE_ZERO;
+  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_ZERO)
+            && REAL_VALUES_IDENTICAL(op1,NEGATIVE_INF)) /* +0 / -inf = -0 */
+           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_ZERO)
+               && REAL_VALUES_IDENTICAL(op1,POSITIVE_INF))) /* -0 / +inf = -0 */
+    return NEGATIVE_ZERO;
+  /* Now we can assume that both of op0 and 1/op1 are finite, at least 1 of them
+     is non-0, and that neither of them is an unsigned 0. */
+  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_ZERO)
+            && REAL_VALUE_ISPOSITIVE(op1)) /* +0 / +non-0 = +0 */
+           || (REAL_VALUE_ISPOSITIVE(op0)
+               && REAL_VALUES_IDENTICAL(op1,POSITIVE_INF)) /* +finite / +inf = +0 */
+           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_ZERO)
+               && REAL_VALUE_ISNEGATIVE(op1)) /* -0 / -non-0 = +0 */
+           || (REAL_VALUE_ISNEGATIVE(op0)
+               && REAL_VALUES_IDENTICAL(op1,NEGATIVE_INF))) /* -finite / -inf = +0 */
+    return POSITIVE_ZERO;
+  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_ZERO)
+            && REAL_VALUE_ISNEGATIVE(op1)) /* +0 / -non-0 = -0 */
+           || (REAL_VALUE_ISPOSITIVE(op0)
+               && REAL_VALUES_IDENTICAL(op1,NEGATIVE_INF)) /* +finite / -inf = -0 */
+           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_ZERO)
+               && REAL_VALUE_ISPOSITIVE(op1)) /* -0 / +non-0 = -0 */
+           || (REAL_VALUE_ISNEGATIVE(op0)
+               && REAL_VALUES_IDENTICAL(op1,POSITIVE_INF))) /* -finite / +inf = -0 */
+    return NEGATIVE_ZERO;
+  /* Now we can assume that both values are finite and non-0. */
+  else if (REAL_VALUE_ISPOSITIVE(op0) && REAL_VALUE_ISPOSITIVE(op1))
+    return bcdppdiv(op0,op1,exactresult);
+  else if (REAL_VALUE_ISPOSITIVE(op0)) /* and op1 negative */
+    return REAL_VALUE_NEGATE(bcdppdiv(op0,REAL_VALUE_NEGATE(op1),exactresult));
+  else if (REAL_VALUE_ISPOSITIVE(op1)) /* and op0 negative */
+    return REAL_VALUE_NEGATE(bcdppdiv(REAL_VALUE_NEGATE(op0),op1,exactresult));
+  else /* both negative */
+    return bcdppdiv(REAL_VALUE_NEGATE(op0),REAL_VALUE_NEGATE(op1),exactresult);
+}
+
+/* Compute min of 2 SMAP II BCD floats. */
+static smap_bcd_float bcdmin(smap_bcd_float op0, smap_bcd_float op1)
+{
+  if (REAL_VALUE_ISNANUINF(op0) || REAL_VALUE_ISNANUINF(op1)) /* keep NAN,
+                    UNSIGNED_INF is neither smaller nor larger than the other */
+    return NAN;
+  else if (REAL_VALUES_IDENTICAL(op0,NEGATIVE_INF)
+           || REAL_VALUES_IDENTICAL(op1,NEGATIVE_INF)) /* keep -infinity */
+    return NEGATIVE_INF;
+  else if (REAL_VALUES_IDENTICAL(op0,POSITIVE_INF)) /* all numbers are smaller
+                                                       than +infinity */
+    return op1;
+  else if (REAL_VALUES_IDENTICAL(op1,POSITIVE_INF)) /* all numbers are smaller
+                                                       than +infinity */
+    return op0;
+  /* Now, we can assume that all values are finite. */
+  else if (REAL_VALUES_LESS(op0,op1)) /* if op0<op1, return op0 */
+    return op0;
+  else /* if op0>=op1, return op1 */
+    return op1;
+}
+
+/* Compute max of 2 SMAP II BCD floats. */
+static smap_bcd_float bcdmax(smap_bcd_float op0, smap_bcd_float op1)
+{
+  if (REAL_VALUE_ISNANUINF(op0) || REAL_VALUE_ISNANUINF(op1)) /* keep NAN,
+                    UNSIGNED_INF is neither smaller nor larger than the other */
+    return NAN;
+  else if (REAL_VALUES_IDENTICAL(op0,POSITIVE_INF)
+           || REAL_VALUES_IDENTICAL(op1,POSITIVE_INF)) /* keep +infinity */
+    return POSITIVE_INF;
+  else if (REAL_VALUES_IDENTICAL(op0,NEGATIVE_INF)) /* all numbers are smaller
+                                                       than -infinity */
+    return op1;
+  else if (REAL_VALUES_IDENTICAL(op1,NEGATIVE_INF)) /* all numbers are smaller
+                                                       than -infinity */
+    return op0;
+  /* Now, we can assume that all values are finite. */
+  else if (REAL_VALUES_LESS(op0,op1)) /* if op0<op1, return op1 */
+    return op1;
+  else /* if op0>=op1, return op0 */
+    return op0;
+}
 
 /* Perform the binary or unary operation described by CODE.
    For a unary operation, leave OP1 NULL.  This function returns
@@ -982,6 +1593,37 @@
 real_arithmetic (REAL_VALUE_TYPE *r, int icode, const REAL_VALUE_TYPE *op0,
 		 const REAL_VALUE_TYPE *op1)
 {
+  switch (icode)
+    {
+    case PLUS_EXPR:
+      *r = bcdadd (*op0, *op1);
+      return true;
+
+    case MINUS_EXPR:
+      *r = bcdsub (*op0, *op1);
+      return true;
+
+    case MULT_EXPR:
+      *r = bcdmul (*op0, *op1);
+      return true;
+
+    case RDIV_EXPR:
+      *r = bcddiv (*op0, *op1, NULL);
+      return true;
+
+    case MIN_EXPR:
+      *r = bcdmin (*op0, *op1);
+      return false;
+
+    case MAX_EXPR:
+      *r = bcdmax (*op0, *op1);
+      return false;
+
+    default:
+      gcc_unreachable ();
+    }
+
+#if 0
   enum tree_code code = icode;
 
   switch (code)
@@ -1033,9 +1675,11 @@
     default:
       gcc_unreachable ();
     }
+#endif /* 0 */
   return false;
 }
 
+#if 0
 /* Legacy.  Similar, but return the result directly.  */
 
 REAL_VALUE_TYPE
@@ -1046,6 +1690,7 @@
   real_arithmetic (&r, icode, op0, op1);
   return r;
 }
+#endif /* 0 */
 
 bool
 real_compare (int icode, const REAL_VALUE_TYPE *op0,
@@ -1056,39 +1701,40 @@
   switch (code)
     {
     case LT_EXPR:
-      return do_compare (op0, op1, 1) < 0;
+      return REAL_VALUES_LESS (*op0, *op1);
     case LE_EXPR:
-      return do_compare (op0, op1, 1) <= 0;
+      return !real_compare (UNGT_EXPR, op0, op1);
     case GT_EXPR:
-      return do_compare (op0, op1, -1) > 0;
+      return real_compare (LT_EXPR, op1, op0);
     case GE_EXPR:
-      return do_compare (op0, op1, -1) >= 0;
+      return !real_compare (UNLT_EXPR, op0, op1);
     case EQ_EXPR:
-      return do_compare (op0, op1, -1) == 0;
+      return REAL_VALUES_EQUAL (*op0, *op1);
     case NE_EXPR:
-      return do_compare (op0, op1, -1) != 0;
+      return !real_compare (EQ_EXPR, op0, op1);
     case UNORDERED_EXPR:
-      return op0->cl == rvc_nan || op1->cl == rvc_nan;
+      return REAL_VALUE_ISNANUINF (*op0) || REAL_VALUE_ISNANUINF (*op1);
     case ORDERED_EXPR:
-      return op0->cl != rvc_nan && op1->cl != rvc_nan;
+      return !real_compare (UNORDERED_EXPR, op0, op1);
     case UNLT_EXPR:
-      return do_compare (op0, op1, -1) < 0;
+      return real_compare (UNORDERED_EXPR, op0, op1) || real_compare (LT_EXPR, op0, op1);
     case UNLE_EXPR:
-      return do_compare (op0, op1, -1) <= 0;
+      return !real_compare (GT_EXPR, op0, op1);
     case UNGT_EXPR:
-      return do_compare (op0, op1, 1) > 0;
+      return real_compare (UNORDERED_EXPR, op0, op1) || real_compare (GT_EXPR, op0, op1);
     case UNGE_EXPR:
-      return do_compare (op0, op1, 1) >= 0;
+      return !real_compare (LT_EXPR, op0, op1);
     case UNEQ_EXPR:
-      return do_compare (op0, op1, 0) == 0;
+      return real_compare (UNORDERED_EXPR, op0, op1) || real_compare (EQ_EXPR, op0, op1);
     case LTGT_EXPR:
-      return do_compare (op0, op1, 0) != 0;
+      return !real_compare (UNEQ_EXPR, op0, op1);
 
     default:
       gcc_unreachable ();
     }
 }
 
+#if 0
 /* Return floor log2(R).  */
 
 int
@@ -1209,6 +1855,7 @@
 
   return true;
 }
+#endif /* 0 */
 
 /* Try to change R into its exact multiplicative inverse in machine
    mode MODE.  Return true if successful.  */
@@ -1216,6 +1863,13 @@
 bool
 exact_real_inverse (enum machine_mode mode, REAL_VALUE_TYPE *r)
 {
+  int exactresult=0;
+  smap_bcd_float one={0x4000,0x1000000000000000ull}, invr;
+
+  invr = bcddiv(one,*r,&exactresult);
+  if (exactresult) *r=invr;
+  return exactresult;
+#if 0
   const REAL_VALUE_TYPE *one = real_digit (1);
   REAL_VALUE_TYPE u;
   int i;
@@ -1245,8 +1899,10 @@
 
   *r = u;
   return true;
+#endif /* 0 */
 }
 
+#if 0
 /* Render R as an integer.  */
 
 HOST_WIDE_INT
@@ -1298,6 +1954,7 @@
       gcc_unreachable ();
     }
 }
+#endif /* 0 */
 
 /* Likewise, but to an integer pair, HI+LOW.  */
 
@@ -1305,6 +1962,59 @@
 real_to_integer2 (HOST_WIDE_INT *plow, HOST_WIDE_INT *phigh,
 		  const REAL_VALUE_TYPE *r)
 {
+  unsigned short exponent = (r->exponent & 0x7fff);
+  unsigned HOST_WIDE_INT low = 0, high = 0;
+  int e, i;
+  unsigned long long mantissa = r->mantissa;
+
+  /* Return 0 for transfinite, zero or |*r|<1 */
+  if (!REAL_VALUE_ISFINITE(*r) || REAL_VALUE_ISZERO(*r) || exponent < 0x4000) {
+    *plow = *phigh = 0;
+    return;
+  }
+
+  /* Compute the effective exponent */
+  e = (int)exponent - (0x4000+15);
+
+  /* Delete any digits following the decimal point right now */
+  if (e < 0) {
+    mantissa >>= ((-e)<<2);
+    e = 0;
+  } else if (e > 2*HOST_BITS_PER_WIDE_INT) {
+    /* We'll multiply by 10^(2*HBPWI)=5^(2*HBPWI)*2^(2*HBPWI). This will zero
+       out all digits. So avoid the long loop and return 0 right now. */
+    *plow = *phigh = 0;
+    return;
+  }
+
+  /* Convert the mantissa from BCD to binary */
+  for (i=60;i>=0;i-=4) {
+    /* Multiply by 10 using x*10=(x<<3)+(x<<1) */
+    high = (high<<3) + (low>>(HOST_BITS_PER_WIDE_INT-3)) /* (x<<3) */
+           + (high<<1) + (low>>(HOST_BITS_PER_WIDE_INT-1)) /* (x<<1) */
+           + ((low<<3) + (low<<1) < (low<<1)); /* (carry) */
+    low = (low<<3) + (low<<1);
+    low += (mantissa>>i)&15;
+  }
+
+  /* Multiply by 10^e */
+  for (i=0;i<e;i++) {
+    /* Multiply by 10 using x*10=(x<<3)+(x<<1) */
+    high = (high<<3) + (low>>(HOST_BITS_PER_WIDE_INT-3)) /* (x<<3) */
+           + (high<<1) + (low>>(HOST_BITS_PER_WIDE_INT-1)) /* (x<<1) */
+           + ((low<<3) + (low<<1) < (low<<1)); /* (carry) */
+    low = (low<<3) + (low<<1);
+  }
+
+  /* Negate the result if *r was negative */
+  if (r->exponent >= 0x8000) {
+	if (low == 0)
+	  high = -high;
+	else
+	  low = -low, high = ~high;
+  }
+
+#if 0
   REAL_VALUE_TYPE t;
   HOST_WIDE_INT low, high;
   int exp;
@@ -1370,11 +2080,13 @@
     default:
       gcc_unreachable ();
     }
+#endif /* 0 */
 
   *plow = low;
   *phigh = high;
 }
 
+#if 0
 /* A subroutine of real_to_decimal.  Compute the quotient and remainder
    of NUM / DEN.  Return the quotient and place the remainder in NUM.
    It is expected that NUM / DEN are close enough that the quotient is
@@ -1749,6 +2461,326 @@
 
   sprintf (p, "p%+d", exp);
 }
+#endif /* 0 */
+
+static void real_value_dtof (REAL_VALUE_TYPE *r, const char *string)
+{
+	const char *strpart = string;
+	unsigned char state = 0;
+	unsigned long long mpmul = 0x1000000000000000ull;
+	signed short expshift = -1;
+	unsigned short exp = 0;
+	unsigned short expmul = 1;
+	unsigned short expadd = 0;
+	int endrounding = -1;
+	r->mantissa = 0;
+	while (strpart && *strpart)
+	{
+		switch (state)
+		{
+			case 0:
+				if (*strpart == '.')
+				{
+					state = 1;
+					break;
+				}
+				else if (*strpart == '+')
+					expadd = 0;
+				else if (*strpart == '-')
+					expadd = 0x8000;
+				else if (((*strpart) >= '0' && (*strpart) <= '9') && ((r->mantissa) || (*strpart != '0')))
+					expshift++;
+				else if ((*strpart == 'i') || (*strpart == 'I'))
+				{
+					if (expadd == 0x8000)
+						*r = NEGATIVE_INF;
+					else
+						*r = POSITIVE_INF;
+					expadd = 0x3FFF;
+					strpart = 0;
+				}
+				else if ((*strpart == 'n') || (*strpart == 'N'))
+				{
+					*r = NAN;
+					expadd = 0x3FFF;
+					strpart = 0;
+				}
+			case 1:
+				if ((*strpart == 'e') || (*strpart == 'E'))
+					state = 2;
+				else if ((*strpart) >= '0' && (*strpart) <= '9')
+				{
+					if (mpmul)
+						r->mantissa |= (*strpart - '0') * mpmul;
+					else if (endrounding < 0)
+						endrounding = (*strpart >= '5');
+					if (r->mantissa)
+						mpmul /= 0x10;
+					else if (state)
+						expshift--;
+				}
+				break;
+			case 2:
+				if (*strpart == '+')
+					expmul = 1;
+				else if (*strpart == '-')
+					expmul = -1;
+				if ((*strpart) >= '0' && (*strpart) <= '9')
+				{
+					exp *= 10;
+					exp += (*strpart - '0');
+				}
+				break;
+		}
+		if (strpart)
+			strpart++;
+		else
+			break;
+	}
+	if (!(r->mantissa))
+		*r = ZERO;
+	else if (expadd != 0x3FFF)
+	{
+		r->exponent = exp * expmul + 0x4000 + expshift;
+		if (r->exponent>0x4000+16383) /* exponent too large, overflow to +infinity */
+			*r = POSITIVE_INF;
+		else if (r->exponent<0x4000-16383) /* exponent too small, underflow to +0 */
+			*r = POSITIVE_ZERO;
+		else if (endrounding > 0)
+			bcdpadd1ulp (r);
+		r->exponent += expadd;
+	}
+}
+
+typedef struct {
+  int ndigits;
+  unsigned char *digits;
+  long effexp;
+} arbprec_decimal;
+
+static void arbprec_pack (arbprec_decimal *r)
+{
+  unsigned char *p = r->digits;
+  if (r->ndigits) {
+    while (p < r->digits + r->ndigits && !*p) p++;
+    r->ndigits -= p - r->digits;
+    memmove (r->digits, p, r->ndigits);
+    if (r->ndigits) {
+      p = r->digits + r->ndigits - 1;
+      while (p > r->digits && !*p) {
+        p--;
+        r->effexp++;
+      }
+      r->ndigits = (p + 1) - r->digits;
+    }
+    r->digits = xrealloc (r->digits, r->ndigits);
+  }
+}
+
+static void arbprec_mul2 (arbprec_decimal *r)
+{
+  unsigned char *p;
+  unsigned char carry = 0;
+  r->ndigits++;
+  r->digits = xrealloc (r->digits, r->ndigits);
+  for (p = r->digits + r->ndigits - 1; p > r->digits; p--) {
+    unsigned char digit = (p[-1]<<1) + carry;
+    *p = digit % 10;
+    carry = digit / 10;
+  }
+  *p = carry;
+  arbprec_pack (r);
+}
+
+static void arbprec_div2 (arbprec_decimal *r)
+{
+  unsigned char *p;
+  unsigned char carry = 0;
+  r->ndigits++;
+  r->digits = xrealloc (r->digits, r->ndigits);
+  for (p = r->digits; p < r->digits + r->ndigits - 1; p++) {
+    unsigned char digit = (*p>>1) + carry;
+    carry = (*p&1)*5;
+    *p = digit;
+  }
+  *p = carry;
+  r->effexp--;
+  arbprec_pack (r);
+}
+
+static void arbprec_mul16 (arbprec_decimal *r)
+{
+  arbprec_mul2 (r);
+  arbprec_mul2 (r);
+  arbprec_mul2 (r);
+  arbprec_mul2 (r);
+}
+
+static void arbprec_div16 (arbprec_decimal *r)
+{
+  arbprec_div2 (r);
+  arbprec_div2 (r);
+  arbprec_div2 (r);
+  arbprec_div2 (r);
+}
+
+static void arbprec_add (arbprec_decimal *r1, arbprec_decimal *r2)
+{
+  if (!r2->ndigits)
+    return;
+  else if (!r1->ndigits) {
+    r1->digits = xrealloc (r1->digits, r2->ndigits);
+    memcpy (r1->digits, r2->digits, r2->ndigits);
+    r1->ndigits = r2->ndigits;
+    r1->effexp = r2->effexp;
+  } else {
+    if (r1->effexp > r2->effexp) {
+      long effexpdiff = r1->effexp - r2->effexp;
+      r1->digits = xrealloc (r1->digits, r1->ndigits + effexpdiff);
+      memset (r1->digits + r1->ndigits, 0, effexpdiff);
+      r1->ndigits += effexpdiff;
+      r1->effexp = r2->effexp;
+    } else if (r2->effexp > r1->effexp) {
+      long effexpdiff = r2->effexp - r1->effexp;
+      r2->digits = xrealloc (r2->digits, r2->ndigits + effexpdiff);
+      memset (r2->digits + r2->ndigits, 0, effexpdiff);
+      r2->ndigits += effexpdiff;
+      r2->effexp = r1->effexp;
+    }
+
+    {
+      int ndigits = MAX (r1->ndigits, r2->ndigits) + 1;
+      unsigned char *digits = xmalloc (ndigits);
+      unsigned char *p, *q1, *q2;
+      unsigned char carry = 0;
+      for (p = digits + ndigits - 1, q1 = r1->digits + r1->ndigits - 1,
+           q2 = r2->digits + r2->ndigits - 1; p > digits; p--, q1--, q2--) {
+        unsigned char digit = (q1>=r1->digits?*q1:0) + (q2>=r2->digits?*q2:0)
+                              + carry;
+        *p = digit % 10;
+        carry = digit / 10;
+      }
+      *p = carry;
+      free (r1->digits);
+      r1->digits = digits;
+      r1->ndigits = ndigits;
+      arbprec_pack (r1);
+      arbprec_pack (r2);
+    }
+  }
+}
+
+static void arbprec_add_n_times (arbprec_decimal *r1, arbprec_decimal *r2, int n)
+{
+  int i;
+  for (i = 0; i < n; i++) arbprec_add (r1, r2);
+}
+
+static void arbprec_to_bcd (arbprec_decimal *a, smap_bcd_float *r)
+{
+  if (a->ndigits) {
+    long exponent = a->effexp + a->ndigits - 1;
+    if (exponent>16383) /* exponent too large, overflow to +infinity */
+      *r = POSITIVE_INF;
+    else if (exponent<-16383) /* exponent too small, underflow to +0 */
+      *r = POSITIVE_ZERO;
+    else {
+      int i;
+      r->exponent = 0x4000 + exponent;
+      r->mantissa = 0;
+      for (i = 0; i < a->ndigits && i < 16; i++) {
+        r->mantissa = (r->mantissa << 4) + a->digits[i];
+      }
+      for (; i < 16; i++) {
+        r->mantissa <<= 4;
+      }
+      if (a->ndigits > 16 && a->digits[16] >= 5)
+        bcdpadd1ulp (r);
+    }
+  } else {
+    *r = UNSIGNED_ZERO;
+  }
+}
+
+static void real_value_htof (REAL_VALUE_TYPE *res, const char *string)
+{
+	arbprec_decimal r = {0, NULL, 0};
+	const char *strpart = string;
+	signed char state = -1;
+	arbprec_decimal rdiv = {1, NULL, 0};
+	unsigned int negative = 0;
+	unsigned short exp = 0;
+	unsigned short expsign = 1;
+	rdiv.digits = xmalloc (1);
+	*(rdiv.digits) = 1;
+	while (strpart && *strpart)
+	{
+		switch (state)
+		{
+			case -1:
+				if (*strpart == 'x' || *strpart == 'X')
+					state = 0;
+				else if (*strpart == '+')
+					negative = 0;
+				else if (*strpart == '-')
+					negative = 1;
+				break;
+			case 0:
+				if (*strpart == '.')
+				{
+					state = 1;
+					break;
+				}
+				else if ((*strpart >= '0' && *strpart <= '9') || (*strpart >= 'a' && *strpart <= 'f') || (*strpart >= 'A' && *strpart <= 'F'))
+					arbprec_mul16 (&r);
+			case 1:
+				if (state == 1)
+					arbprec_div16 (&rdiv);
+				if ((*strpart == 'p') || (*strpart == 'P'))
+					state = 2;
+				else if (*strpart >= '0' && *strpart <= '9')
+					arbprec_add_n_times (&r, &rdiv, (*strpart - '0'));
+				else if (*strpart >= 'a' && *strpart <= 'f')
+					arbprec_add_n_times (&r, &rdiv, (*strpart - 'a' + 0xA));
+				else if (*strpart >= 'A' && *strpart <= 'F')
+					arbprec_add_n_times (&r, &rdiv, (*strpart - 'A' + 0xA));
+				break;
+			case 2:
+				if (*strpart == '+')
+					expsign = 1;
+				else if (*strpart == '-')
+					expsign = -1;
+				if ((*strpart) >= '0' && (*strpart) <= '9')
+				{
+					exp *= 10;
+					exp += (*strpart - '0');
+				}
+				break;
+		}
+		strpart++;
+	}
+	free (rdiv.digits);
+	if (expsign == 1)
+	{
+		while (exp)
+		{
+			arbprec_mul2 (&r);
+			exp--;
+		}
+	}
+	else
+	{
+		while (exp)
+		{
+			arbprec_div2 (&r);
+			exp--;
+		}
+	}
+	arbprec_to_bcd (&r, res);
+	free (r.digits);
+	if (negative)
+		*res = REAL_VALUE_NEGATE (*res);
+}
 
 /* Initialize R from a decimal or hexadecimal string.  The string is
    assumed to have been syntax checked already.  */
@@ -1756,6 +2788,17 @@
 void
 real_from_string (REAL_VALUE_TYPE *r, const char *str)
 {
+  const char *p = str;
+
+  if (*p == '-' || *p == '+')
+    p++;
+
+  if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
+    real_value_htof (r, str);
+  else
+    real_value_dtof (r, str);
+
+#if 0
   int exp = 0;
   bool sign = false;
 
@@ -1941,6 +2984,7 @@
  overflow:
   get_inf (r, sign);
   return;
+#endif /* 0 */
 }
 
 /* Legacy.  Similar, but return the result directly.  */
@@ -1964,6 +3008,67 @@
 		   unsigned HOST_WIDE_INT low, HOST_WIDE_INT high,
 		   int unsigned_p)
 {
+  int j, e = -1, lastdigit = 0;
+  bool negative = high < 0 && !unsigned_p;
+  unsigned HOST_WIDE_INT uhigh = (unsigned HOST_WIDE_INT)high;
+  unsigned HOST_WIDE_INT ulow = low;
+  unsigned HOST_WIDE_INT remainderh, remainderl, divisorh, divisorl;
+  unsigned long long mantissa = 0;
+
+  if (negative) {
+    uhigh = ~uhigh;
+    if (!ulow) uhigh++; else ulow = -ulow;
+  }
+
+  /* Convert the integer to BCD */
+  while (uhigh || ulow) {
+    remainderh = uhigh; remainderl = ulow;
+    divisorl = uhigh = ulow = 0;
+    divisorh = (HOST_WIDE_INT)10<<(HOST_BITS_PER_WIDE_INT-4);
+    /* Divide the pair of HOST_WIDE_INTs by 10 */
+    for (j=2*HOST_BITS_PER_WIDE_INT-4;j>=0;j--) {
+      /* Shift the result to the left. */
+      uhigh = (uhigh<<1) + (ulow>>(HOST_BITS_PER_WIDE_INT-1));
+      ulow <<= 1;
+      /* Check if the divisor 10 fits into the dividend. */
+      if (divisorh<remainderh || (divisorh==remainderh && divisorl<=remainderl)) {
+        /* Add 1 to the result. */
+        ulow++;
+        if (!ulow) uhigh++; /* handle carry */
+        /* Subtract the divisor from the dividend. */
+        if (remainderl<divisorl) /* handle carry, use unsigned wraparound overflow */
+          remainderh--;
+        remainderl -= divisorl; /* now do the subtraction */
+        remainderh -= divisorh;
+      }
+      if (j) {
+        /* Shift the divisor to the right. */
+        divisorl = ((divisorh&1)<<(HOST_BITS_PER_WIDE_INT-1))+(divisorl>>1);
+        divisorh >>= 1;
+      }
+    }
+    e++;
+    lastdigit = (mantissa&15);
+    mantissa = (mantissa>>4) + ((unsigned long long)remainderl<<60);
+  }
+
+  if (e >= 0) {
+    /* We have a nonnegative exponent. Do the correct rounding for the last
+       digit. */
+
+    r->exponent = e+0x4000;
+    r->mantissa = mantissa;
+
+    if (lastdigit >= 5) bcdpadd1ulp(r);
+  } else {
+    /* We don't have any digit, so our number is actually zero. */
+    *r = UNSIGNED_ZERO;
+  }
+
+  /* Negate *r if the integer was negative */
+  if (negative) *r = REAL_VALUE_NEGATE (*r);
+
+#if 0
   if (low == 0 && high == 0)
     get_zero (r, 0);
   else
@@ -2001,8 +3106,10 @@
 
   if (mode != VOIDmode)
     real_convert (r, mode, r);
+#endif /* 0 */
 }
 
+#if 0
 /* Returns 10**2**N.  */
 
 static const REAL_VALUE_TYPE *
@@ -2490,6 +3597,7 @@
 
   return fmt->p * fmt->log2_b;
 }
+#endif /* 0 */
 
 /* Return a hash value for the given real value.  */
 /* ??? The "unsigned int" return value is intended to be hashval_t,
@@ -2498,6 +3606,12 @@
 unsigned int
 real_hash (const REAL_VALUE_TYPE *r)
 {
+  /* (TIGCC) Very naive hash for lack of something better. -- Kevin Kofler */
+  unsigned int h=r->exponent;
+  return h+(unsigned int)(r->mantissa >>
+                          ((sizeof(unsigned long long)-sizeof(unsigned int))*8));
+
+#if 0
   unsigned int h;
   size_t i;
 
@@ -2534,8 +3648,10 @@
       h ^= r->sig[i];
 
   return h;
+#endif /* 0 */
 }
 
+#if 0
 /* IEEE single-precision format.  */
 
 static void encode_ieee_single (const struct real_format *fmt,
@@ -4705,4 +5821,5 @@
 {
   r->sign = x->sign;
 }
+#endif /* 0 */
 
diff -Naur gcc-4.1.2.orig/gcc/real.h gcc-4.1.2-src/gcc/real.h
--- gcc-4.1.2.orig/gcc/real.h	2005-08-01 23:16:31.000000000 +0200
+++ gcc-4.1.2-src/gcc/real.h	2007-02-19 02:32:34.000000000 +0100
@@ -22,6 +22,22 @@
 #ifndef GCC_REAL_H
 #define GCC_REAL_H
 
+/* (TIGCC) smapbcd.h need this, but gengtype needs it to be in this file. */
+/* (TIGCC) Hack to make gengtype shut up while still packing the structure. */
+#define exponent exponent __attribute__((packed))
+#define mantissa mantissa __attribute__((packed))
+__attribute__ ((packed))
+struct real_value GTY(())
+{
+	unsigned short exponent;
+	unsigned long long mantissa;
+};
+#undef exponent
+#undef mantissa
+
+#include <config/smapbcd.h>
+#define SMAP_BCD_FLOAT_FORMAT 5
+
 #include "machmode.h"
 
 /* An expanded form of the represented number.  */
@@ -40,19 +56,22 @@
 #define SIGSZ			(SIGNIFICAND_BITS / HOST_BITS_PER_LONG)
 #define SIG_MSB			((unsigned long)1 << (HOST_BITS_PER_LONG - 1))
 
+/*
 struct real_value GTY(())
 {
-  /* Use the same underlying type for all bit-fields, so as to make
+  ** Use the same underlying type for all bit-fields, so as to make
      sure they're packed together, otherwise REAL_VALUE_TYPE_SIZE will
-     be miscomputed.  */
-  unsigned int /* ENUM_BITFIELD (real_value_class) */ cl : 2;
+     be miscomputed.  **
+  unsigned int ** ENUM_BITFIELD (real_value_class) ** cl : 2;
   unsigned int sign : 1;
   unsigned int signalling : 1;
   unsigned int canonical : 1;
   unsigned int uexp : EXP_BITS;
   unsigned long sig[SIGSZ];
 };
-
+*/
+  
+#if 0
 #define REAL_EXP(REAL) \
   ((int)((REAL)->uexp ^ (unsigned int)(1 << (EXP_BITS - 1))) \
    - (1 << (EXP_BITS - 1)))
@@ -76,6 +95,9 @@
 /* Verify the guess.  */
 extern char test_real_width
   [sizeof(REAL_VALUE_TYPE) <= REAL_WIDTH*sizeof(HOST_WIDE_INT) ? 1 : -1];
+#endif /* 0 */
+
+#define REAL_WIDTH (11*8 + HOST_BITS_PER_WIDE_INT)/HOST_BITS_PER_WIDE_INT
 
 /* Calculate the format for CONST_DOUBLE.  We need as many slots as
    are necessary to overlay a REAL_VALUE_TYPE on them.  This could be
@@ -111,6 +133,7 @@
 #endif
 
 
+#if 0
 /* Describes the properties of the specific target format in use.  */
 struct real_format
 {
@@ -167,6 +190,7 @@
    case compile-time FP overflow may not model run-time overflow.  */
 #define REAL_MODE_FORMAT_COMPOSITE_P(MODE) \
 	((REAL_MODE_FORMAT(MODE))->pnan < (REAL_MODE_FORMAT (MODE))->p)
+#endif /* 0 */
 
 /* Declare functions in real.c.  */
 
@@ -177,6 +201,7 @@
 /* Compare reals by tree_code.  */
 extern bool real_compare (int, const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
 
+#if 0
 /* Determine whether a floating-point value X is infinite.  */
 extern bool real_isinf (const REAL_VALUE_TYPE *);
 
@@ -209,6 +234,7 @@
 
 /* Render R as an integer.  */
 extern HOST_WIDE_INT real_to_integer (const REAL_VALUE_TYPE *);
+#endif /* 0 */
 extern void real_to_integer2 (HOST_WIDE_INT *, HOST_WIDE_INT *,
 			      const REAL_VALUE_TYPE *);
 
@@ -219,6 +245,7 @@
 extern void real_from_integer (REAL_VALUE_TYPE *, enum machine_mode,
 			       unsigned HOST_WIDE_INT, HOST_WIDE_INT, int);
 
+#if 0
 extern long real_to_target_fmt (long *, const REAL_VALUE_TYPE *,
 				const struct real_format *);
 extern long real_to_target (long *, const REAL_VALUE_TYPE *, enum machine_mode);
@@ -235,10 +262,12 @@
 extern void real_maxval (REAL_VALUE_TYPE *, int, enum machine_mode);
 
 extern void real_2expN (REAL_VALUE_TYPE *, int);
+#endif /* 0 */
 
 extern unsigned int real_hash (const REAL_VALUE_TYPE *);
 
 
+#if 0
 /* Target formats defined in real.c.  */
 extern const struct real_format ieee_single_format;
 extern const struct real_format mips_single_format;
@@ -318,9 +347,11 @@
   real_arithmetic2 (ABS_EXPR, &(X), NULL)
 
 extern int significand_size (enum machine_mode);
+#endif /* 0 */
 
 extern REAL_VALUE_TYPE real_from_string2 (const char *, enum machine_mode);
 
+#if 0
 #define REAL_VALUE_ATOF(s, m) \
   real_from_string2 (s, m)
 
@@ -343,6 +374,7 @@
 extern void real_ldexp (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, int);
 
 /* **** End of software floating point emulator interface macros **** */
+#endif /* 0 */
 
 /* Constant real values 0, 1, 2, 3, 10, -1, -2, 0.5 and 1/3.  */
 
@@ -355,8 +387,10 @@
 extern REAL_VALUE_TYPE dconstm2;
 extern REAL_VALUE_TYPE dconsthalf;
 extern REAL_VALUE_TYPE dconstthird;
+#if 0
 extern REAL_VALUE_TYPE dconstpi;
 extern REAL_VALUE_TYPE dconste;
+#endif /* 0 */
 
 /* Function to return a real value (not a tree node)
    from a given integer constant.  */
@@ -377,6 +411,7 @@
 /* In tree.c: wrap up a REAL_VALUE_TYPE in a tree node.  */
 extern tree build_real (tree, REAL_VALUE_TYPE);
 
+#if 0
 /* Calculate R as the square root of X in the given machine mode.  */
 extern bool real_sqrt (REAL_VALUE_TYPE *, enum machine_mode,
 		       const REAL_VALUE_TYPE *);
@@ -397,5 +432,6 @@
 
 /* Set the sign of R to the sign of X.  */
 extern void real_copysign (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
+#endif /* 0 */
 
 #endif /* ! GCC_REAL_H */
diff -Naur gcc-4.1.2.orig/gcc/rtlanal.c gcc-4.1.2-src/gcc/rtlanal.c
--- gcc-4.1.2.orig/gcc/rtlanal.c	2006-12-16 20:24:56.000000000 +0100
+++ gcc-4.1.2-src/gcc/rtlanal.c	2007-02-19 02:49:27.000000000 +0100
@@ -3164,6 +3164,19 @@
   if (offset == 0 || nregs_xmode == nregs_ymode)
     return 0;
 
+  /* (TIGCC 20050324) Subregs of a 10-byte mode are special, hardcode them. */
+  if (GET_MODE_SIZE (xmode) == 10)
+  {
+     gcc_assert (nregs_xmode == 3);
+
+     if (offset < 4)
+       return 0;
+     else if (offset < 8)
+       return 1;
+     else
+       return 2;
+  }
+
   /* Size of ymode must not be greater than the size of xmode.  */
   mode_multiple = GET_MODE_SIZE (xmode) / GET_MODE_SIZE (ymode);
   gcc_assert (mode_multiple != 0);
@@ -3237,6 +3250,28 @@
 	  ? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN))
     return true;
 
+  /* (TIGCC 20050324) Subregs of a 10-byte mode are special, hardcode them. */
+  if (GET_MODE_SIZE (xmode) == 10)
+  {
+     switch (GET_MODE_SIZE (ymode))
+     {
+       case 1:
+         return (offset == 3 || offset == 7 || offset == 9);
+
+       case 2:
+         return (offset == 2 || offset == 6 || offset == 8);
+
+       case 4:
+         return (offset == 0 || offset == 4);
+
+       case 8:
+         return !offset;
+
+       default:
+         return false;
+     }
+  }
+
   /* If registers store different numbers of bits in the different
      modes, we cannot generally form this subreg.  */
   regsize_xmode = GET_MODE_SIZE (xmode) / nregs_xmode;
diff -Naur gcc-4.1.2.orig/gcc/sdbout.c gcc-4.1.2-src/gcc/sdbout.c
--- gcc-4.1.2.orig/gcc/sdbout.c	2005-06-25 04:02:01.000000000 +0200
+++ gcc-4.1.2-src/gcc/sdbout.c	2007-02-19 02:32:34.000000000 +0100
@@ -1541,9 +1541,7 @@
 #ifdef SDB_OUTPUT_SOURCE_LINE
       SDB_OUTPUT_SOURCE_LINE (asm_out_file, line);
 #else
-      fprintf (asm_out_file, "\t.ln\t%d\n",
-	       ((sdb_begin_function_line > -1)
-		? line - sdb_begin_function_line : 1));
+      fprintf (asm_out_file, "\t.ln\t%d\n", line);
 #endif
     }
 }
diff -Naur gcc-4.1.2.orig/gcc/simplify-rtx.c gcc-4.1.2-src/gcc/simplify-rtx.c
--- gcc-4.1.2.orig/gcc/simplify-rtx.c	2006-08-11 09:52:01.000000000 +0200
+++ gcc-4.1.2-src/gcc/simplify-rtx.c	2007-02-19 02:32:34.000000000 +0100
@@ -494,13 +494,14 @@
 	 both +0, (minus Y X) is the same as (minus X Y).  If the
 	 rounding mode is towards +infinity (or -infinity) then the two
 	 expressions will be rounded differently.  */
+      /* (TIGCC 20050210) This identity is valid for us thanks to unsigned 0. */
       if (GET_CODE (op) == MINUS
-	  && !HONOR_SIGNED_ZEROS (mode)
+	  /*&& !HONOR_SIGNED_ZEROS (mode)*/
 	  && !HONOR_SIGN_DEPENDENT_ROUNDING (mode))
 	return simplify_gen_binary (MINUS, mode, XEXP (op, 1), XEXP (op, 0));
       
       if (GET_CODE (op) == PLUS
-	  && !HONOR_SIGNED_ZEROS (mode)
+	  /*&& !HONOR_SIGNED_ZEROS (mode)*/
 	  && !HONOR_SIGN_DEPENDENT_ROUNDING (mode))
 	{
 	  /* (neg (plus A C)) is simplified to (minus -C A).  */
@@ -701,7 +702,7 @@
 	lv = CONST_DOUBLE_LOW (op),  hv = CONST_DOUBLE_HIGH (op);
 
       REAL_VALUE_FROM_INT (d, lv, hv, mode);
-      d = real_value_truncate (mode, d);
+      d = REAL_VALUE_TRUNCATE (mode, d);
       return CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
     }
   else if (code == UNSIGNED_FLOAT && GET_MODE (op) == VOIDmode
@@ -729,7 +730,7 @@
 	hv = 0, lv &= GET_MODE_MASK (op_mode);
 
       REAL_VALUE_FROM_UNSIGNED_INT (d, lv, hv, mode);
-      d = real_value_truncate (mode, d);
+      d = REAL_VALUE_TRUNCATE (mode, d);
       return CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
     }
 
@@ -991,11 +992,7 @@
       switch (code)
 	{
 	case SQRT:
-	  if (HONOR_SNANS (mode) && real_isnan (&d))
-	    return 0;
-	  real_sqrt (&t, mode, &d);
-	  d = t;
-	  break;
+	  return 0;
 	case ABS:
 	  d = REAL_VALUE_ABS (d);
 	  break;
@@ -1003,7 +1000,7 @@
 	  d = REAL_VALUE_NEGATE (d);
 	  break;
 	case FLOAT_TRUNCATE:
-	  d = real_value_truncate (mode, d);
+	  d = REAL_VALUE_TRUNCATE (mode, d);
 	  break;
 	case FLOAT_EXTEND:
 	  /* All this does is change the mode.  */
@@ -1013,6 +1010,7 @@
 	  break;
 	case NOT:
 	  {
+#if 0
 	    long tmp[4];
 	    int i;
 
@@ -1020,6 +1018,11 @@
 	    for (i = 0; i < 4; i++)
 	      tmp[i] = ~tmp[i];
 	    real_from_target (&d, tmp, mode);
+#else
+	    /* (TIGCC 20050205) Use SMAP BCD representation directly. */
+	    d.exponent = ~d.exponent;
+	    d.mantissa = ~d.mantissa;
+#endif /* 0 */
 	    break;
 	  }
 	default:
@@ -1046,7 +1049,7 @@
       switch (code)
 	{
 	case FIX:
-	  if (REAL_VALUE_ISNAN (x))
+	  if (REAL_VALUE_ISNANUINF (x))
 	    return const0_rtx;
 
 	  /* Test against the signed upper bound.  */
@@ -1091,7 +1094,7 @@
 	  break;
 
 	case UNSIGNED_FIX:
-	  if (REAL_VALUE_ISNAN (x) || REAL_VALUE_NEGATIVE (x))
+	  if (REAL_VALUE_ISNANUINF (x) || REAL_VALUE_NEGATIVE (x))
 	    return const0_rtx;
 
 	  /* Test against the unsigned upper bound.  */
@@ -1438,8 +1441,10 @@
       /* Subtracting 0 has no effect unless the mode has signed zeros
 	 and supports rounding towards -infinity.  In such a case,
 	 0 - 0 is -0.  */
+      /* (TIGCC 20050210) This is invalid independently of the rounding mode
+                          for 3-sign-zeros. */
       if (!(HONOR_SIGNED_ZEROS (mode)
-	    && HONOR_SIGN_DEPENDENT_ROUNDING (mode))
+	    /*&& HONOR_SIGN_DEPENDENT_ROUNDING (mode)*/)
 	  && trueop1 == CONST0_RTX (mode))
 	return op0;
 
@@ -1575,8 +1580,11 @@
 	 x is NaN, since x * 0 is then also NaN.  Nor is it valid
 	 when the mode has signed zeros, since multiplying a negative
 	 number by 0 will give -0, not 0.  */
+      /* (TIGCC 20050210) We can do this for UNSIGNED_ZERO even when honoring
+                          signed zeros.
+         Note: CONST0_RTX (BFmode) is UNSIGNED_ZERO.  */
       if (!HONOR_NANS (mode)
-	  && !HONOR_SIGNED_ZEROS (mode)
+	  /*&& !HONOR_SIGNED_ZEROS (mode)*/
 	  && trueop1 == CONST0_RTX (mode)
 	  && ! side_effects_p (op0))
 	return op1;
@@ -2155,6 +2163,7 @@
 	  || code == IOR
 	  || code == XOR)
 	{
+#if 0
 	  long tmp0[4];
 	  long tmp1[4];
 	  REAL_VALUE_TYPE r;
@@ -2182,6 +2191,31 @@
 	      }
 	    }
 	   real_from_target (&r, tmp0, mode);
+#else
+	  /* (TIGCC 20050205) Use SMAP BCD representation directly. */
+	  const REAL_VALUE_TYPE *tmp1;
+	  REAL_VALUE_TYPE r;
+
+	  r = *CONST_DOUBLE_REAL_VALUE (op0);
+	  tmp1 = CONST_DOUBLE_REAL_VALUE (op1);
+	  switch (code)
+	    {
+	      case AND:
+	        r.exponent &= tmp1->exponent;
+	        r.mantissa &= tmp1->mantissa;
+	        break;
+	      case IOR:
+	        r.exponent |= tmp1->exponent;
+	        r.mantissa |= tmp1->mantissa;
+	        break;
+	      case XOR:
+	        r.exponent ^= tmp1->exponent;
+	        r.mantissa ^= tmp1->mantissa;
+	        break;
+	      default:
+	        gcc_unreachable ();
+	    }
+#endif /* 0 */
 	   return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
 	}
       else
@@ -2261,7 +2295,7 @@
 	  if ((flag_rounding_math
 	       || (REAL_MODE_FORMAT_COMPOSITE_P (mode)
 		   && !flag_unsafe_math_optimizations))
-	      && (inexact || !real_identical (&result, &value)))
+	      && (inexact || !REAL_VALUES_IDENTICAL (result, value)))
 	    return NULL_RTX;
 
 	  return CONST_DOUBLE_FROM_REAL_VALUE (result, mode);
@@ -3115,7 +3149,7 @@
       REAL_VALUE_FROM_CONST_DOUBLE (d1, trueop1);
 
       /* Comparisons are unordered iff at least one of the values is NaN.  */
-      if (REAL_VALUE_ISNAN (d0) || REAL_VALUE_ISNAN (d1))
+      if (REAL_VALUE_ISNANUINF (d0) || REAL_VALUE_ISNANUINF (d1))
 	switch (code)
 	  {
 	  case UNEQ:
@@ -3638,13 +3672,14 @@
 	    }
 	  else
 	    {
-	      long tmp[max_bitsize / 32];
+	      const REAL_VALUE_TYPE *tmp;
 	      int bitsize = GET_MODE_BITSIZE (GET_MODE (el));
 
 	      gcc_assert (GET_MODE_CLASS (GET_MODE (el)) == MODE_FLOAT);
 	      gcc_assert (bitsize <= elem_bitsize);
 	      gcc_assert (bitsize % value_bit == 0);
 
+#if 0
 	      real_to_target (tmp, CONST_DOUBLE_REAL_VALUE (el),
 			      GET_MODE (el));
 
@@ -3666,6 +3701,14 @@
 		 zero.  */
 	      for (; i < elem_bitsize; i += value_bit)
 		*vp++ = 0;
+#else
+	      /* (TIGCC 20050205) Use SMAP BCD representation directly. */
+	      tmp = CONST_DOUBLE_REAL_VALUE (el);
+	      *vp++ = tmp->exponent >> 8;
+	      *vp++ = tmp->exponent;
+	      for (i = 56; i >= 0; i -= 8)
+	        *vp++ = tmp->mantissa >> i;
+#endif /* 0 */
 	    }
 	  break;
 	  
@@ -3763,6 +3806,7 @@
 	case MODE_FLOAT:
 	  {
 	    REAL_VALUE_TYPE r;
+#if 0
 	    long tmp[max_bitsize / 32];
 	    
 	    /* real_from_target wants its input in words affected by
@@ -3782,6 +3826,14 @@
 	      }
 
 	    real_from_target (&r, tmp, outer_submode);
+#else
+	    /* (TIGCC 20050205) Use SMAP BCD representation directly. */
+	    r.exponent = (*vp++ << 8);
+	    r.exponent += *vp++;
+	    r.mantissa = *vp++;
+	    for (i = 0; i < 7; i++)
+	      r.mantissa = (r.mantissa << 8) + *vp++;
+#endif /* 0 */
 	    elems[elem] = CONST_DOUBLE_FROM_REAL_VALUE (r, outer_submode);
 	  }
 	  break;
diff -Naur gcc-4.1.2.orig/gcc/stmt.c gcc-4.1.2-src/gcc/stmt.c
--- gcc-4.1.2.orig/gcc/stmt.c	2006-05-29 08:50:07.000000000 +0200
+++ gcc-4.1.2-src/gcc/stmt.c	2007-02-19 02:32:34.000000000 +0100
@@ -2515,6 +2515,9 @@
 	  use_cost_table
 	    = (TREE_CODE (orig_type) != ENUMERAL_TYPE
 	       && estimate_case_costs (case_list));
+/* (TIGCC 20030907) Don't balance the tree when optimizing for size. A linear
+                    decision tree gives far smaller code. -- Kevin Kofler  */
+	  if (!optimize_size)
 	  balance_case_nodes (&case_list, NULL);
 	  emit_case_nodes (index, case_list, default_label, index_type);
 	  emit_jump (default_label);
@@ -3083,10 +3086,17 @@
 	     does not have any children and is single valued; it would
 	     cost too much space to save so little time.  */
 
+	  /* (TIGCC 20030907) Also omit the conditional branch to default if we are
+	                      optimizing for size. -- Kevin Kofler
+         (TIGCC 20040719) But don't omit branches which are needed for
+                          correctness in case ranges. -- Kevin Kofler  */
+
 	  if (node->right->right || node->right->left
 	      || !tree_int_cst_equal (node->right->low, node->right->high))
 	    {
-	      if (!node_has_low_bound (node, index_type))
+	      if (!node_has_low_bound (node, index_type)
+	          && (!optimize_size
+	              || !tree_int_cst_equal (node->right->low, node->right->high)))
 		{
 		  emit_cmp_and_jump_insns (index,
 					   convert_modes
diff -Naur gcc-4.1.2.orig/gcc/system.h gcc-4.1.2-src/gcc/system.h
--- gcc-4.1.2.orig/gcc/system.h	2005-08-16 02:13:53.000000000 +0200
+++ gcc-4.1.2-src/gcc/system.h	2007-02-19 02:32:34.000000000 +0100
@@ -732,7 +732,7 @@
 
 /* Hooks that are no longer used.  */
  #pragma GCC poison LANG_HOOKS_FUNCTION_MARK LANG_HOOKS_FUNCTION_FREE	\
-	LANG_HOOKS_MARK_TREE LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES \
+	LANG_HOOKS_MARK_TREE \
 	LANG_HOOKS_TREE_INLINING_ESTIMATE_NUM_INSNS \
 	LANG_HOOKS_PUSHLEVEL LANG_HOOKS_SET_BLOCK \
 	LANG_HOOKS_MAYBE_BUILD_CLEANUP LANG_HOOKS_UPDATE_DECL_AFTER_SAVING \
diff -Naur gcc-4.1.2.orig/gcc/toplev.c gcc-4.1.2-src/gcc/toplev.c
--- gcc-4.1.2.orig/gcc/toplev.c	2006-08-03 13:33:49.000000000 +0200
+++ gcc-4.1.2-src/gcc/toplev.c	2007-02-19 02:32:34.000000000 +0100
@@ -415,6 +415,15 @@
     }
 
   src_pwd = xstrdup (pwd);
+/* (TIGCC 20050420) Eliminate duplicate backslashes. */
+#ifdef __WIN32__
+  if (strstr (src_pwd, "\\\\"))
+    {
+      char *p = (char *)src_pwd;
+      while ((p = strstr (p, "\\\\")))
+        memmove (p, p + 1, strlen (p));
+    }
+#endif
   return true;
 }
 
@@ -1760,7 +1769,7 @@
       flag_prefetch_loop_arrays = 0;
     }
 
-#ifndef OBJECT_FORMAT_ELF
+#if 0 /*ndef OBJECT_FORMAT_ELF*/ /* (TIGCC 20040619) Remove pointless warning. */
   if (flag_function_sections && write_symbols != NO_DEBUG)
     warning (0, "-ffunction-sections may affect debugging on some targets");
 #endif
@@ -1783,6 +1792,11 @@
   if (!flag_stack_protect)
     warn_stack_protect = 0;
 
+#if 0 /* (TIGCC 20051224) The unwinding info may not be perfect, but it works
+         well enough for our purposes (remember we only need unwinding for
+         debugging, not EH). Forcing -fno-omit-frame-pointer, on the other
+         hand, really breaks things and defeats the entire purpose of
+         unwinding tables. -- Kevin Kofler */
   /* ??? Unwind info is not correct around the CFG unless either a frame
      pointer is present or A_O_A is set.  Fixing this requires rewriting
      unwind info generation to be aware of the CFG and propagating states
@@ -1794,6 +1808,7 @@
 	       "for correctness");
       flag_omit_frame_pointer = 0;
     }
+#endif /* 0 */
 }
 
 /* Initialize the compiler back end.  */
diff -Naur gcc-4.1.2.orig/gcc/tree.c gcc-4.1.2-src/gcc/tree.c
--- gcc-4.1.2.orig/gcc/tree.c	2007-01-05 21:59:15.000000000 +0100
+++ gcc-4.1.2-src/gcc/tree.c	2007-02-19 02:32:34.000000000 +0100
@@ -1373,7 +1373,7 @@
 
   return ((TREE_CODE (expr) == REAL_CST
 	   && ! TREE_CONSTANT_OVERFLOW (expr)
-	   && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst0))
+	   && REAL_VALUE_ISZERO (TREE_REAL_CST (expr)))
 	  || (TREE_CODE (expr) == COMPLEX_CST
 	      && real_zerop (TREE_REALPART (expr))
 	      && real_zerop (TREE_IMAGPART (expr))));
@@ -6623,17 +6623,14 @@
       return integer_zerop (init);
 
     case REAL_CST:
-      /* ??? Note that this is not correct for C4X float formats.  There,
-	 a bit pattern of all zeros is 1.0; 0.0 is encoded with the most
-	 negative exponent.  */
-      return real_zerop (init)
-	&& ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (init));
+      /* (TIGCC 20050210) For AMS, all zeros is POSITIVE_ZERO. This code tried
+         to use it for both POSITIVE_ZERO and UNSIGNED_ZERO. I fixed that. */
+      return REAL_VALUES_IDENTICAL (TREE_REAL_CST (init), POSITIVE_ZERO);
 
     case COMPLEX_CST:
       return integer_zerop (init)
-	|| (real_zerop (init)
-	    && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (TREE_REALPART (init)))
-	    && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (TREE_IMAGPART (init))));
+	|| (REAL_VALUES_IDENTICAL (TREE_REAL_CST (TREE_REALPART (init)), POSITIVE_ZERO)
+	    && REAL_VALUES_IDENTICAL (TREE_REAL_CST (TREE_IMAGPART (init)), POSITIVE_ZERO));
 
     case VECTOR_CST:
       for (elt = TREE_VECTOR_CST_ELTS (init); elt; elt = TREE_CHAIN (elt))
diff -Naur gcc-4.1.2.orig/gcc/tree.h gcc-4.1.2-src/gcc/tree.h
--- gcc-4.1.2.orig/gcc/tree.h	2007-02-09 03:52:53.000000000 +0100
+++ gcc-4.1.2-src/gcc/tree.h	2007-02-19 02:32:34.000000000 +0100
@@ -3497,6 +3497,7 @@
 /* Return an expr equal to X but certainly not valid as an lvalue.  */
 
 extern tree non_lvalue (tree);
+extern tree pedantic_non_lvalue (tree);
 
 extern tree convert (tree, tree);
 extern unsigned int expr_align (tree);
diff -Naur gcc-4.1.2.orig/gcc/tree-inline.c gcc-4.1.2-src/gcc/tree-inline.c
--- gcc-4.1.2.orig/gcc/tree-inline.c	2007-01-05 14:53:45.000000000 +0100
+++ gcc-4.1.2-src/gcc/tree-inline.c	2007-02-19 02:32:34.000000000 +0100
@@ -2078,6 +2078,48 @@
     verify_cgraph_node (cg_edge->callee);
 #endif
 
+  /* (TIGCC 20040926) The following code by Eric Botcazou fixes an ICE when
+     inlining tries to change the mode of parameters or the return value. Eric
+     Botcazou's comments explain the details.  -- Kevin Kofler  */
+  /* We can't inline functions at a calling point where they are viewed
+     with too different a prototype than the actual one, because the
+     calling convention may not be the same on both sides.  */
+  if (TREE_CODE (TREE_OPERAND (t, 0)) == NOP_EXPR)
+    {
+      tree from_ftype = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 0)));
+      tree to_ftype = TREE_TYPE (fn);
+
+      if (from_ftype != to_ftype)
+	{
+	  tree from_arg, to_arg;
+
+	  /* If the calling point expects a return value and it is too
+	     different from the one actually returned, don't inline.  */
+	  if (! VOID_TYPE_P (TREE_TYPE (from_ftype))
+	      && TYPE_MODE (TREE_TYPE (from_ftype))
+		 != TYPE_MODE (TREE_TYPE (to_ftype)))
+	    goto egress;
+
+	  /* If the calling point doesn't pass at least the correct
+	     number of arguments with the correct modes, don't inline.
+	     Objective-C appears to add a trailing void parameter at
+	     the calling point under certain circumstances.  */
+	  from_arg = TYPE_ARG_TYPES (from_ftype);
+	  to_arg = TYPE_ARG_TYPES (to_ftype);
+
+	  while (to_arg)
+	    {
+	      if (! from_arg
+		  || TYPE_MODE (TREE_VALUE (from_arg))
+		     != TYPE_MODE (TREE_VALUE (to_arg)))
+		goto egress;
+
+	      from_arg = TREE_CHAIN (from_arg);
+	      to_arg = TREE_CHAIN (to_arg);
+	    }
+	}
+    }
+
   /* We will be inlining this callee.  */
 
   id->eh_region = lookup_stmt_eh_region (stmt);
diff -Naur gcc-4.1.2.orig/gcc/tree-object-size.c gcc-4.1.2-src/gcc/tree-object-size.c
--- gcc-4.1.2.orig/gcc/tree-object-size.c	2005-07-03 18:11:42.000000000 +0200
+++ gcc-4.1.2-src/gcc/tree-object-size.c	2007-02-19 02:32:34.000000000 +0100
@@ -247,9 +247,11 @@
 	arg_mask = 2;
 	break;
 	*/
+#if 0 /* (TIGCC 20051221) */
       case BUILT_IN_CALLOC:
 	arg_mask = 3;
 	break;
+#endif /* 0 */
       default:
 	break;
       }
@@ -297,6 +299,7 @@
       case BUILT_IN_STRNCPY:
       case BUILT_IN_STRCAT:
       case BUILT_IN_STRNCAT:
+#if 0 /* (TIGCC 20051221) */
       case BUILT_IN_MEMCPY_CHK:
       case BUILT_IN_MEMMOVE_CHK:
       case BUILT_IN_MEMSET_CHK:
@@ -304,6 +307,7 @@
       case BUILT_IN_STRNCPY_CHK:
       case BUILT_IN_STRCAT_CHK:
       case BUILT_IN_STRNCAT_CHK:
+#endif /* 0 */
 	if (arglist)
 	  return TREE_VALUE (arglist);
 	break;
diff -Naur gcc-4.1.2.orig/gcc/tree-pretty-print.c gcc-4.1.2-src/gcc/tree-pretty-print.c
--- gcc-4.1.2.orig/gcc/tree-pretty-print.c	2005-07-31 22:55:41.000000000 +0200
+++ gcc-4.1.2-src/gcc/tree-pretty-print.c	2007-02-19 02:32:34.000000000 +0100
@@ -608,7 +608,7 @@
 	else
 	  {
 	    char string[100];
-	    real_to_decimal (string, &d, sizeof (string), 0, 1);
+	    REAL_VALUE_TO_STRING (d, string);
 	    pp_string (buffer, string);
 	  }
 #else
diff -Naur gcc-4.1.2.orig/gcc/tree-ssa-ccp.c gcc-4.1.2-src/gcc/tree-ssa-ccp.c
--- gcc-4.1.2.orig/gcc/tree-ssa-ccp.c	2005-11-22 17:56:48.000000000 +0100
+++ gcc-4.1.2-src/gcc/tree-ssa-ccp.c	2007-02-19 02:32:34.000000000 +0100
@@ -2123,6 +2123,7 @@
 static tree
 ccp_fold_builtin (tree stmt, tree fn)
 {
+#if 0 /* (TIGCC 20050205) */
   tree result, val[3];
   tree callee, arglist, a;
   int arg_mask, i, type;
@@ -2278,6 +2279,9 @@
   if (result && ignore)
     result = fold_ignored_result (result);
   return result;
+#else
+  return NULL_TREE;
+#endif /* 0 */
 }
 
 
diff -Naur gcc-4.1.2.orig/gcc/tree-ssa-dom.c gcc-4.1.2-src/gcc/tree-ssa-dom.c
--- gcc-4.1.2.orig/gcc/tree-ssa-dom.c	2006-11-17 10:01:31.000000000 +0100
+++ gcc-4.1.2-src/gcc/tree-ssa-dom.c	2007-02-19 02:32:34.000000000 +0100
@@ -2980,6 +2980,19 @@
 			|| TREE_CODE (stmt) == COND_EXPR
 			|| TREE_CODE (stmt) == SWITCH_EXPR));
 
+  /* (TIGCC 20050206) If -fno-function-cse, keep function call sequences in
+                      their expected form. */
+  if (flag_no_function_cse && may_optimize_p && TREE_CODE (stmt) == MODIFY_EXPR)
+    {
+      block_stmt_iterator bsi2 = si;
+      bsi_next (&bsi2);
+      if (!bsi_end_p (bsi2))
+        {
+          tree call = get_call_expr_in (bsi_stmt (bsi2));
+          if (call && TREE_OPERAND (stmt, 0) == TREE_OPERAND (call, 0)) may_optimize_p = false;
+        }
+    }
+
   if (may_optimize_p)
     may_have_exposed_new_symbols
       |= eliminate_redundant_computations (stmt, ann);
diff -Naur gcc-4.1.2.orig/gcc/tree-ssa-pre.c gcc-4.1.2-src/gcc/tree-ssa-pre.c
--- gcc-4.1.2.orig/gcc/tree-ssa-pre.c	2005-10-19 05:34:50.000000000 +0200
+++ gcc-4.1.2-src/gcc/tree-ssa-pre.c	2007-02-19 02:32:34.000000000 +0100
@@ -2394,6 +2394,19 @@
 	      tree *rhs_p = &TREE_OPERAND (stmt, 1);
 	      tree sprime;
 
+	      /* (TIGCC 20050216) If -fno-function-cse, keep function call sequences in
+	                          their expected form. */
+	      if (flag_no_function_cse)
+	        {
+	          block_stmt_iterator bsi2 = i;
+	          bsi_next (&bsi2);
+	          if (!bsi_end_p (bsi2))
+	            {
+	              tree call = get_call_expr_in (bsi_stmt (bsi2));
+	              if (call && TREE_OPERAND (stmt, 0) == TREE_OPERAND (call, 0)) continue;
+	            }
+	        }
+
 	      sprime = bitmap_find_leader (AVAIL_OUT (b),
 					   vn_lookup (lhs, NULL));
 	      if (sprime 
diff -Naur gcc-4.1.2.orig/gcc/varasm.c gcc-4.1.2-src/gcc/varasm.c
--- gcc-4.1.2.orig/gcc/varasm.c	2006-10-16 11:58:48.000000000 +0200
+++ gcc-4.1.2-src/gcc/varasm.c	2007-02-19 02:32:34.000000000 +0100
@@ -681,6 +681,26 @@
 			  unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED,
 			  unsigned int flags ATTRIBUTE_UNUSED)
 {
+/* (TIGCC 20040725) Implement string merging for TIGCC-extended COFF.
+                    We only handle 2 cases: aligned or unaligned.
+                    SECTION_STRINGS is abused for the unaligned flag. */
+  if (flag_merge_constants
+      && TREE_CODE (decl) == STRING_CST
+      && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
+    {
+      if (align == 8)
+        {
+          named_section_flags (".rodata.__unalignedstr", flags | SECTION_MERGE | SECTION_STRINGS);
+          return;
+        }
+      else if (align == 16)
+        {
+          named_section_flags (".rodata.__alignedstr", flags | SECTION_MERGE);
+          return;
+        }
+    }
+
+#if 0
   HOST_WIDE_INT len;
 
   if (HAVE_GAS_SHF_MERGE && flag_merge_constants
@@ -746,6 +766,7 @@
 	    }
 	}
     }
+#endif
 
   readonly_data_section ();
 }
@@ -757,6 +778,25 @@
 			    unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED,
 			    unsigned int flags ATTRIBUTE_UNUSED)
 {
+/* (TIGCC 20040725) Implement constant merging for TIGCC-extended COFF.
+                    We only handle 2 cases: aligned or unaligned.
+                    SECTION_STRINGS is abused for the unaligned flag. */
+  if (flag_merge_constants
+      && mode != VOIDmode)
+    {
+      if (align == 8)
+        {
+          named_section_flags (".rodata.__unalignedcst", flags | SECTION_MERGE | SECTION_STRINGS);
+          return;
+        }
+      else if (align == 16)
+        {
+          named_section_flags (".rodata.__alignedcst", flags | SECTION_MERGE);
+          return;
+        }
+    }
+
+#if 0
   unsigned int modesize = GET_MODE_BITSIZE (mode);
 
   if (HAVE_GAS_SHF_MERGE && flag_merge_constants
@@ -774,6 +814,7 @@
       named_section_flags (name, flags);
       return;
     }
+#endif
 
   readonly_data_section ();
 }
@@ -1051,12 +1092,25 @@
 void
 assemble_asm (tree string)
 {
+  /* (TIGCC 20050424) Emit proper .loc directives for top-level asm statements,
+     so GNU as won't try to make up its own and cause conflicts. */
+  if (debug_hooks == &dwarf2_debug_hooks)
+    (*debug_hooks->source_line) (input_location.line, input_location.file);
+
+  /* (TIGCC 20050424) Now switch to the text section, so the asm won't end up in
+                      some unknown section. */
+  text_section ();
+
   app_enable ();
 
   if (TREE_CODE (string) == ADDR_EXPR)
     string = TREE_OPERAND (string, 0);
 
   fprintf (asm_out_file, "\t%s\n", TREE_STRING_POINTER (string));
+
+  /* (TIGCC 20050424) And now forget the section we've set. There's no telling
+                      what section the asm switched to. */
+  in_section = no_section;
 }
 
 /* Record an element in the table of global destructors.  SYMBOL is
@@ -1536,9 +1590,18 @@
 	destination = asm_dest_common;
     }
 
-  if (destination != asm_dest_common)
+  /* (TIGCC 20050517) See below for why the TARGET_NO_BSS is necessary here. */
+  if (destination != asm_dest_common || (flag_data_sections && TARGET_NO_BSS))
     {
-      resolve_unique_section (decl, 0, flag_data_sections);
+      /* (TIGCC 20040620) Common symbols are handled by our linker as separate
+         sections, so there is no point in manually creating separate BSS sections
+         under -fdata-sections. The TARGET_NO_BSS check here is a hack (it should
+         not be in supposedly target-independent code), but it is necessary because
+         -mno-bss would otherwise compact everything into a single huge section.
+                                                              -- Kevin Kofler */
+      resolve_unique_section (decl, 0, flag_data_sections
+                                       && ((destination == asm_dest_bss)
+                                           || TARGET_NO_BSS));
       /* Custom sections don't belong here.  */
       if (DECL_SECTION_NAME (decl))
         return false;
@@ -1789,7 +1852,24 @@
     }
 
   /* Switch to the appropriate section.  */
-  resolve_unique_section (decl, reloc, flag_data_sections);
+  /* (TIGCC 20040620) See the note about common symbols above. -- Kevin Kofler */
+  /* (TIGCC 20050206) And always emit mergeable constructors into their own
+                      sections so the linker can merge them, as GCC fails to do
+                      it on its own. */
+  resolve_unique_section (decl, reloc, (flag_data_sections
+                                        && (!((!TREE_PUBLIC(decl) || DECL_COMMON(decl))
+                                              && (DECL_INITIAL (decl) == 0
+                                                  || DECL_INITIAL (decl) == error_mark_node
+                                                  || (flag_zero_initialized_in_bss
+                                                      && !TREE_READONLY (decl)
+                                                      && initializer_zerop (DECL_INITIAL (decl)))))
+                                            || TARGET_NO_BSS))
+                                       || (DECL_INITIAL (decl)
+                                           && TREE_CODE (DECL_INITIAL (decl)) == CONSTRUCTOR
+                                           && (! (reloc
+                                                  || (!TREE_READONLY (decl))
+                                                  || TREE_SIDE_EFFECTS (decl)
+                                                  || !TREE_CONSTANT (DECL_INITIAL (decl))))));
   variable_section (decl, reloc);
 
   /* dbxout.c needs to know this.  */
@@ -2280,7 +2360,16 @@
 void
 assemble_real (REAL_VALUE_TYPE d, enum machine_mode mode, unsigned int align)
 {
-  long data[4];
+  long data[3];
+  unsigned int nalign = min_align (align, 16);
+
+  /* This is how to output a SMAP BCD real constant. */
+  REAL_VALUE_TO_TARGET_SMAP_BCD (d, data);
+  assemble_integer (GEN_INT (data[0]), 2, align, 1);
+  assemble_integer (GEN_INT (data[1]), 4, nalign, 1);
+  assemble_integer (GEN_INT (data[2]), 4, nalign, 1);
+
+#if 0
   int i;
   int bitsize, nelts, nunits, units_per;
 
@@ -2315,6 +2404,7 @@
       assemble_integer (GEN_INT (data[i]), MIN (nunits, units_per), align, 1);
       nunits -= units_per;
     }
+#endif /* 0 */
 }
 
 /* Given an expression EXP with a constant value,
@@ -3312,7 +3402,7 @@
 /* Worker function for output_constant_pool.  Emit POOL.  */
 
 static void
-output_constant_pool_1 (struct constant_descriptor_rtx *desc)
+output_constant_pool_1 (const char *fnname, struct constant_descriptor_rtx *desc)
 {
   rtx x, tmp;
 
@@ -3351,8 +3441,19 @@
     }
 
   /* First switch to correct section.  */
-  targetm.asm_out.select_rtx_section (desc->mode, x, desc->align);
+  if (flag_merge_constants && flag_merge_constant_pools)
+    {
+      /* (TIGCC 20040727) If we want to merge constant pools, we need to
+                          create a separate section for each constant pool.
+                          -- Kevin Kofler  */
+      char name[strlen(fnname)+15];
 
+      sprintf (name, ".rodata.%s.cpool", fnname);
+      named_section_flags (name, SECTION_MERGE);
+    }
+  else
+     targetm.asm_out.select_rtx_section (desc->mode, x, desc->align);
+ 
 #ifdef ASM_OUTPUT_SPECIAL_POOL_ENTRY
   ASM_OUTPUT_SPECIAL_POOL_ENTRY (asm_out_file, x, desc->mode,
 				 desc->align, desc->labelno, done);
@@ -3467,7 +3568,7 @@
 /* Write all the constants in the constant pool.  */
 
 void
-output_constant_pool (const char *fnname ATTRIBUTE_UNUSED,
+output_constant_pool (const char *fnname,
 		      tree fndecl ATTRIBUTE_UNUSED)
 {
   struct rtx_constant_pool *pool = cfun->varasm->pool;
@@ -3483,7 +3584,7 @@
 #endif
 
   for (desc = pool->first; desc ; desc = desc->next)
-    output_constant_pool_1 (desc);
+    output_constant_pool_1 (fnname, desc);
 
 #ifdef ASM_OUTPUT_POOL_EPILOGUE
   ASM_OUTPUT_POOL_EPILOGUE (asm_out_file, fnname, fndecl, pool->offset);
@@ -3527,10 +3628,18 @@
     case MINUS_EXPR:
       reloc = compute_reloc_for_constant (TREE_OPERAND (exp, 0));
       reloc2 = compute_reloc_for_constant (TREE_OPERAND (exp, 1));
+#if 0
       /* The difference of two local labels is computable at link time.  */
+      /* (TIGCC 20040808) That's true, but it is still not valid in a mergeable
+         section. GCC doesn't seem to accept that as a constant anyway (at least
+         in C), but it is never a good idea to let a latent problem just lie
+         around. And besides, this code is unsafe, consider (addr1+addr2)-addr3.
+         Still a potentially valid expression for the assembler and linker, but
+         mishandled awfully by this code. -- Kevin Kofler  */
       if (reloc == 1 && reloc2 == 1)
 	reloc = 0;
       else
+#endif /* 0 */
 	reloc |= reloc2;
       break;
 
@@ -5128,6 +5237,31 @@
 	  || strcmp (name, ".preinit_array") == 0))
     flags |= SECTION_NOTYPE;
 
+/* (TIGCC 20040725) This was mostly copied out of the ELF section selector. It
+                    handles mergeable sections. -- Kevin Kofler */
+  switch (categorize_decl_for_section (decl, reloc, shlib))
+    {
+    case SECCAT_RODATA_MERGE_STR:
+    case SECCAT_RODATA_MERGE_STR_INIT:
+    case SECCAT_RODATA_MERGE_CONST:
+      flags |= SECTION_MERGE;
+      break;
+    default:
+      break;
+    }
+
+  if (DECL_INITIAL (decl) && TREE_CODE (DECL_INITIAL (decl)) == CONSTRUCTOR)
+    {
+      /* (TIGCC 20040727) Put compound literals in mergeable sections in global
+                          compound literal mode. -- Kevin Kofler
+         (TIGCC 20040808) But not if they contain relocations. -- Kevin Kofler */
+      if (! (reloc
+             || (!TREE_READONLY (decl))
+             || TREE_SIDE_EFFECTS (decl)
+             || !TREE_CONSTANT (DECL_INITIAL (decl))))
+          flags |= SECTION_MERGE;
+    }
+
   return flags;
 }
 
@@ -5249,18 +5383,51 @@
 {
   bool readonly = false;
 
+/* (TIGCC 20040725) This was copied out of the ELF section selector. It handles
+                    mergeable sections. -- Kevin Kofler */
+  switch (categorize_decl_for_section (decl, reloc, flag_pic))
+    {
+    case SECCAT_RODATA_MERGE_STR:
+      mergeable_string_section (decl, align, 0);
+      break;
+    case SECCAT_RODATA_MERGE_STR_INIT:
+      mergeable_string_section (DECL_INITIAL (decl), align, 0);
+      break;
+    case SECCAT_RODATA_MERGE_CONST:
+      mergeable_constant_section (DECL_MODE (decl), align, 0);
+      break;
+    default:
+
   if (DECL_P (decl))
     {
+#if 0
+/* (TIGCC 20050206) This doesn't work very well because GCC doesn't merge
+                    the compound literals properly. So I emit them into
+                    individual mergeable sections instead. */
+      if (TREE_CODE (DECL_INITIAL (decl)) == CONSTRUCTOR)
+        {
+          /* (TIGCC 20040727) Put compound literals in mergeable sections in global
+                              compound literal mode. -- Kevin Kofler
+             (TIGCC 20040808) But not if they contain relocations. -- Kevin Kofler */
+          if (! (reloc
+                 || (!TREE_READONLY (decl))
+                 || TREE_SIDE_EFFECTS (decl)
+                 || !TREE_CONSTANT (DECL_INITIAL (decl))))
+            {
+              mergeable_constant_section (DECL_MODE (decl), align, 0);
+              break;
+            }
+        }
+#endif /* 0 */
       if (decl_readonly_section (decl, reloc))
 	readonly = true;
     }
-  else if (TREE_CODE (decl) == CONSTRUCTOR)
+  /* (TIGCC 20040727) Put complex literals in mergeable sections.
+                      -- Kevin Kofler */
+  else if (TREE_CODE (decl) == COMPLEX_CST)
     {
-      if (! ((flag_pic && reloc)
-	     || !TREE_READONLY (decl)
-	     || TREE_SIDE_EFFECTS (decl)
-	     || !TREE_CONSTANT (decl)))
-	readonly = true;
+      mergeable_constant_section (DECL_MODE (decl), align, 0);
+      break;
     }
   else if (TREE_CODE (decl) == STRING_CST)
     readonly = true;
@@ -5271,6 +5438,7 @@
     readonly_data_section ();
   else
     data_section ();
+  } /* end of switch-case */
 }
 
 enum section_category
diff -Naur gcc-4.1.2.orig/gcc/version.c gcc-4.1.2-src/gcc/version.c
--- gcc-4.1.2.orig/gcc/version.c	2005-03-16 07:04:10.000000000 +0100
+++ gcc-4.1.2-src/gcc/version.c	2007-04-17 16:44:02.000000000 +0200
@@ -8,7 +8,7 @@
    in parentheses.  You may also wish to include a number indicating
    the revision of your modified compiler.  */
 
-#define VERSUFFIX ""
+#define VERSUFFIX " (TIGCC 4.1.2-tigcc-2)"
 
 /* This is the location of the online document giving instructions for
    reporting bugs.  If you distribute a modified version of GCC,
@@ -17,7 +17,7 @@
    forward us bugs reported to you, if you determine that they are
    not bugs in your modifications.)  */
 
-const char bug_report_url[] = "<URL:http://gcc.gnu.org/bugs.html>";
+const char bug_report_url[] = "http://tigcc.ticalc.org/";
 
 /* The complete version string, assembled from several pieces.
    BASEVER, DATESTAMP, and DEVPHASE are defined by the Makefile.  */
diff -Naur gcc-4.1.2.orig/libcpp/directives.c gcc-4.1.2-src/libcpp/directives.c
--- gcc-4.1.2.orig/libcpp/directives.c	2006-12-29 09:17:43.000000000 +0100
+++ gcc-4.1.2-src/libcpp/directives.c	2007-02-19 02:32:34.000000000 +0100
@@ -1139,6 +1139,7 @@
 _cpp_init_internal_pragmas (cpp_reader *pfile)
 {
   /* Pragmas in the global namespace.  */
+  register_pragma (pfile, 0, "poison", do_pragma_poison, false, true); /* (TIGCC) */
   register_pragma (pfile, 0, "once", do_pragma_once, false, true);
 
   /* New GCC-specific pragmas should be put in the GCC namespace.  */
diff -Naur gcc-4.1.2.orig/libcpp/expr.c gcc-4.1.2-src/libcpp/expr.c
--- gcc-4.1.2.orig/libcpp/expr.c	2005-06-29 04:34:39.000000000 +0200
+++ gcc-4.1.2-src/libcpp/expr.c	2007-02-19 02:32:34.000000000 +0100
@@ -171,6 +171,13 @@
 	  radix = 16;
 	  str++;
 	}
+      /* Require at least one binary digit to classify it as binary.  */
+      else if ((*str == 'b' || *str == 'B') && (str[1]=='0' || str[1]=='1'))
+	{
+	  radix = 2;
+	  str++;
+	}
+
     }
 
   /* Now scan for a well-formed integer or float.  */
@@ -205,11 +212,15 @@
 	}
     }
 
-  if (float_flag != NOT_FLOAT && radix == 8)
+  if ((float_flag != NOT_FLOAT || CPP_OPTION(pfile,no_auto_octals)) && radix == 8)
     radix = 10;
 
-  if (max_digit >= radix)
-    SYNTAX_ERROR2 ("invalid digit \"%c\" in octal constant", '0' + max_digit);
+  if (max_digit >= radix) {
+    if (radix == 2)
+      SYNTAX_ERROR2 ("invalid digit \"%c\" in binary constant", '0' + max_digit);
+    else
+      SYNTAX_ERROR2 ("invalid digit \"%c\" in octal constant", '0' + max_digit);
+  }
 
   if (float_flag != NOT_FLOAT)
     {
@@ -293,6 +304,12 @@
     result |= CPP_N_DECIMAL;
   else if (radix == 16)
     result |= CPP_N_HEX;
+  else if (radix == 2)
+    {
+      if (CPP_PEDANTIC (pfile))
+        cpp_error(pfile, CPP_DL_PEDWARN, "binary constants are a TIGCC extension");
+      result |= CPP_N_BINARY;
+    }
   else
     result |= CPP_N_OCTAL;
 
@@ -343,6 +360,11 @@
 	  base = 16;
 	  p += 2;
 	}
+      else if ((type & CPP_N_RADIX) == CPP_N_BINARY)
+	{
+	  base = 2;
+	  p += 2;
+	}
 
       /* We can add a digit to numbers strictly less than this without
 	 needing the precision and slowness of double integers.  */
diff -Naur gcc-4.1.2.orig/libcpp/files.c gcc-4.1.2-src/libcpp/files.c
--- gcc-4.1.2.orig/libcpp/files.c	2005-11-04 03:10:19.000000000 +0100
+++ gcc-4.1.2-src/libcpp/files.c	2007-02-19 02:32:34.000000000 +0100
@@ -48,6 +48,11 @@
 #  define set_stdin_to_binary_mode() /* Nothing */
 #endif
 
+/* (TIGCC 20050205) FIXME: This should be handled by configure... */
+#ifdef _WIN32
+#define ssize_t int
+#endif
+
 /* This structure represents a file searched for by CPP, whether it
    exists or not.  An instance may be pointed to by more than one
    file_hash_entry; at present no reference count is kept.  */
diff -Naur gcc-4.1.2.orig/libcpp/include/cpplib.h gcc-4.1.2-src/libcpp/include/cpplib.h
--- gcc-4.1.2.orig/libcpp/include/cpplib.h	2005-11-14 17:28:55.000000000 +0100
+++ gcc-4.1.2-src/libcpp/include/cpplib.h	2007-02-19 02:32:34.000000000 +0100
@@ -399,6 +399,9 @@
   /* True if dependencies should be restored from a precompiled header.  */
   bool restore_pch_deps;
 
+  /* (TIGCC) True if numbers starting with zero should NOT be octal. */
+  unsigned char no_auto_octals;
+
   /* Dependency generation.  */
   struct
   {
@@ -740,6 +743,7 @@
 #define CPP_N_DECIMAL	0x0100
 #define CPP_N_HEX	0x0200
 #define CPP_N_OCTAL	0x0400
+#define CPP_N_BINARY	0x0800
 
 #define CPP_N_UNSIGNED	0x1000	/* Properties.  */
 #define CPP_N_IMAGINARY	0x2000
@@ -803,6 +807,7 @@
    string literal.  Handles all relevant diagnostics.  */
 extern cppchar_t cpp_parse_escape (cpp_reader *, const unsigned char ** pstr,
 				   const unsigned char *limit, int wide);
+extern void cpp_unterminated (cpp_reader *, int);
 
 /* In cpphash.c */
 
diff -Naur gcc-4.1.2.orig/libcpp/init.c gcc-4.1.2-src/libcpp/init.c
--- gcc-4.1.2.orig/libcpp/init.c	2006-01-23 22:51:10.000000000 +0100
+++ gcc-4.1.2-src/libcpp/init.c	2007-02-19 02:32:34.000000000 +0100
@@ -160,6 +160,7 @@
   CPP_OPTION (pfile, warn_dollars) = 1;
   CPP_OPTION (pfile, warn_variadic_macros) = 1;
   CPP_OPTION (pfile, warn_normalize) = normalized_C;
+  CPP_OPTION (pfile, no_auto_octals) = 0; /* (TIGCC) */
 
   /* Default CPP arithmetic to something sensible for the host for the
      benefit of dumb users like fix-header.  */
diff -Naur gcc-4.1.2.orig/libcpp/internal.h gcc-4.1.2-src/libcpp/internal.h
--- gcc-4.1.2.orig/libcpp/internal.h	2005-10-21 19:54:20.000000000 +0200
+++ gcc-4.1.2-src/libcpp/internal.h	2007-02-19 02:32:34.000000000 +0100
@@ -372,6 +372,11 @@
   /* Error counter for exit code.  */
   unsigned int errors;
 
+  /* Line and column where a newline was first seen in a string
+     constant (multi-line strings).  */
+  source_location mls_line;
+  unsigned int mls_col;
+
   /* Buffer to hold macro definition string.  */
   unsigned char *macro_buffer;
   unsigned int macro_buffer_len;
diff -Naur gcc-4.1.2.orig/libcpp/lex.c gcc-4.1.2-src/libcpp/lex.c
--- gcc-4.1.2.orig/libcpp/lex.c	2005-09-20 22:31:37.000000000 +0200
+++ gcc-4.1.2-src/libcpp/lex.c	2007-02-19 02:32:34.000000000 +0100
@@ -212,7 +212,11 @@
     }
 
  done:
-  *d = '\n';
+  /* (TIGCC 20050212) Don't convert \r to \n, switch them instead. */
+  if (*d=='\r' && d[1]=='\n')
+    {*d='\n'; d[1]='\r';}
+  else
+    *d = '\n';
   /* A sentinel note that should never be processed.  */
   add_line_note (buffer, d + 1, '\n');
   buffer->next_line = s + 1;
@@ -588,10 +592,19 @@
 create_literal (cpp_reader *pfile, cpp_token *token, const uchar *base,
 		unsigned int len, enum cpp_ttype type)
 {
+  char *p;
   uchar *dest = _cpp_unaligned_alloc (pfile, len + 1);
 
   memcpy (dest, base, len);
   dest[len] = '\0';
+  /* (TIGCC 20050206) Delete \r characters in multi-line strings. */
+  p = (char *)dest;
+  while (p < (char *)dest + len) {
+    if (*p == '\r') {
+      memmove (p, p + 1, (char *)dest + len - p);
+      len--;
+    } else p++;
+  }
   token->type = type;
   token->val.str.len = len;
   token->val.str.text = dest;
@@ -603,7 +616,10 @@
    literal, or CPP_OTHER if it was not properly terminated.
 
    The spelling is NUL-terminated, but it is not guaranteed that this
-   is the first NUL since embedded NULs are preserved.  */
+   is the first NUL since embedded NULs are preserved.
+
+   Multi-line strings are allowed as a TIGCC extension (removed in the FSF GCC
+   since version 3.3).  */
 static void
 lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base)
 {
@@ -611,7 +627,11 @@
   const uchar *cur;
   cppchar_t terminator;
   enum cpp_ttype type;
+  cpp_buffer *buffer;
+  unsigned int startcol;
 
+  buffer = pfile->buffer;
+  startcol = CPP_BUF_COL (buffer);
   cur = base;
   terminator = *cur++;
   if (terminator == 'L')
@@ -634,9 +654,50 @@
 	break;
       else if (c == '\n')
 	{
-	  cur--;
-	  type = CPP_OTHER;
-	  break;
+	  unsigned int cols;
+
+	  /* In assembly language, silently terminate string and
+	     character literals at end of line.  This is a kludge
+	     around not knowing where comments are.  */
+	  if (CPP_OPTION (pfile, lang) == CLK_ASM && terminator != '>')
+	    {
+	      cur--;
+	      break;
+	    }
+
+	  /* Character constants and header names may not extend over
+	     multiple lines.  In Standard C, neither may strings.
+	     In TIGCC, we accept multiline strings as an
+	     extension, except in #include family directives.  */
+	  if (terminator != '"' || pfile->state.angled_headers)
+	    {
+	      cur--;
+	      type = CPP_OTHER;
+	      break;
+	    }
+
+	  if (CPP_PEDANTIC (pfile))
+	    cpp_error(pfile, CPP_DL_PEDWARN, "ISO C forbids newline in string literal");
+	  buffer->cur = cur - 1;
+	  _cpp_process_line_notes (pfile, true);
+	  if (buffer->next_line >= buffer->rlimit)
+	    {
+	      cur--;
+	      type = CPP_OTHER;
+	      break;
+	    }
+	  _cpp_clean_line (pfile);
+
+	  cols = buffer->next_line - buffer->line_base;
+	  CPP_INCREMENT_LINE (pfile, cols);
+
+	  cur = buffer->cur;
+
+	  if (pfile->mls_line == 0)
+	    {
+	      pfile->mls_line = token->src_loc;
+	      pfile->mls_col = startcol;
+	    }
 	}
       else if (c == '\0')
 	saw_NUL = true;
@@ -1703,3 +1764,18 @@
       return CPP_TOKEN_FLD_NONE;
     }
 }
+
+/* Emits error for unterminated strings.  */
+void
+cpp_unterminated (cpp_reader *pfile, int term)
+{
+  cpp_error (pfile, CPP_DL_ERROR, "missing terminating %c character", term);
+
+  if (term == '\"' && pfile->mls_line && pfile->mls_line != pfile->line_table->highest_line)
+    {
+      cpp_error_with_line (pfile, CPP_DL_ERROR, pfile->mls_line, pfile->mls_col,
+			   "possible start of unterminated string literal");
+      pfile->mls_line = 0;
+    }
+}
+
diff -Naur gcc-4.1.2.orig/libcpp/macro.c gcc-4.1.2-src/libcpp/macro.c
--- gcc-4.1.2.orig/libcpp/macro.c	2006-01-23 22:51:10.000000000 +0100
+++ gcc-4.1.2-src/libcpp/macro.c	2007-02-19 02:32:34.000000000 +0100
@@ -768,6 +768,11 @@
   macro_arg *arg;
   _cpp_buff *buff;
 
+  /* (TIGCC) If 'SYMSTR' is used with a string literal, it should be
+             converted automatically to 'SYMSTR_CONST'.  */
+  cpp_hashnode *orig_node=node; /* save the original node in case we change it */
+  symstr_const: /* start again from here after changing SYMSTR to SYMSTR_CONST */
+
   /* First, fully macro-expand arguments, calculating the number of
      tokens in the final expansion as we go.  The ordering of the if
      statements below is subtle; we must handle stringification before
@@ -801,6 +806,33 @@
 	  }
       }
 
+  if (!ustrcmp (node->ident.str, U"SYMSTR"))
+  {
+    /* Accept one or more literal strings. If there are multiple ones, they
+       concatenate. Ignore any padding.
+       Refuse any other argument type. */
+    unsigned int i;
+    cpp_hashnode *newnode;
+
+    for (i=0;i<args->expanded_count;i++)
+    {
+      if ((args->expanded[i]->type != CPP_STRING)
+          && (args->expanded[i]->type != CPP_PADDING)) goto notconststring;
+    }
+
+    /* Change the macro to SYMSTR_CONST, if it is defined. */
+    newnode = cpp_lookup (pfile, U"SYMSTR_CONST",
+                          sizeof ("SYMSTR_CONST") - 1);
+    if (newnode->type == NT_MACRO) {
+      node = newnode;
+      macro = node->value.macro;
+      goto symstr_const; /* Start over from the beginning. */
+    }
+
+    notconststring:;
+  }
+  /* (END TIGCC) */
+
   /* Now allocate space for the expansion, copy the tokens and replace
      the arguments.  */
   buff = _cpp_get_buff (pfile, total * sizeof (cpp_token *));
@@ -887,7 +919,10 @@
     if (args[i].expanded)
       free (args[i].expanded);
 
-  push_ptoken_context (pfile, node, buff, first, dest - first);
+  push_ptoken_context (pfile, orig_node, buff, first, dest - first);
+  /* (TIGCC) Always use the ORIGINAL node here, not the modified one. Doing
+             otherwise would make subsequent expansions of SYMSTR fail after
+             the first conversion to SYMSTR_CONST. */
 }
 
 /* Return a special padding token, with padding inherited from SOURCE.  */
