OSDN Git Service

* config/dsp16xx/dsp16xx.md: Rewrite for more efficient code and
authorcollison <collison@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 14 Oct 2001 02:14:28 +0000 (02:14 +0000)
committercollison <collison@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 14 Oct 2001 02:14:28 +0000 (02:14 +0000)
add scheduling support.
* config/dsp16xx/dsp16xx.h: Rewrite for more efficient code.
* config/dsp16xx/dsp16xx.c: Rewrite for more efficient code.
* config/dsp16xx/dsp16xx-protos.h: Add new function prototypes.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@46248 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/config/dsp16xx/dsp16xx-protos.h
gcc/config/dsp16xx/dsp16xx.c
gcc/config/dsp16xx/dsp16xx.h
gcc/config/dsp16xx/dsp16xx.md

index 6401f70..02ba7b8 100644 (file)
@@ -29,6 +29,8 @@ extern int sp_operand PARAMS ((rtx, enum machine_mode));
 extern int sp_operand2 PARAMS ((rtx, enum machine_mode));
 extern int nonmemory_arith_operand PARAMS ((rtx, enum machine_mode));
 extern int dsp16xx_comparison_operator PARAMS ((rtx, enum machine_mode));
+extern int unx_comparison_operator PARAMS ((rtx, enum machine_mode));
+extern int signed_comparison_operator PARAMS ((rtx, enum machine_mode));
 
 extern void notice_update_cc PARAMS ((rtx));
 extern void double_reg_from_memory PARAMS ((rtx[]));
@@ -77,7 +79,11 @@ extern void asm_output_local PARAMS ((FILE *, const char *, int, int));
 extern void asm_output_float PARAMS ((FILE *, double));
 extern void asm_output_long PARAMS ((FILE *, long));
 extern void dsp16xx_file_start PARAMS ((void));
+extern void coff_dsp16xx_file_start PARAMS ((FILE *));
+extern void luxworks_dsp16xx_file_start PARAMS ((FILE *));
 extern struct rtx_def *(*dsp16xx_compare_gen) PARAMS (());
 extern int hard_regno_mode_ok PARAMS ((int, enum machine_mode));
 extern enum reg_class dsp16xx_reg_class_from_letter PARAMS ((int));
 extern int regno_reg_class PARAMS ((int));
+extern void function_prologue PARAMS ((FILE *, int));
+extern void function_epilogue PARAMS ((FILE *, int));
index 74de0d0..8ca95a6 100644 (file)
@@ -1,6 +1,6 @@
 /* Subroutines for assembler code output on the DSP1610.
    Copyright (C) 1994, 1995, 1997, 1998, 2001 Free Software Foundation, Inc.
-   Contributed by Michael Collison (collison@world.std.com).
+   Contributed by Michael Collison (collison@isisinc.net).
 
 This file is part of GNU CC.
 
@@ -37,7 +37,7 @@ Boston, MA 02111-1307, USA.  */
 #include "ggc.h"
 #include "toplev.h"
 #include "recog.h"
-#include "tm_p.h"
+#include "dsp16xx-protos.h"
 #include "target.h"
 #include "target-def.h"
 
@@ -58,7 +58,7 @@ const char *save_chip_name;
 
 rtx dsp16xx_compare_op0;
 rtx dsp16xx_compare_op1;
-rtx (*dsp16xx_compare_gen) PARAMS (());
+struct rtx_def *(*dsp16xx_compare_gen)();
 
 static const char *fp;
 static const char *sp;
@@ -149,7 +149,7 @@ static const char *const lshift_right_asm_first[] =
 static int reg_save_size PARAMS ((void));
 static void dsp16xx_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
 static void dsp16xx_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
-\f
+
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_FUNCTION_PROLOGUE
 #define TARGET_ASM_FUNCTION_PROLOGUE dsp16xx_output_function_prologue
@@ -157,7 +157,7 @@ static void dsp16xx_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
 #define TARGET_ASM_FUNCTION_EPILOGUE dsp16xx_output_function_epilogue
 
 struct gcc_target targetm = TARGET_INITIALIZER;
-\f
+
 int 
 hard_regno_mode_ok (regno, mode)
      int regno;
@@ -208,6 +208,12 @@ dsp16xx_reg_class_from_letter (c)
     {
     case 'A':
       return ACCUM_REGS;
+
+    case 'l':
+      return A0_REG;
+
+    case 'C':
+      return A1_REG;
       
     case 'h':
       return ACCUM_HIGH_REGS;
@@ -242,9 +248,6 @@ dsp16xx_reg_class_from_letter (c)
     case 'd':
       return ACCUM_Y_OR_P_REGS;
 
-    case 'C':
-      return NO_FRAME_Y_ADDR_REGS;
-
     case 'a':
       return Y_ADDR_REGS;
 
@@ -279,7 +282,7 @@ dsp16xx_reg_class_from_letter (c)
       return SLOW_MEM_LOAD_REGS;
 
     default:
-      abort ();
+      return NO_REGS;
     }
 }
 /* Return the class number of the smallest class containing
@@ -368,210 +371,16 @@ class_max_nregs(class, mode)
 
 enum reg_class
 limit_reload_class (mode, class)
-     enum machine_mode mode;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
      enum reg_class class;
 {
-  switch ((int) class)
-    {
-    case NO_REGS:
-    case A0H_REG:
-    case A0L_REG:
-    case A0_REG:
-    case A1H_REG:
-      return class;
-
-    case ACCUM_HIGH_REGS:
-      abort ();
-
-    case A1L_REG:
-    case ACCUM_LOW_REGS:
-    case A1_REG:
-      return class;
-
-    case ACCUM_REGS:
-      if (GET_MODE_SIZE(mode) == 1)
-       return ACCUM_LOW_REGS;
-      else
-       return class;
-
-    case X_REG:
-    case X_OR_ACCUM_LOW_REGS:
-      return class;
-
-    case X_OR_ACCUM_REGS:
-      if (GET_MODE_SIZE(mode) == 1)
-       return X_OR_ACCUM_LOW_REGS;
-      else
-       return class;
-
-    case YH_REG:
-      return class;
-
-    case YH_OR_ACCUM_HIGH_REGS:
-      abort ();
-
-    case X_OR_YH_REGS:
-      return class;
-
-    case YL_REG:
-      /* Register 'yl' is invalid for QImode, so we should never
-        see it. */
-      abort ();
-
-    case YL_OR_ACCUM_LOW_REGS:
-    case X_OR_YL_REGS:
-      return class;
-
-    case Y_REG:
-      if (GET_MODE_SIZE(mode) > 1)
-       return class;
-      else
-       return YH_REG;
-
-    case ACCUM_OR_Y_REGS:
-      if (GET_MODE_SIZE(mode) > 1)
-       return class;
-      else
-       return YL_OR_ACCUM_LOW_REGS;
-
-    case PH_REG:
-    case X_OR_PH_REGS:
-    case PL_REG:
-    case PL_OR_ACCUM_LOW_REGS:
-    case X_OR_PL_REGS:
-      return class;
-
-    case P_REG:
-      if (GET_MODE_SIZE(mode) > 1)
-       return class;
-      else
-       return PL_REG;
-
-    case ACCUM_OR_P_REGS:
-      if (GET_MODE_SIZE(mode) > 1)
-       return class;
-      else
-       return PL_OR_ACCUM_LOW_REGS;
-
-    case YL_OR_P_REGS:
-    case ACCUM_LOW_OR_YL_OR_P_REGS:
-      return class;
-
-    case Y_OR_P_REGS:
-      return class;
-
-    case ACCUM_Y_OR_P_REGS:
-      if (GET_MODE_SIZE(mode) > 1)
-       return class;
-      else
-       return ACCUM_LOW_OR_YL_OR_P_REGS;
-
-    case NO_FRAME_Y_ADDR_REGS:
-    case Y_ADDR_REGS: 
-    case ACCUM_LOW_OR_Y_ADDR_REGS:
-      return class;
-
-    case ACCUM_OR_Y_ADDR_REGS:
-      if (GET_MODE_SIZE(mode) > 1)
-       return ACCUM_REGS;
-      else
-       return ACCUM_LOW_OR_Y_ADDR_REGS;
-
-    case X_OR_Y_ADDR_REGS:
-      return class;
-
-    case Y_OR_Y_ADDR_REGS:
-    case P_OR_Y_ADDR_REGS:
-    case NON_HIGH_YBASE_ELIGIBLE_REGS:
-
-    case J_REG:
-      return class;
-
-    case YBASE_ELIGIBLE_REGS:
-      if (GET_MODE_SIZE(mode) > 1)
-       return ACCUM_Y_P_OR_YBASE_REGS;
-      else
-       return NON_HIGH_YBASE_ELIGIBLE_REGS;
-
-    case J_OR_DAU_16_BIT_REGS:
-      if (GET_MODE_SIZE(mode) == 1)
-       return J_REG;
-      else
-       return class;
-
-    case BMU_REGS:
-    case NOHIGH_NON_ADDR_REGS:
-      return class;
-
-    case NON_ADDR_REGS:
-      if (GET_MODE_SIZE(mode) > 1)
-       return class;
-      else
-       return NOHIGH_NON_ADDR_REGS;
-
-    case NOHIGH_NON_YBASE_REGS:
-      return class;
-
-    case NON_YBASE_REGS:
-      if (GET_MODE_SIZE(mode) > 1)
-       return class;
-      else
-       return NOHIGH_NON_YBASE_REGS;
-
-    case YBASE_VIRT_REGS:
-    case ACCUM_LOW_OR_YBASE_REGS:
-      return class;
-      
-    case ACCUM_OR_YBASE_REGS:
-      if (GET_MODE_SIZE(mode) > 1)
-       return class;
-      else
-       return ACCUM_LOW_OR_YBASE_REGS;
-
-    case X_OR_YBASE_REGS:
-      return class;
-
-    case Y_OR_YBASE_REGS:
-    case ACCUM_LOW_YL_PL_OR_YBASE_REGS:
-    case P_OR_YBASE_REGS:
-      return class;
-
-    case ACCUM_Y_P_OR_YBASE_REGS:
-      return ACCUM_LOW_YL_PL_OR_YBASE_REGS;
-
-    case Y_ADDR_OR_YBASE_REGS:
-    case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS:
-      return class;
-
-    case YBASE_OR_YBASE_ELIGIBLE_REGS:
-      if (GET_MODE_SIZE(mode) > 1)
-       return class;
-      else
-       return YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS;
-
-    case NO_HIGH_ALL_REGS:
-      return class;
-
-    case ALL_REGS:
-      if (GET_MODE_SIZE(mode) > 1)
-       return class;
-      else
-       return NO_HIGH_ALL_REGS;
-
-    default:
-      return class;
-    }
+  return class;
 }
 
 int
 dsp16xx_register_move_cost (from, to)
      enum reg_class from, to;
 {
-#if 0
-  if (from == NO_REGS || to == NO_REGS || (from == to))
-    return 2;
-#endif
-
   if (from == A0H_REG || from == A0L_REG || from == A0_REG ||
       from == A1H_REG || from == ACCUM_HIGH_REGS || from == A1L_REG ||
       from == ACCUM_LOW_REGS || from == A1_REG || from == ACCUM_REGS)
@@ -589,18 +398,20 @@ dsp16xx_register_move_cost (from, to)
       return 2;
     }
 
-#if 0
   if (from == YBASE_VIRT_REGS)
     {
+      if (to == YBASE_VIRT_REGS)
+       return 16;
+
       if (to == X_REG || to == YH_REG || to == YL_REG ||
          to == Y_REG || to == PL_REG || to == PH_REG ||
          to == P_REG || to == Y_ADDR_REGS || to == YBASE_ELIGIBLE_REGS ||
          to == Y_OR_P_REGS)
        {
-         return 2;
+         return 8;
        }
       else
-       return 4;
+       return 10;
     }
 
   if (to == YBASE_VIRT_REGS)
@@ -610,13 +421,13 @@ dsp16xx_register_move_cost (from, to)
          from == P_REG || from == Y_ADDR_REGS || from == YBASE_ELIGIBLE_REGS ||
          from == Y_OR_P_REGS)
        {
-         return 2;
+         return 8;
        }
       else
-       return 4;
+       return 10;
     }
-#endif
-  return 4;
+
+  return 8;
 }
 
 /* Given an rtx X being reloaded into a reg required to be
@@ -636,13 +447,341 @@ preferred_reload_class (x, class)
 
   if (CONSTANT_P (x))
     {
-      if (class == ALL_REGS)
-       return NON_YBASE_REGS;
+      switch ((int) class)
+       {
+       case YBASE_VIRT_REGS:
+         return (!reload_in_progress ? NO_REGS : class);
+
+       case ACCUM_LOW_OR_YBASE_REGS:
+         return ACCUM_LOW_REGS;
+
+       case ACCUM_OR_YBASE_REGS:
+         return ACCUM_REGS;
+
+       case X_OR_YBASE_REGS:
+         return X_REG;
+
+       case Y_OR_YBASE_REGS:
+         return Y_REG;
+
+       case ACCUM_LOW_YL_PL_OR_YBASE_REGS:
+         return YL_OR_PL_OR_ACCUM_LOW_REGS;
+
+       case P_OR_YBASE_REGS:
+         return P_REG;
+
+       case ACCUM_Y_P_OR_YBASE_REGS:
+         return ACCUM_Y_OR_P_REGS;
+
+       case Y_ADDR_OR_YBASE_REGS:
+         return Y_ADDR_REGS;
+
+       case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS:
+         return NON_HIGH_YBASE_ELIGIBLE_REGS;;
+         
+       case YBASE_OR_YBASE_ELIGIBLE_REGS:
+         return YBASE_ELIGIBLE_REGS;
+
+       case NO_HIGH_ALL_REGS:
+         return NOHIGH_NON_YBASE_REGS;
+
+       case ALL_REGS:
+         return NON_YBASE_REGS;
+
+       default:
+         return class;
+       }
+    }
+
+  /* If x is not an accumulator or a ybase register, restrict the class of registers
+     we can copy the register into */
+
+  if (REG_P (x) && !IS_ACCUM_REG (REGNO (x)) && !IS_YBASE_REGISTER_WINDOW (REGNO (x)))
+    {
+      switch ((int) class)
+       {
+       case NO_REGS:
+       case A0H_REG: case A0L_REG: case A0_REG: case A1H_REG:
+       case ACCUM_HIGH_REGS: case A1L_REG: case ACCUM_LOW_REGS: 
+       case A1_REG: case ACCUM_REGS:
+         return class;
+
+       case X_REG: 
+         return (!reload_in_progress ? NO_REGS : class);
+
+       case X_OR_ACCUM_LOW_REGS: 
+         return ACCUM_LOW_REGS;
+
+       case X_OR_ACCUM_REGS:
+         return ACCUM_REGS;
+
+       case YH_REG:
+         return (!reload_in_progress ? NO_REGS : class);
+
+       case YH_OR_ACCUM_HIGH_REGS:
+         return ACCUM_HIGH_REGS;
+
+       case X_OR_YH_REGS: 
+       case YL_REG:
+         return (!reload_in_progress ? NO_REGS : class);
+
+       case YL_OR_ACCUM_LOW_REGS: 
+         return ACCUM_LOW_REGS;
+
+       case X_OR_YL_REGS:
+       case X_OR_Y_REGS: case Y_REG:
+         return (!reload_in_progress ? NO_REGS : class);
+
+       case ACCUM_OR_Y_REGS: 
+         return ACCUM_REGS;
+
+       case PH_REG:
+       case X_OR_PH_REGS: case PL_REG: 
+         return (!reload_in_progress ? NO_REGS : class);
+
+       case PL_OR_ACCUM_LOW_REGS:
+         return ACCUM_LOW_REGS;
+
+       case X_OR_PL_REGS:
+         return (!reload_in_progress ? NO_REGS : class);
+
+       case YL_OR_PL_OR_ACCUM_LOW_REGS: 
+         return ACCUM_LOW_REGS;
+
+       case P_REG:
+         return (!reload_in_progress ? NO_REGS : class);
+
+       case ACCUM_OR_P_REGS: 
+         return ACCUM_REGS;
+
+       case YL_OR_P_REGS:
+         return (!reload_in_progress ? NO_REGS : class);
+
+       case ACCUM_LOW_OR_YL_OR_P_REGS: 
+         return ACCUM_LOW_REGS;
+
+       case Y_OR_P_REGS:
+         return (!reload_in_progress ? NO_REGS : class);
+
+       case ACCUM_Y_OR_P_REGS: 
+         return ACCUM_REGS;
+
+       case NO_FRAME_Y_ADDR_REGS:
+       case Y_ADDR_REGS:
+         return (!reload_in_progress ? NO_REGS : class);
+
+       case ACCUM_LOW_OR_Y_ADDR_REGS:
+         return ACCUM_LOW_REGS;
+
+       case ACCUM_OR_Y_ADDR_REGS: 
+         return ACCUM_REGS;
+
+       case X_OR_Y_ADDR_REGS:
+       case Y_OR_Y_ADDR_REGS: 
+       case P_OR_Y_ADDR_REGS:
+         return (!reload_in_progress ? NO_REGS : class);
+
+       case NON_HIGH_YBASE_ELIGIBLE_REGS: 
+         return ACCUM_LOW_REGS;
+
+       case YBASE_ELIGIBLE_REGS:
+         return ACCUM_REGS;
+
+       case J_REG:
+       case J_OR_DAU_16_BIT_REGS:
+       case BMU_REGS: 
+         return (!reload_in_progress ? NO_REGS : class);
+
+       case YBASE_VIRT_REGS:
+         if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
+           return class;
+         else
+           return (!reload_in_progress ? NO_REGS : class);
+
+       case ACCUM_LOW_OR_YBASE_REGS:
+         if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
+           return class;
+         else
+           return ACCUM_LOW_REGS;
+
+       case ACCUM_OR_YBASE_REGS:
+         if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
+           return class;
+         else
+           return ACCUM_REGS;
+
+       case X_OR_YBASE_REGS:
+       case Y_OR_YBASE_REGS:
+         if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
+           return YBASE_VIRT_REGS;
+         else
+           return (!reload_in_progress ? NO_REGS : class);
+
+       case ACCUM_LOW_YL_PL_OR_YBASE_REGS:
+         if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
+           return ACCUM_LOW_OR_YBASE_REGS;
+         else
+           return ACCUM_LOW_REGS;
+
+       case P_OR_YBASE_REGS:
+         if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
+           return YBASE_VIRT_REGS;
+         else
+           return (!reload_in_progress ? NO_REGS : class);
+
+       case ACCUM_Y_P_OR_YBASE_REGS:
+         if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
+           return ACCUM_OR_YBASE_REGS;
+         else
+           return ACCUM_REGS;
+
+       case Y_ADDR_OR_YBASE_REGS:
+         if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
+           return YBASE_VIRT_REGS;
+         else
+           return (!reload_in_progress ? NO_REGS : class);
+
+       case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS:
+         if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
+           return ACCUM_LOW_OR_YBASE_REGS;
+         else
+           return ACCUM_LOW_REGS;
+
+       case YBASE_OR_YBASE_ELIGIBLE_REGS:
+         if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
+           return ACCUM_OR_YBASE_REGS;
+         else
+           return ACCUM_REGS;
+
+       case NO_HIGH_ALL_REGS:
+         if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
+           return ACCUM_LOW_OR_YBASE_REGS;
+         else
+           return ACCUM_LOW_REGS;
+
+       case ALL_REGS: 
+         if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
+           return ACCUM_OR_YBASE_REGS;
+         else
+           return ACCUM_REGS;
+
+       case NOHIGH_NON_ADDR_REGS:
+           return ACCUM_LOW_REGS;
+
+       case NON_ADDR_REGS:
+       case SLOW_MEM_LOAD_REGS:
+           return ACCUM_REGS;
+
+       case NOHIGH_NON_YBASE_REGS:
+           return ACCUM_LOW_REGS;
+
+       case NO_ACCUM_NON_YBASE_REGS:
+         return (!reload_in_progress ? NO_REGS : class);
+
+       case NON_YBASE_REGS:
+           return ACCUM_REGS;
+
+       default:
+         return class;
+       }
     }
 
-  if (class == ALL_REGS && REG_P (x) && !TARGET_RESERVE_YBASE
+  /* If x (the input) is a ybase register, restrict the class of registers
+     we can copy the register into */
+
+  if (REG_P (x) && !TARGET_RESERVE_YBASE
       && IS_YBASE_REGISTER_WINDOW (REGNO(x)))
-    return YBASE_ELIGIBLE_REGS;
+    {
+      switch ((int) class)
+       {
+       case NO_REGS:
+       case A0H_REG: case A0L_REG: case A0_REG: case A1H_REG:
+       case ACCUM_HIGH_REGS: case A1L_REG: case ACCUM_LOW_REGS: 
+       case A1_REG: case ACCUM_REGS: case X_REG: 
+       case X_OR_ACCUM_LOW_REGS: case X_OR_ACCUM_REGS:
+       case YH_REG: case YH_OR_ACCUM_HIGH_REGS:
+       case X_OR_YH_REGS: case YL_REG:
+       case YL_OR_ACCUM_LOW_REGS: case X_OR_YL_REGS:
+       case X_OR_Y_REGS: case Y_REG:
+       case ACCUM_OR_Y_REGS: case PH_REG:
+       case X_OR_PH_REGS: case PL_REG: 
+       case PL_OR_ACCUM_LOW_REGS: case X_OR_PL_REGS:
+       case YL_OR_PL_OR_ACCUM_LOW_REGS: case P_REG:
+       case ACCUM_OR_P_REGS: case YL_OR_P_REGS:
+       case ACCUM_LOW_OR_YL_OR_P_REGS: case Y_OR_P_REGS:
+       case ACCUM_Y_OR_P_REGS: case NO_FRAME_Y_ADDR_REGS:
+       case Y_ADDR_REGS: case ACCUM_LOW_OR_Y_ADDR_REGS:
+       case ACCUM_OR_Y_ADDR_REGS: case X_OR_Y_ADDR_REGS:
+       case Y_OR_Y_ADDR_REGS: case P_OR_Y_ADDR_REGS:
+       case NON_HIGH_YBASE_ELIGIBLE_REGS: case YBASE_ELIGIBLE_REGS:
+       default:
+         return class;
+
+       case J_REG:
+         return (!reload_in_progress ? NO_REGS : class);
+
+       case J_OR_DAU_16_BIT_REGS:
+         return ACCUM_HIGH_REGS;
+
+       case BMU_REGS: 
+       case YBASE_VIRT_REGS:
+         return (!reload_in_progress ? NO_REGS : class);
+
+       case ACCUM_LOW_OR_YBASE_REGS:
+         return ACCUM_LOW_REGS;
+
+       case ACCUM_OR_YBASE_REGS:
+         return ACCUM_REGS;
+
+       case X_OR_YBASE_REGS:
+         return X_REG;
+
+       case Y_OR_YBASE_REGS:
+         return Y_REG;
+
+       case ACCUM_LOW_YL_PL_OR_YBASE_REGS:
+         return YL_OR_PL_OR_ACCUM_LOW_REGS; 
+
+       case P_OR_YBASE_REGS:
+         return P_REG;
+
+       case ACCUM_Y_P_OR_YBASE_REGS:
+         return ACCUM_Y_OR_P_REGS;
+
+       case Y_ADDR_OR_YBASE_REGS:
+         return Y_ADDR_REGS;
+
+       case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS:
+         return NON_HIGH_YBASE_ELIGIBLE_REGS;
+
+       case YBASE_OR_YBASE_ELIGIBLE_REGS:
+         return YBASE_ELIGIBLE_REGS;
+
+       case NO_HIGH_ALL_REGS:
+         return NON_HIGH_YBASE_ELIGIBLE_REGS;
+
+       case ALL_REGS: 
+         return YBASE_ELIGIBLE_REGS;
+
+       case NOHIGH_NON_ADDR_REGS:
+         return ACCUM_LOW_OR_YL_OR_P_REGS;
+
+       case NON_ADDR_REGS:
+         return ACCUM_Y_OR_P_REGS;
+
+       case SLOW_MEM_LOAD_REGS:
+         return ACCUM_OR_Y_ADDR_REGS;
+
+       case NOHIGH_NON_YBASE_REGS:
+         return NON_HIGH_YBASE_ELIGIBLE_REGS;
+
+       case NO_ACCUM_NON_YBASE_REGS:
+         return Y_ADDR_REGS;
+
+       case NON_YBASE_REGS:
+         return YBASE_ELIGIBLE_REGS;
+       }
+    }
 
   if (GET_CODE (x) == PLUS)
     {
@@ -655,6 +794,12 @@ preferred_reload_class (x, class)
          if (class == ACCUM_HIGH_REGS)
            return class;
 
+         /* If the accumulators are not part of the class
+            being reloaded into, return NO_REGS */
+#if 0
+         if (!reg_class_subset_p (ACCUM_REGS, class))
+           return (!reload_in_progress ? NO_REGS : class);
+#endif
          if (reg_class_subset_p (ACCUM_HIGH_REGS, class))
            return ACCUM_HIGH_REGS;
 
@@ -678,14 +823,54 @@ preferred_reload_class (x, class)
     }
   else if (GET_CODE (x) == MEM)
     {
-      if (class == ALL_REGS)
+      /* We can't copy from a memory location into a
+        ybase register */
+      if (reg_class_subset_p(YBASE_VIRT_REGS, class))
        {
-#if 0
-         if (GET_MODE(x) == HImode)
-           return NO_ACCUM_NON_YBASE_REGS;
-         else
-#endif
-           return NON_YBASE_REGS;
+         switch ((int) class)
+           {
+           case YBASE_VIRT_REGS:
+             return (!reload_in_progress ? NO_REGS : class);
+
+           case ACCUM_LOW_OR_YBASE_REGS:
+             return ACCUM_LOW_REGS;
+
+           case ACCUM_OR_YBASE_REGS:
+             return ACCUM_REGS;
+
+           case X_OR_YBASE_REGS:
+             return X_REG;
+
+           case Y_OR_YBASE_REGS:
+             return Y_REG;
+
+           case ACCUM_LOW_YL_PL_OR_YBASE_REGS:
+             return YL_OR_PL_OR_ACCUM_LOW_REGS;
+
+           case P_OR_YBASE_REGS:
+             return P_REG;
+
+           case ACCUM_Y_P_OR_YBASE_REGS:
+             return ACCUM_Y_OR_P_REGS;
+
+           case Y_ADDR_OR_YBASE_REGS:
+             return Y_ADDR_REGS;
+
+           case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS:
+             return NON_HIGH_YBASE_ELIGIBLE_REGS;
+         
+           case YBASE_OR_YBASE_ELIGIBLE_REGS:
+             return YBASE_ELIGIBLE_REGS;
+
+           case NO_HIGH_ALL_REGS:
+             return NOHIGH_NON_YBASE_REGS;
+
+           case ALL_REGS:
+             return NON_YBASE_REGS;
+
+           default:
+             return class;
+           }
        }
       else
        return class;
@@ -709,6 +894,18 @@ secondary_reload_class (class, mode, in)
   if (GET_CODE (in) == REG || GET_CODE (in) == SUBREG)
     regno = true_regnum (in);
 
+  /* If we are reloading a plus into a high accumulator register,
+     we need a scratch low accumulator, because the low half gets
+     clobbered */
+
+  if (class == ACCUM_HIGH_REGS 
+      || class == A1H_REG
+      || class == A0H_REG)
+    {
+      if (GET_CODE (in) == PLUS && mode == QImode)
+       return ACCUM_LOW_REGS;
+    }
+
   if (class == ACCUM_HIGH_REGS 
       || class == ACCUM_LOW_REGS
       || class == A1L_REG
@@ -737,6 +934,12 @@ secondary_reload_class (class, mode, in)
       (regno >= REG_A0 && regno < REG_A1L + 1))
     return NO_REGS;
 
+  if (class == ACCUM_OR_YBASE_REGS && REG_P(in)
+      && IS_YBASE_ELIGIBLE_REG(regno))
+    {
+      return NO_REGS;
+    }
+
   /* We can copy the ybase registers into:
      r0-r3, a0-a1, y, p, & x or the union of
      any of these. */
@@ -1128,6 +1331,9 @@ compute_frame_size (size)
   long extra_size;
   long reg_size;
 
+  /* This value is needed to compute reg_size */
+  current_frame_info.function_makes_calls = !leaf_function_p ();
+
   reg_size = 0;
   extra_size = 0;
   var_size = size;
@@ -1145,7 +1351,6 @@ compute_frame_size (size)
   current_frame_info.reg_size    = reg_size;
   current_frame_info.initialized = reload_completed;
   current_frame_info.reg_size   = reg_size / UNITS_PER_WORD;
-  current_frame_info.function_makes_calls = dsp16xx_makes_calls ();
 
   if (reg_size)
     {
@@ -1157,13 +1362,29 @@ compute_frame_size (size)
   return total_size;
 }
 
+int frame_size()
+{
+  return (int) compute_frame_size(get_frame_size());
+}
+
+int frame_pointer_offset()
+{
+  if (!leaf_function_p())
+    return ( -(current_function_outgoing_args_size + 1) );
+  else
+    return 1;
+}
+
 int
 dsp16xx_call_saved_register (regno)
      int regno;
 {
+#if 0
+  if (regno == REG_PR && current_frame_info.function_makes_calls)
+    return 1;
+#endif
   return (regs_ever_live[regno] && !call_used_regs[regno] &&
          !IS_YBASE_REGISTER_WINDOW(regno));
-
 }
 
 int
@@ -1182,10 +1403,10 @@ ybase_regs_ever_used ()
   return live;
 }
 
-static void 
+void 
 dsp16xx_output_function_prologue (file, size)
      FILE *file;
-     HOST_WIDE_INT size;
+     int  size;
 {
   int regno;
   long total_size;
@@ -1197,14 +1418,14 @@ dsp16xx_output_function_prologue (file, size)
   total_size = compute_frame_size (size);
   
   fprintf( file, "\t/* FUNCTION PROLOGUE: */\n" );
-  fprintf (file, "\t/* total=%ld, vars= %ld, regs= %d, args=%d, extra= %ld */\n",
+  fprintf (file, "\t/* total=%d, vars= %d, regs= %d, args=%d, extra= %d */\n",
           current_frame_info.total_size,
           current_frame_info.var_size,
           current_frame_info.reg_size,
           current_function_outgoing_args_size,
           current_frame_info.extra_size);
   
-  fprintf (file, "\t/* fp save offset= %ld, sp save_offset= %ld */\n\n",
+  fprintf (file, "\t/* fp save offset= %d, sp save_offset= %d */\n\n",
           current_frame_info.fp_save_offset,
           current_frame_info.sp_save_offset);
   /* Set up the 'ybase' register window. */
@@ -1219,58 +1440,51 @@ dsp16xx_output_function_prologue (file, size)
       fprintf (file, "\t%s=%s\n", reg_names[REG_YBASE], a1h);
     }
   
-#if 0
-  if (current_frame_info.function_makes_calls)
-    fprintf( file, "\t*%s++=%s\n", sp, rr );   /* Push return address */
-#endif
-  
-  
   if (current_frame_info.var_size)
     {
       if (current_frame_info.var_size == 1)
        fprintf (file, "\t*%s++\n", sp);
-      else if (SMALL_INTVAL (current_frame_info.var_size)
-              && ((current_frame_info.var_size & 0x8000) == 0))
-       fprintf (file, "\t%s=%ld\n\t*%s++%s\n", reg_names[REG_J],
-                current_frame_info.var_size, sp, reg_names[REG_J]);
       else
-       error ("Stack size > 32k");
+        {
+         if(SMALL_INTVAL(current_frame_info.var_size) && ((current_frame_info.var_size & 0x8000) == 0))
+           fprintf (file, "\t%s=%d\n\t*%s++%s\n", reg_names[REG_J], current_frame_info.var_size, sp, reg_names[REG_J]);
+         else
+           fatal_error ("Stack size > 32k");
+       }
     }
   
-  /* Save any registers this function uses, unless they are used in a call,
-     in which case we don't need to.  */
+  /* Save any registers this function uses, unless they are
+   * used in a call, in which case we don't need to
+   */
   
-  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++ regno)
+  for( regno = 0; regno < FIRST_PSEUDO_REGISTER; ++ regno )
     if (dsp16xx_call_saved_register (regno)) 
       {
-#if OLD_REGISTER_SAVE
-       fprintf (file, "\t*%s++=%s\n", sp, reg_names[regno]);
-#else
-       fprintf (file, "\tpush(*%s)=%s\n", sp, reg_names[regno]);
-#endif
+       fprintf( file, "\tpush(*%s)=%s\n", sp, reg_names[regno] );
       }
-  
+
+  /* For debugging purposes, we want the return address to be at a predictable
+     location */
+  if (current_frame_info.function_makes_calls)
+    fprintf( file, "\tpush(*%s)=%s\n", sp, reg_names[RETURN_ADDRESS_REGNUM]);
+
   if (current_frame_info.args_size)
     {
       if (current_frame_info.args_size == 1)
        fprintf (file, "\t*%s++\n", sp);
-      else if (SMALL_INTVAL (current_frame_info.args_size)
-              && (current_frame_info.args_size & 0x8000) == 0)
-       fprintf (file, "\t%s=%ld\n\t*%s++%s\n", reg_names[REG_J],
-                current_frame_info.args_size, sp, reg_names[REG_J]);
       else
        error ("Stack size > 32k");
     }
-  
+   
   if (frame_pointer_needed)
     {
-      fprintf (file, "\t%s=%s\n", a1h, sp);
-      fprintf (file, "\t%s=%s\n", fp, a1h);  /* Establish new base frame */
-      fprintf (file, "\t%s=%ld\n", reg_names[REG_J], -total_size);
-      fprintf (file, "\t*%s++%s\n", fp, reg_names[REG_J]);
+      fprintf( file, "\t%s=%s\n", a1h, sp );
+      fprintf( file, "\t%s=%s\n", fp, a1h );  /* Establish new base frame */
+      fprintf( file, "\t%s=%d\n", reg_names[REG_J], -total_size);
+      fprintffile, "\t*%s++%s\n", fp, reg_names[REG_J]);
     }
   
-  fprintf (file, "\t/* END FUNCTION PROLOGUE: */\n\n");
+  fprintf( file, "\t/* END FUNCTION PROLOGUE: */\n\n" );
 }
 
 void
@@ -1300,16 +1514,12 @@ init_emulation_routines ()
  dsp16xx_lshrhi3_libcall = (rtx) 0;
 
 }
-
-static void
+void
 dsp16xx_output_function_epilogue (file, size)
      FILE *file;
-     HOST_WIDE_INT size ATTRIBUTE_UNUSED;
+     int size ATTRIBUTE_UNUSED;
 {
   int regno;
-#if OLD_REGISTER_SAVE  
-  int initial_stack_dec = 0;
-#endif
   
   fp = reg_names[FRAME_POINTER_REGNUM];
   sp = reg_names[STACK_POINTER_REGNUM];
@@ -1324,7 +1534,7 @@ dsp16xx_output_function_epilogue (file, size)
        fprintf (file, "\t*%s--\n", sp);
       else
        {
-         fprintf (file, "\t%s=%ld\n\t*%s++%s\n", 
+         fprintf (file, "\t%s=%d\n\t*%s++%s\n", 
                   reg_names[REG_J], -current_frame_info.args_size, sp, reg_names[REG_J]);
        }
     }
@@ -1338,40 +1548,23 @@ dsp16xx_output_function_epilogue (file, size)
        fprintf (file, "\t%s=%sh-32\n", reg_names[REG_A1], a1h);
       fprintf (file, "\t%s=%s\n", reg_names[REG_YBASE], a1h);
     }
+
+  if (current_frame_info.function_makes_calls)
+    fprintf( file, "\t%s=pop(*%s)\n", reg_names[RETURN_ADDRESS_REGNUM], sp );
   
   for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; --regno)
     if (dsp16xx_call_saved_register(regno))
       {
-#if OLD_REGISTER_SAVE
-       if (!initial_stack_dec)
-         {
-           initial_stack_dec = 1;
-           fprintf (file, "\t*%s--\n", sp);
-         }
-#endif
-
-#if OLD_REGISTER_SAVE
-       fprintf( file, "\t%s=*%s--\n", reg_names[regno], sp );
-#else
        fprintf( file, "\t%s=pop(*%s)\n", reg_names[regno], sp );
-#endif
       }
   
-  /* If we restored any registers we have to account for the
-     initial pre-decrement. But only if we had any local variables
-     or spills. */
-#if OLD_REGISTER_SAVE  
-  if (initial_stack_dec) 
-    fprintf (file, "\t*%s++\n", sp);
-#endif
-  
   if (current_frame_info.var_size)
     {
       if (current_frame_info.var_size == 1)
        fprintf (file, "\t*%s--\n", sp);
       else
        {
-         fprintf (file, "\t%s=%ld\n\t*%s++%s\n", 
+         fprintf (file, "\t%s=%d\n\t*%s++%s\n", 
                   reg_names[REG_J], -current_frame_info.var_size, sp, reg_names[REG_J]);
        }
     }
@@ -1427,7 +1620,7 @@ double_reg_from_memory (operands)
     else if (GET_CODE(XEXP(operands[1],0)) == PLUS)
     {
       rtx addr;
-      int offset;
+      int offset = 0;
 
       output_asm_insn ("%u0=%1", operands);
 
@@ -1477,7 +1670,7 @@ double_reg_to_memory (operands)
     else if (GET_CODE(XEXP(operands[0],0)) == PLUS)
     {
       rtx addr;
-      int offset;
+      int offset = 0;
 
       output_asm_insn ("%0=%u1", operands);
 
@@ -1489,10 +1682,9 @@ double_reg_to_memory (operands)
       else if (GET_CODE (XEXP(addr,1)) == CONST_INT)
        offset = INTVAL(XEXP(addr,1)) + 1;
       else
-       abort ();
+       fatal_error ("Invalid addressing mode");
 
-      fprintf (asm_out_file, "\t*(%d)=%s\n", offset + 31,
-              reg_names[REGNO(operands[1]) + 1]);
+      fprintf (asm_out_file, "\t*(%d)=%s\n", offset + 31, reg_names[REGNO(operands[1]) + 1]);
     }
     else
     {
@@ -1541,15 +1733,6 @@ override_options ()
                                        strlen(const_seg_name) + 3);
   sprintf (tmp, ".rsect \"%s\"", const_seg_name);
   
-  if (optimize)
-    {
-      if (TARGET_OPTIMIZE_SPEED)
-       {
-         flag_unroll_loops = 1;
-         flag_inline_functions = 1;
-       }
-    }
-
   /* Mark our global variables for GC.  */
   ggc_add_rtx_root (&dsp16xx_addhf3_libcall, 1);
   ggc_add_rtx_root (&dsp16xx_subhf3_libcall, 1);
@@ -1574,13 +1757,31 @@ override_options ()
   ggc_add_rtx_root (&dsp16xx_lshrhi3_libcall, 1);
 }
 
+int
+next_cc_user_unsigned (insn)
+     rtx insn;
+{
+  switch (next_cc_user_code (insn))
+    {
+    case GTU:
+    case GEU:
+    case LTU:
+    case LEU:
+      return 1;
+    default:
+      return 0;
+    }
+}
 
 enum rtx_code
 next_cc_user_code (insn)
      rtx insn;
 {
+  /* If no insn could be found we assume that the jump has been
+     deleted and the compare will be deleted later. */
+
   if ( !(insn = next_cc0_user (insn)))
-    abort ();
+    return (enum rtx_code) 0;
   else if (GET_CODE (insn) == JUMP_INSN
           && GET_CODE (PATTERN (insn)) == SET
           && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE)
@@ -1593,22 +1794,6 @@ next_cc_user_code (insn)
     abort ();
 }
 
-int
-next_cc_user_unsigned (insn)
-     rtx insn;
-{
-  switch (next_cc_user_code (insn))
-    {
-    case GTU:
-    case GEU:
-    case LTU:
-    case LEU:
-      return 1;
-    default:
-      return 0;
-    }
-}
-
 void
 print_operand(file, op, letter)
      FILE *file;
@@ -1689,19 +1874,57 @@ print_operand(file, op, letter)
        else if (letter == 'h')
          fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);
         else if (letter == 'U')
-         fprintf (file, HOST_WIDE_INT_PRINT_HEX, (val >> 16) & 0xffff);
+         fprintf(file, HOST_WIDE_INT_PRINT_HEX, (val >> 16) & 0xffff);
         else
-         output_addr_const (file, op);
-      }
-    else if (code == CONST_DOUBLE && GET_MODE (op) != DImode)
+           output_addr_const( file, op );
+    }
+    else if( code == CONST_DOUBLE && GET_MODE(op) != DImode )
+    {
+         union { double d; int i[2]; } u;
+         union { float f; int i; } u1;
+         u.i[0] = CONST_DOUBLE_LOW (op);
+         u.i[1] = CONST_DOUBLE_HIGH (op);
+         u1.f = u.d;
+          fprintf( file, "0x%x", u1.i );
+    }
+    else if (code == CONST)
       {
-       union {double d; int i[2]; } u;
-       union {float f; int i; } u1;
-
-       u.i[0] = CONST_DOUBLE_LOW (op);
-       u.i[1] = CONST_DOUBLE_HIGH (op);
-       u1.f = u.d;
-       fprintf (file, "0x%x", u1.i);
+       rtx addr = XEXP (op, 0);
+       
+       if (GET_CODE (addr) != PLUS)
+         {
+           output_addr_const( file, op);
+           return;
+         }
+       
+       if ((GET_CODE (XEXP (addr, 0)) == SYMBOL_REF
+            || GET_CODE (XEXP (addr, 0)) == LABEL_REF)
+           && (GET_CODE (XEXP (addr, 1)) == CONST_INT))
+         {
+           int n = INTVAL (XEXP(addr, 1));
+           output_addr_const (file, XEXP (addr, 0));
+           
+           if (n >= 0)
+             fprintf (file, "+");
+           
+           n = (int) (short) n;
+           fprintf (file, "%d", n);
+         }
+       else if ((GET_CODE (XEXP (addr, 1)) == SYMBOL_REF
+                 || GET_CODE (XEXP (addr, 1)) == LABEL_REF)
+                && (GET_CODE (XEXP (addr, 0)) == CONST_INT))
+         {
+           int n = INTVAL (XEXP(addr, 0));
+           output_addr_const (file, XEXP (addr, 1));
+           
+           if (n >= 0)
+             fprintf (file, "+");
+           
+           n = (int) (short) n;
+           fprintf (file, "%d", n);
+         }
+       else
+         output_addr_const( file, op);
       }
     else
       output_addr_const (file, op);
@@ -1714,7 +1937,7 @@ print_operand_address(file, addr)
      rtx addr;
 {
   rtx base;
-  int offset;
+  int offset = 0;;
   
   switch (GET_CODE (addr))
     {
@@ -1737,10 +1960,10 @@ print_operand_address(file, addr)
          if (offset >= -31 && offset <= 0)
            offset = 31 + offset;
          else
-           abort ();
+           fatal_error ("Invalid offset in ybase addressing");
        }
       else
-       abort ();
+       fatal_error ("Invalid register in ybase addressing");
       
       fprintf (file, "*(%d)", offset);
       break;
@@ -1777,17 +2000,22 @@ static int
 reg_save_size ()
 {
   int reg_save_size = 0;
- int regno;
 int regno;
+
   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
     if (dsp16xx_call_saved_register (regno))
       {
        reg_save_size += UNITS_PER_WORD;
       }
 
+  /* If the function makes calls we will save need to save the 'pr' register */
+  if (current_frame_info.function_makes_calls)
+    reg_save_size += 1;
+
   return (reg_save_size);
 }
 
+#if 0
 int
 dsp16xx_starting_frame_offset()
 {
@@ -1802,6 +2030,7 @@ dsp16xx_starting_frame_offset()
 
   return (reg_save_size);
 }
+#endif
 
 int
 initial_frame_pointer_offset()
@@ -1913,7 +2142,7 @@ emit_1600_core_shift (shift_op, operands, shift_amount)
       shift_asm_ptr_first = lshift_right_asm_first;
     }
   else
-    abort ();
+    fatal_error ("Invalid shift operator in emit_1600_core_shift");
 
   while (shift_amount != 0)
     {
@@ -1956,6 +2185,57 @@ emit_1600_core_shift (shift_op, operands, shift_amount)
     }
 }
 #endif
+
+int
+num_1600_core_shifts (shift_amount)
+int shift_amount;
+{
+  int quotient;
+  int i;
+  int first_shift_emitted = 0;
+  int num_shifts = 0;
+
+  while (shift_amount != 0)
+    {
+      if (shift_amount/16)
+       {
+         quotient = shift_amount/16;
+         shift_amount = shift_amount - (quotient * 16);
+         for (i = 0; i < quotient; i++)
+           num_shifts++;
+         first_shift_emitted = 1;
+       }
+      else if (shift_amount/8)
+       {
+         quotient = shift_amount/8;
+         shift_amount = shift_amount - (quotient * 8);
+         for (i = 0; i < quotient; i++)
+           num_shifts++;
+
+         first_shift_emitted = 1;
+       }
+      else if (shift_amount/4)
+       {
+         quotient = shift_amount/4;
+         shift_amount = shift_amount - (quotient * 4);
+         for (i = 0; i < quotient; i++)
+           num_shifts++;
+
+         first_shift_emitted = 1;
+       }
+      else if (shift_amount/1)
+       {
+         quotient = shift_amount/1;
+         shift_amount = shift_amount - (quotient * 1);
+         for (i = 0; i < quotient; i++)
+           num_shifts++;
+
+         first_shift_emitted = 1;
+       }
+    }
+  return num_shifts;
+}
+
 void
 asm_output_common(file, name, size, rounded)
      FILE *file;
@@ -2134,6 +2414,9 @@ dsp16xx_function_arg (args_so_far, mode, type, named)
          && (mode == HImode || GET_MODE_CLASS(mode) == MODE_FLOAT))
        args_so_far++;
 
+      if (type == void_type_node)
+       return (struct rtx_def *) 0;
+
       if (named && args_so_far < 4 && !MUST_PASS_IN_STACK (mode,type))
        return gen_rtx_REG (mode, args_so_far + FIRST_REG_FOR_FUNCTION_ARG);
       else
@@ -2166,13 +2449,50 @@ dsp16xx_function_arg_advance (cum, mode, type, named)
 }
 
 void
-dsp16xx_file_start ()
+coff_dsp16xx_file_start (file)
+     FILE *file;
 {
-  fprintf (asm_out_file, "#include <%s.h>\n", save_chip_name);
-#if 0
-       if (TARGET_BMU)
-               fprintf (asm_out_file, "#include <1610.h>\n");
+  fprintf (file, "#include <%s.h>\n", save_chip_name);
+}
+
+void
+luxworks_dsp16xx_file_start (file)
+     FILE *file;
+{
+  char *temp_filename;
+  int len, err_code;
+
+
+  fprintf(file, "\t.debug ");
+  err_code = (TARGET_DEBUG) ? fprintf (file, "yes, ") : fprintf (file, "no, ");
+  err_code = (TARGET_SAVE_TEMPS) ? fprintf (file, "asm, ") : fprintf (file, "temp, ");
+  len = strlen (main_input_filename);
+  temp_filename = (char *) xmalloc (len + 2);
+  strcpy (temp_filename, main_input_filename);
+#ifdef __CYGWIN32__
+    p = temp_filename;
+    while (*p != '\0') {
+    if (*p == '\\')
+        *p = '/';
+         p++;
+         }
 #endif
+    fprintf(file, "\"%s\"\n", temp_filename);
+    fprintf(file, "");
+
+  fprintf (file, "#include <%s.h>\n", save_chip_name);
+
+   /*
+    * Add dummy sections, so that they always exist in the 
+    * object code. These have been created so that the number and
+    * type of sections remain consistent with and without -g option. Note
+    * that the .data, .text, .const and .bss are always created when -g
+    * is provided as an option. 
+    */
+   fprintf(file, "\t.rsect \".text\" , nodelete\n");
+   fprintf(file, "\t.rsect \".data\" , nodelete\n");
+   fprintf(file, "\t.rsect \".const\" , nodelete\n");
+   fprintf(file, "\t.rsect \".bss\" , nodelete\n");
 }
 
 rtx
@@ -2192,7 +2512,7 @@ gen_tst_reg (x)
   else if (mode == HImode)
     emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, x));
   else
-    abort ();
+    fatal_error ("Invalid mode for gen_tst_reg");
 
   return cc0_rtx;
 }
@@ -2243,28 +2563,19 @@ gen_compare_reg (code, x, y)
       if (code == GTU || code == GEU
          || code == LTU || code == LEU)
        {
-#if 1
-         emit_insn (gen_rtx_PARALLEL
-                    (VOIDmode,
+         emit_insn (gen_rtx_PARALLEL 
+                    (VOIDmode, 
                      gen_rtvec (5,
-                                gen_rtx_SET (VOIDmode, cc0_rtx,
-                                             gen_rtx_COMPARE (VOIDmode,
-                                                              x, y)),
-                                gen_rtx_CLOBBER (VOIDmode,
+                                gen_rtx_SET (VOIDmode, cc0_rtx, 
+                                             gen_rtx_COMPARE (VOIDmode, x, y)),
+                                gen_rtx_CLOBBER (VOIDmode, 
                                                  gen_rtx_SCRATCH (QImode)),
-                                gen_rtx_CLOBBER (VOIDmode,
+                                gen_rtx_CLOBBER (VOIDmode, 
                                                  gen_rtx_SCRATCH (QImode)),
-                                gen_rtx_CLOBBER (VOIDmode,
+                                gen_rtx_CLOBBER (VOIDmode, 
                                                  gen_rtx_SCRATCH (QImode)),
-                                gen_rtx_CLOBBER (VOIDmode,
+                                gen_rtx_CLOBBER (VOIDmode, 
                                                  gen_rtx_SCRATCH (QImode)))));
-#else
-         if (!dsp16xx_ucmphi2_libcall)
-           dsp16xx_ucmphi2_libcall = gen_rtx_SYMBOL_REF (Pmode, UCMPHI2_LIBCALL);
-         emit_library_call (dsp16xx_ucmphi2_libcall, 1, HImode, 2,
-                            x, HImode, y, HImode);
-         emit_insn (gen_tsthi_1 (copy_to_reg(hard_libcall_value (HImode))));
-#endif
        }
       else
        emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx,
@@ -2273,7 +2584,7 @@ gen_compare_reg (code, x, y)
                                                 force_reg (HImode,y))));
     }
   else
-    abort ();
+    fatal_error ("Invalid mode for integer comparison in gen_compare_reg");
 
   return cc0_rtx;
 }
@@ -2297,3 +2608,49 @@ output_block_move (operands)
   fprintf (asm_out_file, "\t}\n");
   return "";
 }
+
+int
+uns_comparison_operator (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  if (mode == VOIDmode || GET_MODE (op) == mode)
+    {
+      enum rtx_code code;
+      
+      code = GET_CODE(op);
+
+      if (code == LEU || code == LTU || code == GEU
+         || code == GTU)
+       {
+         return 1;
+       }
+      else
+       return 0;
+    }
+
+  return 0;
+}
+
+int
+signed_comparison_operator (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  if (mode == VOIDmode || GET_MODE (op) == mode)
+    {
+      enum rtx_code code;
+      
+      code = GET_CODE(op);
+
+      if (!(code == LEU || code == LTU || code == GEU
+         || code == GTU))
+       {
+         return 1;
+       }
+      else
+       return 0;
+    }
+
+  return 0;
+}
index f98d678..dae1d74 100644 (file)
@@ -1,7 +1,7 @@
 /* Definitions of target machine for GNU compiler.  AT&T DSP1600.
    Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001
    Free Software Foundation, Inc.
-   Contributed by Michael Collison (collison@world.std.com).
+   Contributed by Michael Collison (collison@isisinc.net).
 
 This file is part of GNU CC.
 
@@ -74,7 +74,9 @@ extern struct rtx_def *dsp16xx_lshrhi3_libcall;
 #ifdef  CC1_SPEC
 #undef  CC1_SPEC
 #endif
-#define CC1_SPEC       ""
+#define CC1_SPEC       "%{!O*:-O}"
+
+#define CPP_SPEC       "%{!O*:-D__OPTIMIZE__}"
 
 /* Define this as a spec to call the AT&T assembler */
 
@@ -111,22 +113,29 @@ extern struct rtx_def *dsp16xx_lshrhi3_libcall;
 
 
 /* Tell gcc where to look for the startfile */
-#define STANDARD_STARTFILE_PREFIX   "/d1600/lib"
+/*#define STANDARD_STARTFILE_PREFIX   "/d1600/lib"*/
 
-/* Tell gcc where to look for its executables */
-#define STANDARD_EXEC_PREFIX  "/d1600/bin"
+/* Tell gcc where to look for it's executables */
+/*#define STANDARD_EXEC_PREFIX  "/d1600/bin"*/
 
 /* Command line options to the AT&T assembler */
-#define ASM_SPEC  "%{v:-V} %{g*:-g}"
+#define ASM_SPEC  "%{V} %{v:%{!V:-V}} %{g*:-g}"
 
 /* Command line options for the AT&T linker */
-#define LINK_SPEC "%{v:-V} %{minit:-i}  \
-%{!ifile*:%{mmap1:-ifile m1_deflt.if%s}         \
-          %{mmap2:-ifile m2_deflt.if%s}         \
-          %{mmap3:-ifile m3_deflt.if%s}         \
-          %{mmap4:-ifile m4_deflt.if%s}         \
-          %{!mmap*:-ifile m4_deflt.if%s}}       \
-%{ifile*} %{!r:-a}"
+
+#define LINK_SPEC "%{V} %{v:%{!V:-V}} %{minit:-i}  \
+%{!ifile*:%{mmap1:m1_deflt.if%s}         \
+          %{mmap2:m2_deflt.if%s}         \
+          %{mmap3:m3_deflt.if%s}         \
+          %{mmap4:m4_deflt.if%s}         \
+          %{!mmap*:m4_deflt.if%s}}       \
+%{ifile*:%*} %{r}"
+
+/* Include path is determined from the environment variable */
+#define INCLUDE_DEFAULTS     \
+{                            \
+  { 0, 0, 0 }                \
+}
 
 /* Names to predefine in the preprocessor for this target machine.  */
 #ifdef __MSDOS__
@@ -145,8 +154,6 @@ extern int target_flags;
 #define MASK_NEAR_CALL       0x00000002    /* The call is on the same 4k page */
 #define MASK_NEAR_JUMP       0x00000004    /* The jump is on the same 4k page */
 #define MASK_BMU             0x00000008    /* Use the 'bmu' shift instructions */
-#define MASK_OPTIMIZE_MEMORY 0x00000010    /* Optimize to conserve memory */
-#define MASK_OPTIMIZE_SPEED  0x00000020    /* Optimize for speed */
 #define MASK_MAP1            0x00000040    /* Link with map1 */
 #define MASK_MAP2            0x00000080    /* Link with map2 */
 #define MASK_MAP3            0x00000100    /* Link with map3 */
@@ -154,8 +161,9 @@ extern int target_flags;
 #define MASK_YBASE_HIGH      0x00000400    /* The ybase register window starts high */
 #define MASK_INIT           0x00000800    /* Have the linker generate tables to
                                              initialize data at startup */
-#define MASK_INLINE_MULT     0x00001000    /* Inline 32 bit multiplies */
 #define MASK_RESERVE_YBASE   0x00002000    /* Reserved the ybase registers */
+#define MASK_DEBUG           0x00004000           /* Debugging turned on*/
+#define MASK_SAVE_TEMPS      0x00008000    /* Save temps. option seen */
 
 /* Compile passing first two args in regs 0 and 1.
    This exists only to test compiler features that will
@@ -177,12 +185,6 @@ extern int target_flags;
    Unit. */
 #define TARGET_BMU (target_flags & MASK_BMU)
 
-/* Optimize to conserve memory */
-#define TARGET_OPTIMIZE_MEMORY (target_flags & MASK_OPTIMIZE_MEMORY)
-
-/* Optimize for maximum speed */
-#define TARGET_OPTIMIZE_SPEED   (target_flags & MASK_OPTIMIZE_SPEED)
-
 #define TARGET_YBASE_HIGH (target_flags & MASK_YBASE_HIGH)
 
 /* Direct the linker to output extra info for initialized data */
@@ -193,6 +195,13 @@ extern int target_flags;
 /* Reserve the ybase registers *(0) - *(31) */
 #define TARGET_RESERVE_YBASE (target_flags & MASK_RESERVE_YBASE)
 
+/* We turn this option on internally after seeing "-g" */
+#define TARGET_DEBUG            (target_flags & MASK_DEBUG)
+
+/* We turn this option on internally after seeing "-save-temps */
+#define TARGET_SAVE_TEMPS       (target_flags & MASK_SAVE_TEMPS)
+
+
 /* Macro to define tables used to set the flags.
    This is a list in braces of pairs in braces,
    each pair being { "NAME", VALUE }
@@ -200,31 +209,46 @@ extern int target_flags;
    An empty string NAME is used to identify the default VALUE.  */
 
 
-#define TARGET_SWITCHES                        \
-  {                                           \
-    { "regparm",       MASK_REGPARM},         \
-    { "no-regparm",   -MASK_REGPARM},         \
-    { "no-near-call", -MASK_NEAR_CALL},        \
-    { "near-jump",     MASK_NEAR_JUMP},        \
-    { "no-near-jump", -MASK_NEAR_JUMP},        \
-    { "bmu",           MASK_BMU},              \
-    { "no-bmu",       -MASK_BMU},              \
-    { "Om",            MASK_OPTIMIZE_MEMORY},  \
-    { "Os",            MASK_OPTIMIZE_SPEED},   \
-    { "map1",          MASK_MAP1},             \
-    { "map2",          MASK_MAP2},             \
-    { "map3",          MASK_MAP3},             \
-    { "map4",          MASK_MAP4},             \
-    { "ybase-high",    MASK_YBASE_HIGH},       \
-    { "init",          MASK_INIT},             \
-    { "inline-mult",   MASK_INLINE_MULT},      \
-    { "reserve-ybase", MASK_RESERVE_YBASE},    \
-    { "",              TARGET_DEFAULT}         \
+#define TARGET_SWITCHES                                           \
+  {                                                              \
+    { "regparm",       MASK_REGPARM,                              \
+      N_("Pass parameters in registers (default)") },             \
+    { "no-regparm",   -MASK_REGPARM,                             \
+      N_("Don't pass parameters in registers") },                 \
+    { "near-call",     MASK_NEAR_JUMP,                            \
+      N_("Generate code for near calls") },                       \
+    { "no-near-call", -MASK_NEAR_CALL,                            \
+      N_("Don't generate code for near calls") },                 \
+    { "near-jump",     MASK_NEAR_JUMP,                            \
+      N_("Generate code for near jumps") },                       \
+    { "no-near-jump", -MASK_NEAR_JUMP,                            \
+      N_("Don't generate code for near jumps") },                 \
+    { "bmu",           MASK_BMU,                                  \
+      N_("Generate code for a bit-manipulation unit") },          \
+    { "no-bmu",       -MASK_BMU,                                  \
+      N_("Don't generate code for a bit-manipulation unit") },    \
+    { "map1",          MASK_MAP1,                                 \
+      N_("Generate code for memory map1") },                      \
+    { "map2",          MASK_MAP2,                                 \
+      N_("Generate code for memory map2") },                      \
+    { "map3",          MASK_MAP3,                                 \
+      N_("Generate code for memory map3") },                      \
+    { "map4",          MASK_MAP4,                                 \
+      N_("Generate code for memory map4") },                      \
+    { "init",          MASK_INIT,                                 \
+      N_("Ouput extra code for initialized data") },              \
+    { "reserve-ybase", MASK_RESERVE_YBASE,                        \
+      N_("Don't let reg. allocator use ybase registers") },       \
+    { "debug",         MASK_DEBUG,                                \
+      N_("Output extra debug info in Luxworks environment") },    \
+    { "save-temporaries",    MASK_SAVE_TEMPS,                     \
+      N_("Save temp. files in Luxworks environment") },           \
+    { "",              TARGET_DEFAULT, ""}                        \
   }
 
 /* Default target_flags if no switches are specified */
 #ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT  MASK_OPTIMIZE_MEMORY|MASK_REGPARM|MASK_YBASE_HIGH
+#define TARGET_DEFAULT  MASK_REGPARM|MASK_YBASE_HIGH
 #endif
 
 /* This macro is similar to `TARGET_SWITCHES' but defines names of
@@ -246,11 +270,16 @@ extern int target_flags;
 
 #define TARGET_OPTIONS                                         \
 {                                                              \
-  { "text=",   &text_seg_name  },                              \
-  { "data=",   &data_seg_name  },                              \
-  { "bss=",    &bss_seg_name   },                              \
-  { "const=",   &const_seg_name },                              \
-  { "chip=",    &chip_name      }                               \
+  { "text=",   &text_seg_name,                                 \
+    N_("Specify alternate name for text section") },            \
+  { "data=",   &data_seg_name,                                 \
+    N_("Specify alternate name for data section") },            \
+  { "bss=",    &bss_seg_name,                                  \
+    N_("Specify alternate name for bss section") },             \
+  { "const=",   &const_seg_name,                                \
+    N_("Specify alternate name for constant section") },        \
+  { "chip=",    &chip_name,                                     \
+    N_("Specify alternate name for dsp16xx chip") },            \
 }
 
 /* Sometimes certain combinations of command options do not make sense
@@ -264,18 +293,21 @@ extern int target_flags;
 
 #define OVERRIDE_OPTIONS override_options ()
 
-#define OPTIMIZATION_OPTIONS(LEVEL,SIZE)               \
-do                                                     \
-  {                                                    \
-    flag_gnu_linker             = FALSE;               \
-                                                       \
-    if (SIZE)                                          \
-      {                                                        \
-       flag_strength_reduce    = FALSE;                \
-       flag_inline_functions   = FALSE;                \
-      }                                                        \
-  }                                                    \
-while (0)
+#define OPTIMIZATION_OPTIONS(LEVEL,SIZE)              \
+{                                                     \
+    flag_gnu_linker             = FALSE;              \
+                                                      \
+    if (LEVEL >= 2)                                   \
+    {                                                 \
+        /* The dsp16xx family has so few registers    \
+         * that running the first instruction         \
+         * scheduling is bad for reg. allocation      \
+         * since it increases lifetimes of pseudos.   \
+         * So turn of first scheduling pass.          \
+         */                                           \
+        flag_schedule_insns          = FALSE;         \
+    }                                                 \
+}
 \f
 /* STORAGE LAYOUT */
 
@@ -287,7 +319,7 @@ while (0)
 /* Define this if most significant bit is lowest numbered
    in instructions that operate on numbered bit-fields.
  */
-#define BITS_BIG_ENDIAN  1
+#define BITS_BIG_ENDIAN  0
 
 /* Define this if most significant byte of a word is the lowest numbered.
    We define big-endian, but since the 1600 series cannot address bytes
@@ -377,12 +409,13 @@ while (0)
 /* A C expression for a string describing the name of the data type to use for
    size values. */
 
-#define SIZE_TYPE    "long unsigned int"
+#define SIZE_TYPE    "unsigned int"
 
-/* A C expression for a string describing the name of the datat type to use for the
+/* A C expression for a string describing the name of the data type to use for the
    result of subtracting two pointers */
 
-#define PTRDIFF_TYPE "long int"
+#define PTRDIFF_TYPE "int"
+
 \f
 /* REGISTER USAGE.  */
 
@@ -475,6 +508,10 @@ while (0)
 /* Do we have a virtual ybase register */
 #define IS_YBASE_REGISTER_WINDOW(REGNO) ((REGNO) >= REG_YBASE0 && (REGNO) <= REG_YBASE31)
 
+#define IS_YBASE_ELIGIBLE_REG(REGNO) (IS_ACCUM_REG (REGNO) || IS_ADDRESS_REGISTER(REGNO) \
+                                      || REGNO == REG_X || REGNO == REG_Y || REGNO == REG_YL \
+                                      || REGNO == REG_PROD || REGNO == REG_PRODL)
+
 #define IS_ADDRESS_REGISTER(REGNO) ((REGNO) >= REG_R0 && (REGNO) <= REG_R3)
 
 #define FIXED_REGISTERS     \
@@ -483,7 +520,7 @@ while (0)
  1,                         \
  0, 0, 0, 0,                \
  1, 1, 1,                   \
0, 0,                      \
1, 0,                      \
  0, 0, 0, 0, 0, 0, 0, 0,    \
  0, 0, 0, 0, 0, 0, 0, 0,    \
  0, 0, 0, 0, 0, 0, 0, 0,    \
@@ -501,17 +538,17 @@ while (0)
    bit manipulation registers.  */
 
 
-#define CALL_USED_REGISTERS   \
-{1, 1, 1, 1, 0, 1, 1, 1, 1,   \
- 1, 0, 0, 1, 1, 1, 1,         \
- 1,                           \
- 0, 0, 1, 1,                  \
- 1, 1, 1,                     \
0, 1,                        \
- 0, 0, 0, 0, 0, 0, 0, 0,      \
- 0, 0, 0, 0, 0, 0, 0, 0,      \
- 0, 0, 0, 0, 0, 0, 0, 0,      \
- 0, 0, 0, 0, 0, 0, 0, 0}
+#define CALL_USED_REGISTERS                    \
+{1, 1, 1, 1, 0, 1, 1, 1, 1,    /* 0-8 */       \
+ 1, 0, 0, 1, 1, 1, 1,          /* 9-15 */      \
+ 1,                             /* 16 */       \
+ 0, 0, 1, 1,                   /* 17-20 */     \
+ 1, 1, 1,                      /* 21-23 */     \
1, 1,                         /* 24-25 */     \
+ 0, 0, 0, 0, 0, 0, 0, 0,       /* 26-33 */     \
+ 0, 0, 0, 0, 0, 0, 0, 0,       /* 34-41 */     \
+ 0, 0, 0, 0, 0, 0, 0, 0,       /* 42-49 */     \
+ 0, 0, 0, 0, 0, 0, 0, 0}       /* 50-57 */
 
 /* List the order in which to allocate registers.  Each register must be
    listed once, even those in FIXED_REGISTERS.
@@ -519,6 +556,7 @@ while (0)
    We allocate in the following order:
  */
 
+#if 0
 #define REG_ALLOC_ORDER                                        \
 { REG_R0, REG_R1, REG_R2, REG_PROD, REG_Y, REG_X,       \
   REG_PRODL, REG_YL, REG_AR0, REG_AR1,                  \
@@ -534,7 +572,24 @@ while (0)
   REG_YBASE20, REG_YBASE21, REG_YBASE22, REG_YBASE23,   \
   REG_YBASE24, REG_YBASE25, REG_YBASE26, REG_YBASE27,   \
   REG_YBASE28, REG_YBASE29, REG_YBASE30, REG_YBASE31 }
-
+#else
+#define REG_ALLOC_ORDER                                 \
+{                                                       \
+  REG_A0, REG_A0L, REG_A1, REG_A1L, REG_Y, REG_YL,      \
+  REG_PROD,                                             \
+  REG_PRODL, REG_R0, REG_J, REG_K, REG_AR2, REG_AR3,    \
+  REG_X, REG_R1, REG_R2, REG_RB, REG_AR0, REG_AR1,      \
+  REG_YBASE0, REG_YBASE1, REG_YBASE2, REG_YBASE3,       \
+  REG_YBASE4, REG_YBASE5, REG_YBASE6, REG_YBASE7,       \
+  REG_YBASE8, REG_YBASE9, REG_YBASE10, REG_YBASE11,     \
+  REG_YBASE12, REG_YBASE13, REG_YBASE14, REG_YBASE15,   \
+  REG_YBASE16, REG_YBASE17, REG_YBASE18, REG_YBASE19,   \
+  REG_YBASE20, REG_YBASE21, REG_YBASE22, REG_YBASE23,   \
+  REG_YBASE24, REG_YBASE25, REG_YBASE26, REG_YBASE27,   \
+  REG_YBASE28, REG_YBASE29, REG_YBASE30, REG_YBASE31,   \
+  REG_R3, REG_YBASE, REG_PT, REG_C0, REG_C1, REG_C2,    \
+  REG_PR }
+#endif
 /* Zero or more C statements that may conditionally modify two
    variables `fixed_regs' and `call_used_regs' (both of type `char
    []') after they have been initialized from the two preceding
@@ -978,23 +1033,32 @@ enum reg_class
    'I' requires a non-negative 16-bit value.
    'J' requires a non-negative 9-bit value
    'K' requires a constant 0 operand.
-   'L' requires 16-bit value
+   'L' constant for use in add or sub from low 16-bits
    'M' 32-bit value -- low 16-bits zero
+   'N' constant for use incrementing or decrementing a address register
+   'O' constant for use with and'ing only high 16-bit
+   'P' constant for use with and'ing only low 16-bit
  */
 
 #define SMALL_INT(X) (SMALL_INTVAL (INTVAL (X)))
 #define SMALL_INTVAL(I) ((unsigned) (I) < 0x10000)
 #define SHORT_IMMEDIATE(X)  (SHORT_INTVAL (INTVAL(X)))
 #define SHORT_INTVAL(I)     ((unsigned) (I) < 0x100)
+#define ADD_LOW_16(I)       ((I) >= 0 && (I) <= 32767)
+#define ADD_HIGH_16(I)      (((I) & 0x0000ffff) == 0)
+#define AND_LOW_16(I)       ((I) >= 0 && (I) <= 32767)
+#define AND_HIGH_16(I)      (((I) & 0x0000ffff) == 0)
 
 #define CONST_OK_FOR_LETTER_P(VALUE, C)                           \
    ((C) == 'I' ? (SMALL_INTVAL(VALUE))                            \
     : (C) == 'J' ? (SHORT_INTVAL(VALUE))                          \
     : (C) == 'K' ? ((VALUE) == 0)                                 \
-    : (C) == 'L' ? ! ((VALUE) & ~0x0000ffff)                     \
-    : (C) == 'M' ? ! ((VALUE) & ~0xffff0000)                     \
-    : (C) == 'N' ? ((VALUE) == -1 || (VALUE) == 1 ||              \
-                    (VALUE) == -2 || (VALUE) == 2)                \
+    : (C) == 'L' ? ((VALUE) >= 0 && (VALUE) <= 32767)             \
+    : (C) == 'M' ? (((VALUE) & 0x0000ffff) == 0)                  \
+    : (C) == 'N' ? ((VALUE) == -1 || (VALUE) == 1                 \
+                    || (VALUE) == -2 || (VALUE) == 2)             \
+    : (C) == 'O' ? (((VALUE) & 0xffff0000) == 0xffff0000)         \
+    : (C) == 'P' ? (((VALUE) & 0x0000ffff) == 0xffff)             \
     : 0)
 
 #define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C)   1
@@ -1043,6 +1107,7 @@ struct dsp16xx_frame_info
   unsigned int  reg_size;      /* # bytes needed to store regs */
   long         fp_save_offset; /* offset from vfp to store registers */
   unsigned long sp_save_offset;        /* offset from new sp to store registers */
+  int          pr_save_offset; /* offset to saved PR */
   int          initialized;    /* != 0 if frame size already calculated */
   int          num_regs;       /* number of registers saved */
   int           function_makes_calls;  /* Does the function make calls */
@@ -1050,6 +1115,8 @@ struct dsp16xx_frame_info
 
 extern struct dsp16xx_frame_info current_frame_info;
 
+#define RETURN_ADDR_OFF current_frame_info.pr_save_offset
+
 /* If we generate an insn to push BYTES bytes,
    this says how many the stack pointer really advances by. */
 /* #define PUSH_ROUNDING(BYTES) ((BYTES)) */
@@ -1402,7 +1469,7 @@ extern struct dsp16xx_frame_info current_frame_info;
    return it with a return statement. */
 #define CONST_COSTS(RTX,CODE,OUTER_CODE)                                \
   case CONST_INT:                                                      \
-    return 0;                                                           \
+    return (unsigned) INTVAL (RTX) < 65536 ? 0 : 2;                     \
   case LABEL_REF:                                                      \
   case SYMBOL_REF:                                                     \
   case CONST:                                                          \
@@ -1427,45 +1494,21 @@ extern struct dsp16xx_frame_info current_frame_info;
     else                                                        \
         return COSTS_N_INSNS (38);                              \
   case PLUS:                                                    \
-    if (GET_MODE_CLASS (GET_MODE (X)) == MODE_INT)              \
-    {                                                           \
-        if (GET_CODE (XEXP (X,1)) == CONST_INT)                 \
-        {                                                       \
-            int number = INTVAL(XEXP (X,1));                    \
-            if (number == 1)                                    \
-               return COSTS_N_INSNS (1);                        \
-            if (INT_FITS_16_BITS(number))                       \
-                return COSTS_N_INSNS (2);                       \
-            else                                                \
-                return COSTS_N_INSNS (4);                       \
-        }                                                       \
-        return COSTS_N_INSNS (1);                               \
-    }                                                           \
-    else                                                        \
-        return COSTS_N_INSNS (38);                              \
   case MINUS:                                                   \
     if (GET_MODE_CLASS (GET_MODE (X)) == MODE_INT)              \
-    {                                                           \
-        if (GET_CODE (XEXP (X,1)) == CONST_INT)                 \
         {                                                       \
-            if (INT_FITS_16_BITS(INTVAL(XEXP(X,1))))            \
-                return COSTS_N_INSNS (2);                       \
-            else                                                \
-                return COSTS_N_INSNS (4);                       \
+          return (1 +                                           \
+                  rtx_cost (XEXP (X, 0), CODE) +                \
+                  rtx_cost (XEXP (X, 1), CODE));                \
         }                                                       \
-        return COSTS_N_INSNS (1);                               \
-    }                                                           \
     else                                                        \
         return COSTS_N_INSNS (38);                              \
+                                                                \
   case AND: case IOR: case XOR:                                 \
-    if (GET_CODE (XEXP (X,1)) == CONST_INT)                     \
-      {                                                         \
-        if (INT_FITS_16_BITS(INTVAL(XEXP(X,1))))                \
-            return COSTS_N_INSNS (2);                           \
-        else                                                    \
-            return COSTS_N_INSNS (4);                           \
-      }                                                         \
-    return COSTS_N_INSNS (1);                                   \
+        return (1 +                                             \
+                rtx_cost (XEXP (X, 0), CODE) +                  \
+                rtx_cost (XEXP (X, 1), CODE));                  \
+                                                                \
   case NEG: case NOT:                                           \
     return COSTS_N_INSNS (1);                                   \
   case ASHIFT:                                                  \
@@ -1478,9 +1521,17 @@ extern struct dsp16xx_frame_info current_frame_info;
             number == 16)                                       \
             return COSTS_N_INSNS (1);                           \
         else                                                    \
+       {                                                       \
+          if (TARGET_BMU)                                       \
             return COSTS_N_INSNS (2);                           \
+          else                                                  \
+            return COSTS_N_INSNS (num_1600_core_shifts(number)); \
+       }                                                       \
       }                                                         \
-    return COSTS_N_INSNS (1);
+    if (TARGET_BMU)                                             \
+      return COSTS_N_INSNS (1);                                 \
+    else                                                        \
+      return COSTS_N_INSNS (15);
 
 /* An expression giving the cost of an addressing mode that contains
    address. */
@@ -1500,7 +1551,7 @@ extern struct dsp16xx_frame_info current_frame_info;
 
 /* A C expression for the cost of a branch instruction. A value of
    1 is the default; */
-#define BRANCH_COST 2
+#define BRANCH_COST 1
 \f
 
 /* Define this because otherwise gcc will try to put the function address
@@ -1566,11 +1617,15 @@ const_section ()                                                   \
 /* THE OVERALL FRAMEWORK OF AN ASSEMBLER FILE */
 
 /* Output at beginning of assembler file.  */
-#define ASM_FILE_START(FILE) dsp16xx_file_start () 
+#define ASM_FILE_START(FILE) coff_dsp16xx_file_start (FILE) 
+
+/* Prevent output of .gcc_compiled */
+#define ASM_IDENTIFY_GCC(FILE)   
 
 /* A C string constant describing how to begin a comment in the target
    assembler language. */
-/* define ASM_COMMENT_START */
+#define ASM_COMMENT_START ""
+#define ASM_COMMENT_END ""
 
 /* Output to assembler file text saying following lines
    may contain character constants, extra white space, comments, etc.  */
@@ -1605,9 +1660,7 @@ const_section ()                                                   \
 #define ASM_OUTPUT_INT(FILE, EXP)    asm_output_long(FILE,INTVAL(EXP))
 
 /* This is how to output an assembler line for a numeric constant byte.  */
-#define ASM_OUTPUT_BYTE(FILE,VALUE) \
-  fprintf ((FILE), "\tint %ld\n", (long)(VALUE))
-
+#define ASM_OUTPUT_BYTE(FILE,VALUE)    ASM_OUTPUT_CHAR(FILE,GEN_INT(VALUE))
 
 /* This is how we output a 'c' character string. For the 16xx
    assembler we have to do it one letter at a time */
@@ -1643,7 +1696,7 @@ const_section ()                                                   \
              fprintf (asm_out_file, "%d", c);                                \
              /* After an octal-escape, if a digit follows,                   \
                 terminate one string constant and start another.             \
-                The VAX assembler fails to stop reading the escape           \
+                The Vax assembler fails to stop reading the escape           \
                 after three digits, so this is the only way we               \
                 can get it to parse the data properly.                       \
              if (i < thissize - 1                                            \
@@ -1683,6 +1736,10 @@ const_section ()                                                   \
     (OUTPUT) = (char *) alloca (strlen (NAME) + 11);                   \
     ASM_GENERATE_INTERNAL_LABEL (OUTPUT, temp, LABELNO);               \
   } while (0)
+
+#define ASM_OPEN_PAREN "("
+#define ASM_CLOSE_PAREN ")"
+
 \f
 /* OUTPUT OF UNINITIALIZED VARIABLES */
 
@@ -1837,17 +1894,19 @@ const_section ()                                                   \
 
 /* CONTROLLING DEBUGGING INFORMATION FORMAT */
 
-/* Define this macro if GCC should produce COFF-style debugging output
-   for SDB in response to the '-g' option */
-#define SDB_DEBUGGING_INFO
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
 
-/* Support generating stabs for the listing file generator */
-#define DBX_DEBUGGING_INFO
+#define DBX_REGISTER_NUMBER(REGNO)   (REGNO)
 
-/* The default format when -g is given is still COFF debug info */
-#define PREFERRED_DEBUGGING_TYPE SDB_DEBUG
+#define ASM_OUTPUT_DEF(asm_out_file, LABEL1, LABEL2) \
+         do {                                          \
+        fprintf (asm_out_file, ".alias " ); \
+         ASM_OUTPUT_LABELREF(asm_out_file, LABEL1);  \
+        fprintf (asm_out_file, "=" ); \
+         ASM_OUTPUT_LABELREF(asm_out_file, LABEL2); \
+        fprintf (asm_out_file, "\n" );                 \
+        } while (0)
 
-#define DBX_REGISTER_NUMBER(REGNO)   (REGNO)
 \f
 /* MISCELLANEOUS PARAMETERS */
 
@@ -1899,17 +1958,12 @@ const_section ()                                                   \
 #define TARGET_VERSION fprintf (stderr, " (%s, %s)", VERSION_INFO1, __DATE__)
 #endif
 
-#define VERSION_INFO1 "AT&T DSP16xx C Cross Compiler, version 1.2.0"
+#define VERSION_INFO1 "Lucent DSP16xx C Cross Compiler, version 1.3.0b"
 
 
 /* Define this as 1 if `char' should by default be signed; else as 0.  */
 #define DEFAULT_SIGNED_CHAR 1
 
-/* If this macro is defined, GNU CC gathers statistics about the number and
-   kind of tree node it allocates during each run. The option '-fstats' will
-   tell the compiler to print these statistics about the sizes of it obstacks. */
-#define GATHER_STATISTICS
-
 /* Define this so gcc does not output a call to __main, since we
    are not currently supporting c++. */
 #define INIT_SECTION_ASM_OP  1
index 29d9acd..1f44420 100644 (file)
@@ -1,6 +1,6 @@
 ;;- Machine description for the AT&T DSP1600 for GNU C compiler
 ;;  Copyright (C) 1994, 1995, 1997, 1998, 2001 Free Software Foundation, Inc.
-;;  Contributed by Michael Collison (collison@world.std.com).
+;;  Contributed by Michael Collison (collison@isisinc.net).
 
 ;; This file is part of GNU CC.
 
 
 ; Classification of each insn.  Some insns of TYPE_BRANCH are multi-word.
 (define_attr "type"
-  "jump,cond_jump,call,load_i,load,move,store,malu,malu_mul,special,f3_alu,f3_alu_i,shift_i,shift,bfield_i,bfield,nop,ld_short_i"
+  "jump,cond_jump,call,load_i,load,move,store,malu,malu_mul,tstqi,special,special_2,f3_alu,f3_alu_i,f3_alu_i_mult,shift_i,shift,shift_multiple,shift_i_multiple,bfield_i,bfield,nop,ld_short_i,data_move,data_move_i,data_move_memory,data_move_memory_2,data_move_short_i,data_move_multiple,data_move_2,nothing"
   (const_string "malu"))
 
-; Length in # of instructions of each insn.  The values are not exact, but
-; are safe.
-(define_attr "length" ""
-  (cond [(eq_attr "type" "cond_jump,f3_alu_i,shift_i,bfield_i,load_i")
-        (const_int 2)]
-       (const_int 1)))
+;; Data arithmetic unit
+(define_function_unit "dau" 1 1 (eq_attr "type" "data_move,data_move_i,f3_alu_i") 2 0)
+
+(define_function_unit "dau" 1 1 (eq_attr "type" "special_2") 3 0)
+
+(define_function_unit "dau" 1 1 (eq_attr "type" "data_move_2") 4 0)
+
+;; Bit manipulation
+(define_function_unit "bmu" 1 1 (eq_attr "type" "shift_i,shift_i_multiple") 2 0)
+
+(define_function_unit "bmu" 1 1 (eq_attr "type" "shift_multiple") 4 0)
+
+;; Y-memory addressing arithmetic unit
+(define_function_unit "yaau" 1 1 (eq_attr "type" "data_move_memory") 2 0)
+
+(define_function_unit "yaau" 1 1 (eq_attr "type" "data_move_memory_2") 4 0)
 
 \f
 ;;  ....................
   DONE;
 }")
 
+(define_split
+  [(set (cc0)
+       (match_operand:QI 0 "register_operand" "j,q"))
+   (clobber (match_scratch:QI 1 "=k,u"))]
+  "reload_completed"
+  [(set (match_dup 1)
+       (const_int 0))
+   (parallel [(set (cc0)
+                  (match_dup 0))
+             (use (match_dup 1))])]
+  "")
+
+(define_insn "tstqi_split"
+  [(set (cc0)
+       (match_operand:QI 0 "register_operand" "j,q"))
+   (use (match_scratch:QI 1 "=k,u"))]
+  ""
+  "@
+   %b0-0
+   %b0-0"
+  [(set_attr "type" "f3_alu_i,f3_alu_i")])
+
 (define_insn "tstqi_1"
   [(set (cc0)
        (match_operand:QI 0 "register_operand" "j,q"))
   "@
    %1=0\;%b0-0
    %1=0\;%b0-0"
-  [(set_attr "type" "malu,malu")])
+  [(set_attr "type" "tstqi,tstqi")])
 
 \f
 ;;
 
 (define_insn ""
   [(set (cc0)
-       (and:HI (match_operand:HI 0 "register_operand" "A,!A,A")
-               (match_operand:HI 1 "nonmemory_operand" "Z,A,I")))]
+       (and:HI (match_operand:HI 0 "register_operand" "A,!A")
+               (match_operand:HI 1 "register_operand" "Z,A")))]
   "" 
   "*
 {
           case 0:
           case 1:
              return \"%0&%1\";
-
-          case 2:
-             return \"%0&%H1\";
-           default:
-              abort();
          }
 }"
-  [(set_attr "type" "f3_alu,malu,f3_alu_i")])
+  [(set_attr "type" "f3_alu,f3_alu")])
 
 
 ;;(define_insn ""
       else if (IS_YBASE_REGISTER_WINDOW (REGNO (operands[0])))
        output_asm_insn (\"a0=%u0\;a0l=%w0\", operands);
       else
-       abort ();
+       fatal_error (\"Invalid register for compare\");
     }
   else if (GET_CODE(operands[0]) == CONST_INT)
     output_asm_insn (\"a0=%U0\;a0l=%H0\", operands);
       else if (IS_YBASE_REGISTER_WINDOW (REGNO (operands[1])))
        output_asm_insn (\"a1=%u1\;a1l=%w1\", operands);
       else
-       abort ();
+       fatal_error (\"Invalid register for compare\");
     }
   else if (GET_CODE (operands[1]) == MEM)
     {
     }
  }")
 
+(define_split
+  [(set (cc0)
+       (compare (match_operand:QI 0 "register_operand" "")
+                (match_operand:QI 1 "register_operand" "")))
+   (clobber (match_scratch:QI 2 ""))
+   (clobber (match_scratch:QI 3 ""))]
+  "reload_completed && next_cc_user_unsigned (insn)"
+  [(set (match_dup 2)
+       (const_int 0))
+   (set (match_dup 3)
+       (const_int 0))
+   (parallel [(set (cc0)
+                  (compare (match_dup 0)
+                           (match_dup 1)))
+             (use (match_dup 2))
+             (use (match_dup 3))])]
+  "")
+
+(define_split
+  [(set (cc0)
+       (compare (match_operand:QI 0 "register_operand" "")
+                (match_operand:QI 1 "const_int_operand" "")))
+   (clobber (match_scratch:QI 2 ""))
+   (clobber (match_scratch:QI 3 ""))]
+  "reload_completed && next_cc_user_unsigned (insn)"
+  [(set (match_dup 2)
+       (const_int 0))
+   (parallel [(set (cc0)
+                  (compare (match_dup 0)
+                           (match_dup 1)))
+             (use (match_dup 2))])]
+  "")
+
+(define_insn "cmpqi_split_unsigned_reg"
+  [(set (cc0) (compare (match_operand:QI 0 "register_operand"  "k,k,!k,u,u,!u")
+                       (match_operand:QI 1 "register_operand"  "w,z,u,w,z,k")))
+       (use (match_scratch:QI 2 "=j,j,j,q,q,q"))
+       (use (match_scratch:QI 3 "=v,y,q,v,y,j"))]
+  "next_cc_user_unsigned (insn)"
+  "@
+   %2-%3
+   %2-%3
+   %2-%3
+   %2-%3
+   %2-%3
+   %2-%3"
+  [(set_attr "type" "malu,malu,malu,malu,malu,malu")])
+
+(define_insn "cmpqi_split_unsigned_int"
+  [(set (cc0) (compare (match_operand:QI 0 "register_operand"  "k,u")
+                       (match_operand:QI 1 "const_int_operand" "i,i")))
+       (use (match_scratch:QI 2 "=j,q"))]
+  "next_cc_user_unsigned (insn)"
+  "@
+   %0-%H1
+   %0-%H1"
+  [(set_attr "type" "f3_alu_i,f3_alu_i")])
+
 (define_insn ""
   [(set (cc0) (compare (match_operand:QI 0 "register_operand"  "k,k,!k,k,u,u,!u,u")
                        (match_operand:QI 1 "nonmemory_operand" "w,z,u,i,w,z,k,i")))
    %2=0\;%3=0\;%2-%3
    %2=0\;%0-%H1")
 
+(define_split
+  [(set (cc0)
+       (compare (match_operand:QI 0 "register_operand" "")
+                (match_operand:QI 1 "register_operand" "")))
+   (clobber (match_scratch:QI 2 ""))
+   (clobber (match_scratch:QI 3 ""))]
+  "reload_completed"
+  [(set (match_dup 2)
+       (const_int 0))
+   (set (match_dup 3)
+       (const_int 0))
+   (parallel [(set (cc0)
+                  (compare (match_dup 0)
+                           (match_dup 1)))
+             (use (match_dup 2))
+             (use (match_dup 3))])]
+  "")
+
+(define_split
+  [(set (cc0)
+       (compare (match_operand:QI 0 "register_operand" "")
+                (match_operand:QI 1 "const_int_operand" "")))
+   (clobber (match_scratch:QI 2 ""))
+   (clobber (match_scratch:QI 3 ""))]
+  "reload_completed"
+  [(set (match_dup 2)
+       (const_int 0))
+   (parallel [(set (cc0)
+                  (compare (match_dup 0)
+                           (match_dup 1)))
+             (use (match_dup 2))])]
+  "")
+
+(define_insn "cmpqi_split_reg"
+  [(set (cc0) (compare (match_operand:QI 0 "register_operand"  "j,j,!j,q,q,!q")
+                       (match_operand:QI 1 "register_operand"  "v,y,q,v,y,j")))
+       (use (match_scratch:QI 2 "=k,k,k,u,u,u"))
+       (use (match_scratch:QI 3 "=w,z,u,w,z,k"))]
+  ""
+  "@
+   %0-%1
+   %0-%1
+   %0-%1
+   %0-%1
+   %0-%1
+   %0-%1"
+  [(set_attr "type" "malu,malu,malu,malu,malu,malu")])
+
+
+(define_insn "cmpqi_split_int"
+  [(set (cc0) (compare (match_operand:QI 0 "register_operand"  "j,q")
+                       (match_operand:QI 1 "const_int_operand" "i,i")))
+       (use (match_scratch:QI 2 "=k,u"))]
+  ""
+  "@
+   %b0-%H1
+   %b0-%H1"
+  [(set_attr "type" "f3_alu_i,f3_alu_i")])
 
 (define_insn ""
   [(set (cc0) (compare (match_operand:QI 0 "register_operand"  "j,j,!j,j,q,q,!q,q")
 ;;
 ;;  ....................
 
+(define_split
+  [(set (match_operand:HI 0 "register_operand" "")
+       (plus:HI (match_operand:HI 1 "register_operand" "")
+                (match_operand:HI 2 "const_int_operand" "")))]
+  "reload_completed && !ADD_LOW_16(INTVAL(operands[2])) && 
+   !ADD_HIGH_16(INTVAL(operands[2]))"
+  [(parallel [(set (match_dup 3)
+                  (plus:QI (match_dup 4)
+                           (match_dup 5)))
+             (clobber (match_dup 6))])
+
+   (parallel [(set (match_dup 6)
+                  (plus:QI (match_dup 7)
+                           (match_dup 8)))
+             (clobber (match_scratch:QI 9 ""))])]
+  "
+{
+  operands[3] = gen_lowpart(QImode, operands[0]);
+  operands[4] = gen_lowpart(QImode, operands[1]);
+  operands[5] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff);
+
+  operands[6] = gen_highpart(QImode, operands[0]);
+  operands[7] = gen_highpart(QImode, operands[0]);
+  operands[8] = gen_rtx (CONST_INT, VOIDmode, (((INTVAL (operands[2]) & 0xffff0000) >> 16) & 0xffff));
+}")
+
 
 (define_insn "addhi3"
-  [(set (match_operand:HI 0 "register_operand" "=A,A,A")
-       (plus:HI (match_operand:HI 1 "register_operand" "%A,A,A")
-                (match_operand:HI 2 "nonmemory_operand" "Z,d,i")))]
+  [(set (match_operand:HI 0 "register_operand" "=A,A,A,A,A")
+       (plus:HI (match_operand:HI 1 "register_operand" "%A,A,A,A,A")
+                (match_operand:HI 2 "nonmemory_operand" "Z,d,L,M,?i")))]
   ""
   "@
    %0=%1+%2
    %0=%1+%2
+   %0=%w1+%H2
+   %0=%b1+%U2
    %0=%w1+%H2\;%0=%b0+%U2"
-  [(set_attr "type" "malu,malu,f3_alu_i")])
+  [(set_attr "type" "malu,malu,f3_alu_i,f3_alu_i,f3_alu_i")])
 
 (define_insn ""
   [(set (match_operand:QI 0 "register_operand" "=k,u,!k,!u")
 
        
 (define_insn "match_addqi3"
-  [(set (match_operand:QI 0 "register_operand" "=!a,!a,k,u,!k,!u,h,!a")
-       (plus:QI (match_operand:QI 1 "register_operand" "0,0,uk,uk,uk,uk,h,0")
-                (match_operand:QI 2 "nonmemory_operand" "W,N,wzi,wzi,uk,uk,i,n")))
-       (clobber (match_scratch:QI 3 "=X,X,j,q,j,q,X,W"))]
+  [(set (match_operand:QI 0 "register_operand" "=a,a,k,u,k,u,!k,!u,j,j,q,q")
+       (plus:QI (match_operand:QI 1 "register_operand" "0,0,uk,uk,uk,uk,uk,uk,0,q,0,j")
+                (match_operand:QI 2 "nonmemory_operand" "W,N,i,i,wz,wz,uk,uk,i,i,i,i")))
+       (clobber (match_scratch:QI 3 "=X,X,j,q,j,q,j,q,X,k,X,u"))]
   ""
   "*
 {
 
     case 2:
     case 3:
-      if (!CONSTANT_P(operands[2]))
-        return \"%m0=%m1+%m2\";
-      else
         return \"%m0=%1+%H2\";
 
     case 4:
     case 5:
-      return \"%m0=%m1+%m2\";
+        return \"%m0=%m1+%m2\";
 
-    case 6:
-      return \"%0=%b1+%H2\";
 
+    case 6:
     case 7:
-      return \"%3=%2\;*%0++%3\";
-    default:
-      abort();
+      return \"%m0=%m1+%m2\";
+
+    case 8:
+    case 9:
+    case 10:
+    case 11:
+      return \"%0=%b1+%H2\";
     }
-}")
+}"
+[(set_attr "type" "data_move_memory,data_move_multiple,f3_alu_i,f3_alu_i,f3_alu,f3_alu,f3_alu,f3_alu,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i")])
+
 
 (define_expand "addhf3"
   [(set (match_operand:HF 0 "register_operand" "")
 ;;
 ;;  ....................
 
+(define_split
+  [(set (match_operand:HI 0 "register_operand" "")
+       (minus:HI (match_operand:HI 1 "register_operand" "")
+                 (match_operand:HI 2 "const_int_operand" "")))]
+  "reload_completed && !ADD_LOW_16(INTVAL(operands[2])) && 
+   !ADD_HIGH_16(INTVAL(operands[2]))"
+  [(parallel [(set (match_dup 3)
+                  (minus:QI (match_dup 4)
+                            (match_dup 5)))
+             (clobber (match_dup 6))])
+
+   (parallel [(set (match_dup 6)
+                  (minus:QI (match_dup 7)
+                            (match_dup 8)))
+             (clobber (match_scratch:QI 9 ""))])]
+  "
+{
+  operands[3] = gen_lowpart(QImode, operands[0]);
+  operands[4] = gen_lowpart(QImode, operands[1]);
+  operands[5] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff);
+
+  operands[6] = gen_highpart(QImode, operands[0]);
+  operands[7] = gen_highpart(QImode, operands[0]);
+  operands[8] = gen_rtx (CONST_INT, VOIDmode, (((INTVAL (operands[2]) & 0xffff0000) >> 16) & 0xffff));
+}")
+
+
 (define_insn "subhi3"
-  [(set (match_operand:HI 0 "register_operand" "=A,A,A")
-       (minus:HI (match_operand:HI 1 "register_operand" "A,A,A")
-                 (match_operand:HI 2 "nonmemory_operand" "Z,d,i")))]
+  [(set (match_operand:HI 0 "register_operand" "=A,A,A,A,A")
+       (minus:HI (match_operand:HI 1 "register_operand" "A,A,A,A,A")
+                 (match_operand:HI 2 "nonmemory_operand" "Z,d,L,M,?i")))]
   ""
   "@
    %0=%1-%2
    %0=%1-%2
+   %0=%w1-%H2
+   %0=%b1-%U2
    %0=%w1-%H2\;%0=%b0-%U2"
-  [(set_attr "type" "malu,malu,f3_alu_i")])
+  [(set_attr "type" "malu,malu,f3_alu_i,f3_alu_i,f3_alu_i")])
 
 (define_insn "subqi3"
-  [(set (match_operand:QI 0 "register_operand" "=?*a,k,u,!k,!u")
-       (minus:QI (match_operand:QI 1 "register_operand" "0,uk,uk,uk,uk")
-                (match_operand:QI 2 "nonmemory_operand" "n,wzi,wzi,uk,uk")))
-       (clobber (match_scratch:QI 3 "=W,j,q,j,q"))]
+  [(set (match_operand:QI 0 "register_operand" "=a,k,u,k,u,!k,!u,j,j,q,q")
+       (minus:QI (match_operand:QI 1 "register_operand" "0,uk,uk,uk,uk,uk,uk,0,q,0,j")
+                (match_operand:QI 2 "nonmemory_operand" "N,i,i,wz,wz,uk,uk,i,i,i,i")))
+       (clobber (match_scratch:QI 3 "=X,j,q,j,q,j,q,X,k,X,u"))]
   ""
   "*
 {
     case 0:
       switch (INTVAL (operands[2]))
        {
-       case 0:
-         return \"\";
-         
        case 1:
          return \"*%0--\";
          
        case -1:
          return \"*%0++\";
-         
+
        default:
          operands[2] = GEN_INT (-INTVAL (operands[2]));
          
       
     case 1:
     case 2:
-      if (!CONSTANT_P(operands[2]))
-        return \"%m0=%m1-%m2\";
-      else
         return \"%m0=%1-%H2\";
 
     case 3:
     case 4:
+        return \"%m0=%m1-%m2\";
+
+    case 5:
+    case 6:
       return \"%m0=%m1-%m2\";
-    default:
-      abort();
+
+    case 7: case 8:
+    case 9: case 10:
+      return \"%0=%b1-%H2\";
     }
-}")
+}"
+[(set_attr "type" "data_move_multiple,f3_alu_i,f3_alu_i,f3_alu,f3_alu,f3_alu,f3_alu,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i")])
 
 (define_expand "subhf3"
   [(set (match_operand:HF 0 "register_operand" "")
   [(set_attr "type" "special")])
 
 (define_expand "neghf2"
-  [(set (match_operand:HF 0 "general_operand" "")
-       (neg:HF (match_operand:HF 1 "general_operand" "")))]
+  [(set (match_operand:HF 0 "register_operand" "")
+       (neg:HF (match_operand:HF 1 "register_operand" "")))]
   ""
-"
+  "
 {
-  if (!dsp16xx_neghf2_libcall)
-    dsp16xx_neghf2_libcall = gen_rtx_SYMBOL_REF (Pmode, NEGHF2_LIBCALL);
-  
-  emit_library_call (dsp16xx_neghf2_libcall, 1, HFmode, 1,
-                    operands[1], HFmode);
-  emit_move_insn (operands[0], hard_libcall_value(HFmode));
-  DONE;
-}")
+  rtx result;
+  rtx target;
+
+    {
+      target = gen_lowpart(HImode, operands[0]);
+      result = expand_binop (HImode, xor_optab,
+                            gen_lowpart(HImode, operands[1]),
+                            GEN_INT(0x80000000), target, 0, OPTAB_WIDEN);
+      if (result == 0)
+       abort ();
 
+      if (result != target)
+       emit_move_insn (result, target);
 
+      /* Make a place for REG_EQUAL.  */
+      emit_move_insn (operands[0], operands[0]);
+      DONE;
+    }
+}")
 
 ;;
 ;;  ....................
   "%0=%1*%2"
   [(set_attr "type" "malu_mul")])
 
-(define_insn "umulqihi3"
-  [(set (match_operand:HI 0 "register_operand" "=t")
-        (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "%x"))
-                 (zero_extend:HI (match_operand:QI 2 "register_operand" "y"))))]
-  ""
-  "%0=%1*%2"
-  [(set_attr "type" "malu_mul")])
-
 (define_expand "mulhf3"
   [(set (match_operand:HF 0 "register_operand" "")
        (mult:HF (match_operand:HF 1 "register_operand" "")
 ;; Logical Instructions
 ;;
 
+(define_split
+  [(set (match_operand:HI 0 "register_operand" "")
+       (and:HI (match_operand:HI 1 "register_operand" "")
+                (match_operand:HI 2 "const_int_operand" "")))]
+  "reload_completed && !AND_LOW_16(INTVAL(operands[2])) && 
+   !AND_HIGH_16(INTVAL(operands[2])) 
+   && (REGNO (operands[0]) == REGNO (operands[1]))"
+  [(parallel [(set (match_dup 3)
+                  (and:QI (match_dup 4)
+                          (match_dup 5)))
+             (clobber (match_scratch:QI 6 ""))])
+   (parallel [(set (match_dup 7)
+                  (and:QI (match_dup 8)
+                          (match_dup 9)))
+             (clobber (match_scratch:QI 10 ""))])]
+  "
+{
+  operands[3] = gen_lowpart(QImode, operands[0]);
+  operands[4] = gen_lowpart(QImode, operands[1]);
+  operands[5] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff);
+
+  operands[7] = gen_highpart(QImode, operands[0]);
+  operands[8] = gen_highpart(QImode, operands[0]);
+  operands[9] = gen_rtx (CONST_INT, VOIDmode, (((INTVAL (operands[2]) & 0xffff0000) >> 16) & 0xffff));
+}")
+
+(define_split
+  [(set (match_operand:HI 0 "register_operand" "")
+       (and:HI (match_operand:HI 1 "register_operand" "")
+               (match_operand:HI 2 "const_int_operand" "")))]
+  "reload_completed && !AND_LOW_16(INTVAL(operands[2])) && 
+   !AND_HIGH_16(INTVAL(operands[2]))
+   && (REGNO (operands[0]) != REGNO (operands[1]))"
+  [(parallel [(set (match_dup 3)
+                  (and:QI (match_dup 4)
+                          (match_dup 5)))
+             (clobber (match_dup 6))])
+   (parallel [(set (match_dup 6)
+                  (and:QI (match_dup 7)
+                          (match_dup 8)))
+             (clobber (match_scratch:QI 9 ""))])]
+  "
+{
+  operands[3] = gen_lowpart(QImode, operands[0]);
+  operands[4] = gen_lowpart(QImode, operands[1]);
+  operands[5] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff);
+
+  operands[6] = gen_highpart(QImode, operands[0]);
+  operands[7] = gen_highpart(QImode, operands[0]);
+  operands[8] = gen_rtx (CONST_INT, VOIDmode, (((INTVAL (operands[2]) & 0xffff0000) >> 16) & 0xffff));
+}")
+
 (define_insn "andhi3"
-  [(set (match_operand:HI 0 "register_operand" "=A,A,?A")
-        (and:HI (match_operand:HI 1 "register_operand" "%A,!A,A")
-                (match_operand:HI 2 "nonmemory_operand" "Z,A,i")))]
+  [(set (match_operand:HI 0 "register_operand" "=A,A,A,A,?A")
+        (and:HI (match_operand:HI 1 "register_operand" "%A,!A,A,A,A")
+                (match_operand:HI 2 "nonmemory_operand" "Z,A,O,P,i")))]
   ""
   "@
    %0=%1&%2
    %0=%1&%2
+   %0=%w1&%H2
+   %0=%b1&%U2
    %0=%w1&%H2\;%0=%b0&%U2"
-  [(set_attr "type" "f3_alu,f3_alu,f3_alu_i")])
+  [(set_attr "type" "f3_alu,f3_alu,f3_alu_i,f3_alu_i,f3_alu_i_mult")])
 
 (define_insn "andqi3"
-  [(set (match_operand:QI 0 "register_operand" "=k,u,uk,!k,!u,j,q,jq,!j,!q")
-       (and:QI (match_operand:QI 1 "register_operand" "uk,uk,uk,uk,uk,jq,jq,jq,jq,jq")
-               (match_operand:QI 2 "nonmemory_operand" "wz,wz,i,uk,uk,yv,yv,i,jq,jq")))
-       (clobber (match_scratch:QI 3 "=j,q,X,j,q,k,u,X,k,u"))]
-   ""
-   "@
+  [(set (match_operand:QI 0 "register_operand" "=k,u,!k,!u,k,u,k,u,j,q,j,q,j,q,!j,!q")
+       (and:QI (match_operand:QI 1 "register_operand" "%uk,uk,uk,uk,0,0,u,k,jq,jq,0,0,q,j,jq,jq")
+               (match_operand:QI 2 "nonmemory_operand" "wz,wz,uk,uk,i,i,i,i,yv,yv,i,i,i,i,jq,jq")))
+   (clobber (match_scratch:QI 3 "=j,q,j,q,X,X,j,q,k,u,X,X,k,u,k,u"))]
+  ""
+  "@
     %m0=%m1&%m2
     %m0=%m1&%m2
-    %m0=%1&%H2
     %m0=%m1&%m2
     %m0=%m1&%m2
+    %m0=%1&%H2
+    %m0=%1&%H2
+    %m0=%1&%H2
+    %m0=%1&%H2
     %m0=%m1&%m2
     %m0=%m1&%m2
     %m0=%b1&%H2
+    %m0=%b1&%H2
+    %m0=%b1&%H2
+    %m0=%b1&%H2
     %m0=%m1&%m2
-    %m0=%m1&%m2")
+    %m0=%m1&%m2"
+  [(set_attr "type" "f3_alu,f3_alu,f3_alu,f3_alu,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu,f3_alu,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu,f3_alu")])
+
+
+(define_split
+  [(set (match_operand:HI 0 "register_operand" "")
+       (ior:HI (match_operand:HI 1 "register_operand" "")
+               (match_operand:HI 2 "const_int_operand" "")))]
+  "reload_completed && !SMALL_INTVAL(INTVAL(operands[2])) && 
+   !ADD_HIGH_16(INTVAL(operands[2]))
+   && (REGNO (operands[0]) == REGNO (operands[1]))"
+  [(parallel [(set (match_dup 3)
+                  (ior:QI (match_dup 4)
+                          (match_dup 5)))
+             (clobber (match_scratch:QI 6 ""))])
+   (parallel [(set (match_dup 7)
+                  (ior:QI (match_dup 8)
+                          (match_dup 9)))
+             (clobber (match_scratch:QI 10 ""))])]
+  "
+{
+  operands[3] = gen_lowpart(QImode, operands[0]);
+  operands[4] = gen_lowpart(QImode, operands[1]);
+  operands[5] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff);
+
+  operands[7] = gen_highpart(QImode, operands[0]);
+  operands[8] = gen_highpart(QImode, operands[0]);
+  operands[9] = gen_rtx (CONST_INT, VOIDmode, (((INTVAL (operands[2]) & 0xffff0000) >> 16) & 0xffff));
+}")
+
+(define_split
+  [(set (match_operand:HI 0 "register_operand" "")
+       (ior:HI (match_operand:HI 1 "register_operand" "")
+               (match_operand:HI 2 "const_int_operand" "")))]
+  "reload_completed && !SMALL_INTVAL(INTVAL(operands[2])) && 
+   !ADD_HIGH_16(INTVAL(operands[2]))
+   && (REGNO (operands[0]) != REGNO (operands[1]))"
+  [(parallel [(set (match_dup 3)
+                  (ior:QI (match_dup 4)
+                          (match_dup 5)))
+             (clobber (match_dup 6))])
+   (parallel [(set (match_dup 6)
+                  (ior:QI (match_dup 7)
+                          (match_dup 8)))
+             (clobber (match_scratch:QI 9 ""))])]
+  "
+{
+  operands[3] = gen_lowpart(QImode, operands[0]);
+  operands[4] = gen_lowpart(QImode, operands[1]);
+  operands[5] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff);
+
+  operands[6] = gen_highpart(QImode, operands[0]);
+  operands[7] = gen_highpart(QImode, operands[0]);
+  operands[8] = gen_rtx (CONST_INT, VOIDmode, (((INTVAL (operands[2]) & 0xffff0000) >> 16) & 0xffff));
+}")
+
 
 (define_insn "iorhi3"
-  [(set (match_operand:HI 0 "register_operand" "=A,A,A,?A")
-        (ior:HI (match_operand:HI 1 "register_operand" "%A,!A,A,A")
-                (match_operand:HI 2 "nonmemory_operand" "Z,A,I,i")))]
+  [(set (match_operand:HI 0 "register_operand" "=A,A,A,A,?A")
+        (ior:HI (match_operand:HI 1 "register_operand" "%A,!A,A,A,A")
+                (match_operand:HI 2 "nonmemory_operand" "Z,A,I,M,i")))]
  ""
  "@
    %0=%u1|%u2
    %0=%u1|%u2
    %0=%w1|%H2
+   %0=%b1|%U2
    %0=%w1|%H2\;%0=%b0|%U2"
-  [(set_attr "type" "f3_alu,f3_alu,f3_alu_i,f3_alu_i")])
+  [(set_attr "type" "f3_alu,f3_alu,f3_alu_i,f3_alu_i,f3_alu_i_mult")])
 
 (define_insn "iorqi3"
-  [(set (match_operand:QI 0 "register_operand" "=k,u,uk,!k,!u,j,q,jq,!j,!q")
-       (ior:QI (match_operand:QI 1 "register_operand" "uk,uk,uk,uk,uk,jq,jq,jq,jq,jq")
-               (match_operand:QI 2 "nonmemory_operand" "wz,wz,i,uk,uk,yv,yv,i,jq,jq")))
-       (clobber (match_scratch:QI 3 "=j,q,X,j,q,k,u,X,k,u"))]
-   ""
-   "@
+  [(set (match_operand:QI 0 "register_operand" "=k,u,!k,!u,k,u,k,u,j,q,j,q,j,q,!j,!q")
+       (ior:QI (match_operand:QI 1 "register_operand" "%uk,uk,uk,uk,0,0,u,k,jq,jq,0,0,q,j,jq,jq")
+               (match_operand:QI 2 "nonmemory_operand" "wz,wz,uk,uk,i,i,i,i,yv,yv,i,i,i,i,jq,jq")))
+   (clobber (match_scratch:QI 3 "=j,q,j,q,X,X,j,q,k,u,X,X,k,u,k,u"))]
+  ""
+  "@
     %m0=%m1|%m2
     %m0=%m1|%m2
-    %m0=%1|%H2
     %m0=%m1|%m2
     %m0=%m1|%m2
+    %m0=%1|%H2
+    %m0=%1|%H2
+    %m0=%1|%H2
+    %m0=%1|%H2
     %m0=%m1|%m2
     %m0=%m1|%m2
     %m0=%b1|%H2
+    %m0=%b1|%H2
+    %m0=%b1|%H2
+    %m0=%b1|%H2
     %m0=%m1|%m2
-    %m0=%m1|%m2")
+    %m0=%m1|%m2"
+  [(set_attr "type" "f3_alu,f3_alu,f3_alu,f3_alu,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu,f3_alu,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu,f3_alu")])
+
+
+
+(define_split
+  [(set (match_operand:HI 0 "register_operand" "")
+       (xor:HI (match_operand:HI 1 "register_operand" "")
+               (match_operand:HI 2 "const_int_operand" "")))]
+  "reload_completed && !SMALL_INTVAL(INTVAL(operands[2])) && 
+   !ADD_HIGH_16(INTVAL(operands[2]))
+   && (REGNO (operands[0]) == REGNO (operands[1]))"
+  [(parallel [(set (match_dup 3)
+                  (xor:QI (match_dup 4)
+                          (match_dup 5)))
+             (clobber (match_scratch:QI 6 ""))])
+   (parallel [(set (match_dup 7)
+                  (xor:QI (match_dup 8)
+                          (match_dup 9)))
+             (clobber (match_scratch:QI 10 ""))])]
+  "
+{
+  operands[3] = gen_lowpart(QImode, operands[0]);
+  operands[4] = gen_lowpart(QImode, operands[1]);
+  operands[5] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff);
+
+  operands[7] = gen_highpart(QImode, operands[0]);
+  operands[8] = gen_highpart(QImode, operands[0]);
+  operands[9] = gen_rtx (CONST_INT, VOIDmode, (((INTVAL (operands[2]) & 0xffff0000) >> 16) & 0xffff));
+}")
+
+(define_split
+  [(set (match_operand:HI 0 "register_operand" "")
+       (xor:HI (match_operand:HI 1 "register_operand" "")
+               (match_operand:HI 2 "const_int_operand" "")))]
+  "reload_completed && !SMALL_INTVAL(INTVAL(operands[2])) && 
+   !ADD_HIGH_16(INTVAL(operands[2]))
+   && (REGNO (operands[0]) != REGNO (operands[1]))"
+  [(parallel [(set (match_dup 3)
+                  (xor:QI (match_dup 4)
+                          (match_dup 5)))
+             (clobber (match_dup 6))])
+   (parallel [(set (match_dup 6)
+                  (xor:QI (match_dup 7)
+                          (match_dup 8)))
+             (clobber (match_scratch:QI 9 ""))])]
+  "
+{
+  operands[3] = gen_lowpart(QImode, operands[0]);
+  operands[4] = gen_lowpart(QImode, operands[1]);
+  operands[5] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff);
+
+  operands[6] = gen_highpart(QImode, operands[0]);
+  operands[7] = gen_highpart(QImode, operands[0]);
+  operands[8] = gen_rtx (CONST_INT, VOIDmode, (((INTVAL (operands[2]) & 0xffff0000) >> 16) & 0xffff));
+}")
 
 (define_insn "xorhi3"
-  [(set (match_operand:HI 0 "register_operand" "=A,A,A,?A")
-        (xor:HI (match_operand:HI 1 "register_operand" "%A,!A,A,A")
-                (match_operand:HI 2 "nonmemory_operand" "Z,A,I,i")))]
+  [(set (match_operand:HI 0 "register_operand" "=A,A,A,A,?A")
+        (xor:HI (match_operand:HI 1 "register_operand" "%A,!A,A,A,A")
+                (match_operand:HI 2 "nonmemory_operand" "Z,A,I,M,i")))]
   ""
   "@
    %0=%1^%2
    %0=%1^%2
    %0=%w1^%H2
+   %0=%b1^%U2
    %0=%w1^%H2\;%0=%b0^%U2"
-  [(set_attr "type" "f3_alu,f3_alu,f3_alu_i,f3_alu_i")])
+  [(set_attr "type" "f3_alu,f3_alu,f3_alu_i,f3_alu_i,f3_alu_i_mult")])
 
 (define_insn "xorqi3"
-  [(set (match_operand:QI 0 "register_operand" "=k,u,uk,!k,!u,j,q,jq,!j,!q")
-       (xor:QI (match_operand:QI 1 "register_operand" "uk,uk,uk,uk,uk,jq,jq,jq,jq,jq")
-               (match_operand:QI 2 "nonmemory_operand" "wz,wz,i,uk,uk,yv,yv,i,jq,jq")))
-       (clobber (match_scratch:QI 3 "=j,q,X,j,q,k,u,X,k,u"))]
-   ""
-   "@
+  [(set (match_operand:QI 0 "register_operand" "=k,u,!k,!u,k,u,k,u,j,q,j,q,j,q,!j,!q")
+       (xor:QI (match_operand:QI 1 "register_operand" "%uk,uk,uk,uk,0,0,u,k,jq,jq,0,0,q,j,jq,jq")
+               (match_operand:QI 2 "nonmemory_operand" "wz,wz,uk,uk,i,i,i,i,yv,yv,i,i,i,i,jq,jq")))
+   (clobber (match_scratch:QI 3 "=j,q,j,q,X,X,j,q,k,u,X,X,k,u,k,u"))]
+  ""
+  "@
     %m0=%m1^%m2
     %m0=%m1^%m2
-    %m0=%1^%H2
     %m0=%m1^%m2
     %m0=%m1^%m2
+    %m0=%1^%H2
+    %m0=%1^%H2
+    %m0=%1^%H2
+    %m0=%1^%H2
     %m0=%m1^%m2
     %m0=%m1^%m2
     %m0=%b1^%H2
+    %m0=%b1^%H2
+    %m0=%b1^%H2
+    %m0=%b1^%H2
     %m0=%m1^%m2
-    %m0=%m1^%m2")
+    %m0=%m1^%m2"
+  [(set_attr "type" "f3_alu,f3_alu,f3_alu,f3_alu,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu,f3_alu,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu,f3_alu")])
 
 (define_insn "one_cmplhi2"
   [(set (match_operand:HI 0 "register_operand" "=A")
   "%0= ~%1"
   [(set_attr "type" "special")])
 
+
 (define_insn "one_cmplqi2"
-  [(set (match_operand:QI 0 "register_operand" "=ku,jq")
-        (not:QI (match_operand:QI 1 "register_operand" "ku,jq")))]
+  [(set (match_operand:QI 0 "register_operand" "=k,k,u,u,j,j,q,q")
+        (not:QI (match_operand:QI 1 "register_operand" "0,u,0,q,0,q,0,j")))
+   (clobber (match_scratch:QI 2 "=X,j,X,q,X,k,X,u"))]
   ""
   "@
    %m0= %1 ^ 0xffff
+   %m0= %1 ^ 0xffff
+   %m0= %1 ^ 0xffff
+   %m0= %1 ^ 0xffff
+   %m0= %b1 ^ 0xffff
+   %m0= %b1 ^ 0xffff
+   %m0= %b1 ^ 0xffff
    %m0= %b1 ^ 0xffff"
-  [(set_attr "type" "special")])
+  [(set_attr "type" "f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i")])
 
 \f
 ;;
 ;; MOVE INSTRUCTIONS
 ;;
 
+(define_split
+  [(set (mem:HI (match_operand:QI 0 "register_operand" ""))
+       (match_operand:HI 1 "register_operand" ""))]
+  "reload_completed && (operands[0] != stack_pointer_rtx)"
+  [(set (mem:QI (post_inc:QI (match_dup 0)))
+       (match_dup 2))
+   (set (mem:QI (post_dec:QI (match_dup 0)))
+       (match_dup 3))]
+  "
+{
+  operands[2] = gen_highpart(QImode, operands[1]);
+  operands[3] = gen_lowpart(QImode, operands[1]);
+}")
+
+
+(define_split
+  [(set (match_operand:HI 0 "register_operand" "")
+       (mem:HI (match_operand:QI 1 "register_operand" "")))]
+  "reload_completed && (operands[1] != stack_pointer_rtx)"
+  [(set (match_dup 2)
+       (mem:QI (post_inc:QI (match_dup 1))))
+   (set (match_dup 3)
+       (mem:QI (post_dec:QI (match_dup 1))))]
+  "
+{
+  operands[2] = gen_highpart(QImode, operands[0]);
+  operands[3] = gen_lowpart(QImode, operands[0]);
+}")
+
+(define_split
+  [(set (mem:HI (post_inc:HI (match_operand:QI 0 "register_operand" "")))
+       (match_operand:HI 1 "register_operand" ""))]
+  "reload_completed"
+  [(set (mem:QI (post_inc:QI (match_dup 0)))
+       (match_dup 2))
+   (set (mem:QI (post_inc:QI (match_dup 0)))
+       (match_dup 3))]
+  "
+{
+  operands[2] = gen_highpart(QImode, operands[1]);
+  operands[3] = gen_lowpart(QImode, operands[1]);
+}")
+
+(define_split
+  [(set (match_operand:HI 0 "register_operand" "")
+       (mem:HI (post_inc:HI (match_operand:QI 1 "register_operand" ""))))]
+  "reload_completed"
+  [(set (match_dup 2)
+       (mem:QI (post_inc:QI (match_dup 1))))
+   (set (match_dup 3)
+       (mem:QI (post_inc:QI (match_dup 1))))]
+  "
+{
+  operands[2] = gen_highpart(QImode, operands[0]);
+  operands[3] = gen_lowpart(QImode, operands[0]);
+}")
+
+
+(define_split
+  [(set (match_operand:HI 0 "register_operand" "")
+       (match_operand:HI 1 "register_operand" ""))]
+  "reload_completed && 
+   !(IS_ACCUM_REG (REGNO(operands[0])) && 
+    (REGNO(operands[1]) == REG_PROD || REGNO(operands[1]) == REG_Y))"
+  [(set (match_dup 2)
+       (match_dup 3))
+   (set (match_dup 4)
+       (match_dup 5))]
+  "
+{
+  operands[2] = gen_highpart(QImode, operands[0]);
+  operands[3] = gen_highpart(QImode, operands[1]);
+  operands[4] = gen_lowpart(QImode, operands[0]);
+  operands[5] = gen_lowpart(QImode, operands[1]);
+}")
+
+(define_split
+  [(set (match_operand:HI 0 "register_operand" "")
+       (match_operand:HI 1 "const_int_operand" ""))]
+  "reload_completed"
+  [(set (match_dup 2)
+       (match_dup 3))
+   (set (match_dup 4)
+       (match_dup 5))]
+   "
+{
+  operands[2] = gen_lowpart(QImode, operands[0]);
+  operands[3] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 0xffff);
+
+  operands[4] = gen_highpart(QImode, operands[0]);
+  operands[5] = gen_rtx (CONST_INT, VOIDmode, (((INTVAL (operands[1]) & 0xffff0000) >> 16) & 0xffff));
+}")
+
 (define_expand "movhi"
   [(set (match_operand:HI 0 "general_operand" "")
        (match_operand:HI 1 "general_operand" ""))]
                case 8:
                case 9:
                   return \"\";
-                default:
-                   abort();
         }
 }"
-[(set_attr "type" "move,move,load_i,load_i,load,store,load,store,move,move")])
+[(set_attr "type" "special,data_move_multiple,f3_alu,data_move_multiple,data_move_multiple,data_move_multiple,data_move_multiple,data_move_multiple,nothing,nothing")])
 
 
 ;; NOTE: It is cheaper to do 'y = *r0', than 'r0 = *r0'.
        switch (which_alternative)
        {
                case 0:
-                  /* We have to use the move mnemonic otherwise the 1610 will
+                  /* We have to use the move mneumonic otherwise the 1610 will
                      attempt to transfer all 32-bits of 'y', 'p' or an accumulator
                      , which we don't want */
                   if (REGNO(operands[1]) == REG_Y || REGNO(operands[1]) == REG_PROD
 
                 case 9: case 10:
                   return \"%0=%1\";
-                default:
-                   abort();
        }
-}")
+}"
+[(set_attr "type" "data_move,data_move,data_move_short_i,data_move_i,data_move_memory,data_move_memory,data_move_memory,data_move_memory,nothing,malu,malu")])
 
 (define_insn "match_movqi2"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=A,r,aW,c,?D,m<>,e,Y,r,xyz,m<>")
        switch (which_alternative)
        {
                case 0:
-                  /* We have to use the move mnemonic otherwise the 1610 will
+                  /* We have to use the move mneumonic otherwise the 1610 will
                      attempt to transfer all 32-bits of 'y', 'p' or an accumulator
                      , which we don't want */
                   if (REGNO(operands[1]) == REG_Y || REGNO(operands[1]) == REG_PROD
 
                 case 9: case 10:
                   return \"%0=%1\";
-                default:
-                   abort();
        }
-}")
+}"
+[(set_attr "type" "data_move,data_move,data_move_short_i,data_move_i,data_move_memory,data_move_memory,data_move_memory,data_move_memory,nothing,malu,malu")])
 
 (define_expand "reload_inqi"
   [(set (match_operand:QI 0 "register_operand" "=u")
   operands[5] = addr0;
   operands[6] = addr1;
 
-  operands[0] = replace_equiv_address (operands[0], addr0);
-  operands[1] = replace_equiv_address (operands[1], addr1);
+  operands[0] = change_address (operands[0], VOIDmode, addr0);
+  operands[1] = change_address (operands[1], VOIDmode, addr1);
 }")
 
 (define_insn ""
                case 5:
                case 6:
                   return \"%u0=%u1\;%w0=%w1\";
-                default:
-                   abort();
         }
 }"
 [(set_attr "type" "move,move,load_i,load,store,load,store")])
   "
 {
        operands[2] = gen_reg_rtx (HImode);
-       operands[3] = gen_rtx_SUBREG (QImode, operands[2], GET_MODE_SIZE (QImode));
+       operands[3] = gen_rtx_SUBREG (QImode, operands[2], 1);
 }")
 
+(define_insn "internal_extendqihi2"
+  [(set (match_operand:HI 0 "register_operand" "=A")
+       (sign_extend:HI (match_operand:QI 1 "register_operand" "ku")))]
+  "TARGET_BMU"
+  "%0 = extracts(%m1, 0x1000)"
+[(set_attr "type" "shift_i")])
+
 ;;(define_insn "extendqihi2"
 ;;  [(set (match_operand:HI 0 "register_operand" "=A")
 ;;        (sign_extend:HI (match_operand:QI 1 "register_operand" "h")))]
 ;;    }
 ;; }")
 
+;;(define_expand "zero_extendqihi2"
+;;  [(clobber (match_dup 2))
+;;   (set (match_dup 3) (match_operand:QI 1 "register_operand" ""))
+;;   (set (match_operand:HI 0 "register_operand" "")
+;;     (ashift:HI (match_dup 2)
+;;                (const_int 16)))
+;;   (set (match_dup 0)
+;;     (lshiftrt:HI (match_dup 0) (const_int 16)))]
+;;  ""
+;;  "
+;;{
+;;     operands[2] = gen_reg_rtx (HImode);
+;;     operands[3] = gen_rtx (SUBREG, QImode, operands[2], 1);
+;;}")
+
 (define_expand "zero_extendqihi2"
-  [(clobber (match_dup 2))
-   (set (match_dup 3) (match_operand:QI 1 "register_operand" ""))
-   (set (match_operand:HI 0 "register_operand" "")
-       (ashift:HI (match_dup 2)
-                  (const_int 16)))
-   (set (match_dup 0)
-       (lshiftrt:HI (match_dup 0) (const_int 16)))]
+  [(set (match_operand:HI 0 "register_operand" "")
+      (zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
   ""
-  "
-{
-       operands[2] = gen_reg_rtx (HImode);
-       operands[3] = gen_rtx_SUBREG (QImode, operands[2], GET_MODE_SIZE (QImode));
-}")
+  "")  
+       
+
+(define_insn "match_zero_extendqihi_bmu"
+  [(set (match_operand:HI 0 "register_operand" "=?*Z,?*Z,?A,A")
+        (zero_extend:HI (match_operand:QI 1 "register_operand" "?A,?*Y,*Z*x*a*W*Y,ku")))]
+  "TARGET_BMU"
+  "*
+ {
+    switch (which_alternative)
+      {
+        case 0:
+          return \"%w0=%1\;%0=0\";
+
+        case 1:
+          return \"%w0=%1\;%0=0\";
+
+        case 2:
+          if (REGNO(operands[1]) == (REGNO(operands[0]) + 1))
+            return \"%0=0\";
+          else if (REGNO(operands[1]) == REG_Y || REGNO(operands[1]) == REG_PROD
+                  || IS_ACCUM_REG(REGNO(operands[1])))
+          {
+            return \"move %w0=%1\;%0=0\";
+          }
+          else
+            return \"%w0=%1\;%0=0\";
+
+       case 3:
+         return \"%0 = extractz(%m1, 0x1000)\";
+      }
+  }"
+  [(set_attr "type" "data_move_2,data_move_2,data_move_2,shift_i")])
 
+(define_insn "match_zero_extendqihi2_nobmu"
+  [(set (match_operand:HI 0 "register_operand" "=?Z,?Z,A")
+        (zero_extend:HI (match_operand:QI 1 "register_operand" "A,Y,r")))]
+  ""
+  "*
+ {
+    switch (which_alternative)
+      {
+        case 0:
+          return \"%w0=%1\;%0=0\";
+
+        case 1:
+          return \"%w0=%1\;%0=0\";
+
+        case 2:
+          if (REGNO(operands[1]) + 1 == (REGNO(operands[0]) + 1))
+            return \"%0=0\";
+          else if (REGNO(operands[1]) == REG_Y || REGNO(operands[1]) == REG_PROD
+                  || IS_ACCUM_REG(REGNO(operands[1])))
+          {
+            return \"move %w0=%1\;%0=0\";
+          }
+          else
+            return \"%w0=%1\;%0=0\";
+      }
+  }"
+  [(set_attr "type" "data_move_2,data_move_2,data_move_2")])
 
+;;
+;; Floating point conversions
+;;
 (define_expand "floathihf2"
   [(set (match_operand:HF 0 "register_operand" "")
        (float:HF (match_operand:HI 1 "register_operand" "")))]
            rtx stack_slot;
            
            stack_slot = assign_stack_temp (QImode, GET_MODE_SIZE(QImode), 0);
-           stack_slot = validize_mem (stack_slot);
+           stack_slot = change_address (stack_slot, VOIDmode, XEXP (stack_slot, 0));
            emit_move_insn (stack_slot, operands[2]);
            operands[2] = stack_slot;
          }
   else
     {
       output_asm_insn (\"cloop=%2\", operands);
-      output_asm_insn (\"do 0 \{\", operands);
+      output_asm_insn (\"do 0 {\", operands);
       output_asm_insn (\"%0=%0>>1\", operands);
-      return \"\}\";
+      return \"}\";
     }
 }")
                   
   [(set (match_operand:HI 0 "register_operand" "=A")
         (lshiftrt:HI (match_operand:HI 1 "register_operand" "A")
                      (const_int 1)))]
-  ""
+  "!TARGET_BMU"
   "%0=%1>>1\;%0=%b0&0x7fff"
   [(set_attr "type" "special")])
 
   [(set (match_operand:HI 0 "register_operand" "=A")
         (lshiftrt:HI (match_operand:HI 1 "register_operand" "A")
                      (const_int 4)))]
-  ""
+  "!TARGET_BMU"
   "%0=%1>>4\;%0=%b0&0x0fff"
   [(set_attr "type" "special")])
 
   [(set (match_operand:HI 0 "register_operand" "=A")
         (lshiftrt:HI (match_operand:HI 1 "register_operand" "A")
                      (const_int 8)))]
-  ""
+  "!TARGET_BMU"
   "%0=%1>>8\;%0=%b0&0x00ff"
   [(set_attr "type" "special")])
 
   [(set (match_operand:HI 0 "register_operand" "=A")
         (lshiftrt:HI (match_operand:HI 1 "register_operand" "A")
                      (const_int 16)))]
-  ""
+  "!TARGET_BMU"
   "%0=%1>>16\;%0=%b0&0x0000"
   [(set_attr "type" "special")])
 
              rtx stack_slot;
            
              stack_slot = assign_stack_temp (QImode, GET_MODE_SIZE(QImode), 0);
-             stack_slot = validize_mem (stack_slot);
+             stack_slot = change_address (stack_slot, VOIDmode, XEXP (stack_slot, 0));
              emit_move_insn (stack_slot, operands[2]);
              operands[2] = stack_slot;
            }
     {
       output_asm_insn (\"%3=psw\;psw=0\",operands);
       output_asm_insn (\"cloop=%2\", operands);
-      output_asm_insn (\"do 0 \{\", operands);
+      output_asm_insn (\"do 0 {\", operands);
       output_asm_insn (\"%0=%0>>1\", operands);
-      output_asm_insn (\"\}\", operands);
+      output_asm_insn (\"}\", operands);
       return \"psw=%3\";
     }
 }")
 
 (define_insn ""
   [(set (match_operand:HI 0 "register_operand" "=A")
-       (ashift:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "A"))
-                  (const_int 16)))]
-  ""
-  "%0=%1<<16"
-  [(set_attr "type" "special")])
-
-(define_insn ""
-  [(set (match_operand:HI 0 "register_operand" "=A")
         (ashift:HI (match_operand:HI 1 "general_operand" "A")
                    (const_int 16)))]
   ""
        emit_barrier ();
        emit_label (label1);
 
-       if (GET_CODE (operands[2]) != MEM)
+       if (GET_CODE(operands[2]) != MEM)
          {
            rtx stack_slot;
            
            stack_slot = assign_stack_temp (QImode, GET_MODE_SIZE(QImode), 0);
-           stack_slot = validize_mem (stack_slot);
+           stack_slot = change_address (stack_slot, VOIDmode, XEXP (stack_slot, 0));
            emit_move_insn (stack_slot, operands[2]);
            operands[2] = stack_slot;
          }
-
-       emit_insn (gen_match_ashlhi3_nobmu (operands[0], operands[1],
-                                           operands[2]));
+       emit_insn (gen_match_ashlhi3_nobmu (operands[0], operands[1], operands[2]));
        emit_label (label2);
        DONE;
 #endif
    %0=%1<<%2\;move %u0=%u0
    %0=%1<<%H2\;move %u0=%u0
    %0=%1<<%2\;move %u0=%u0"
-  [(set_attr "type" "shift,shift_i,shift")])
+  [(set_attr "type" "shift_multiple,shift_multiple,shift_multiple")])
 
 (define_insn "match_ashlhi3_nobmu"
   [(set (match_operand:HI 0 "register_operand" "=A,A")
   else
     {
       output_asm_insn (\"cloop=%2\", operands);
-      output_asm_insn (\"do 0 \{\", operands);
+      output_asm_insn (\"do 0 {\", operands);
       output_asm_insn (\"%0=%0<<1\", operands);
-      return \"\}\";
+      return \"}\";
     }
 }")
 
 \f
 
+
+(define_insn "extv"
+  [(set (match_operand:QI 0 "register_operand" "=k,u")
+       (sign_extract:QI (match_operand:QI 1 "register_operand" "ku,ku")
+                        (match_operand:QI 2 "const_int_operand" "n,n")
+                        (match_operand:QI 3 "const_int_operand" "n,n")))
+       (clobber (match_scratch:QI 4 "=j,q"))]
+  "TARGET_BMU"
+  "*
+{
+       operands[5]
+       = GEN_INT ((INTVAL (operands[2]) << 8) + (INTVAL (operands[3]) & 0xff));
+       return \"%m0 = extracts (%m1, %H5)\";
+}"
+[(set_attr "type" "shift_i")])
+
+(define_insn "extzv"
+  [(set (match_operand:QI 0 "register_operand" "=k,u")
+       (zero_extract:QI (match_operand:QI 1 "register_operand" "ku,ku")
+                        (match_operand:QI 2 "const_int_operand" "n,n")
+                        (match_operand:QI 3 "const_int_operand" "n,n")))
+       (clobber (match_scratch:QI 4 "=j,q"))]
+  "TARGET_BMU"
+  "*
+{
+       operands[5]
+       = GEN_INT ((INTVAL (operands[2]) << 8) + (INTVAL (operands[3]) & 0xff));
+       return \"%m0 = extractz (%m1, %H5)\";
+}"
+[(set_attr "type" "shift_i")])
+
+;;
+;; conditional instructions
+;;
+
+(define_expand "seq"
+  [(set (match_operand:QI 0 "register_operand" "")
+       (eq:QI (match_dup 1) (const_int 0)))]
+  ""
+  "
+{ 
+   if (dsp16xx_compare_gen == gen_compare_reg)
+     operands[1] = (*dsp16xx_compare_gen)(EQ, dsp16xx_compare_op0, dsp16xx_compare_op1);
+   else
+     operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0);
+}")
+
+(define_expand "sne"
+  [(set (match_operand:QI 0 "register_operand" "")
+       (ne:QI (match_dup 1) (const_int 0)))]
+  ""
+  "
+{ 
+   if (dsp16xx_compare_gen == gen_compare_reg)
+     operands[1] = (*dsp16xx_compare_gen)(NE, dsp16xx_compare_op0, dsp16xx_compare_op1);
+   else
+     operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0);
+}")
+
+
+(define_expand "sgt"
+  [(set (match_operand:QI 0 "register_operand" "")
+       (gt:QI (match_dup 1) (const_int 0)))]
+  ""
+  "
+{ 
+   if (dsp16xx_compare_gen == gen_compare_reg)
+     operands[1] = (*dsp16xx_compare_gen)(GT, dsp16xx_compare_op0, dsp16xx_compare_op1);
+   else
+     operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0);
+}")
+
+
+(define_expand "slt"
+  [(set (match_operand:QI 0 "register_operand" "")
+       (lt:QI (match_dup 1) (const_int 0)))]
+  ""
+  "
+{ 
+   if (dsp16xx_compare_gen == gen_compare_reg)
+     operands[1] = (*dsp16xx_compare_gen)(LT, dsp16xx_compare_op0, dsp16xx_compare_op1);
+   else
+     operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0);
+}")
+
+(define_expand "sge"
+  [(set (match_operand:QI 0 "register_operand" "")
+       (ge:QI (match_dup 1) (const_int 0)))]
+  ""
+  "
+{ 
+   if (dsp16xx_compare_gen == gen_compare_reg)
+     operands[1] = (*dsp16xx_compare_gen)(GE, dsp16xx_compare_op0, dsp16xx_compare_op1);
+   else
+     operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0);
+}")
+
+
+(define_expand "sle"
+  [(set (match_operand:QI 0 "register_operand" "")
+       (le:QI (match_dup 1) (const_int 0)))]
+  ""
+  "
+{ 
+   if (dsp16xx_compare_gen == gen_compare_reg)
+     operands[1] = (*dsp16xx_compare_gen)(LE, dsp16xx_compare_op0, dsp16xx_compare_op1);
+   else
+     operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0);
+}")
+
+
+(define_expand "sgtu"
+  [(set (match_operand:QI 0 "register_operand" "")
+       (gtu:QI (match_dup 1) (const_int 0)))]
+  ""
+  "
+{ 
+   if (dsp16xx_compare_gen == gen_compare_reg)
+     operands[1] = (*dsp16xx_compare_gen)(GTU, dsp16xx_compare_op0, dsp16xx_compare_op1);
+   else
+     operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0);
+}")
+
+
+(define_expand "sltu"
+  [(set (match_operand:QI 0 "register_operand" "")
+       (ltu:QI (match_dup 1) (const_int 0)))]
+  ""
+  "
+{ 
+   if (dsp16xx_compare_gen == gen_compare_reg)
+     operands[1] = (*dsp16xx_compare_gen)(LTU, dsp16xx_compare_op0, dsp16xx_compare_op1);
+   else
+     operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0);
+}")
+
+
+(define_expand "sgeu"
+  [(set (match_operand:QI 0 "register_operand" "")
+       (geu:QI (match_dup 1) (const_int 0)))]
+  ""
+  "
+{ 
+   if (dsp16xx_compare_gen == gen_compare_reg)
+     operands[1] = (*dsp16xx_compare_gen)(GEU, dsp16xx_compare_op0, dsp16xx_compare_op1);
+   else
+     operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0);
+}")
+
+
+(define_expand "sleu"
+  [(set (match_operand:QI 0 "register_operand" "")
+       (leu:QI (match_dup 1) (const_int 0)))]
+  ""
+  "
+{ 
+   if (dsp16xx_compare_gen == gen_compare_reg)
+     operands[1] = (*dsp16xx_compare_gen)(LEU, dsp16xx_compare_op0, dsp16xx_compare_op1);
+   else
+     operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0);
+}")
+
+
+(define_insn "scc"
+  [(set (match_operand:QI 0 "register_operand" "=jq")
+       (match_operator:QI 1 "comparison_operator" [(cc0) (const_int 0)]))]
+  ""
+  "%0 = 0\;if %C1 %b0 = %b0 + 1"
+  [(set_attr "type" "special_2")])
+
 ;;
 ;; Jump Instructions
 ;;
 
 
 (define_peephole
-  [(set (match_operand:QI 0 "register_operand" "=A")
-        (reg:QI 16))
-   (call (mem:QI (match_dup 0))
-        (match_operand 1 "" "i"))]
-   ""
-   "call pt")
+  [(parallel [(set (cc0) 
+                  (compare (match_operand:QI 0 "register_operand"  "k,k,!k,u,u,!u")
+                           (match_operand:QI 1 "register_operand"  "w,z,u,w,z,k")))
+             (use (match_operand:QI 2 "register_operand" "=j,j,j,q,q,q"))
+             (use (match_operand:QI 3 "register_operand" "=v,y,q,v,y,j"))])
+   (set (pc)   
+       (if_then_else (match_operator 5 "uns_comparison_operator" 
+                                      [(cc0) (const_int 0)])
+                     (label_ref (match_operand 4 "" ""))
+                     (pc)))]
+  "!TARGET_NEAR_JUMP"
+  "pt=%l4\;%2-%3\;if %C5 goto pt")
+
+(define_peephole
+  [(parallel [(set (cc0) 
+                  (compare (match_operand:QI 0 "register_operand"  "k,k,!k,u,u,!u")
+                           (match_operand:QI 1 "register_operand"  "w,z,u,w,z,k")))
+             (use (match_operand:QI 2 "register_operand" "=j,j,j,q,q,q"))
+             (use (match_operand:QI 3 "register_operand" "=v,y,q,v,y,j"))])
+   (set (pc)   
+       (if_then_else (match_operator 5 "uns_comparison_operator" 
+                                      [(cc0) (const_int 0)])
+                     (pc)
+                     (label_ref (match_operand 4 "" ""))))]
+  "!TARGET_NEAR_JUMP"
+  "pt=%l4\;%2-%3\;if %I5 goto pt")
+
+
+(define_peephole
+  [(parallel [(set (cc0) 
+                  (compare (match_operand:QI 0 "register_operand"  "k,u")
+                           (match_operand:QI 1 "const_int_operand" "i,i")))
+             (use (match_operand:QI 2 "register_operand" "=j,q"))])
+   (set (pc)   
+       (if_then_else (match_operator 4 "uns_comparison_operator" 
+                                      [(cc0) (const_int 0)])
+                     (label_ref (match_operand 3 "" ""))
+                     (pc)))]
+  "!TARGET_NEAR_JUMP"
+  "pt=%l3\;%0-%H1\;if %C4 goto pt")
+
+(define_peephole
+  [(parallel [(set (cc0) 
+                  (compare (match_operand:QI 0 "register_operand"  "k,u")
+                           (match_operand:QI 1 "const_int_operand" "i,i")))
+             (use (match_operand:QI 2 "register_operand" "=j,q"))])
+   (set (pc)   
+       (if_then_else (match_operator 4 "uns_comparison_operator" 
+                                      [(cc0) (const_int 0)])
+                     (pc)
+                     (label_ref (match_operand 3 "" ""))))]
+  "!TARGET_NEAR_JUMP"
+  "pt=%l3\;%0-%H1\;if %I4 goto pt")
+
+;;
+;;; QImode SIGNED COMPARE PEEPHOLE OPTIMIZATIONS
+;;
+
+(define_peephole
+  [(parallel [(set (cc0) 
+                  (compare (match_operand:QI 0 "register_operand"  "j,j,h,q,q,q")
+                           (match_operand:QI 1 "register_operand"  "v,y,q,v,y,j")))
+             (use (match_operand:QI 2 "register_operand" "=k,k,k,u,u,u"))
+             (use (match_operand:QI 3 "register_operand" "=w,z,u,w,z,k"))])
+   (set (pc)   
+       (if_then_else (match_operator 5 "signed_comparison_operator" 
+                                      [(cc0) (const_int 0)])
+                     (label_ref (match_operand 4 "" ""))
+                     (pc)))]
+  "!TARGET_NEAR_JUMP"
+  "pt=%l4\;%0-%1\;if %C5 goto pt")
+
+
+(define_peephole
+  [(parallel [(set (cc0) 
+                  (compare (match_operand:QI 0 "register_operand"  "j,j,j,q,q,q")
+                           (match_operand:QI 1 "register_operand"  "v,y,q,v,y,j")))
+             (use (match_operand:QI 2 "register_operand" "=k,k,k,u,u,u"))
+             (use (match_operand:QI 3 "register_operand" "=w,z,u,w,z,k"))])
+   (set (pc)   
+       (if_then_else (match_operator 5 "signed_comparison_operator" 
+                                      [(cc0) (const_int 0)])
+                     (pc)
+                     (label_ref (match_operand 4 "" ""))))]
+  "!TARGET_NEAR_JUMP"
+  "pt=%l4\;%0-%1\;if %I5 goto pt")
 
 
 (define_peephole
-  [(set (match_operand:QI 0 "register_operand" "=A")
-        (reg:QI 16))
-   (set (match_operand 1 "" "")
-        (call (mem:QI (match_dup 0))
-             (match_operand 2 "" "i")))]
-   ""
-   "call pt")
+  [(parallel [(set (cc0) 
+                  (compare (match_operand:QI 0 "register_operand"  "j,q")
+                           (match_operand:QI 1 "const_int_operand" "i,i")))
+             (use (match_operand:QI 2 "register_operand" "=k,u"))])
+   (set (pc)   
+       (if_then_else (match_operator 4 "signed_comparison_operator" 
+                                      [(cc0) (const_int 0)])
+                     (label_ref (match_operand 3 "" ""))
+                     (pc)))]
+  "!TARGET_NEAR_JUMP"
+  "pt=%l3\;%b0-%H1\;if %C4 goto pt")
 
 (define_peephole
-  [(set (match_operand:HI 0 "register_operand" "=A")
-       (ashift:HI (match_operand:HI 1 "register_operand" "A")
-                  (const_int 16)))
-   (set (match_operand:HI 2 "register_operand" "")
-       (match_dup 0))
-   (set (match_dup 0)
-       (ashiftrt:HI (match_dup 0) (const_int 16)))
-   (set (match_dup 2)
-       (match_dup 0))]
-  ""
-  "%0=%1<<16\;%0=%0>>16\;%u2=%u0\;%w2=%w0")
+  [(parallel [(set (cc0) 
+                  (compare (match_operand:QI 0 "register_operand"  "j,q")
+                           (match_operand:QI 1 "const_int_operand" "i,i")))
+             (use (match_operand:QI 2 "register_operand" "=k,u"))])
+   (set (pc)   
+       (if_then_else (match_operator 4 "signed_comparison_operator" 
+                                      [(cc0) (const_int 0)])
+                     (pc)
+                     (label_ref (match_operand 3 "" ""))))]
+  "!TARGET_NEAR_JUMP"
+  "pt=%l3\;%b0-%H1\;if %I4 goto pt")
+
+;; TST PEEPHOLE PATTERNS
 
 (define_peephole
-  [(set (match_operand:HI 0 "register_operand" "=A")
-       (ashift:HI (match_operand:HI 1 "register_operand" "A")
-                  (const_int 16)))
-   (set (match_operand:HI 2 "register_operand" "")
-       (match_dup 0))
-   (set (match_dup 0)
-       (lshiftrt:HI (match_dup 0) (const_int 16)))
-   (set (match_dup 2)
-       (match_dup 0))]
-  ""
-  "%0=%1<<16\;%0=%0>>16\;%0=%b0&0x0000\;%u2=%u0\;%w2=%w0")
+  [(parallel [(set (cc0) 
+                  (match_operand:QI 0 "register_operand"  "j,q"))
+             (use (match_operand:QI 1 "register_operand" "=k,u"))])
+   (set (pc)   
+       (if_then_else (match_operator 3 "signed_comparison_operator" 
+                                      [(cc0) (const_int 0)])
+                     (pc)
+                     (label_ref (match_operand 2 "" ""))))]
+  "!TARGET_NEAR_JUMP"
+  "pt=%l2\;%b0-0\;if %I3 goto pt")
+
+(define_peephole
+  [(parallel [(set (cc0) 
+                  (match_operand:QI 0 "register_operand"  "j,q"))
+             (use (match_operand:QI 1 "register_operand" "=k,u"))])
+   (set (pc)   
+       (if_then_else (match_operator 3 "signed_comparison_operator" 
+                                      [(cc0) (const_int 0)])
+                     (label_ref (match_operand 2 "" ""))
+                     (pc)))]
+  "!TARGET_NEAR_JUMP"
+  "pt=%l2\;%b0-0\;if %C3 goto pt")
+
+;; HImode peephole patterns
+
+(define_peephole
+  [(set (cc0) 
+       (compare (match_operand:HI 0 "register_operand"  "A,A")
+                (match_operand:HI 1 "register_operand"  "Z,A")))
+   (set (pc)   
+       (if_then_else (match_operator 3 "signed_comparison_operator" 
+                                      [(cc0) (const_int 0)])
+                     (label_ref (match_operand 2 "" ""))
+                     (pc)))]
+  "!TARGET_NEAR_JUMP"
+  "pt=%l2\;%0-%1\;if %C3 goto pt")
+
+(define_peephole
+  [(set (cc0) 
+       (compare (match_operand:HI 0 "register_operand"  "A,A")
+                (match_operand:HI 1 "register_operand"  "Z,A")))
+   (set (pc)   
+       (if_then_else (match_operator 3 "signed_comparison_operator" 
+                                      [(cc0) (const_int 0)])
+                     (pc)
+                     (label_ref (match_operand 2 "" ""))))]
+  "!TARGET_NEAR_JUMP"
+  "pt=%l2\;%0-%1\;if %I3 goto pt")