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