Commit dff06f62 by Michael Collison

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
parent 48d24deb
...@@ -29,6 +29,8 @@ extern int sp_operand PARAMS ((rtx, enum machine_mode)); ...@@ -29,6 +29,8 @@ extern int sp_operand PARAMS ((rtx, enum machine_mode));
extern int sp_operand2 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 nonmemory_arith_operand PARAMS ((rtx, enum machine_mode));
extern int dsp16xx_comparison_operator 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 notice_update_cc PARAMS ((rtx));
extern void double_reg_from_memory 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)); ...@@ -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_float PARAMS ((FILE *, double));
extern void asm_output_long PARAMS ((FILE *, long)); extern void asm_output_long PARAMS ((FILE *, long));
extern void dsp16xx_file_start PARAMS ((void)); 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 struct rtx_def *(*dsp16xx_compare_gen) PARAMS (());
extern int hard_regno_mode_ok PARAMS ((int, enum machine_mode)); extern int hard_regno_mode_ok PARAMS ((int, enum machine_mode));
extern enum reg_class dsp16xx_reg_class_from_letter PARAMS ((int)); extern enum reg_class dsp16xx_reg_class_from_letter PARAMS ((int));
extern int regno_reg_class PARAMS ((int)); extern int regno_reg_class PARAMS ((int));
extern void function_prologue PARAMS ((FILE *, int));
extern void function_epilogue PARAMS ((FILE *, int));
/* Subroutines for assembler code output on the DSP1610. /* Subroutines for assembler code output on the DSP1610.
Copyright (C) 1994, 1995, 1997, 1998, 2001 Free Software Foundation, Inc. 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. This file is part of GNU CC.
...@@ -37,7 +37,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -37,7 +37,7 @@ Boston, MA 02111-1307, USA. */
#include "ggc.h" #include "ggc.h"
#include "toplev.h" #include "toplev.h"
#include "recog.h" #include "recog.h"
#include "tm_p.h" #include "dsp16xx-protos.h"
#include "target.h" #include "target.h"
#include "target-def.h" #include "target-def.h"
...@@ -58,7 +58,7 @@ const char *save_chip_name; ...@@ -58,7 +58,7 @@ const char *save_chip_name;
rtx dsp16xx_compare_op0; rtx dsp16xx_compare_op0;
rtx dsp16xx_compare_op1; rtx dsp16xx_compare_op1;
rtx (*dsp16xx_compare_gen) PARAMS (()); struct rtx_def *(*dsp16xx_compare_gen)();
static const char *fp; static const char *fp;
static const char *sp; static const char *sp;
...@@ -149,7 +149,7 @@ static const char *const lshift_right_asm_first[] = ...@@ -149,7 +149,7 @@ static const char *const lshift_right_asm_first[] =
static int reg_save_size PARAMS ((void)); static int reg_save_size PARAMS ((void));
static void dsp16xx_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT)); static void dsp16xx_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
static void dsp16xx_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT)); static void dsp16xx_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
/* Initialize the GCC target structure. */ /* Initialize the GCC target structure. */
#undef TARGET_ASM_FUNCTION_PROLOGUE #undef TARGET_ASM_FUNCTION_PROLOGUE
#define TARGET_ASM_FUNCTION_PROLOGUE dsp16xx_output_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)); ...@@ -157,7 +157,7 @@ static void dsp16xx_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
#define TARGET_ASM_FUNCTION_EPILOGUE dsp16xx_output_function_epilogue #define TARGET_ASM_FUNCTION_EPILOGUE dsp16xx_output_function_epilogue
struct gcc_target targetm = TARGET_INITIALIZER; struct gcc_target targetm = TARGET_INITIALIZER;
int int
hard_regno_mode_ok (regno, mode) hard_regno_mode_ok (regno, mode)
int regno; int regno;
...@@ -208,6 +208,12 @@ dsp16xx_reg_class_from_letter (c) ...@@ -208,6 +208,12 @@ dsp16xx_reg_class_from_letter (c)
{ {
case 'A': case 'A':
return ACCUM_REGS; return ACCUM_REGS;
case 'l':
return A0_REG;
case 'C':
return A1_REG;
case 'h': case 'h':
return ACCUM_HIGH_REGS; return ACCUM_HIGH_REGS;
...@@ -242,9 +248,6 @@ dsp16xx_reg_class_from_letter (c) ...@@ -242,9 +248,6 @@ dsp16xx_reg_class_from_letter (c)
case 'd': case 'd':
return ACCUM_Y_OR_P_REGS; return ACCUM_Y_OR_P_REGS;
case 'C':
return NO_FRAME_Y_ADDR_REGS;
case 'a': case 'a':
return Y_ADDR_REGS; return Y_ADDR_REGS;
...@@ -279,7 +282,7 @@ dsp16xx_reg_class_from_letter (c) ...@@ -279,7 +282,7 @@ dsp16xx_reg_class_from_letter (c)
return SLOW_MEM_LOAD_REGS; return SLOW_MEM_LOAD_REGS;
default: default:
abort (); return NO_REGS;
} }
} }
/* Return the class number of the smallest class containing /* Return the class number of the smallest class containing
...@@ -368,210 +371,16 @@ class_max_nregs(class, mode) ...@@ -368,210 +371,16 @@ class_max_nregs(class, mode)
enum reg_class enum reg_class
limit_reload_class (mode, class) limit_reload_class (mode, class)
enum machine_mode mode; enum machine_mode mode ATTRIBUTE_UNUSED;
enum reg_class class; enum reg_class class;
{ {
switch ((int) class) return 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;
}
} }
int int
dsp16xx_register_move_cost (from, to) dsp16xx_register_move_cost (from, to)
enum reg_class 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 || if (from == A0H_REG || from == A0L_REG || from == A0_REG ||
from == A1H_REG || from == ACCUM_HIGH_REGS || from == A1L_REG || from == A1H_REG || from == ACCUM_HIGH_REGS || from == A1L_REG ||
from == ACCUM_LOW_REGS || from == A1_REG || from == ACCUM_REGS) from == ACCUM_LOW_REGS || from == A1_REG || from == ACCUM_REGS)
...@@ -589,18 +398,20 @@ dsp16xx_register_move_cost (from, to) ...@@ -589,18 +398,20 @@ dsp16xx_register_move_cost (from, to)
return 2; return 2;
} }
#if 0
if (from == YBASE_VIRT_REGS) if (from == YBASE_VIRT_REGS)
{ {
if (to == YBASE_VIRT_REGS)
return 16;
if (to == X_REG || to == YH_REG || to == YL_REG || if (to == X_REG || to == YH_REG || to == YL_REG ||
to == Y_REG || to == PL_REG || to == PH_REG || to == Y_REG || to == PL_REG || to == PH_REG ||
to == P_REG || to == Y_ADDR_REGS || to == YBASE_ELIGIBLE_REGS || to == P_REG || to == Y_ADDR_REGS || to == YBASE_ELIGIBLE_REGS ||
to == Y_OR_P_REGS) to == Y_OR_P_REGS)
{ {
return 2; return 8;
} }
else else
return 4; return 10;
} }
if (to == YBASE_VIRT_REGS) if (to == YBASE_VIRT_REGS)
...@@ -610,13 +421,13 @@ dsp16xx_register_move_cost (from, to) ...@@ -610,13 +421,13 @@ dsp16xx_register_move_cost (from, to)
from == P_REG || from == Y_ADDR_REGS || from == YBASE_ELIGIBLE_REGS || from == P_REG || from == Y_ADDR_REGS || from == YBASE_ELIGIBLE_REGS ||
from == Y_OR_P_REGS) from == Y_OR_P_REGS)
{ {
return 2; return 8;
} }
else else
return 4; return 10;
} }
#endif
return 4; return 8;
} }
/* Given an rtx X being reloaded into a reg required to be /* Given an rtx X being reloaded into a reg required to be
...@@ -636,13 +447,341 @@ preferred_reload_class (x, class) ...@@ -636,13 +447,341 @@ preferred_reload_class (x, class)
if (CONSTANT_P (x)) if (CONSTANT_P (x))
{ {
if (class == ALL_REGS) switch ((int) class)
return NON_YBASE_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 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))) && 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) if (GET_CODE (x) == PLUS)
{ {
...@@ -655,6 +794,12 @@ preferred_reload_class (x, class) ...@@ -655,6 +794,12 @@ preferred_reload_class (x, class)
if (class == ACCUM_HIGH_REGS) if (class == ACCUM_HIGH_REGS)
return class; 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)) if (reg_class_subset_p (ACCUM_HIGH_REGS, class))
return ACCUM_HIGH_REGS; return ACCUM_HIGH_REGS;
...@@ -678,14 +823,54 @@ preferred_reload_class (x, class) ...@@ -678,14 +823,54 @@ preferred_reload_class (x, class)
} }
else if (GET_CODE (x) == MEM) 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 switch ((int) class)
if (GET_MODE(x) == HImode) {
return NO_ACCUM_NON_YBASE_REGS; case YBASE_VIRT_REGS:
else return (!reload_in_progress ? NO_REGS : class);
#endif
return NON_YBASE_REGS; 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 else
return class; return class;
...@@ -709,6 +894,18 @@ secondary_reload_class (class, mode, in) ...@@ -709,6 +894,18 @@ secondary_reload_class (class, mode, in)
if (GET_CODE (in) == REG || GET_CODE (in) == SUBREG) if (GET_CODE (in) == REG || GET_CODE (in) == SUBREG)
regno = true_regnum (in); 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 if (class == ACCUM_HIGH_REGS
|| class == ACCUM_LOW_REGS || class == ACCUM_LOW_REGS
|| class == A1L_REG || class == A1L_REG
...@@ -737,6 +934,12 @@ secondary_reload_class (class, mode, in) ...@@ -737,6 +934,12 @@ secondary_reload_class (class, mode, in)
(regno >= REG_A0 && regno < REG_A1L + 1)) (regno >= REG_A0 && regno < REG_A1L + 1))
return NO_REGS; 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: /* We can copy the ybase registers into:
r0-r3, a0-a1, y, p, & x or the union of r0-r3, a0-a1, y, p, & x or the union of
any of these. */ any of these. */
...@@ -1128,6 +1331,9 @@ compute_frame_size (size) ...@@ -1128,6 +1331,9 @@ compute_frame_size (size)
long extra_size; long extra_size;
long reg_size; long reg_size;
/* This value is needed to compute reg_size */
current_frame_info.function_makes_calls = !leaf_function_p ();
reg_size = 0; reg_size = 0;
extra_size = 0; extra_size = 0;
var_size = size; var_size = size;
...@@ -1145,7 +1351,6 @@ compute_frame_size (size) ...@@ -1145,7 +1351,6 @@ compute_frame_size (size)
current_frame_info.reg_size = reg_size; current_frame_info.reg_size = reg_size;
current_frame_info.initialized = reload_completed; current_frame_info.initialized = reload_completed;
current_frame_info.reg_size = reg_size / UNITS_PER_WORD; current_frame_info.reg_size = reg_size / UNITS_PER_WORD;
current_frame_info.function_makes_calls = dsp16xx_makes_calls ();
if (reg_size) if (reg_size)
{ {
...@@ -1157,13 +1362,29 @@ compute_frame_size (size) ...@@ -1157,13 +1362,29 @@ compute_frame_size (size)
return total_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 int
dsp16xx_call_saved_register (regno) dsp16xx_call_saved_register (regno)
int 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] && return (regs_ever_live[regno] && !call_used_regs[regno] &&
!IS_YBASE_REGISTER_WINDOW(regno)); !IS_YBASE_REGISTER_WINDOW(regno));
} }
int int
...@@ -1182,10 +1403,10 @@ ybase_regs_ever_used () ...@@ -1182,10 +1403,10 @@ ybase_regs_ever_used ()
return live; return live;
} }
static void void
dsp16xx_output_function_prologue (file, size) dsp16xx_output_function_prologue (file, size)
FILE *file; FILE *file;
HOST_WIDE_INT size; int size;
{ {
int regno; int regno;
long total_size; long total_size;
...@@ -1197,14 +1418,14 @@ dsp16xx_output_function_prologue (file, size) ...@@ -1197,14 +1418,14 @@ dsp16xx_output_function_prologue (file, size)
total_size = compute_frame_size (size); total_size = compute_frame_size (size);
fprintf( file, "\t/* FUNCTION PROLOGUE: */\n" ); 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.total_size,
current_frame_info.var_size, current_frame_info.var_size,
current_frame_info.reg_size, current_frame_info.reg_size,
current_function_outgoing_args_size, current_function_outgoing_args_size,
current_frame_info.extra_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.fp_save_offset,
current_frame_info.sp_save_offset); current_frame_info.sp_save_offset);
/* Set up the 'ybase' register window. */ /* Set up the 'ybase' register window. */
...@@ -1219,58 +1440,51 @@ dsp16xx_output_function_prologue (file, size) ...@@ -1219,58 +1440,51 @@ dsp16xx_output_function_prologue (file, size)
fprintf (file, "\t%s=%s\n", reg_names[REG_YBASE], a1h); 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)
{ {
if (current_frame_info.var_size == 1) if (current_frame_info.var_size == 1)
fprintf (file, "\t*%s++\n", sp); 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 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, /* Save any registers this function uses, unless they are
in which case we don't need to. */ * 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 (dsp16xx_call_saved_register (regno))
{ {
#if OLD_REGISTER_SAVE fprintf( file, "\tpush(*%s)=%s\n", sp, reg_names[regno] );
fprintf (file, "\t*%s++=%s\n", sp, reg_names[regno]);
#else
fprintf (file, "\tpush(*%s)=%s\n", sp, reg_names[regno]);
#endif
} }
/* 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)
{ {
if (current_frame_info.args_size == 1) if (current_frame_info.args_size == 1)
fprintf (file, "\t*%s++\n", sp); 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 else
error ("Stack size > 32k"); error ("Stack size > 32k");
} }
if (frame_pointer_needed) if (frame_pointer_needed)
{ {
fprintf (file, "\t%s=%s\n", a1h, sp); fprintf( file, "\t%s=%s\n", a1h, sp );
fprintf (file, "\t%s=%s\n", fp, a1h); /* Establish new base frame */ 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=%d\n", reg_names[REG_J], -total_size);
fprintf (file, "\t*%s++%s\n", fp, reg_names[REG_J]); 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 void
...@@ -1300,16 +1514,12 @@ init_emulation_routines () ...@@ -1300,16 +1514,12 @@ init_emulation_routines ()
dsp16xx_lshrhi3_libcall = (rtx) 0; dsp16xx_lshrhi3_libcall = (rtx) 0;
} }
void
static void
dsp16xx_output_function_epilogue (file, size) dsp16xx_output_function_epilogue (file, size)
FILE *file; FILE *file;
HOST_WIDE_INT size ATTRIBUTE_UNUSED; int size ATTRIBUTE_UNUSED;
{ {
int regno; int regno;
#if OLD_REGISTER_SAVE
int initial_stack_dec = 0;
#endif
fp = reg_names[FRAME_POINTER_REGNUM]; fp = reg_names[FRAME_POINTER_REGNUM];
sp = reg_names[STACK_POINTER_REGNUM]; sp = reg_names[STACK_POINTER_REGNUM];
...@@ -1324,7 +1534,7 @@ dsp16xx_output_function_epilogue (file, size) ...@@ -1324,7 +1534,7 @@ dsp16xx_output_function_epilogue (file, size)
fprintf (file, "\t*%s--\n", sp); fprintf (file, "\t*%s--\n", sp);
else 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]); reg_names[REG_J], -current_frame_info.args_size, sp, reg_names[REG_J]);
} }
} }
...@@ -1338,40 +1548,23 @@ dsp16xx_output_function_epilogue (file, size) ...@@ -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=%sh-32\n", reg_names[REG_A1], a1h);
fprintf (file, "\t%s=%s\n", reg_names[REG_YBASE], 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) for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; --regno)
if (dsp16xx_call_saved_register(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 ); 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)
{ {
if (current_frame_info.var_size == 1) if (current_frame_info.var_size == 1)
fprintf (file, "\t*%s--\n", sp); fprintf (file, "\t*%s--\n", sp);
else 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]); reg_names[REG_J], -current_frame_info.var_size, sp, reg_names[REG_J]);
} }
} }
...@@ -1427,7 +1620,7 @@ double_reg_from_memory (operands) ...@@ -1427,7 +1620,7 @@ double_reg_from_memory (operands)
else if (GET_CODE(XEXP(operands[1],0)) == PLUS) else if (GET_CODE(XEXP(operands[1],0)) == PLUS)
{ {
rtx addr; rtx addr;
int offset; int offset = 0;
output_asm_insn ("%u0=%1", operands); output_asm_insn ("%u0=%1", operands);
...@@ -1477,7 +1670,7 @@ double_reg_to_memory (operands) ...@@ -1477,7 +1670,7 @@ double_reg_to_memory (operands)
else if (GET_CODE(XEXP(operands[0],0)) == PLUS) else if (GET_CODE(XEXP(operands[0],0)) == PLUS)
{ {
rtx addr; rtx addr;
int offset; int offset = 0;
output_asm_insn ("%0=%u1", operands); output_asm_insn ("%0=%u1", operands);
...@@ -1489,10 +1682,9 @@ double_reg_to_memory (operands) ...@@ -1489,10 +1682,9 @@ double_reg_to_memory (operands)
else if (GET_CODE (XEXP(addr,1)) == CONST_INT) else if (GET_CODE (XEXP(addr,1)) == CONST_INT)
offset = INTVAL(XEXP(addr,1)) + 1; offset = INTVAL(XEXP(addr,1)) + 1;
else else
abort (); fatal_error ("Invalid addressing mode");
fprintf (asm_out_file, "\t*(%d)=%s\n", offset + 31, fprintf (asm_out_file, "\t*(%d)=%s\n", offset + 31, reg_names[REGNO(operands[1]) + 1]);
reg_names[REGNO(operands[1]) + 1]);
} }
else else
{ {
...@@ -1541,15 +1733,6 @@ override_options () ...@@ -1541,15 +1733,6 @@ override_options ()
strlen(const_seg_name) + 3); strlen(const_seg_name) + 3);
sprintf (tmp, ".rsect \"%s\"", const_seg_name); 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. */ /* Mark our global variables for GC. */
ggc_add_rtx_root (&dsp16xx_addhf3_libcall, 1); ggc_add_rtx_root (&dsp16xx_addhf3_libcall, 1);
ggc_add_rtx_root (&dsp16xx_subhf3_libcall, 1); ggc_add_rtx_root (&dsp16xx_subhf3_libcall, 1);
...@@ -1574,13 +1757,31 @@ override_options () ...@@ -1574,13 +1757,31 @@ override_options ()
ggc_add_rtx_root (&dsp16xx_lshrhi3_libcall, 1); 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 enum rtx_code
next_cc_user_code (insn) next_cc_user_code (insn)
rtx 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))) if ( !(insn = next_cc0_user (insn)))
abort (); return (enum rtx_code) 0;
else if (GET_CODE (insn) == JUMP_INSN else if (GET_CODE (insn) == JUMP_INSN
&& GET_CODE (PATTERN (insn)) == SET && GET_CODE (PATTERN (insn)) == SET
&& GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE) && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE)
...@@ -1593,22 +1794,6 @@ next_cc_user_code (insn) ...@@ -1593,22 +1794,6 @@ next_cc_user_code (insn)
abort (); 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 void
print_operand(file, op, letter) print_operand(file, op, letter)
FILE *file; FILE *file;
...@@ -1689,19 +1874,57 @@ print_operand(file, op, letter) ...@@ -1689,19 +1874,57 @@ print_operand(file, op, letter)
else if (letter == 'h') else if (letter == 'h')
fprintf (file, HOST_WIDE_INT_PRINT_DEC, val); fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);
else if (letter == 'U') 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 else
output_addr_const (file, op); output_addr_const( file, op );
} }
else if (code == CONST_DOUBLE && GET_MODE (op) != DImode) 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; rtx addr = XEXP (op, 0);
union {float f; int i; } u1;
if (GET_CODE (addr) != PLUS)
u.i[0] = CONST_DOUBLE_LOW (op); {
u.i[1] = CONST_DOUBLE_HIGH (op); output_addr_const( file, op);
u1.f = u.d; return;
fprintf (file, "0x%x", u1.i); }
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 else
output_addr_const (file, op); output_addr_const (file, op);
...@@ -1714,7 +1937,7 @@ print_operand_address(file, addr) ...@@ -1714,7 +1937,7 @@ print_operand_address(file, addr)
rtx addr; rtx addr;
{ {
rtx base; rtx base;
int offset; int offset = 0;;
switch (GET_CODE (addr)) switch (GET_CODE (addr))
{ {
...@@ -1737,10 +1960,10 @@ print_operand_address(file, addr) ...@@ -1737,10 +1960,10 @@ print_operand_address(file, addr)
if (offset >= -31 && offset <= 0) if (offset >= -31 && offset <= 0)
offset = 31 + offset; offset = 31 + offset;
else else
abort (); fatal_error ("Invalid offset in ybase addressing");
} }
else else
abort (); fatal_error ("Invalid register in ybase addressing");
fprintf (file, "*(%d)", offset); fprintf (file, "*(%d)", offset);
break; break;
...@@ -1777,17 +2000,22 @@ static int ...@@ -1777,17 +2000,22 @@ static int
reg_save_size () reg_save_size ()
{ {
int reg_save_size = 0; int reg_save_size = 0;
int regno; int regno;
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (dsp16xx_call_saved_register (regno)) if (dsp16xx_call_saved_register (regno))
{ {
reg_save_size += UNITS_PER_WORD; 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); return (reg_save_size);
} }
#if 0
int int
dsp16xx_starting_frame_offset() dsp16xx_starting_frame_offset()
{ {
...@@ -1802,6 +2030,7 @@ dsp16xx_starting_frame_offset() ...@@ -1802,6 +2030,7 @@ dsp16xx_starting_frame_offset()
return (reg_save_size); return (reg_save_size);
} }
#endif
int int
initial_frame_pointer_offset() initial_frame_pointer_offset()
...@@ -1913,7 +2142,7 @@ emit_1600_core_shift (shift_op, operands, shift_amount) ...@@ -1913,7 +2142,7 @@ emit_1600_core_shift (shift_op, operands, shift_amount)
shift_asm_ptr_first = lshift_right_asm_first; shift_asm_ptr_first = lshift_right_asm_first;
} }
else else
abort (); fatal_error ("Invalid shift operator in emit_1600_core_shift");
while (shift_amount != 0) while (shift_amount != 0)
{ {
...@@ -1956,6 +2185,57 @@ emit_1600_core_shift (shift_op, operands, shift_amount) ...@@ -1956,6 +2185,57 @@ emit_1600_core_shift (shift_op, operands, shift_amount)
} }
} }
#endif #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 void
asm_output_common(file, name, size, rounded) asm_output_common(file, name, size, rounded)
FILE *file; FILE *file;
...@@ -2134,6 +2414,9 @@ dsp16xx_function_arg (args_so_far, mode, type, named) ...@@ -2134,6 +2414,9 @@ dsp16xx_function_arg (args_so_far, mode, type, named)
&& (mode == HImode || GET_MODE_CLASS(mode) == MODE_FLOAT)) && (mode == HImode || GET_MODE_CLASS(mode) == MODE_FLOAT))
args_so_far++; 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)) 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); return gen_rtx_REG (mode, args_so_far + FIRST_REG_FOR_FUNCTION_ARG);
else else
...@@ -2166,13 +2449,50 @@ dsp16xx_function_arg_advance (cum, mode, type, named) ...@@ -2166,13 +2449,50 @@ dsp16xx_function_arg_advance (cum, mode, type, named)
} }
void void
dsp16xx_file_start () coff_dsp16xx_file_start (file)
FILE *file;
{ {
fprintf (asm_out_file, "#include <%s.h>\n", save_chip_name); fprintf (file, "#include <%s.h>\n", save_chip_name);
#if 0 }
if (TARGET_BMU)
fprintf (asm_out_file, "#include <1610.h>\n"); 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 #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 rtx
...@@ -2192,7 +2512,7 @@ gen_tst_reg (x) ...@@ -2192,7 +2512,7 @@ gen_tst_reg (x)
else if (mode == HImode) else if (mode == HImode)
emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, x)); emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, x));
else else
abort (); fatal_error ("Invalid mode for gen_tst_reg");
return cc0_rtx; return cc0_rtx;
} }
...@@ -2243,28 +2563,19 @@ gen_compare_reg (code, x, y) ...@@ -2243,28 +2563,19 @@ gen_compare_reg (code, x, y)
if (code == GTU || code == GEU if (code == GTU || code == GEU
|| code == LTU || code == LEU) || code == LTU || code == LEU)
{ {
#if 1 emit_insn (gen_rtx_PARALLEL
emit_insn (gen_rtx_PARALLEL (VOIDmode,
(VOIDmode,
gen_rtvec (5, gen_rtvec (5,
gen_rtx_SET (VOIDmode, cc0_rtx, gen_rtx_SET (VOIDmode, cc0_rtx,
gen_rtx_COMPARE (VOIDmode, gen_rtx_COMPARE (VOIDmode, x, y)),
x, y)), gen_rtx_CLOBBER (VOIDmode,
gen_rtx_CLOBBER (VOIDmode,
gen_rtx_SCRATCH (QImode)), gen_rtx_SCRATCH (QImode)),
gen_rtx_CLOBBER (VOIDmode, gen_rtx_CLOBBER (VOIDmode,
gen_rtx_SCRATCH (QImode)), gen_rtx_SCRATCH (QImode)),
gen_rtx_CLOBBER (VOIDmode, gen_rtx_CLOBBER (VOIDmode,
gen_rtx_SCRATCH (QImode)), gen_rtx_SCRATCH (QImode)),
gen_rtx_CLOBBER (VOIDmode, gen_rtx_CLOBBER (VOIDmode,
gen_rtx_SCRATCH (QImode))))); 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 else
emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx,
...@@ -2273,7 +2584,7 @@ gen_compare_reg (code, x, y) ...@@ -2273,7 +2584,7 @@ gen_compare_reg (code, x, y)
force_reg (HImode,y)))); force_reg (HImode,y))));
} }
else else
abort (); fatal_error ("Invalid mode for integer comparison in gen_compare_reg");
return cc0_rtx; return cc0_rtx;
} }
...@@ -2297,3 +2608,49 @@ output_block_move (operands) ...@@ -2297,3 +2608,49 @@ output_block_move (operands)
fprintf (asm_out_file, "\t}\n"); fprintf (asm_out_file, "\t}\n");
return ""; 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;
}
/* Definitions of target machine for GNU compiler. AT&T DSP1600. /* Definitions of target machine for GNU compiler. AT&T DSP1600.
Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001 Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001
Free Software Foundation, Inc. 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. This file is part of GNU CC.
...@@ -74,7 +74,9 @@ extern struct rtx_def *dsp16xx_lshrhi3_libcall; ...@@ -74,7 +74,9 @@ extern struct rtx_def *dsp16xx_lshrhi3_libcall;
#ifdef CC1_SPEC #ifdef CC1_SPEC
#undef CC1_SPEC #undef CC1_SPEC
#endif #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 */ /* Define this as a spec to call the AT&T assembler */
...@@ -111,22 +113,29 @@ extern struct rtx_def *dsp16xx_lshrhi3_libcall; ...@@ -111,22 +113,29 @@ extern struct rtx_def *dsp16xx_lshrhi3_libcall;
/* Tell gcc where to look for the startfile */ /* 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 */ /* Tell gcc where to look for it's executables */
#define STANDARD_EXEC_PREFIX "/d1600/bin" /*#define STANDARD_EXEC_PREFIX "/d1600/bin"*/
/* Command line options to the AT&T assembler */ /* 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 */ /* Command line options for the AT&T linker */
#define LINK_SPEC "%{v:-V} %{minit:-i} \
%{!ifile*:%{mmap1:-ifile m1_deflt.if%s} \ #define LINK_SPEC "%{V} %{v:%{!V:-V}} %{minit:-i} \
%{mmap2:-ifile m2_deflt.if%s} \ %{!ifile*:%{mmap1:m1_deflt.if%s} \
%{mmap3:-ifile m3_deflt.if%s} \ %{mmap2:m2_deflt.if%s} \
%{mmap4:-ifile m4_deflt.if%s} \ %{mmap3:m3_deflt.if%s} \
%{!mmap*:-ifile m4_deflt.if%s}} \ %{mmap4:m4_deflt.if%s} \
%{ifile*} %{!r:-a}" %{!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. */ /* Names to predefine in the preprocessor for this target machine. */
#ifdef __MSDOS__ #ifdef __MSDOS__
...@@ -145,8 +154,6 @@ extern int target_flags; ...@@ -145,8 +154,6 @@ extern int target_flags;
#define MASK_NEAR_CALL 0x00000002 /* The call is on the same 4k page */ #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_NEAR_JUMP 0x00000004 /* The jump is on the same 4k page */
#define MASK_BMU 0x00000008 /* Use the 'bmu' shift instructions */ #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_MAP1 0x00000040 /* Link with map1 */
#define MASK_MAP2 0x00000080 /* Link with map2 */ #define MASK_MAP2 0x00000080 /* Link with map2 */
#define MASK_MAP3 0x00000100 /* Link with map3 */ #define MASK_MAP3 0x00000100 /* Link with map3 */
...@@ -154,8 +161,9 @@ extern int target_flags; ...@@ -154,8 +161,9 @@ extern int target_flags;
#define MASK_YBASE_HIGH 0x00000400 /* The ybase register window starts high */ #define MASK_YBASE_HIGH 0x00000400 /* The ybase register window starts high */
#define MASK_INIT 0x00000800 /* Have the linker generate tables to #define MASK_INIT 0x00000800 /* Have the linker generate tables to
initialize data at startup */ initialize data at startup */
#define MASK_INLINE_MULT 0x00001000 /* Inline 32 bit multiplies */
#define MASK_RESERVE_YBASE 0x00002000 /* Reserved the ybase registers */ #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. /* Compile passing first two args in regs 0 and 1.
This exists only to test compiler features that will This exists only to test compiler features that will
...@@ -177,12 +185,6 @@ extern int target_flags; ...@@ -177,12 +185,6 @@ extern int target_flags;
Unit. */ Unit. */
#define TARGET_BMU (target_flags & MASK_BMU) #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) #define TARGET_YBASE_HIGH (target_flags & MASK_YBASE_HIGH)
/* Direct the linker to output extra info for initialized data */ /* Direct the linker to output extra info for initialized data */
...@@ -193,6 +195,13 @@ extern int target_flags; ...@@ -193,6 +195,13 @@ extern int target_flags;
/* Reserve the ybase registers *(0) - *(31) */ /* Reserve the ybase registers *(0) - *(31) */
#define TARGET_RESERVE_YBASE (target_flags & MASK_RESERVE_YBASE) #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. /* Macro to define tables used to set the flags.
This is a list in braces of pairs in braces, This is a list in braces of pairs in braces,
each pair being { "NAME", VALUE } each pair being { "NAME", VALUE }
...@@ -200,31 +209,46 @@ extern int target_flags; ...@@ -200,31 +209,46 @@ extern int target_flags;
An empty string NAME is used to identify the default VALUE. */ An empty string NAME is used to identify the default VALUE. */
#define TARGET_SWITCHES \ #define TARGET_SWITCHES \
{ \ { \
{ "regparm", MASK_REGPARM}, \ { "regparm", MASK_REGPARM, \
{ "no-regparm", -MASK_REGPARM}, \ N_("Pass parameters in registers (default)") }, \
{ "no-near-call", -MASK_NEAR_CALL}, \ { "no-regparm", -MASK_REGPARM, \
{ "near-jump", MASK_NEAR_JUMP}, \ N_("Don't pass parameters in registers") }, \
{ "no-near-jump", -MASK_NEAR_JUMP}, \ { "near-call", MASK_NEAR_JUMP, \
{ "bmu", MASK_BMU}, \ N_("Generate code for near calls") }, \
{ "no-bmu", -MASK_BMU}, \ { "no-near-call", -MASK_NEAR_CALL, \
{ "Om", MASK_OPTIMIZE_MEMORY}, \ N_("Don't generate code for near calls") }, \
{ "Os", MASK_OPTIMIZE_SPEED}, \ { "near-jump", MASK_NEAR_JUMP, \
{ "map1", MASK_MAP1}, \ N_("Generate code for near jumps") }, \
{ "map2", MASK_MAP2}, \ { "no-near-jump", -MASK_NEAR_JUMP, \
{ "map3", MASK_MAP3}, \ N_("Don't generate code for near jumps") }, \
{ "map4", MASK_MAP4}, \ { "bmu", MASK_BMU, \
{ "ybase-high", MASK_YBASE_HIGH}, \ N_("Generate code for a bit-manipulation unit") }, \
{ "init", MASK_INIT}, \ { "no-bmu", -MASK_BMU, \
{ "inline-mult", MASK_INLINE_MULT}, \ N_("Don't generate code for a bit-manipulation unit") }, \
{ "reserve-ybase", MASK_RESERVE_YBASE}, \ { "map1", MASK_MAP1, \
{ "", TARGET_DEFAULT} \ 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 */ /* Default target_flags if no switches are specified */
#ifndef TARGET_DEFAULT #ifndef TARGET_DEFAULT
#define TARGET_DEFAULT MASK_OPTIMIZE_MEMORY|MASK_REGPARM|MASK_YBASE_HIGH #define TARGET_DEFAULT MASK_REGPARM|MASK_YBASE_HIGH
#endif #endif
/* This macro is similar to `TARGET_SWITCHES' but defines names of /* This macro is similar to `TARGET_SWITCHES' but defines names of
...@@ -246,11 +270,16 @@ extern int target_flags; ...@@ -246,11 +270,16 @@ extern int target_flags;
#define TARGET_OPTIONS \ #define TARGET_OPTIONS \
{ \ { \
{ "text=", &text_seg_name }, \ { "text=", &text_seg_name, \
{ "data=", &data_seg_name }, \ N_("Specify alternate name for text section") }, \
{ "bss=", &bss_seg_name }, \ { "data=", &data_seg_name, \
{ "const=", &const_seg_name }, \ N_("Specify alternate name for data section") }, \
{ "chip=", &chip_name } \ { "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 /* Sometimes certain combinations of command options do not make sense
...@@ -264,18 +293,21 @@ extern int target_flags; ...@@ -264,18 +293,21 @@ extern int target_flags;
#define OVERRIDE_OPTIONS override_options () #define OVERRIDE_OPTIONS override_options ()
#define OPTIMIZATION_OPTIONS(LEVEL,SIZE) \ #define OPTIMIZATION_OPTIONS(LEVEL,SIZE) \
do \ { \
{ \ flag_gnu_linker = FALSE; \
flag_gnu_linker = FALSE; \ \
\ if (LEVEL >= 2) \
if (SIZE) \ { \
{ \ /* The dsp16xx family has so few registers \
flag_strength_reduce = FALSE; \ * that running the first instruction \
flag_inline_functions = FALSE; \ * scheduling is bad for reg. allocation \
} \ * since it increases lifetimes of pseudos. \
} \ * So turn of first scheduling pass. \
while (0) */ \
flag_schedule_insns = FALSE; \
} \
}
/* STORAGE LAYOUT */ /* STORAGE LAYOUT */
...@@ -287,7 +319,7 @@ while (0) ...@@ -287,7 +319,7 @@ while (0)
/* Define this if most significant bit is lowest numbered /* Define this if most significant bit is lowest numbered
in instructions that operate on numbered bit-fields. 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. /* 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 We define big-endian, but since the 1600 series cannot address bytes
...@@ -377,12 +409,13 @@ while (0) ...@@ -377,12 +409,13 @@ while (0)
/* A C expression for a string describing the name of the data type to use for /* A C expression for a string describing the name of the data type to use for
size values. */ 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 */ result of subtracting two pointers */
#define PTRDIFF_TYPE "long int" #define PTRDIFF_TYPE "int"
/* REGISTER USAGE. */ /* REGISTER USAGE. */
...@@ -475,6 +508,10 @@ while (0) ...@@ -475,6 +508,10 @@ while (0)
/* Do we have a virtual ybase register */ /* Do we have a virtual ybase register */
#define IS_YBASE_REGISTER_WINDOW(REGNO) ((REGNO) >= REG_YBASE0 && (REGNO) <= REG_YBASE31) #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 IS_ADDRESS_REGISTER(REGNO) ((REGNO) >= REG_R0 && (REGNO) <= REG_R3)
#define FIXED_REGISTERS \ #define FIXED_REGISTERS \
...@@ -483,7 +520,7 @@ while (0) ...@@ -483,7 +520,7 @@ while (0)
1, \ 1, \
0, 0, 0, 0, \ 0, 0, 0, 0, \
1, 1, 1, \ 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, \ 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) ...@@ -501,17 +538,17 @@ while (0)
bit manipulation registers. */ bit manipulation registers. */
#define CALL_USED_REGISTERS \ #define CALL_USED_REGISTERS \
{1, 1, 1, 1, 0, 1, 1, 1, 1, \ {1, 1, 1, 1, 0, 1, 1, 1, 1, /* 0-8 */ \
1, 0, 0, 1, 1, 1, 1, \ 1, 0, 0, 1, 1, 1, 1, /* 9-15 */ \
1, \ 1, /* 16 */ \
0, 0, 1, 1, \ 0, 0, 1, 1, /* 17-20 */ \
1, 1, 1, \ 1, 1, 1, /* 21-23 */ \
0, 1, \ 1, 1, /* 24-25 */ \
0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, /* 26-33 */ \
0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, /* 34-41 */ \
0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, /* 42-49 */ \
0, 0, 0, 0, 0, 0, 0, 0} 0, 0, 0, 0, 0, 0, 0, 0} /* 50-57 */
/* List the order in which to allocate registers. Each register must be /* List the order in which to allocate registers. Each register must be
listed once, even those in FIXED_REGISTERS. listed once, even those in FIXED_REGISTERS.
...@@ -519,6 +556,7 @@ while (0) ...@@ -519,6 +556,7 @@ while (0)
We allocate in the following order: We allocate in the following order:
*/ */
#if 0
#define REG_ALLOC_ORDER \ #define REG_ALLOC_ORDER \
{ REG_R0, REG_R1, REG_R2, REG_PROD, REG_Y, REG_X, \ { REG_R0, REG_R1, REG_R2, REG_PROD, REG_Y, REG_X, \
REG_PRODL, REG_YL, REG_AR0, REG_AR1, \ REG_PRODL, REG_YL, REG_AR0, REG_AR1, \
...@@ -534,7 +572,24 @@ while (0) ...@@ -534,7 +572,24 @@ while (0)
REG_YBASE20, REG_YBASE21, REG_YBASE22, REG_YBASE23, \ REG_YBASE20, REG_YBASE21, REG_YBASE22, REG_YBASE23, \
REG_YBASE24, REG_YBASE25, REG_YBASE26, REG_YBASE27, \ REG_YBASE24, REG_YBASE25, REG_YBASE26, REG_YBASE27, \
REG_YBASE28, REG_YBASE29, REG_YBASE30, REG_YBASE31 } 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 /* Zero or more C statements that may conditionally modify two
variables `fixed_regs' and `call_used_regs' (both of type `char variables `fixed_regs' and `call_used_regs' (both of type `char
[]') after they have been initialized from the two preceding []') after they have been initialized from the two preceding
...@@ -978,23 +1033,32 @@ enum reg_class ...@@ -978,23 +1033,32 @@ enum reg_class
'I' requires a non-negative 16-bit value. 'I' requires a non-negative 16-bit value.
'J' requires a non-negative 9-bit value 'J' requires a non-negative 9-bit value
'K' requires a constant 0 operand. '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 '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_INT(X) (SMALL_INTVAL (INTVAL (X)))
#define SMALL_INTVAL(I) ((unsigned) (I) < 0x10000) #define SMALL_INTVAL(I) ((unsigned) (I) < 0x10000)
#define SHORT_IMMEDIATE(X) (SHORT_INTVAL (INTVAL(X))) #define SHORT_IMMEDIATE(X) (SHORT_INTVAL (INTVAL(X)))
#define SHORT_INTVAL(I) ((unsigned) (I) < 0x100) #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) \ #define CONST_OK_FOR_LETTER_P(VALUE, C) \
((C) == 'I' ? (SMALL_INTVAL(VALUE)) \ ((C) == 'I' ? (SMALL_INTVAL(VALUE)) \
: (C) == 'J' ? (SHORT_INTVAL(VALUE)) \ : (C) == 'J' ? (SHORT_INTVAL(VALUE)) \
: (C) == 'K' ? ((VALUE) == 0) \ : (C) == 'K' ? ((VALUE) == 0) \
: (C) == 'L' ? ! ((VALUE) & ~0x0000ffff) \ : (C) == 'L' ? ((VALUE) >= 0 && (VALUE) <= 32767) \
: (C) == 'M' ? ! ((VALUE) & ~0xffff0000) \ : (C) == 'M' ? (((VALUE) & 0x0000ffff) == 0) \
: (C) == 'N' ? ((VALUE) == -1 || (VALUE) == 1 || \ : (C) == 'N' ? ((VALUE) == -1 || (VALUE) == 1 \
(VALUE) == -2 || (VALUE) == 2) \ || (VALUE) == -2 || (VALUE) == 2) \
: (C) == 'O' ? (((VALUE) & 0xffff0000) == 0xffff0000) \
: (C) == 'P' ? (((VALUE) & 0x0000ffff) == 0xffff) \
: 0) : 0)
#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 1 #define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 1
...@@ -1043,6 +1107,7 @@ struct dsp16xx_frame_info ...@@ -1043,6 +1107,7 @@ struct dsp16xx_frame_info
unsigned int reg_size; /* # bytes needed to store regs */ unsigned int reg_size; /* # bytes needed to store regs */
long fp_save_offset; /* offset from vfp to store registers */ long fp_save_offset; /* offset from vfp to store registers */
unsigned long sp_save_offset; /* offset from new sp 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 initialized; /* != 0 if frame size already calculated */
int num_regs; /* number of registers saved */ int num_regs; /* number of registers saved */
int function_makes_calls; /* Does the function make calls */ int function_makes_calls; /* Does the function make calls */
...@@ -1050,6 +1115,8 @@ struct dsp16xx_frame_info ...@@ -1050,6 +1115,8 @@ struct dsp16xx_frame_info
extern struct dsp16xx_frame_info current_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, /* If we generate an insn to push BYTES bytes,
this says how many the stack pointer really advances by. */ this says how many the stack pointer really advances by. */
/* #define PUSH_ROUNDING(BYTES) ((BYTES)) */ /* #define PUSH_ROUNDING(BYTES) ((BYTES)) */
...@@ -1402,7 +1469,7 @@ extern struct dsp16xx_frame_info current_frame_info; ...@@ -1402,7 +1469,7 @@ extern struct dsp16xx_frame_info current_frame_info;
return it with a return statement. */ return it with a return statement. */
#define CONST_COSTS(RTX,CODE,OUTER_CODE) \ #define CONST_COSTS(RTX,CODE,OUTER_CODE) \
case CONST_INT: \ case CONST_INT: \
return 0; \ return (unsigned) INTVAL (RTX) < 65536 ? 0 : 2; \
case LABEL_REF: \ case LABEL_REF: \
case SYMBOL_REF: \ case SYMBOL_REF: \
case CONST: \ case CONST: \
...@@ -1427,45 +1494,21 @@ extern struct dsp16xx_frame_info current_frame_info; ...@@ -1427,45 +1494,21 @@ extern struct dsp16xx_frame_info current_frame_info;
else \ else \
return COSTS_N_INSNS (38); \ return COSTS_N_INSNS (38); \
case PLUS: \ 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: \ case MINUS: \
if (GET_MODE_CLASS (GET_MODE (X)) == MODE_INT) \ 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 (1 + \
return COSTS_N_INSNS (2); \ rtx_cost (XEXP (X, 0), CODE) + \
else \ rtx_cost (XEXP (X, 1), CODE)); \
return COSTS_N_INSNS (4); \
} \ } \
return COSTS_N_INSNS (1); \
} \
else \ else \
return COSTS_N_INSNS (38); \ return COSTS_N_INSNS (38); \
\
case AND: case IOR: case XOR: \ case AND: case IOR: case XOR: \
if (GET_CODE (XEXP (X,1)) == CONST_INT) \ return (1 + \
{ \ rtx_cost (XEXP (X, 0), CODE) + \
if (INT_FITS_16_BITS(INTVAL(XEXP(X,1)))) \ rtx_cost (XEXP (X, 1), CODE)); \
return COSTS_N_INSNS (2); \ \
else \
return COSTS_N_INSNS (4); \
} \
return COSTS_N_INSNS (1); \
case NEG: case NOT: \ case NEG: case NOT: \
return COSTS_N_INSNS (1); \ return COSTS_N_INSNS (1); \
case ASHIFT: \ case ASHIFT: \
...@@ -1478,9 +1521,17 @@ extern struct dsp16xx_frame_info current_frame_info; ...@@ -1478,9 +1521,17 @@ extern struct dsp16xx_frame_info current_frame_info;
number == 16) \ number == 16) \
return COSTS_N_INSNS (1); \ return COSTS_N_INSNS (1); \
else \ else \
{ \
if (TARGET_BMU) \
return COSTS_N_INSNS (2); \ 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 /* An expression giving the cost of an addressing mode that contains
address. */ address. */
...@@ -1500,7 +1551,7 @@ extern struct dsp16xx_frame_info current_frame_info; ...@@ -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 /* A C expression for the cost of a branch instruction. A value of
1 is the default; */ 1 is the default; */
#define BRANCH_COST 2 #define BRANCH_COST 1
/* Define this because otherwise gcc will try to put the function address /* Define this because otherwise gcc will try to put the function address
...@@ -1566,11 +1617,15 @@ const_section () \ ...@@ -1566,11 +1617,15 @@ const_section () \
/* THE OVERALL FRAMEWORK OF AN ASSEMBLER FILE */ /* THE OVERALL FRAMEWORK OF AN ASSEMBLER FILE */
/* Output at beginning of 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 /* A C string constant describing how to begin a comment in the target
assembler language. */ assembler language. */
/* define ASM_COMMENT_START */ #define ASM_COMMENT_START ""
#define ASM_COMMENT_END ""
/* Output to assembler file text saying following lines /* Output to assembler file text saying following lines
may contain character constants, extra white space, comments, etc. */ may contain character constants, extra white space, comments, etc. */
...@@ -1605,9 +1660,7 @@ const_section () \ ...@@ -1605,9 +1660,7 @@ const_section () \
#define ASM_OUTPUT_INT(FILE, EXP) asm_output_long(FILE,INTVAL(EXP)) #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. */ /* This is how to output an assembler line for a numeric constant byte. */
#define ASM_OUTPUT_BYTE(FILE,VALUE) \ #define ASM_OUTPUT_BYTE(FILE,VALUE) ASM_OUTPUT_CHAR(FILE,GEN_INT(VALUE))
fprintf ((FILE), "\tint %ld\n", (long)(VALUE))
/* This is how we output a 'c' character string. For the 16xx /* This is how we output a 'c' character string. For the 16xx
assembler we have to do it one letter at a time */ assembler we have to do it one letter at a time */
...@@ -1643,7 +1696,7 @@ const_section () \ ...@@ -1643,7 +1696,7 @@ const_section () \
fprintf (asm_out_file, "%d", c); \ fprintf (asm_out_file, "%d", c); \
/* After an octal-escape, if a digit follows, \ /* After an octal-escape, if a digit follows, \
terminate one string constant and start another. \ 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 \ after three digits, so this is the only way we \
can get it to parse the data properly. \ can get it to parse the data properly. \
if (i < thissize - 1 \ if (i < thissize - 1 \
...@@ -1683,6 +1736,10 @@ const_section () \ ...@@ -1683,6 +1736,10 @@ const_section () \
(OUTPUT) = (char *) alloca (strlen (NAME) + 11); \ (OUTPUT) = (char *) alloca (strlen (NAME) + 11); \
ASM_GENERATE_INTERNAL_LABEL (OUTPUT, temp, LABELNO); \ ASM_GENERATE_INTERNAL_LABEL (OUTPUT, temp, LABELNO); \
} while (0) } while (0)
#define ASM_OPEN_PAREN "("
#define ASM_CLOSE_PAREN ")"
/* OUTPUT OF UNINITIALIZED VARIABLES */ /* OUTPUT OF UNINITIALIZED VARIABLES */
...@@ -1837,17 +1894,19 @@ const_section () \ ...@@ -1837,17 +1894,19 @@ const_section () \
/* CONTROLLING DEBUGGING INFORMATION FORMAT */ /* CONTROLLING DEBUGGING INFORMATION FORMAT */
/* Define this macro if GCC should produce COFF-style debugging output #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
for SDB in response to the '-g' option */
#define SDB_DEBUGGING_INFO
/* Support generating stabs for the listing file generator */ #define DBX_REGISTER_NUMBER(REGNO) (REGNO)
#define DBX_DEBUGGING_INFO
/* The default format when -g is given is still COFF debug info */ #define ASM_OUTPUT_DEF(asm_out_file, LABEL1, LABEL2) \
#define PREFERRED_DEBUGGING_TYPE SDB_DEBUG 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 */ /* MISCELLANEOUS PARAMETERS */
...@@ -1899,17 +1958,12 @@ const_section () \ ...@@ -1899,17 +1958,12 @@ const_section () \
#define TARGET_VERSION fprintf (stderr, " (%s, %s)", VERSION_INFO1, __DATE__) #define TARGET_VERSION fprintf (stderr, " (%s, %s)", VERSION_INFO1, __DATE__)
#endif #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 this as 1 if `char' should by default be signed; else as 0. */
#define DEFAULT_SIGNED_CHAR 1 #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 /* Define this so gcc does not output a call to __main, since we
are not currently supporting c++. */ are not currently supporting c++. */
#define INIT_SECTION_ASM_OP 1 #define INIT_SECTION_ASM_OP 1
......
;;- Machine description for the AT&T DSP1600 for GNU C compiler ;;- Machine description for the AT&T DSP1600 for GNU C compiler
;; Copyright (C) 1994, 1995, 1997, 1998, 2001 Free Software Foundation, Inc. ;; 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. ;; This file is part of GNU CC.
...@@ -36,15 +36,25 @@ ...@@ -36,15 +36,25 @@
; Classification of each insn. Some insns of TYPE_BRANCH are multi-word. ; Classification of each insn. Some insns of TYPE_BRANCH are multi-word.
(define_attr "type" (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")) (const_string "malu"))
; Length in # of instructions of each insn. The values are not exact, but ;; Data arithmetic unit
; are safe. (define_function_unit "dau" 1 1 (eq_attr "type" "data_move,data_move_i,f3_alu_i") 2 0)
(define_attr "length" ""
(cond [(eq_attr "type" "cond_jump,f3_alu_i,shift_i,bfield_i,load_i") (define_function_unit "dau" 1 1 (eq_attr "type" "special_2") 3 0)
(const_int 2)]
(const_int 1))) (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 @@ ...@@ -84,6 +94,28 @@
DONE; 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" (define_insn "tstqi_1"
[(set (cc0) [(set (cc0)
(match_operand:QI 0 "register_operand" "j,q")) (match_operand:QI 0 "register_operand" "j,q"))
...@@ -92,7 +124,7 @@ ...@@ -92,7 +124,7 @@
"@ "@
%1=0\;%b0-0 %1=0\;%b0-0
%1=0\;%b0-0" %1=0\;%b0-0"
[(set_attr "type" "malu,malu")]) [(set_attr "type" "tstqi,tstqi")])
;; ;;
...@@ -104,8 +136,8 @@ ...@@ -104,8 +136,8 @@
(define_insn "" (define_insn ""
[(set (cc0) [(set (cc0)
(and:HI (match_operand:HI 0 "register_operand" "A,!A,A") (and:HI (match_operand:HI 0 "register_operand" "A,!A")
(match_operand:HI 1 "nonmemory_operand" "Z,A,I")))] (match_operand:HI 1 "register_operand" "Z,A")))]
"" ""
"* "*
{ {
...@@ -114,14 +146,9 @@ ...@@ -114,14 +146,9 @@
case 0: case 0:
case 1: case 1:
return \"%0&%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 "" ;;(define_insn ""
...@@ -178,7 +205,7 @@ ...@@ -178,7 +205,7 @@
else if (IS_YBASE_REGISTER_WINDOW (REGNO (operands[0]))) else if (IS_YBASE_REGISTER_WINDOW (REGNO (operands[0])))
output_asm_insn (\"a0=%u0\;a0l=%w0\", operands); output_asm_insn (\"a0=%u0\;a0l=%w0\", operands);
else else
abort (); fatal_error (\"Invalid register for compare\");
} }
else if (GET_CODE(operands[0]) == CONST_INT) else if (GET_CODE(operands[0]) == CONST_INT)
output_asm_insn (\"a0=%U0\;a0l=%H0\", operands); output_asm_insn (\"a0=%U0\;a0l=%H0\", operands);
...@@ -198,7 +225,7 @@ ...@@ -198,7 +225,7 @@
else if (IS_YBASE_REGISTER_WINDOW (REGNO (operands[1]))) else if (IS_YBASE_REGISTER_WINDOW (REGNO (operands[1])))
output_asm_insn (\"a1=%u1\;a1l=%w1\", operands); output_asm_insn (\"a1=%u1\;a1l=%w1\", operands);
else else
abort (); fatal_error (\"Invalid register for compare\");
} }
else if (GET_CODE (operands[1]) == MEM) else if (GET_CODE (operands[1]) == MEM)
{ {
...@@ -243,6 +270,64 @@ ...@@ -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 "" (define_insn ""
[(set (cc0) (compare (match_operand:QI 0 "register_operand" "k,k,!k,k,u,u,!u,u") [(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"))) (match_operand:QI 1 "nonmemory_operand" "w,z,u,i,w,z,k,i")))
...@@ -259,6 +344,64 @@ ...@@ -259,6 +344,64 @@
%2=0\;%3=0\;%2-%3 %2=0\;%3=0\;%2-%3
%2=0\;%0-%H1") %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 "" (define_insn ""
[(set (cc0) (compare (match_operand:QI 0 "register_operand" "j,j,!j,j,q,q,!q,q") [(set (cc0) (compare (match_operand:QI 0 "register_operand" "j,j,!j,j,q,q,!q,q")
...@@ -304,17 +447,45 @@ ...@@ -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" (define_insn "addhi3"
[(set (match_operand:HI 0 "register_operand" "=A,A,A") [(set (match_operand:HI 0 "register_operand" "=A,A,A,A,A")
(plus:HI (match_operand:HI 1 "register_operand" "%A,A,A") (plus:HI (match_operand:HI 1 "register_operand" "%A,A,A,A,A")
(match_operand:HI 2 "nonmemory_operand" "Z,d,i")))] (match_operand:HI 2 "nonmemory_operand" "Z,d,L,M,?i")))]
"" ""
"@ "@
%0=%1+%2 %0=%1+%2
%0=%1+%2 %0=%1+%2
%0=%w1+%H2
%0=%b1+%U2
%0=%w1+%H2\;%0=%b0+%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 "" (define_insn ""
[(set (match_operand:QI 0 "register_operand" "=k,u,!k,!u") [(set (match_operand:QI 0 "register_operand" "=k,u,!k,!u")
...@@ -354,10 +525,10 @@ ...@@ -354,10 +525,10 @@
(define_insn "match_addqi3" (define_insn "match_addqi3"
[(set (match_operand:QI 0 "register_operand" "=!a,!a,k,u,!k,!u,h,!a") [(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,h,0") (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,wzi,wzi,uk,uk,i,n"))) (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,X,W"))] (clobber (match_scratch:QI 3 "=X,X,j,q,j,q,j,q,X,k,X,u"))]
"" ""
"* "*
{ {
...@@ -384,24 +555,26 @@ ...@@ -384,24 +555,26 @@
case 2: case 2:
case 3: case 3:
if (!CONSTANT_P(operands[2]))
return \"%m0=%m1+%m2\";
else
return \"%m0=%1+%H2\"; return \"%m0=%1+%H2\";
case 4: case 4:
case 5: case 5:
return \"%m0=%m1+%m2\"; return \"%m0=%m1+%m2\";
case 6:
return \"%0=%b1+%H2\";
case 6:
case 7: case 7:
return \"%3=%2\;*%0++%3\"; return \"%m0=%m1+%m2\";
default:
abort(); 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" (define_expand "addhf3"
[(set (match_operand:HF 0 "register_operand" "") [(set (match_operand:HF 0 "register_operand" "")
...@@ -428,22 +601,51 @@ ...@@ -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" (define_insn "subhi3"
[(set (match_operand:HI 0 "register_operand" "=A,A,A") [(set (match_operand:HI 0 "register_operand" "=A,A,A,A,A")
(minus:HI (match_operand:HI 1 "register_operand" "A,A,A") (minus:HI (match_operand:HI 1 "register_operand" "A,A,A,A,A")
(match_operand:HI 2 "nonmemory_operand" "Z,d,i")))] (match_operand:HI 2 "nonmemory_operand" "Z,d,L,M,?i")))]
"" ""
"@ "@
%0=%1-%2 %0=%1-%2
%0=%1-%2 %0=%1-%2
%0=%w1-%H2
%0=%b1-%U2
%0=%w1-%H2\;%0=%b0-%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" (define_insn "subqi3"
[(set (match_operand:QI 0 "register_operand" "=?*a,k,u,!k,!u") [(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") (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,wzi,wzi,uk,uk"))) (match_operand:QI 2 "nonmemory_operand" "N,i,i,wz,wz,uk,uk,i,i,i,i")))
(clobber (match_scratch:QI 3 "=W,j,q,j,q"))] (clobber (match_scratch:QI 3 "=X,j,q,j,q,j,q,X,k,X,u"))]
"" ""
"* "*
{ {
...@@ -452,15 +654,12 @@ ...@@ -452,15 +654,12 @@
case 0: case 0:
switch (INTVAL (operands[2])) switch (INTVAL (operands[2]))
{ {
case 0:
return \"\";
case 1: case 1:
return \"*%0--\"; return \"*%0--\";
case -1: case -1:
return \"*%0++\"; return \"*%0++\";
default: default:
operands[2] = GEN_INT (-INTVAL (operands[2])); operands[2] = GEN_INT (-INTVAL (operands[2]));
...@@ -472,18 +671,22 @@ ...@@ -472,18 +671,22 @@
case 1: case 1:
case 2: case 2:
if (!CONSTANT_P(operands[2]))
return \"%m0=%m1-%m2\";
else
return \"%m0=%1-%H2\"; return \"%m0=%1-%H2\";
case 3: case 3:
case 4: case 4:
return \"%m0=%m1-%m2\";
case 5:
case 6:
return \"%m0=%m1-%m2\"; 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" (define_expand "subhf3"
[(set (match_operand:HF 0 "register_operand" "") [(set (match_operand:HF 0 "register_operand" "")
...@@ -510,21 +713,30 @@ ...@@ -510,21 +713,30 @@
[(set_attr "type" "special")]) [(set_attr "type" "special")])
(define_expand "neghf2" (define_expand "neghf2"
[(set (match_operand:HF 0 "general_operand" "") [(set (match_operand:HF 0 "register_operand" "")
(neg:HF (match_operand:HF 1 "general_operand" "")))] (neg:HF (match_operand:HF 1 "register_operand" "")))]
"" ""
" "
{ {
if (!dsp16xx_neghf2_libcall) rtx result;
dsp16xx_neghf2_libcall = gen_rtx_SYMBOL_REF (Pmode, NEGHF2_LIBCALL); rtx target;
emit_library_call (dsp16xx_neghf2_libcall, 1, HFmode, 1, {
operands[1], HFmode); target = gen_lowpart(HImode, operands[0]);
emit_move_insn (operands[0], hard_libcall_value(HFmode)); result = expand_binop (HImode, xor_optab,
DONE; 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 @@ ...@@ -566,14 +778,6 @@
"%0=%1*%2" "%0=%1*%2"
[(set_attr "type" "malu_mul")]) [(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" (define_expand "mulhf3"
[(set (match_operand:HF 0 "register_operand" "") [(set (match_operand:HF 0 "register_operand" "")
(mult:HF (match_operand:HF 1 "register_operand" "") (mult:HF (match_operand:HF 1 "register_operand" "")
...@@ -767,94 +971,279 @@ ...@@ -767,94 +971,279 @@
;; Logical Instructions ;; 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" (define_insn "andhi3"
[(set (match_operand:HI 0 "register_operand" "=A,A,?A") [(set (match_operand:HI 0 "register_operand" "=A,A,A,A,?A")
(and:HI (match_operand:HI 1 "register_operand" "%A,!A,A") (and:HI (match_operand:HI 1 "register_operand" "%A,!A,A,A,A")
(match_operand:HI 2 "nonmemory_operand" "Z,A,i")))] (match_operand:HI 2 "nonmemory_operand" "Z,A,O,P,i")))]
"" ""
"@ "@
%0=%1&%2 %0=%1&%2
%0=%1&%2 %0=%1&%2
%0=%w1&%H2
%0=%b1&%U2
%0=%w1&%H2\;%0=%b0&%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" (define_insn "andqi3"
[(set (match_operand:QI 0 "register_operand" "=k,u,uk,!k,!u,j,q,jq,!j,!q") [(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,uk,jq,jq,jq,jq,jq") (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,i,uk,uk,yv,yv,i,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,X,j,q,k,u,X,k,u"))] (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=%m1&%m2 %m0=%m1&%m2
%m0=%1&%H2
%m0=%m1&%m2 %m0=%m1&%m2
%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=%m1&%m2 %m0=%m1&%m2
%m0=%b1&%H2 %m0=%b1&%H2
%m0=%b1&%H2
%m0=%b1&%H2
%m0=%b1&%H2
%m0=%m1&%m2 %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" (define_insn "iorhi3"
[(set (match_operand:HI 0 "register_operand" "=A,A,A,?A") [(set (match_operand:HI 0 "register_operand" "=A,A,A,A,?A")
(ior:HI (match_operand:HI 1 "register_operand" "%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,i")))] (match_operand:HI 2 "nonmemory_operand" "Z,A,I,M,i")))]
"" ""
"@ "@
%0=%u1|%u2 %0=%u1|%u2
%0=%u1|%u2 %0=%u1|%u2
%0=%w1|%H2 %0=%w1|%H2
%0=%b1|%U2
%0=%w1|%H2\;%0=%b0|%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" (define_insn "iorqi3"
[(set (match_operand:QI 0 "register_operand" "=k,u,uk,!k,!u,j,q,jq,!j,!q") [(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,uk,jq,jq,jq,jq,jq") (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,i,uk,uk,yv,yv,i,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,X,j,q,k,u,X,k,u"))] (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=%m1|%m2 %m0=%m1|%m2
%m0=%1|%H2
%m0=%m1|%m2 %m0=%m1|%m2
%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=%m1|%m2 %m0=%m1|%m2
%m0=%b1|%H2 %m0=%b1|%H2
%m0=%b1|%H2
%m0=%b1|%H2
%m0=%b1|%H2
%m0=%m1|%m2 %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" (define_insn "xorhi3"
[(set (match_operand:HI 0 "register_operand" "=A,A,A,?A") [(set (match_operand:HI 0 "register_operand" "=A,A,A,A,?A")
(xor:HI (match_operand:HI 1 "register_operand" "%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,i")))] (match_operand:HI 2 "nonmemory_operand" "Z,A,I,M,i")))]
"" ""
"@ "@
%0=%1^%2 %0=%1^%2
%0=%1^%2 %0=%1^%2
%0=%w1^%H2 %0=%w1^%H2
%0=%b1^%U2
%0=%w1^%H2\;%0=%b0^%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" (define_insn "xorqi3"
[(set (match_operand:QI 0 "register_operand" "=k,u,uk,!k,!u,j,q,jq,!j,!q") [(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,uk,jq,jq,jq,jq,jq") (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,i,uk,uk,yv,yv,i,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,X,j,q,k,u,X,k,u"))] (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=%m1^%m2 %m0=%m1^%m2
%m0=%1^%H2
%m0=%m1^%m2 %m0=%m1^%m2
%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=%m1^%m2 %m0=%m1^%m2
%m0=%b1^%H2 %m0=%b1^%H2
%m0=%b1^%H2
%m0=%b1^%H2
%m0=%b1^%H2
%m0=%m1^%m2 %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" (define_insn "one_cmplhi2"
[(set (match_operand:HI 0 "register_operand" "=A") [(set (match_operand:HI 0 "register_operand" "=A")
...@@ -863,20 +1252,121 @@ ...@@ -863,20 +1252,121 @@
"%0= ~%1" "%0= ~%1"
[(set_attr "type" "special")]) [(set_attr "type" "special")])
(define_insn "one_cmplqi2" (define_insn "one_cmplqi2"
[(set (match_operand:QI 0 "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" "ku,jq")))] (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= %1 ^ 0xffff
%m0= %b1 ^ 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 ;; 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" (define_expand "movhi"
[(set (match_operand:HI 0 "general_operand" "") [(set (match_operand:HI 0 "general_operand" "")
(match_operand:HI 1 "general_operand" ""))] (match_operand:HI 1 "general_operand" ""))]
...@@ -918,11 +1408,9 @@ ...@@ -918,11 +1408,9 @@
case 8: case 8:
case 9: case 9:
return \"\"; 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'. ;; NOTE: It is cheaper to do 'y = *r0', than 'r0 = *r0'.
...@@ -952,7 +1440,7 @@ ...@@ -952,7 +1440,7 @@
switch (which_alternative) switch (which_alternative)
{ {
case 0: 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 attempt to transfer all 32-bits of 'y', 'p' or an accumulator
, which we don't want */ , which we don't want */
if (REGNO(operands[1]) == REG_Y || REGNO(operands[1]) == REG_PROD if (REGNO(operands[1]) == REG_Y || REGNO(operands[1]) == REG_PROD
...@@ -985,10 +1473,9 @@ ...@@ -985,10 +1473,9 @@
case 9: case 10: case 9: case 10:
return \"%0=%1\"; 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" (define_insn "match_movqi2"
[(set (match_operand:QI 0 "nonimmediate_operand" "=A,r,aW,c,?D,m<>,e,Y,r,xyz,m<>") [(set (match_operand:QI 0 "nonimmediate_operand" "=A,r,aW,c,?D,m<>,e,Y,r,xyz,m<>")
...@@ -1000,7 +1487,7 @@ ...@@ -1000,7 +1487,7 @@
switch (which_alternative) switch (which_alternative)
{ {
case 0: 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 attempt to transfer all 32-bits of 'y', 'p' or an accumulator
, which we don't want */ , which we don't want */
if (REGNO(operands[1]) == REG_Y || REGNO(operands[1]) == REG_PROD if (REGNO(operands[1]) == REG_Y || REGNO(operands[1]) == REG_PROD
...@@ -1033,10 +1520,9 @@ ...@@ -1033,10 +1520,9 @@
case 9: case 10: case 9: case 10:
return \"%0=%1\"; 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" (define_expand "reload_inqi"
[(set (match_operand:QI 0 "register_operand" "=u") [(set (match_operand:QI 0 "register_operand" "=u")
...@@ -1131,8 +1617,8 @@ ...@@ -1131,8 +1617,8 @@
operands[5] = addr0; operands[5] = addr0;
operands[6] = addr1; operands[6] = addr1;
operands[0] = replace_equiv_address (operands[0], addr0); operands[0] = change_address (operands[0], VOIDmode, addr0);
operands[1] = replace_equiv_address (operands[1], addr1); operands[1] = change_address (operands[1], VOIDmode, addr1);
}") }")
(define_insn "" (define_insn ""
...@@ -1190,8 +1676,6 @@ ...@@ -1190,8 +1676,6 @@
case 5: case 5:
case 6: case 6:
return \"%u0=%u1\;%w0=%w1\"; return \"%u0=%u1\;%w0=%w1\";
default:
abort();
} }
}" }"
[(set_attr "type" "move,move,load_i,load,store,load,store")]) [(set_attr "type" "move,move,load_i,load,store,load,store")])
...@@ -1258,9 +1742,16 @@ ...@@ -1258,9 +1742,16 @@
" "
{ {
operands[2] = gen_reg_rtx (HImode); 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" ;;(define_insn "extendqihi2"
;; [(set (match_operand:HI 0 "register_operand" "=A") ;; [(set (match_operand:HI 0 "register_operand" "=A")
;; (sign_extend:HI (match_operand:QI 1 "register_operand" "h")))] ;; (sign_extend:HI (match_operand:QI 1 "register_operand" "h")))]
...@@ -1296,22 +1787,90 @@ ...@@ -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" (define_expand "zero_extendqihi2"
[(clobber (match_dup 2)) [(set (match_operand:HI 0 "register_operand" "")
(set (match_dup 3) (match_operand:QI 1 "register_operand" "")) (zero_extend:HI (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], 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" (define_expand "floathihf2"
[(set (match_operand:HF 0 "register_operand" "") [(set (match_operand:HF 0 "register_operand" "")
(float:HF (match_operand:HI 1 "register_operand" "")))] (float:HF (match_operand:HI 1 "register_operand" "")))]
...@@ -1467,7 +2026,7 @@ ...@@ -1467,7 +2026,7 @@
rtx stack_slot; rtx stack_slot;
stack_slot = assign_stack_temp (QImode, GET_MODE_SIZE(QImode), 0); 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]); emit_move_insn (stack_slot, operands[2]);
operands[2] = stack_slot; operands[2] = stack_slot;
} }
...@@ -1506,9 +2065,9 @@ ...@@ -1506,9 +2065,9 @@
else else
{ {
output_asm_insn (\"cloop=%2\", 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 (\"%0=%0>>1\", operands);
return \"\}\"; return \"}\";
} }
}") }")
...@@ -1521,7 +2080,7 @@ ...@@ -1521,7 +2080,7 @@
[(set (match_operand:HI 0 "register_operand" "=A") [(set (match_operand:HI 0 "register_operand" "=A")
(lshiftrt:HI (match_operand:HI 1 "register_operand" "A") (lshiftrt:HI (match_operand:HI 1 "register_operand" "A")
(const_int 1)))] (const_int 1)))]
"" "!TARGET_BMU"
"%0=%1>>1\;%0=%b0&0x7fff" "%0=%1>>1\;%0=%b0&0x7fff"
[(set_attr "type" "special")]) [(set_attr "type" "special")])
...@@ -1529,7 +2088,7 @@ ...@@ -1529,7 +2088,7 @@
[(set (match_operand:HI 0 "register_operand" "=A") [(set (match_operand:HI 0 "register_operand" "=A")
(lshiftrt:HI (match_operand:HI 1 "register_operand" "A") (lshiftrt:HI (match_operand:HI 1 "register_operand" "A")
(const_int 4)))] (const_int 4)))]
"" "!TARGET_BMU"
"%0=%1>>4\;%0=%b0&0x0fff" "%0=%1>>4\;%0=%b0&0x0fff"
[(set_attr "type" "special")]) [(set_attr "type" "special")])
...@@ -1537,7 +2096,7 @@ ...@@ -1537,7 +2096,7 @@
[(set (match_operand:HI 0 "register_operand" "=A") [(set (match_operand:HI 0 "register_operand" "=A")
(lshiftrt:HI (match_operand:HI 1 "register_operand" "A") (lshiftrt:HI (match_operand:HI 1 "register_operand" "A")
(const_int 8)))] (const_int 8)))]
"" "!TARGET_BMU"
"%0=%1>>8\;%0=%b0&0x00ff" "%0=%1>>8\;%0=%b0&0x00ff"
[(set_attr "type" "special")]) [(set_attr "type" "special")])
...@@ -1545,7 +2104,7 @@ ...@@ -1545,7 +2104,7 @@
[(set (match_operand:HI 0 "register_operand" "=A") [(set (match_operand:HI 0 "register_operand" "=A")
(lshiftrt:HI (match_operand:HI 1 "register_operand" "A") (lshiftrt:HI (match_operand:HI 1 "register_operand" "A")
(const_int 16)))] (const_int 16)))]
"" "!TARGET_BMU"
"%0=%1>>16\;%0=%b0&0x0000" "%0=%1>>16\;%0=%b0&0x0000"
[(set_attr "type" "special")]) [(set_attr "type" "special")])
...@@ -1592,7 +2151,7 @@ ...@@ -1592,7 +2151,7 @@
rtx stack_slot; rtx stack_slot;
stack_slot = assign_stack_temp (QImode, GET_MODE_SIZE(QImode), 0); 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]); emit_move_insn (stack_slot, operands[2]);
operands[2] = stack_slot; operands[2] = stack_slot;
} }
...@@ -1633,9 +2192,9 @@ ...@@ -1633,9 +2192,9 @@
{ {
output_asm_insn (\"%3=psw\;psw=0\",operands); output_asm_insn (\"%3=psw\;psw=0\",operands);
output_asm_insn (\"cloop=%2\", 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 (\"%0=%0>>1\", operands);
output_asm_insn (\"\}\", operands); output_asm_insn (\"}\", operands);
return \"psw=%3\"; return \"psw=%3\";
} }
}") }")
...@@ -1673,14 +2232,6 @@ ...@@ -1673,14 +2232,6 @@
(define_insn "" (define_insn ""
[(set (match_operand:HI 0 "register_operand" "=A") [(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") (ashift:HI (match_operand:HI 1 "general_operand" "A")
(const_int 16)))] (const_int 16)))]
"" ""
...@@ -1729,18 +2280,16 @@ ...@@ -1729,18 +2280,16 @@
emit_barrier (); emit_barrier ();
emit_label (label1); emit_label (label1);
if (GET_CODE (operands[2]) != MEM) if (GET_CODE(operands[2]) != MEM)
{ {
rtx stack_slot; rtx stack_slot;
stack_slot = assign_stack_temp (QImode, GET_MODE_SIZE(QImode), 0); 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]); emit_move_insn (stack_slot, operands[2]);
operands[2] = stack_slot; 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); emit_label (label2);
DONE; DONE;
#endif #endif
...@@ -1757,7 +2306,7 @@ ...@@ -1757,7 +2306,7 @@
%0=%1<<%2\;move %u0=%u0 %0=%1<<%2\;move %u0=%u0
%0=%1<<%H2\;move %u0=%u0 %0=%1<<%H2\;move %u0=%u0
%0=%1<<%2\;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" (define_insn "match_ashlhi3_nobmu"
[(set (match_operand:HI 0 "register_operand" "=A,A") [(set (match_operand:HI 0 "register_operand" "=A,A")
...@@ -1774,14 +2323,184 @@ ...@@ -1774,14 +2323,184 @@
else else
{ {
output_asm_insn (\"cloop=%2\", 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 (\"%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 ;; Jump Instructions
;; ;;
...@@ -2138,45 +2857,168 @@ ...@@ -2138,45 +2857,168 @@
(define_peephole (define_peephole
[(set (match_operand:QI 0 "register_operand" "=A") [(parallel [(set (cc0)
(reg:QI 16)) (compare (match_operand:QI 0 "register_operand" "k,k,!k,u,u,!u")
(call (mem:QI (match_dup 0)) (match_operand:QI 1 "register_operand" "w,z,u,w,z,k")))
(match_operand 1 "" "i"))] (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"))])
"call pt") (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 (define_peephole
[(set (match_operand:QI 0 "register_operand" "=A") [(parallel [(set (cc0)
(reg:QI 16)) (compare (match_operand:QI 0 "register_operand" "j,q")
(set (match_operand 1 "" "") (match_operand:QI 1 "const_int_operand" "i,i")))
(call (mem:QI (match_dup 0)) (use (match_operand:QI 2 "register_operand" "=k,u"))])
(match_operand 2 "" "i")))] (set (pc)
"" (if_then_else (match_operator 4 "signed_comparison_operator"
"call pt") [(cc0) (const_int 0)])
(label_ref (match_operand 3 "" ""))
(pc)))]
"!TARGET_NEAR_JUMP"
"pt=%l3\;%b0-%H1\;if %C4 goto pt")
(define_peephole (define_peephole
[(set (match_operand:HI 0 "register_operand" "=A") [(parallel [(set (cc0)
(ashift:HI (match_operand:HI 1 "register_operand" "A") (compare (match_operand:QI 0 "register_operand" "j,q")
(const_int 16))) (match_operand:QI 1 "const_int_operand" "i,i")))
(set (match_operand:HI 2 "register_operand" "") (use (match_operand:QI 2 "register_operand" "=k,u"))])
(match_dup 0)) (set (pc)
(set (match_dup 0) (if_then_else (match_operator 4 "signed_comparison_operator"
(ashiftrt:HI (match_dup 0) (const_int 16))) [(cc0) (const_int 0)])
(set (match_dup 2) (pc)
(match_dup 0))] (label_ref (match_operand 3 "" ""))))]
"" "!TARGET_NEAR_JUMP"
"%0=%1<<16\;%0=%0>>16\;%u2=%u0\;%w2=%w0") "pt=%l3\;%b0-%H1\;if %I4 goto pt")
;; TST PEEPHOLE PATTERNS
(define_peephole (define_peephole
[(set (match_operand:HI 0 "register_operand" "=A") [(parallel [(set (cc0)
(ashift:HI (match_operand:HI 1 "register_operand" "A") (match_operand:QI 0 "register_operand" "j,q"))
(const_int 16))) (use (match_operand:QI 1 "register_operand" "=k,u"))])
(set (match_operand:HI 2 "register_operand" "") (set (pc)
(match_dup 0)) (if_then_else (match_operator 3 "signed_comparison_operator"
(set (match_dup 0) [(cc0) (const_int 0)])
(lshiftrt:HI (match_dup 0) (const_int 16))) (pc)
(set (match_dup 2) (label_ref (match_operand 2 "" ""))))]
(match_dup 0))] "!TARGET_NEAR_JUMP"
"" "pt=%l2\;%b0-0\;if %I3 goto pt")
"%0=%1<<16\;%0=%0>>16\;%0=%b0&0x0000\;%u2=%u0\;%w2=%w0")
(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")
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment