diff --git a/gcc/config/dsp16xx/dsp16xx-protos.h b/gcc/config/dsp16xx/dsp16xx-protos.h index 6401f70ee49..02ba7b8c4f7 100644 --- a/gcc/config/dsp16xx/dsp16xx-protos.h +++ b/gcc/config/dsp16xx/dsp16xx-protos.h @@ -29,6 +29,8 @@ extern int sp_operand PARAMS ((rtx, enum machine_mode)); extern int sp_operand2 PARAMS ((rtx, enum machine_mode)); extern int nonmemory_arith_operand PARAMS ((rtx, enum machine_mode)); extern int dsp16xx_comparison_operator PARAMS ((rtx, enum machine_mode)); +extern int unx_comparison_operator PARAMS ((rtx, enum machine_mode)); +extern int signed_comparison_operator PARAMS ((rtx, enum machine_mode)); extern void notice_update_cc PARAMS ((rtx)); extern void double_reg_from_memory PARAMS ((rtx[])); @@ -77,7 +79,11 @@ extern void asm_output_local PARAMS ((FILE *, const char *, int, int)); extern void asm_output_float PARAMS ((FILE *, double)); extern void asm_output_long PARAMS ((FILE *, long)); extern void dsp16xx_file_start PARAMS ((void)); +extern void coff_dsp16xx_file_start PARAMS ((FILE *)); +extern void luxworks_dsp16xx_file_start PARAMS ((FILE *)); extern struct rtx_def *(*dsp16xx_compare_gen) PARAMS (()); extern int hard_regno_mode_ok PARAMS ((int, enum machine_mode)); extern enum reg_class dsp16xx_reg_class_from_letter PARAMS ((int)); extern int regno_reg_class PARAMS ((int)); +extern void function_prologue PARAMS ((FILE *, int)); +extern void function_epilogue PARAMS ((FILE *, int)); diff --git a/gcc/config/dsp16xx/dsp16xx.c b/gcc/config/dsp16xx/dsp16xx.c index 74de0d084e0..8ca95a6bac6 100644 --- a/gcc/config/dsp16xx/dsp16xx.c +++ b/gcc/config/dsp16xx/dsp16xx.c @@ -1,6 +1,6 @@ /* Subroutines for assembler code output on the DSP1610. Copyright (C) 1994, 1995, 1997, 1998, 2001 Free Software Foundation, Inc. - Contributed by Michael Collison (collison@world.std.com). + Contributed by Michael Collison (collison@isisinc.net). This file is part of GNU CC. @@ -37,7 +37,7 @@ Boston, MA 02111-1307, USA. */ #include "ggc.h" #include "toplev.h" #include "recog.h" -#include "tm_p.h" +#include "dsp16xx-protos.h" #include "target.h" #include "target-def.h" @@ -58,7 +58,7 @@ const char *save_chip_name; rtx dsp16xx_compare_op0; rtx dsp16xx_compare_op1; -rtx (*dsp16xx_compare_gen) PARAMS (()); +struct rtx_def *(*dsp16xx_compare_gen)(); static const char *fp; static const char *sp; @@ -149,7 +149,7 @@ static const char *const lshift_right_asm_first[] = static int reg_save_size PARAMS ((void)); static void dsp16xx_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT)); static void dsp16xx_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT)); - + /* Initialize the GCC target structure. */ #undef TARGET_ASM_FUNCTION_PROLOGUE #define TARGET_ASM_FUNCTION_PROLOGUE dsp16xx_output_function_prologue @@ -157,7 +157,7 @@ static void dsp16xx_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT)); #define TARGET_ASM_FUNCTION_EPILOGUE dsp16xx_output_function_epilogue struct gcc_target targetm = TARGET_INITIALIZER; - + int hard_regno_mode_ok (regno, mode) int regno; @@ -208,6 +208,12 @@ dsp16xx_reg_class_from_letter (c) { case 'A': return ACCUM_REGS; + + case 'l': + return A0_REG; + + case 'C': + return A1_REG; case 'h': return ACCUM_HIGH_REGS; @@ -242,9 +248,6 @@ dsp16xx_reg_class_from_letter (c) case 'd': return ACCUM_Y_OR_P_REGS; - case 'C': - return NO_FRAME_Y_ADDR_REGS; - case 'a': return Y_ADDR_REGS; @@ -279,7 +282,7 @@ dsp16xx_reg_class_from_letter (c) return SLOW_MEM_LOAD_REGS; default: - abort (); + return NO_REGS; } } /* Return the class number of the smallest class containing @@ -368,210 +371,16 @@ class_max_nregs(class, mode) enum reg_class limit_reload_class (mode, class) - enum machine_mode mode; + enum machine_mode mode ATTRIBUTE_UNUSED; enum reg_class class; { - switch ((int) class) - { - case NO_REGS: - case A0H_REG: - case A0L_REG: - case A0_REG: - case A1H_REG: - return class; - - case ACCUM_HIGH_REGS: - abort (); - - case A1L_REG: - case ACCUM_LOW_REGS: - case A1_REG: - return class; - - case ACCUM_REGS: - if (GET_MODE_SIZE(mode) == 1) - return ACCUM_LOW_REGS; - else - return class; - - case X_REG: - case X_OR_ACCUM_LOW_REGS: - return class; - - case X_OR_ACCUM_REGS: - if (GET_MODE_SIZE(mode) == 1) - return X_OR_ACCUM_LOW_REGS; - else - return class; - - case YH_REG: - return class; - - case YH_OR_ACCUM_HIGH_REGS: - abort (); - - case X_OR_YH_REGS: - return class; - - case YL_REG: - /* Register 'yl' is invalid for QImode, so we should never - see it. */ - abort (); - - case YL_OR_ACCUM_LOW_REGS: - case X_OR_YL_REGS: - return class; - - case Y_REG: - if (GET_MODE_SIZE(mode) > 1) - return class; - else - return YH_REG; - - case ACCUM_OR_Y_REGS: - if (GET_MODE_SIZE(mode) > 1) - return class; - else - return YL_OR_ACCUM_LOW_REGS; - - case PH_REG: - case X_OR_PH_REGS: - case PL_REG: - case PL_OR_ACCUM_LOW_REGS: - case X_OR_PL_REGS: - return class; - - case P_REG: - if (GET_MODE_SIZE(mode) > 1) - return class; - else - return PL_REG; - - case ACCUM_OR_P_REGS: - if (GET_MODE_SIZE(mode) > 1) - return class; - else - return PL_OR_ACCUM_LOW_REGS; - - case YL_OR_P_REGS: - case ACCUM_LOW_OR_YL_OR_P_REGS: - return class; - - case Y_OR_P_REGS: - return class; - - case ACCUM_Y_OR_P_REGS: - if (GET_MODE_SIZE(mode) > 1) - return class; - else - return ACCUM_LOW_OR_YL_OR_P_REGS; - - case NO_FRAME_Y_ADDR_REGS: - case Y_ADDR_REGS: - case ACCUM_LOW_OR_Y_ADDR_REGS: - return class; - - case ACCUM_OR_Y_ADDR_REGS: - if (GET_MODE_SIZE(mode) > 1) - return ACCUM_REGS; - else - return ACCUM_LOW_OR_Y_ADDR_REGS; - - case X_OR_Y_ADDR_REGS: - return class; - - case Y_OR_Y_ADDR_REGS: - case P_OR_Y_ADDR_REGS: - case NON_HIGH_YBASE_ELIGIBLE_REGS: - - case J_REG: - return class; - - case YBASE_ELIGIBLE_REGS: - if (GET_MODE_SIZE(mode) > 1) - return ACCUM_Y_P_OR_YBASE_REGS; - else - return NON_HIGH_YBASE_ELIGIBLE_REGS; - - case J_OR_DAU_16_BIT_REGS: - if (GET_MODE_SIZE(mode) == 1) - return J_REG; - else - return class; - - case BMU_REGS: - case NOHIGH_NON_ADDR_REGS: - return class; - - case NON_ADDR_REGS: - if (GET_MODE_SIZE(mode) > 1) - return class; - else - return NOHIGH_NON_ADDR_REGS; - - case NOHIGH_NON_YBASE_REGS: - return class; - - case NON_YBASE_REGS: - if (GET_MODE_SIZE(mode) > 1) - return class; - else - return NOHIGH_NON_YBASE_REGS; - - case YBASE_VIRT_REGS: - case ACCUM_LOW_OR_YBASE_REGS: - return class; - - case ACCUM_OR_YBASE_REGS: - if (GET_MODE_SIZE(mode) > 1) - return class; - else - return ACCUM_LOW_OR_YBASE_REGS; - - case X_OR_YBASE_REGS: - return class; - - case Y_OR_YBASE_REGS: - case ACCUM_LOW_YL_PL_OR_YBASE_REGS: - case P_OR_YBASE_REGS: - return class; - - case ACCUM_Y_P_OR_YBASE_REGS: - return ACCUM_LOW_YL_PL_OR_YBASE_REGS; - - case Y_ADDR_OR_YBASE_REGS: - case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS: - return class; - - case YBASE_OR_YBASE_ELIGIBLE_REGS: - if (GET_MODE_SIZE(mode) > 1) - return class; - else - return YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS; - - case NO_HIGH_ALL_REGS: - return class; - - case ALL_REGS: - if (GET_MODE_SIZE(mode) > 1) - return class; - else - return NO_HIGH_ALL_REGS; - - default: - return class; - } + return class; } int dsp16xx_register_move_cost (from, to) enum reg_class from, to; { -#if 0 - if (from == NO_REGS || to == NO_REGS || (from == to)) - return 2; -#endif - if (from == A0H_REG || from == A0L_REG || from == A0_REG || from == A1H_REG || from == ACCUM_HIGH_REGS || from == A1L_REG || from == ACCUM_LOW_REGS || from == A1_REG || from == ACCUM_REGS) @@ -589,18 +398,20 @@ dsp16xx_register_move_cost (from, to) return 2; } -#if 0 if (from == YBASE_VIRT_REGS) { + if (to == YBASE_VIRT_REGS) + return 16; + if (to == X_REG || to == YH_REG || to == YL_REG || to == Y_REG || to == PL_REG || to == PH_REG || to == P_REG || to == Y_ADDR_REGS || to == YBASE_ELIGIBLE_REGS || to == Y_OR_P_REGS) { - return 2; + return 8; } else - return 4; + return 10; } if (to == YBASE_VIRT_REGS) @@ -610,13 +421,13 @@ dsp16xx_register_move_cost (from, to) from == P_REG || from == Y_ADDR_REGS || from == YBASE_ELIGIBLE_REGS || from == Y_OR_P_REGS) { - return 2; + return 8; } else - return 4; + return 10; } -#endif - return 4; + + return 8; } /* Given an rtx X being reloaded into a reg required to be @@ -636,13 +447,341 @@ preferred_reload_class (x, class) if (CONSTANT_P (x)) { - if (class == ALL_REGS) - return NON_YBASE_REGS; + switch ((int) class) + { + case YBASE_VIRT_REGS: + return (!reload_in_progress ? NO_REGS : class); + + case ACCUM_LOW_OR_YBASE_REGS: + return ACCUM_LOW_REGS; + + case ACCUM_OR_YBASE_REGS: + return ACCUM_REGS; + + case X_OR_YBASE_REGS: + return X_REG; + + case Y_OR_YBASE_REGS: + return Y_REG; + + case ACCUM_LOW_YL_PL_OR_YBASE_REGS: + return YL_OR_PL_OR_ACCUM_LOW_REGS; + + case P_OR_YBASE_REGS: + return P_REG; + + case ACCUM_Y_P_OR_YBASE_REGS: + return ACCUM_Y_OR_P_REGS; + + case Y_ADDR_OR_YBASE_REGS: + return Y_ADDR_REGS; + + case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS: + return NON_HIGH_YBASE_ELIGIBLE_REGS;; + + case YBASE_OR_YBASE_ELIGIBLE_REGS: + return YBASE_ELIGIBLE_REGS; + + case NO_HIGH_ALL_REGS: + return NOHIGH_NON_YBASE_REGS; + + case ALL_REGS: + return NON_YBASE_REGS; + + default: + return class; + } } - if (class == ALL_REGS && REG_P (x) && !TARGET_RESERVE_YBASE + /* 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 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,25 +1757,6 @@ override_options () ggc_add_rtx_root (&dsp16xx_lshrhi3_libcall, 1); } - -enum rtx_code -next_cc_user_code (insn) - rtx insn; -{ - if ( !(insn = next_cc0_user (insn))) - abort (); - else if (GET_CODE (insn) == JUMP_INSN - && GET_CODE (PATTERN (insn)) == SET - && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE) - return GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)); - else if (GET_CODE (insn) == INSN - && GET_CODE (PATTERN (insn)) == SET - && comparison_operator (SET_SRC (PATTERN (insn)), VOIDmode)) - return GET_CODE (SET_SRC (PATTERN (insn))); - else - abort (); -} - int next_cc_user_unsigned (insn) rtx insn; @@ -1609,6 +1773,27 @@ next_cc_user_unsigned (insn) } } +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))) + 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) + return GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)); + else if (GET_CODE (insn) == INSN + && GET_CODE (PATTERN (insn)) == SET + && comparison_operator (SET_SRC (PATTERN (insn)), VOIDmode)) + return GET_CODE (SET_SRC (PATTERN (insn))); + else + abort (); +} + void print_operand(file, op, letter) FILE *file; @@ -1689,19 +1874,57 @@ print_operand(file, op, letter) else if (letter == 'h') fprintf (file, HOST_WIDE_INT_PRINT_DEC, val); else if (letter == 'U') - fprintf (file, HOST_WIDE_INT_PRINT_HEX, (val >> 16) & 0xffff); + fprintf(file, HOST_WIDE_INT_PRINT_HEX, (val >> 16) & 0xffff); else - output_addr_const (file, op); - } - else if (code == CONST_DOUBLE && GET_MODE (op) != DImode) + output_addr_const( file, op ); + } + else if( code == CONST_DOUBLE && GET_MODE(op) != DImode ) + { + union { double d; int i[2]; } u; + union { float f; int i; } u1; + u.i[0] = CONST_DOUBLE_LOW (op); + u.i[1] = CONST_DOUBLE_HIGH (op); + u1.f = u.d; + fprintf( file, "0x%x", u1.i ); + } + else if (code == CONST) { - union {double d; int i[2]; } u; - union {float f; int i; } u1; - - u.i[0] = CONST_DOUBLE_LOW (op); - u.i[1] = CONST_DOUBLE_HIGH (op); - u1.f = u.d; - fprintf (file, "0x%x", u1.i); + rtx addr = XEXP (op, 0); + + if (GET_CODE (addr) != PLUS) + { + output_addr_const( file, op); + return; + } + + if ((GET_CODE (XEXP (addr, 0)) == SYMBOL_REF + || GET_CODE (XEXP (addr, 0)) == LABEL_REF) + && (GET_CODE (XEXP (addr, 1)) == CONST_INT)) + { + int n = INTVAL (XEXP(addr, 1)); + output_addr_const (file, XEXP (addr, 0)); + + if (n >= 0) + fprintf (file, "+"); + + n = (int) (short) n; + fprintf (file, "%d", n); + } + else if ((GET_CODE (XEXP (addr, 1)) == SYMBOL_REF + || GET_CODE (XEXP (addr, 1)) == LABEL_REF) + && (GET_CODE (XEXP (addr, 0)) == CONST_INT)) + { + int n = INTVAL (XEXP(addr, 0)); + output_addr_const (file, XEXP (addr, 1)); + + if (n >= 0) + fprintf (file, "+"); + + n = (int) (short) n; + fprintf (file, "%d", n); + } + else + output_addr_const( file, op); } else output_addr_const (file, op); @@ -1714,7 +1937,7 @@ print_operand_address(file, addr) rtx addr; { rtx base; - int offset; + int offset = 0;; switch (GET_CODE (addr)) { @@ -1737,10 +1960,10 @@ print_operand_address(file, addr) if (offset >= -31 && offset <= 0) offset = 31 + offset; else - abort (); + fatal_error ("Invalid offset in ybase addressing"); } else - abort (); + fatal_error ("Invalid register in ybase addressing"); fprintf (file, "*(%d)", offset); break; @@ -1777,17 +2000,22 @@ static int reg_save_size () { int reg_save_size = 0; - int regno; - + int regno; + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) if (dsp16xx_call_saved_register (regno)) { reg_save_size += UNITS_PER_WORD; } + /* If the function makes calls we will save need to save the 'pr' register */ + if (current_frame_info.function_makes_calls) + reg_save_size += 1; + return (reg_save_size); } +#if 0 int dsp16xx_starting_frame_offset() { @@ -1802,6 +2030,7 @@ dsp16xx_starting_frame_offset() return (reg_save_size); } +#endif int initial_frame_pointer_offset() @@ -1913,7 +2142,7 @@ emit_1600_core_shift (shift_op, operands, shift_amount) shift_asm_ptr_first = lshift_right_asm_first; } else - abort (); + fatal_error ("Invalid shift operator in emit_1600_core_shift"); while (shift_amount != 0) { @@ -1956,6 +2185,57 @@ emit_1600_core_shift (shift_op, operands, shift_amount) } } #endif + +int +num_1600_core_shifts (shift_amount) +int shift_amount; +{ + int quotient; + int i; + int first_shift_emitted = 0; + int num_shifts = 0; + + while (shift_amount != 0) + { + if (shift_amount/16) + { + quotient = shift_amount/16; + shift_amount = shift_amount - (quotient * 16); + for (i = 0; i < quotient; i++) + num_shifts++; + first_shift_emitted = 1; + } + else if (shift_amount/8) + { + quotient = shift_amount/8; + shift_amount = shift_amount - (quotient * 8); + for (i = 0; i < quotient; i++) + num_shifts++; + + first_shift_emitted = 1; + } + else if (shift_amount/4) + { + quotient = shift_amount/4; + shift_amount = shift_amount - (quotient * 4); + for (i = 0; i < quotient; i++) + num_shifts++; + + first_shift_emitted = 1; + } + else if (shift_amount/1) + { + quotient = shift_amount/1; + shift_amount = shift_amount - (quotient * 1); + for (i = 0; i < quotient; i++) + num_shifts++; + + first_shift_emitted = 1; + } + } + return num_shifts; +} + void asm_output_common(file, name, size, rounded) FILE *file; @@ -2134,6 +2414,9 @@ dsp16xx_function_arg (args_so_far, mode, type, named) && (mode == HImode || GET_MODE_CLASS(mode) == MODE_FLOAT)) args_so_far++; + if (type == void_type_node) + return (struct rtx_def *) 0; + if (named && args_so_far < 4 && !MUST_PASS_IN_STACK (mode,type)) return gen_rtx_REG (mode, args_so_far + FIRST_REG_FOR_FUNCTION_ARG); else @@ -2166,13 +2449,50 @@ dsp16xx_function_arg_advance (cum, mode, type, named) } void -dsp16xx_file_start () +coff_dsp16xx_file_start (file) + FILE *file; { - fprintf (asm_out_file, "#include <%s.h>\n", save_chip_name); -#if 0 - if (TARGET_BMU) - fprintf (asm_out_file, "#include <1610.h>\n"); + fprintf (file, "#include <%s.h>\n", save_chip_name); +} + +void +luxworks_dsp16xx_file_start (file) + FILE *file; +{ + char *temp_filename; + int len, err_code; + + + fprintf(file, "\t.debug "); + err_code = (TARGET_DEBUG) ? fprintf (file, "yes, ") : fprintf (file, "no, "); + err_code = (TARGET_SAVE_TEMPS) ? fprintf (file, "asm, ") : fprintf (file, "temp, "); + len = strlen (main_input_filename); + temp_filename = (char *) xmalloc (len + 2); + strcpy (temp_filename, main_input_filename); +#ifdef __CYGWIN32__ + p = temp_filename; + while (*p != '\0') { + if (*p == '\\') + *p = '/'; + p++; + } #endif + fprintf(file, "\"%s\"\n", temp_filename); + fprintf(file, ""); + + fprintf (file, "#include <%s.h>\n", save_chip_name); + + /* + * Add dummy sections, so that they always exist in the + * object code. These have been created so that the number and + * type of sections remain consistent with and without -g option. Note + * that the .data, .text, .const and .bss are always created when -g + * is provided as an option. + */ + fprintf(file, "\t.rsect \".text\" , nodelete\n"); + fprintf(file, "\t.rsect \".data\" , nodelete\n"); + fprintf(file, "\t.rsect \".const\" , nodelete\n"); + fprintf(file, "\t.rsect \".bss\" , nodelete\n"); } rtx @@ -2192,7 +2512,7 @@ gen_tst_reg (x) else if (mode == HImode) emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, x)); else - abort (); + fatal_error ("Invalid mode for gen_tst_reg"); return cc0_rtx; } @@ -2243,28 +2563,19 @@ gen_compare_reg (code, x, y) if (code == GTU || code == GEU || code == LTU || code == LEU) { -#if 1 - emit_insn (gen_rtx_PARALLEL - (VOIDmode, + emit_insn (gen_rtx_PARALLEL + (VOIDmode, gen_rtvec (5, - gen_rtx_SET (VOIDmode, cc0_rtx, - gen_rtx_COMPARE (VOIDmode, - x, y)), - gen_rtx_CLOBBER (VOIDmode, + gen_rtx_SET (VOIDmode, cc0_rtx, + gen_rtx_COMPARE (VOIDmode, x, y)), + gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (QImode)), - gen_rtx_CLOBBER (VOIDmode, + gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (QImode)), - gen_rtx_CLOBBER (VOIDmode, + gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (QImode)), - gen_rtx_CLOBBER (VOIDmode, + gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (QImode))))); -#else - if (!dsp16xx_ucmphi2_libcall) - dsp16xx_ucmphi2_libcall = gen_rtx_SYMBOL_REF (Pmode, UCMPHI2_LIBCALL); - emit_library_call (dsp16xx_ucmphi2_libcall, 1, HImode, 2, - x, HImode, y, HImode); - emit_insn (gen_tsthi_1 (copy_to_reg(hard_libcall_value (HImode)))); -#endif } else emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, @@ -2273,7 +2584,7 @@ gen_compare_reg (code, x, y) force_reg (HImode,y)))); } else - abort (); + fatal_error ("Invalid mode for integer comparison in gen_compare_reg"); return cc0_rtx; } @@ -2297,3 +2608,49 @@ output_block_move (operands) fprintf (asm_out_file, "\t}\n"); return ""; } + +int +uns_comparison_operator (op, mode) + rtx op; + enum machine_mode mode; +{ + if (mode == VOIDmode || GET_MODE (op) == mode) + { + enum rtx_code code; + + code = GET_CODE(op); + + if (code == LEU || code == LTU || code == GEU + || code == GTU) + { + return 1; + } + else + return 0; + } + + return 0; +} + +int +signed_comparison_operator (op, mode) + rtx op; + enum machine_mode mode; +{ + if (mode == VOIDmode || GET_MODE (op) == mode) + { + enum rtx_code code; + + code = GET_CODE(op); + + if (!(code == LEU || code == LTU || code == GEU + || code == GTU)) + { + return 1; + } + else + return 0; + } + + return 0; +} diff --git a/gcc/config/dsp16xx/dsp16xx.h b/gcc/config/dsp16xx/dsp16xx.h index f98d6789d24..dae1d742c49 100644 --- a/gcc/config/dsp16xx/dsp16xx.h +++ b/gcc/config/dsp16xx/dsp16xx.h @@ -1,7 +1,7 @@ /* Definitions of target machine for GNU compiler. AT&T DSP1600. Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001 Free Software Foundation, Inc. - Contributed by Michael Collison (collison@world.std.com). + Contributed by Michael Collison (collison@isisinc.net). This file is part of GNU CC. @@ -74,7 +74,9 @@ extern struct rtx_def *dsp16xx_lshrhi3_libcall; #ifdef CC1_SPEC #undef CC1_SPEC #endif -#define CC1_SPEC "" +#define CC1_SPEC "%{!O*:-O}" + +#define CPP_SPEC "%{!O*:-D__OPTIMIZE__}" /* Define this as a spec to call the AT&T assembler */ @@ -111,22 +113,29 @@ extern struct rtx_def *dsp16xx_lshrhi3_libcall; /* Tell gcc where to look for the startfile */ -#define STANDARD_STARTFILE_PREFIX "/d1600/lib" +/*#define STANDARD_STARTFILE_PREFIX "/d1600/lib"*/ -/* Tell gcc where to look for its executables */ -#define STANDARD_EXEC_PREFIX "/d1600/bin" +/* Tell gcc where to look for it's executables */ +/*#define STANDARD_EXEC_PREFIX "/d1600/bin"*/ /* Command line options to the AT&T assembler */ -#define ASM_SPEC "%{v:-V} %{g*:-g}" +#define ASM_SPEC "%{V} %{v:%{!V:-V}} %{g*:-g}" /* Command line options for the AT&T linker */ -#define LINK_SPEC "%{v:-V} %{minit:-i} \ -%{!ifile*:%{mmap1:-ifile m1_deflt.if%s} \ - %{mmap2:-ifile m2_deflt.if%s} \ - %{mmap3:-ifile m3_deflt.if%s} \ - %{mmap4:-ifile m4_deflt.if%s} \ - %{!mmap*:-ifile m4_deflt.if%s}} \ -%{ifile*} %{!r:-a}" + +#define LINK_SPEC "%{V} %{v:%{!V:-V}} %{minit:-i} \ +%{!ifile*:%{mmap1:m1_deflt.if%s} \ + %{mmap2:m2_deflt.if%s} \ + %{mmap3:m3_deflt.if%s} \ + %{mmap4:m4_deflt.if%s} \ + %{!mmap*:m4_deflt.if%s}} \ +%{ifile*:%*} %{r}" + +/* Include path is determined from the environment variable */ +#define INCLUDE_DEFAULTS \ +{ \ + { 0, 0, 0 } \ +} /* Names to predefine in the preprocessor for this target machine. */ #ifdef __MSDOS__ @@ -145,8 +154,6 @@ extern int target_flags; #define MASK_NEAR_CALL 0x00000002 /* The call is on the same 4k page */ #define MASK_NEAR_JUMP 0x00000004 /* The jump is on the same 4k page */ #define MASK_BMU 0x00000008 /* Use the 'bmu' shift instructions */ -#define MASK_OPTIMIZE_MEMORY 0x00000010 /* Optimize to conserve memory */ -#define MASK_OPTIMIZE_SPEED 0x00000020 /* Optimize for speed */ #define MASK_MAP1 0x00000040 /* Link with map1 */ #define MASK_MAP2 0x00000080 /* Link with map2 */ #define MASK_MAP3 0x00000100 /* Link with map3 */ @@ -154,8 +161,9 @@ extern int target_flags; #define MASK_YBASE_HIGH 0x00000400 /* The ybase register window starts high */ #define MASK_INIT 0x00000800 /* Have the linker generate tables to initialize data at startup */ -#define MASK_INLINE_MULT 0x00001000 /* Inline 32 bit multiplies */ #define MASK_RESERVE_YBASE 0x00002000 /* Reserved the ybase registers */ +#define MASK_DEBUG 0x00004000 /* Debugging turned on*/ +#define MASK_SAVE_TEMPS 0x00008000 /* Save temps. option seen */ /* Compile passing first two args in regs 0 and 1. This exists only to test compiler features that will @@ -177,12 +185,6 @@ extern int target_flags; Unit. */ #define TARGET_BMU (target_flags & MASK_BMU) -/* Optimize to conserve memory */ -#define TARGET_OPTIMIZE_MEMORY (target_flags & MASK_OPTIMIZE_MEMORY) - -/* Optimize for maximum speed */ -#define TARGET_OPTIMIZE_SPEED (target_flags & MASK_OPTIMIZE_SPEED) - #define TARGET_YBASE_HIGH (target_flags & MASK_YBASE_HIGH) /* Direct the linker to output extra info for initialized data */ @@ -193,6 +195,13 @@ extern int target_flags; /* Reserve the ybase registers *(0) - *(31) */ #define TARGET_RESERVE_YBASE (target_flags & MASK_RESERVE_YBASE) +/* We turn this option on internally after seeing "-g" */ +#define TARGET_DEBUG (target_flags & MASK_DEBUG) + +/* We turn this option on internally after seeing "-save-temps */ +#define TARGET_SAVE_TEMPS (target_flags & MASK_SAVE_TEMPS) + + /* Macro to define tables used to set the flags. This is a list in braces of pairs in braces, each pair being { "NAME", VALUE } @@ -200,31 +209,46 @@ extern int target_flags; An empty string NAME is used to identify the default VALUE. */ -#define TARGET_SWITCHES \ - { \ - { "regparm", MASK_REGPARM}, \ - { "no-regparm", -MASK_REGPARM}, \ - { "no-near-call", -MASK_NEAR_CALL}, \ - { "near-jump", MASK_NEAR_JUMP}, \ - { "no-near-jump", -MASK_NEAR_JUMP}, \ - { "bmu", MASK_BMU}, \ - { "no-bmu", -MASK_BMU}, \ - { "Om", MASK_OPTIMIZE_MEMORY}, \ - { "Os", MASK_OPTIMIZE_SPEED}, \ - { "map1", MASK_MAP1}, \ - { "map2", MASK_MAP2}, \ - { "map3", MASK_MAP3}, \ - { "map4", MASK_MAP4}, \ - { "ybase-high", MASK_YBASE_HIGH}, \ - { "init", MASK_INIT}, \ - { "inline-mult", MASK_INLINE_MULT}, \ - { "reserve-ybase", MASK_RESERVE_YBASE}, \ - { "", TARGET_DEFAULT} \ +#define TARGET_SWITCHES \ + { \ + { "regparm", MASK_REGPARM, \ + N_("Pass parameters in registers (default)") }, \ + { "no-regparm", -MASK_REGPARM, \ + N_("Don't pass parameters in registers") }, \ + { "near-call", MASK_NEAR_JUMP, \ + N_("Generate code for near calls") }, \ + { "no-near-call", -MASK_NEAR_CALL, \ + N_("Don't generate code for near calls") }, \ + { "near-jump", MASK_NEAR_JUMP, \ + N_("Generate code for near jumps") }, \ + { "no-near-jump", -MASK_NEAR_JUMP, \ + N_("Don't generate code for near jumps") }, \ + { "bmu", MASK_BMU, \ + N_("Generate code for a bit-manipulation unit") }, \ + { "no-bmu", -MASK_BMU, \ + N_("Don't generate code for a bit-manipulation unit") }, \ + { "map1", MASK_MAP1, \ + N_("Generate code for memory map1") }, \ + { "map2", MASK_MAP2, \ + N_("Generate code for memory map2") }, \ + { "map3", MASK_MAP3, \ + N_("Generate code for memory map3") }, \ + { "map4", MASK_MAP4, \ + N_("Generate code for memory map4") }, \ + { "init", MASK_INIT, \ + N_("Ouput extra code for initialized data") }, \ + { "reserve-ybase", MASK_RESERVE_YBASE, \ + N_("Don't let reg. allocator use ybase registers") }, \ + { "debug", MASK_DEBUG, \ + N_("Output extra debug info in Luxworks environment") }, \ + { "save-temporaries", MASK_SAVE_TEMPS, \ + N_("Save temp. files in Luxworks environment") }, \ + { "", TARGET_DEFAULT, ""} \ } /* Default target_flags if no switches are specified */ #ifndef TARGET_DEFAULT -#define TARGET_DEFAULT MASK_OPTIMIZE_MEMORY|MASK_REGPARM|MASK_YBASE_HIGH +#define TARGET_DEFAULT MASK_REGPARM|MASK_YBASE_HIGH #endif /* This macro is similar to `TARGET_SWITCHES' but defines names of @@ -246,11 +270,16 @@ extern int target_flags; #define TARGET_OPTIONS \ { \ - { "text=", &text_seg_name }, \ - { "data=", &data_seg_name }, \ - { "bss=", &bss_seg_name }, \ - { "const=", &const_seg_name }, \ - { "chip=", &chip_name } \ + { "text=", &text_seg_name, \ + N_("Specify alternate name for text section") }, \ + { "data=", &data_seg_name, \ + N_("Specify alternate name for data section") }, \ + { "bss=", &bss_seg_name, \ + N_("Specify alternate name for bss section") }, \ + { "const=", &const_seg_name, \ + N_("Specify alternate name for constant section") }, \ + { "chip=", &chip_name, \ + N_("Specify alternate name for dsp16xx chip") }, \ } /* Sometimes certain combinations of command options do not make sense @@ -264,18 +293,21 @@ extern int target_flags; #define OVERRIDE_OPTIONS override_options () -#define OPTIMIZATION_OPTIONS(LEVEL,SIZE) \ -do \ - { \ - flag_gnu_linker = FALSE; \ - \ - if (SIZE) \ - { \ - flag_strength_reduce = FALSE; \ - flag_inline_functions = FALSE; \ - } \ - } \ -while (0) +#define OPTIMIZATION_OPTIONS(LEVEL,SIZE) \ +{ \ + flag_gnu_linker = FALSE; \ + \ + if (LEVEL >= 2) \ + { \ + /* The dsp16xx family has so few registers \ + * that running the first instruction \ + * scheduling is bad for reg. allocation \ + * since it increases lifetimes of pseudos. \ + * So turn of first scheduling pass. \ + */ \ + flag_schedule_insns = FALSE; \ + } \ +} /* STORAGE LAYOUT */ @@ -287,7 +319,7 @@ while (0) /* Define this if most significant bit is lowest numbered in instructions that operate on numbered bit-fields. */ -#define BITS_BIG_ENDIAN 1 +#define BITS_BIG_ENDIAN 0 /* Define this if most significant byte of a word is the lowest numbered. We define big-endian, but since the 1600 series cannot address bytes @@ -377,12 +409,13 @@ while (0) /* A C expression for a string describing the name of the data type to use for size values. */ -#define SIZE_TYPE "long unsigned int" +#define SIZE_TYPE "unsigned int" -/* A C expression for a string describing the name of the datat type to use for the +/* A C expression for a string describing the name of the data type to use for the result of subtracting two pointers */ -#define PTRDIFF_TYPE "long int" +#define PTRDIFF_TYPE "int" + /* REGISTER USAGE. */ @@ -475,6 +508,10 @@ while (0) /* Do we have a virtual ybase register */ #define IS_YBASE_REGISTER_WINDOW(REGNO) ((REGNO) >= REG_YBASE0 && (REGNO) <= REG_YBASE31) +#define IS_YBASE_ELIGIBLE_REG(REGNO) (IS_ACCUM_REG (REGNO) || IS_ADDRESS_REGISTER(REGNO) \ + || REGNO == REG_X || REGNO == REG_Y || REGNO == REG_YL \ + || REGNO == REG_PROD || REGNO == REG_PRODL) + #define IS_ADDRESS_REGISTER(REGNO) ((REGNO) >= REG_R0 && (REGNO) <= REG_R3) #define FIXED_REGISTERS \ @@ -483,7 +520,7 @@ while (0) 1, \ 0, 0, 0, 0, \ 1, 1, 1, \ - 0, 0, \ + 1, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, \ @@ -501,17 +538,17 @@ while (0) bit manipulation registers. */ -#define CALL_USED_REGISTERS \ -{1, 1, 1, 1, 0, 1, 1, 1, 1, \ - 1, 0, 0, 1, 1, 1, 1, \ - 1, \ - 0, 0, 1, 1, \ - 1, 1, 1, \ - 0, 1, \ - 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0} +#define CALL_USED_REGISTERS \ +{1, 1, 1, 1, 0, 1, 1, 1, 1, /* 0-8 */ \ + 1, 0, 0, 1, 1, 1, 1, /* 9-15 */ \ + 1, /* 16 */ \ + 0, 0, 1, 1, /* 17-20 */ \ + 1, 1, 1, /* 21-23 */ \ + 1, 1, /* 24-25 */ \ + 0, 0, 0, 0, 0, 0, 0, 0, /* 26-33 */ \ + 0, 0, 0, 0, 0, 0, 0, 0, /* 34-41 */ \ + 0, 0, 0, 0, 0, 0, 0, 0, /* 42-49 */ \ + 0, 0, 0, 0, 0, 0, 0, 0} /* 50-57 */ /* List the order in which to allocate registers. Each register must be listed once, even those in FIXED_REGISTERS. @@ -519,6 +556,7 @@ while (0) We allocate in the following order: */ +#if 0 #define REG_ALLOC_ORDER \ { REG_R0, REG_R1, REG_R2, REG_PROD, REG_Y, REG_X, \ REG_PRODL, REG_YL, REG_AR0, REG_AR1, \ @@ -534,7 +572,24 @@ while (0) REG_YBASE20, REG_YBASE21, REG_YBASE22, REG_YBASE23, \ REG_YBASE24, REG_YBASE25, REG_YBASE26, REG_YBASE27, \ REG_YBASE28, REG_YBASE29, REG_YBASE30, REG_YBASE31 } - +#else +#define REG_ALLOC_ORDER \ +{ \ + REG_A0, REG_A0L, REG_A1, REG_A1L, REG_Y, REG_YL, \ + REG_PROD, \ + REG_PRODL, REG_R0, REG_J, REG_K, REG_AR2, REG_AR3, \ + REG_X, REG_R1, REG_R2, REG_RB, REG_AR0, REG_AR1, \ + REG_YBASE0, REG_YBASE1, REG_YBASE2, REG_YBASE3, \ + REG_YBASE4, REG_YBASE5, REG_YBASE6, REG_YBASE7, \ + REG_YBASE8, REG_YBASE9, REG_YBASE10, REG_YBASE11, \ + REG_YBASE12, REG_YBASE13, REG_YBASE14, REG_YBASE15, \ + REG_YBASE16, REG_YBASE17, REG_YBASE18, REG_YBASE19, \ + REG_YBASE20, REG_YBASE21, REG_YBASE22, REG_YBASE23, \ + REG_YBASE24, REG_YBASE25, REG_YBASE26, REG_YBASE27, \ + REG_YBASE28, REG_YBASE29, REG_YBASE30, REG_YBASE31, \ + REG_R3, REG_YBASE, REG_PT, REG_C0, REG_C1, REG_C2, \ + REG_PR } +#endif /* Zero or more C statements that may conditionally modify two variables `fixed_regs' and `call_used_regs' (both of type `char []') after they have been initialized from the two preceding @@ -978,23 +1033,32 @@ enum reg_class 'I' requires a non-negative 16-bit value. 'J' requires a non-negative 9-bit value 'K' requires a constant 0 operand. - 'L' requires 16-bit value + 'L' constant for use in add or sub from low 16-bits 'M' 32-bit value -- low 16-bits zero + 'N' constant for use incrementing or decrementing a address register + 'O' constant for use with and'ing only high 16-bit + 'P' constant for use with and'ing only low 16-bit */ #define SMALL_INT(X) (SMALL_INTVAL (INTVAL (X))) #define SMALL_INTVAL(I) ((unsigned) (I) < 0x10000) #define SHORT_IMMEDIATE(X) (SHORT_INTVAL (INTVAL(X))) #define SHORT_INTVAL(I) ((unsigned) (I) < 0x100) +#define ADD_LOW_16(I) ((I) >= 0 && (I) <= 32767) +#define ADD_HIGH_16(I) (((I) & 0x0000ffff) == 0) +#define AND_LOW_16(I) ((I) >= 0 && (I) <= 32767) +#define AND_HIGH_16(I) (((I) & 0x0000ffff) == 0) #define CONST_OK_FOR_LETTER_P(VALUE, C) \ ((C) == 'I' ? (SMALL_INTVAL(VALUE)) \ : (C) == 'J' ? (SHORT_INTVAL(VALUE)) \ : (C) == 'K' ? ((VALUE) == 0) \ - : (C) == 'L' ? ! ((VALUE) & ~0x0000ffff) \ - : (C) == 'M' ? ! ((VALUE) & ~0xffff0000) \ - : (C) == 'N' ? ((VALUE) == -1 || (VALUE) == 1 || \ - (VALUE) == -2 || (VALUE) == 2) \ + : (C) == 'L' ? ((VALUE) >= 0 && (VALUE) <= 32767) \ + : (C) == 'M' ? (((VALUE) & 0x0000ffff) == 0) \ + : (C) == 'N' ? ((VALUE) == -1 || (VALUE) == 1 \ + || (VALUE) == -2 || (VALUE) == 2) \ + : (C) == 'O' ? (((VALUE) & 0xffff0000) == 0xffff0000) \ + : (C) == 'P' ? (((VALUE) & 0x0000ffff) == 0xffff) \ : 0) #define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 1 @@ -1043,6 +1107,7 @@ struct dsp16xx_frame_info unsigned int reg_size; /* # bytes needed to store regs */ long fp_save_offset; /* offset from vfp to store registers */ unsigned long sp_save_offset; /* offset from new sp to store registers */ + int pr_save_offset; /* offset to saved PR */ int initialized; /* != 0 if frame size already calculated */ int num_regs; /* number of registers saved */ int function_makes_calls; /* Does the function make calls */ @@ -1050,6 +1115,8 @@ struct dsp16xx_frame_info extern struct dsp16xx_frame_info current_frame_info; +#define RETURN_ADDR_OFF current_frame_info.pr_save_offset + /* If we generate an insn to push BYTES bytes, this says how many the stack pointer really advances by. */ /* #define PUSH_ROUNDING(BYTES) ((BYTES)) */ @@ -1402,7 +1469,7 @@ extern struct dsp16xx_frame_info current_frame_info; return it with a return statement. */ #define CONST_COSTS(RTX,CODE,OUTER_CODE) \ case CONST_INT: \ - return 0; \ + return (unsigned) INTVAL (RTX) < 65536 ? 0 : 2; \ case LABEL_REF: \ case SYMBOL_REF: \ case CONST: \ @@ -1427,45 +1494,21 @@ extern struct dsp16xx_frame_info current_frame_info; else \ return COSTS_N_INSNS (38); \ case PLUS: \ - if (GET_MODE_CLASS (GET_MODE (X)) == MODE_INT) \ - { \ - if (GET_CODE (XEXP (X,1)) == CONST_INT) \ - { \ - int number = INTVAL(XEXP (X,1)); \ - if (number == 1) \ - return COSTS_N_INSNS (1); \ - if (INT_FITS_16_BITS(number)) \ - return COSTS_N_INSNS (2); \ - else \ - return COSTS_N_INSNS (4); \ - } \ - return COSTS_N_INSNS (1); \ - } \ - else \ - return COSTS_N_INSNS (38); \ case MINUS: \ if (GET_MODE_CLASS (GET_MODE (X)) == MODE_INT) \ - { \ - if (GET_CODE (XEXP (X,1)) == CONST_INT) \ { \ - if (INT_FITS_16_BITS(INTVAL(XEXP(X,1)))) \ - return COSTS_N_INSNS (2); \ - else \ - return COSTS_N_INSNS (4); \ + return (1 + \ + rtx_cost (XEXP (X, 0), CODE) + \ + rtx_cost (XEXP (X, 1), CODE)); \ } \ - return COSTS_N_INSNS (1); \ - } \ else \ return COSTS_N_INSNS (38); \ + \ case AND: case IOR: case XOR: \ - if (GET_CODE (XEXP (X,1)) == CONST_INT) \ - { \ - if (INT_FITS_16_BITS(INTVAL(XEXP(X,1)))) \ - return COSTS_N_INSNS (2); \ - else \ - return COSTS_N_INSNS (4); \ - } \ - return COSTS_N_INSNS (1); \ + return (1 + \ + rtx_cost (XEXP (X, 0), CODE) + \ + rtx_cost (XEXP (X, 1), CODE)); \ + \ case NEG: case NOT: \ return COSTS_N_INSNS (1); \ case ASHIFT: \ @@ -1478,9 +1521,17 @@ extern struct dsp16xx_frame_info current_frame_info; number == 16) \ return COSTS_N_INSNS (1); \ else \ + { \ + if (TARGET_BMU) \ return COSTS_N_INSNS (2); \ + else \ + return COSTS_N_INSNS (num_1600_core_shifts(number)); \ + } \ } \ - return COSTS_N_INSNS (1); + if (TARGET_BMU) \ + return COSTS_N_INSNS (1); \ + else \ + return COSTS_N_INSNS (15); /* An expression giving the cost of an addressing mode that contains address. */ @@ -1500,7 +1551,7 @@ extern struct dsp16xx_frame_info current_frame_info; /* A C expression for the cost of a branch instruction. A value of 1 is the default; */ -#define BRANCH_COST 2 +#define BRANCH_COST 1 /* Define this because otherwise gcc will try to put the function address @@ -1566,11 +1617,15 @@ const_section () \ /* THE OVERALL FRAMEWORK OF AN ASSEMBLER FILE */ /* Output at beginning of assembler file. */ -#define ASM_FILE_START(FILE) dsp16xx_file_start () +#define ASM_FILE_START(FILE) coff_dsp16xx_file_start (FILE) + +/* Prevent output of .gcc_compiled */ +#define ASM_IDENTIFY_GCC(FILE) /* A C string constant describing how to begin a comment in the target assembler language. */ -/* define ASM_COMMENT_START */ +#define ASM_COMMENT_START "" +#define ASM_COMMENT_END "" /* Output to assembler file text saying following lines may contain character constants, extra white space, comments, etc. */ @@ -1605,9 +1660,7 @@ const_section () \ #define ASM_OUTPUT_INT(FILE, EXP) asm_output_long(FILE,INTVAL(EXP)) /* This is how to output an assembler line for a numeric constant byte. */ -#define ASM_OUTPUT_BYTE(FILE,VALUE) \ - fprintf ((FILE), "\tint %ld\n", (long)(VALUE)) - +#define ASM_OUTPUT_BYTE(FILE,VALUE) ASM_OUTPUT_CHAR(FILE,GEN_INT(VALUE)) /* This is how we output a 'c' character string. For the 16xx assembler we have to do it one letter at a time */ @@ -1643,7 +1696,7 @@ const_section () \ fprintf (asm_out_file, "%d", c); \ /* After an octal-escape, if a digit follows, \ terminate one string constant and start another. \ - The VAX assembler fails to stop reading the escape \ + The Vax assembler fails to stop reading the escape \ after three digits, so this is the only way we \ can get it to parse the data properly. \ if (i < thissize - 1 \ @@ -1683,6 +1736,10 @@ const_section () \ (OUTPUT) = (char *) alloca (strlen (NAME) + 11); \ ASM_GENERATE_INTERNAL_LABEL (OUTPUT, temp, LABELNO); \ } while (0) + +#define ASM_OPEN_PAREN "(" +#define ASM_CLOSE_PAREN ")" + /* OUTPUT OF UNINITIALIZED VARIABLES */ @@ -1837,17 +1894,19 @@ const_section () \ /* CONTROLLING DEBUGGING INFORMATION FORMAT */ -/* Define this macro if GCC should produce COFF-style debugging output - for SDB in response to the '-g' option */ -#define SDB_DEBUGGING_INFO - -/* Support generating stabs for the listing file generator */ -#define DBX_DEBUGGING_INFO - -/* The default format when -g is given is still COFF debug info */ -#define PREFERRED_DEBUGGING_TYPE SDB_DEBUG +#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG #define DBX_REGISTER_NUMBER(REGNO) (REGNO) + +#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) + /* MISCELLANEOUS PARAMETERS */ @@ -1899,17 +1958,12 @@ const_section () \ #define TARGET_VERSION fprintf (stderr, " (%s, %s)", VERSION_INFO1, __DATE__) #endif -#define VERSION_INFO1 "AT&T DSP16xx C Cross Compiler, version 1.2.0" +#define VERSION_INFO1 "Lucent DSP16xx C Cross Compiler, version 1.3.0b" /* Define this as 1 if `char' should by default be signed; else as 0. */ #define DEFAULT_SIGNED_CHAR 1 -/* If this macro is defined, GNU CC gathers statistics about the number and - kind of tree node it allocates during each run. The option '-fstats' will - tell the compiler to print these statistics about the sizes of it obstacks. */ -#define GATHER_STATISTICS - /* Define this so gcc does not output a call to __main, since we are not currently supporting c++. */ #define INIT_SECTION_ASM_OP 1 diff --git a/gcc/config/dsp16xx/dsp16xx.md b/gcc/config/dsp16xx/dsp16xx.md index 29d9acd3bef..1f44420e38f 100644 --- a/gcc/config/dsp16xx/dsp16xx.md +++ b/gcc/config/dsp16xx/dsp16xx.md @@ -1,6 +1,6 @@ ;;- Machine description for the AT&T DSP1600 for GNU C compiler ;; Copyright (C) 1994, 1995, 1997, 1998, 2001 Free Software Foundation, Inc. -;; Contributed by Michael Collison (collison@world.std.com). +;; Contributed by Michael Collison (collison@isisinc.net). ;; This file is part of GNU CC. @@ -36,15 +36,25 @@ ; Classification of each insn. Some insns of TYPE_BRANCH are multi-word. (define_attr "type" - "jump,cond_jump,call,load_i,load,move,store,malu,malu_mul,special,f3_alu,f3_alu_i,shift_i,shift,bfield_i,bfield,nop,ld_short_i" + "jump,cond_jump,call,load_i,load,move,store,malu,malu_mul,tstqi,special,special_2,f3_alu,f3_alu_i,f3_alu_i_mult,shift_i,shift,shift_multiple,shift_i_multiple,bfield_i,bfield,nop,ld_short_i,data_move,data_move_i,data_move_memory,data_move_memory_2,data_move_short_i,data_move_multiple,data_move_2,nothing" (const_string "malu")) -; Length in # of instructions of each insn. The values are not exact, but -; are safe. -(define_attr "length" "" - (cond [(eq_attr "type" "cond_jump,f3_alu_i,shift_i,bfield_i,load_i") - (const_int 2)] - (const_int 1))) +;; Data arithmetic unit +(define_function_unit "dau" 1 1 (eq_attr "type" "data_move,data_move_i,f3_alu_i") 2 0) + +(define_function_unit "dau" 1 1 (eq_attr "type" "special_2") 3 0) + +(define_function_unit "dau" 1 1 (eq_attr "type" "data_move_2") 4 0) + +;; Bit manipulation +(define_function_unit "bmu" 1 1 (eq_attr "type" "shift_i,shift_i_multiple") 2 0) + +(define_function_unit "bmu" 1 1 (eq_attr "type" "shift_multiple") 4 0) + +;; Y-memory addressing arithmetic unit +(define_function_unit "yaau" 1 1 (eq_attr "type" "data_move_memory") 2 0) + +(define_function_unit "yaau" 1 1 (eq_attr "type" "data_move_memory_2") 4 0) ;; .................... @@ -84,6 +94,28 @@ DONE; }") +(define_split + [(set (cc0) + (match_operand:QI 0 "register_operand" "j,q")) + (clobber (match_scratch:QI 1 "=k,u"))] + "reload_completed" + [(set (match_dup 1) + (const_int 0)) + (parallel [(set (cc0) + (match_dup 0)) + (use (match_dup 1))])] + "") + +(define_insn "tstqi_split" + [(set (cc0) + (match_operand:QI 0 "register_operand" "j,q")) + (use (match_scratch:QI 1 "=k,u"))] + "" + "@ + %b0-0 + %b0-0" + [(set_attr "type" "f3_alu_i,f3_alu_i")]) + (define_insn "tstqi_1" [(set (cc0) (match_operand:QI 0 "register_operand" "j,q")) @@ -92,7 +124,7 @@ "@ %1=0\;%b0-0 %1=0\;%b0-0" - [(set_attr "type" "malu,malu")]) + [(set_attr "type" "tstqi,tstqi")]) ;; @@ -104,8 +136,8 @@ (define_insn "" [(set (cc0) - (and:HI (match_operand:HI 0 "register_operand" "A,!A,A") - (match_operand:HI 1 "nonmemory_operand" "Z,A,I")))] + (and:HI (match_operand:HI 0 "register_operand" "A,!A") + (match_operand:HI 1 "register_operand" "Z,A")))] "" "* { @@ -114,14 +146,9 @@ case 0: case 1: return \"%0&%1\"; - - case 2: - return \"%0&%H1\"; - default: - abort(); } }" - [(set_attr "type" "f3_alu,malu,f3_alu_i")]) + [(set_attr "type" "f3_alu,f3_alu")]) ;;(define_insn "" @@ -178,7 +205,7 @@ else if (IS_YBASE_REGISTER_WINDOW (REGNO (operands[0]))) output_asm_insn (\"a0=%u0\;a0l=%w0\", operands); else - abort (); + fatal_error (\"Invalid register for compare\"); } else if (GET_CODE(operands[0]) == CONST_INT) output_asm_insn (\"a0=%U0\;a0l=%H0\", operands); @@ -198,7 +225,7 @@ else if (IS_YBASE_REGISTER_WINDOW (REGNO (operands[1]))) output_asm_insn (\"a1=%u1\;a1l=%w1\", operands); else - abort (); + fatal_error (\"Invalid register for compare\"); } else if (GET_CODE (operands[1]) == MEM) { @@ -243,6 +270,64 @@ } }") +(define_split + [(set (cc0) + (compare (match_operand:QI 0 "register_operand" "") + (match_operand:QI 1 "register_operand" ""))) + (clobber (match_scratch:QI 2 "")) + (clobber (match_scratch:QI 3 ""))] + "reload_completed && next_cc_user_unsigned (insn)" + [(set (match_dup 2) + (const_int 0)) + (set (match_dup 3) + (const_int 0)) + (parallel [(set (cc0) + (compare (match_dup 0) + (match_dup 1))) + (use (match_dup 2)) + (use (match_dup 3))])] + "") + +(define_split + [(set (cc0) + (compare (match_operand:QI 0 "register_operand" "") + (match_operand:QI 1 "const_int_operand" ""))) + (clobber (match_scratch:QI 2 "")) + (clobber (match_scratch:QI 3 ""))] + "reload_completed && next_cc_user_unsigned (insn)" + [(set (match_dup 2) + (const_int 0)) + (parallel [(set (cc0) + (compare (match_dup 0) + (match_dup 1))) + (use (match_dup 2))])] + "") + +(define_insn "cmpqi_split_unsigned_reg" + [(set (cc0) (compare (match_operand:QI 0 "register_operand" "k,k,!k,u,u,!u") + (match_operand:QI 1 "register_operand" "w,z,u,w,z,k"))) + (use (match_scratch:QI 2 "=j,j,j,q,q,q")) + (use (match_scratch:QI 3 "=v,y,q,v,y,j"))] + "next_cc_user_unsigned (insn)" + "@ + %2-%3 + %2-%3 + %2-%3 + %2-%3 + %2-%3 + %2-%3" + [(set_attr "type" "malu,malu,malu,malu,malu,malu")]) + +(define_insn "cmpqi_split_unsigned_int" + [(set (cc0) (compare (match_operand:QI 0 "register_operand" "k,u") + (match_operand:QI 1 "const_int_operand" "i,i"))) + (use (match_scratch:QI 2 "=j,q"))] + "next_cc_user_unsigned (insn)" + "@ + %0-%H1 + %0-%H1" + [(set_attr "type" "f3_alu_i,f3_alu_i")]) + (define_insn "" [(set (cc0) (compare (match_operand:QI 0 "register_operand" "k,k,!k,k,u,u,!u,u") (match_operand:QI 1 "nonmemory_operand" "w,z,u,i,w,z,k,i"))) @@ -259,6 +344,64 @@ %2=0\;%3=0\;%2-%3 %2=0\;%0-%H1") +(define_split + [(set (cc0) + (compare (match_operand:QI 0 "register_operand" "") + (match_operand:QI 1 "register_operand" ""))) + (clobber (match_scratch:QI 2 "")) + (clobber (match_scratch:QI 3 ""))] + "reload_completed" + [(set (match_dup 2) + (const_int 0)) + (set (match_dup 3) + (const_int 0)) + (parallel [(set (cc0) + (compare (match_dup 0) + (match_dup 1))) + (use (match_dup 2)) + (use (match_dup 3))])] + "") + +(define_split + [(set (cc0) + (compare (match_operand:QI 0 "register_operand" "") + (match_operand:QI 1 "const_int_operand" ""))) + (clobber (match_scratch:QI 2 "")) + (clobber (match_scratch:QI 3 ""))] + "reload_completed" + [(set (match_dup 2) + (const_int 0)) + (parallel [(set (cc0) + (compare (match_dup 0) + (match_dup 1))) + (use (match_dup 2))])] + "") + +(define_insn "cmpqi_split_reg" + [(set (cc0) (compare (match_operand:QI 0 "register_operand" "j,j,!j,q,q,!q") + (match_operand:QI 1 "register_operand" "v,y,q,v,y,j"))) + (use (match_scratch:QI 2 "=k,k,k,u,u,u")) + (use (match_scratch:QI 3 "=w,z,u,w,z,k"))] + "" + "@ + %0-%1 + %0-%1 + %0-%1 + %0-%1 + %0-%1 + %0-%1" + [(set_attr "type" "malu,malu,malu,malu,malu,malu")]) + + +(define_insn "cmpqi_split_int" + [(set (cc0) (compare (match_operand:QI 0 "register_operand" "j,q") + (match_operand:QI 1 "const_int_operand" "i,i"))) + (use (match_scratch:QI 2 "=k,u"))] + "" + "@ + %b0-%H1 + %b0-%H1" + [(set_attr "type" "f3_alu_i,f3_alu_i")]) (define_insn "" [(set (cc0) (compare (match_operand:QI 0 "register_operand" "j,j,!j,j,q,q,!q,q") @@ -304,17 +447,45 @@ ;; ;; .................... +(define_split + [(set (match_operand:HI 0 "register_operand" "") + (plus:HI (match_operand:HI 1 "register_operand" "") + (match_operand:HI 2 "const_int_operand" "")))] + "reload_completed && !ADD_LOW_16(INTVAL(operands[2])) && + !ADD_HIGH_16(INTVAL(operands[2]))" + [(parallel [(set (match_dup 3) + (plus:QI (match_dup 4) + (match_dup 5))) + (clobber (match_dup 6))]) + + (parallel [(set (match_dup 6) + (plus:QI (match_dup 7) + (match_dup 8))) + (clobber (match_scratch:QI 9 ""))])] + " +{ + operands[3] = gen_lowpart(QImode, operands[0]); + operands[4] = gen_lowpart(QImode, operands[1]); + operands[5] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff); + + operands[6] = gen_highpart(QImode, operands[0]); + operands[7] = gen_highpart(QImode, operands[0]); + operands[8] = gen_rtx (CONST_INT, VOIDmode, (((INTVAL (operands[2]) & 0xffff0000) >> 16) & 0xffff)); +}") + (define_insn "addhi3" - [(set (match_operand:HI 0 "register_operand" "=A,A,A") - (plus:HI (match_operand:HI 1 "register_operand" "%A,A,A") - (match_operand:HI 2 "nonmemory_operand" "Z,d,i")))] + [(set (match_operand:HI 0 "register_operand" "=A,A,A,A,A") + (plus:HI (match_operand:HI 1 "register_operand" "%A,A,A,A,A") + (match_operand:HI 2 "nonmemory_operand" "Z,d,L,M,?i")))] "" "@ %0=%1+%2 %0=%1+%2 + %0=%w1+%H2 + %0=%b1+%U2 %0=%w1+%H2\;%0=%b0+%U2" - [(set_attr "type" "malu,malu,f3_alu_i")]) + [(set_attr "type" "malu,malu,f3_alu_i,f3_alu_i,f3_alu_i")]) (define_insn "" [(set (match_operand:QI 0 "register_operand" "=k,u,!k,!u") @@ -354,10 +525,10 @@ (define_insn "match_addqi3" - [(set (match_operand:QI 0 "register_operand" "=!a,!a,k,u,!k,!u,h,!a") - (plus:QI (match_operand:QI 1 "register_operand" "0,0,uk,uk,uk,uk,h,0") - (match_operand:QI 2 "nonmemory_operand" "W,N,wzi,wzi,uk,uk,i,n"))) - (clobber (match_scratch:QI 3 "=X,X,j,q,j,q,X,W"))] + [(set (match_operand:QI 0 "register_operand" "=a,a,k,u,k,u,!k,!u,j,j,q,q") + (plus:QI (match_operand:QI 1 "register_operand" "0,0,uk,uk,uk,uk,uk,uk,0,q,0,j") + (match_operand:QI 2 "nonmemory_operand" "W,N,i,i,wz,wz,uk,uk,i,i,i,i"))) + (clobber (match_scratch:QI 3 "=X,X,j,q,j,q,j,q,X,k,X,u"))] "" "* { @@ -384,24 +555,26 @@ case 2: case 3: - if (!CONSTANT_P(operands[2])) - return \"%m0=%m1+%m2\"; - else return \"%m0=%1+%H2\"; case 4: case 5: - return \"%m0=%m1+%m2\"; + return \"%m0=%m1+%m2\"; + case 6: - return \"%0=%b1+%H2\"; - case 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,22 +713,31 @@ [(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=%m1&%m2 %m0=%m1&%m2 %m0=%1&%H2 - %m0=%m1&%m2 - %m0=%m1&%m2 + %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=%m1|%m2 %m0=%m1|%m2 %m0=%1|%H2 - %m0=%m1|%m2 - %m0=%m1|%m2 + %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=%m1^%m2 %m0=%m1^%m2 %m0=%1^%H2 - %m0=%m1^%m2 - %m0=%m1^%m2 + %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\"; } }") @@ -1671,14 +2230,6 @@ "%0=%1<<8" [(set_attr "type" "special")]) -(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") @@ -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 - [(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" "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 - [(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" "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 - [(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) + (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 + [(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 + [(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 + [(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")