aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Collison <collison@gcc.gnu.org>2001-10-14 02:14:28 +0000
committerMichael Collison <collison@gcc.gnu.org>2001-10-14 02:14:28 +0000
commitdff06f62c97fee80fc8f7e4f44ee993ffdacf6ad (patch)
treeac93a3d9669add0c1655c7b1a39e267dd4fcb1cf
parent48d24deb4ee5d801d39135727941d1e8ae1cdde3 (diff)
downloadgcc-dff06f62c97fee80fc8f7e4f44ee993ffdacf6ad.zip
gcc-dff06f62c97fee80fc8f7e4f44ee993ffdacf6ad.tar.gz
gcc-dff06f62c97fee80fc8f7e4f44ee993ffdacf6ad.tar.bz2
dsp16xx.md: Rewrite for more efficient code and add scheduling support.
* config/dsp16xx/dsp16xx.md: Rewrite for more efficient code and 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. From-SVN: r46248
-rw-r--r--gcc/config/dsp16xx/dsp16xx-protos.h6
-rw-r--r--gcc/config/dsp16xx/dsp16xx.c1075
-rw-r--r--gcc/config/dsp16xx/dsp16xx.h328
-rw-r--r--gcc/config/dsp16xx/dsp16xx.md1246
4 files changed, 1957 insertions, 698 deletions
diff --git a/gcc/config/dsp16xx/dsp16xx-protos.h b/gcc/config/dsp16xx/dsp16xx-protos.h
index 6401f70..02ba7b8 100644
--- a/gcc/config/dsp16xx/dsp16xx-protos.h
+++ b/gcc/config/dsp16xx/dsp16xx-protos.h
@@ -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));
diff --git a/gcc/config/dsp16xx/dsp16xx.c b/gcc/config/dsp16xx/dsp16xx.c
index 74de0d0..8ca95a6 100644
--- a/gcc/config/dsp16xx/dsp16xx.c
+++ b/gcc/config/dsp16xx/dsp16xx.c
@@ -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));
-
+
/* 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;
-
+
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);
+ fprintf( file, "\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;
+}
diff --git a/gcc/config/dsp16xx/dsp16xx.h b/gcc/config/dsp16xx/dsp16xx.h
index f98d678..dae1d74 100644
--- a/gcc/config/dsp16xx/dsp16xx.h
+++ b/gcc/config/dsp16xx/dsp16xx.h
@@ -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; \
+ } \
+}
/* 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"
+
/* 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
/* 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 ")"
+
/* 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)
/* 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
diff --git a/gcc/config/dsp16xx/dsp16xx.md b/gcc/config/dsp16xx/dsp16xx.md
index 29d9acd..1f44420 100644
--- a/gcc/config/dsp16xx/dsp16xx.md
+++ b/gcc/config/dsp16xx/dsp16xx.md
@@ -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.
@@ -36,15 +36,25 @@
; 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)
;; ....................
@@ -84,6 +94,28 @@
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"))
@@ -92,7 +124,7 @@
"@
%1=0\;%b0-0
%1=0\;%b0-0"
- [(set_attr "type" "malu,malu")])
+ [(set_attr "type" "tstqi,tstqi")])
;;
@@ -104,8 +136,8 @@
(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")))]
""
"*
{
@@ -114,14 +146,9 @@
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 ""
@@ -178,7 +205,7 @@
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);
@@ -198,7 +225,7 @@
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)
{
@@ -243,6 +270,64 @@
}
}")
+(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")))
@@ -259,6 +344,64 @@
%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")
@@ -304,17 +447,45 @@
;;
;; ....................
+(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")
@@ -354,10 +525,10 @@
(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"))]
""
"*
{
@@ -384,24 +555,26 @@
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" "")
@@ -428,22 +601,51 @@
;;
;; ....................
+(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"))]
""
"*
{
@@ -452,15 +654,12 @@
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]));
@@ -472,18 +671,22 @@
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" "")
@@ -510,21 +713,30 @@
[(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;
+ }
+}")
;;
;; ....................
@@ -566,14 +778,6 @@
"%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" "")
@@ -767,94 +971,279 @@
;; 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")
@@ -863,20 +1252,121 @@
"%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")])
;;
;; 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" ""))]
@@ -918,11 +1408,9 @@
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'.
@@ -952,7 +1440,7 @@
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
@@ -985,10 +1473,9 @@
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<>")
@@ -1000,7 +1487,7 @@
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
@@ -1033,10 +1520,9 @@
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")
@@ -1131,8 +1617,8 @@
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 ""
@@ -1190,8 +1676,6 @@
case 5:
case 6:
return \"%u0=%u1\;%w0=%w1\";
- default:
- abort();
}
}"
[(set_attr "type" "move,move,load_i,load,store,load,store")])
@@ -1258,9 +1742,16 @@
"
{
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")))]
@@ -1296,22 +1787,90 @@
;; }
;; }")
+;;(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" "")))]
@@ -1467,7 +2026,7 @@
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;
}
@@ -1506,9 +2065,9 @@
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 \"}\";
}
}")
@@ -1521,7 +2080,7 @@
[(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")])
@@ -1529,7 +2088,7 @@
[(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")])
@@ -1537,7 +2096,7 @@
[(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")])
@@ -1545,7 +2104,7 @@
[(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")])
@@ -1592,7 +2151,7 @@
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;
}
@@ -1633,9 +2192,9 @@
{
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\";
}
}")
@@ -1673,14 +2232,6 @@
(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)))]
""
@@ -1729,18 +2280,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
@@ -1757,7 +2306,7 @@
%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")
@@ -1774,14 +2323,184 @@
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 \"}\";
}
}")
+
+(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
;;
@@ -2138,45 +2857,168 @@
(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")