From 8d485e2d2fc1894a7db2ca0d60cd08eeb6b9e768 Mon Sep 17 00:00:00 2001 From: Michael Hayes Date: Sun, 30 Jul 2000 08:42:57 +0000 Subject: [PATCH] c4x.c (c4x_emit_move_sequence): Use loadqi_big_constant and loadhi_big_constant if applicable. * config/c4x/c4x.c (c4x_emit_move_sequence): Use loadqi_big_constant and loadhi_big_constant if applicable. * config/c4x/c4x.md (loadqi_big_constant, loadhi_big_constant): Tweak and add new splitter.s From-SVN: r35339 --- gcc/ChangeLog | 7 + gcc/config/c4x/c4x.c | 423 ++++++++++++++++++++++++++---------------- gcc/config/c4x/c4x.md | 114 +++++++++++- 3 files changed, 382 insertions(+), 162 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f8c208286b7..9bf128e481b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2000-07-30 Michael Hayes + + * config/c4x/c4x.c (c4x_emit_move_sequence): Use loadqi_big_constant + and loadhi_big_constant if applicable. + * config/c4x/c4x.md (loadqi_big_constant, loadhi_big_constant): Tweak + and add new splitter.s + 2000-07-30 Michael Hayes * config/c4x/c4x.c (c4x_rptb_insert): Make more robust. diff --git a/gcc/config/c4x/c4x.c b/gcc/config/c4x/c4x.c index dcc48ff7873..15d04f76b7e 100644 --- a/gcc/config/c4x/c4x.c +++ b/gcc/config/c4x/c4x.c @@ -60,7 +60,7 @@ rtx floatunshihf2_libfunc; static int c4x_leaf_function; -static char *float_reg_names[] = FLOAT_REGISTER_NAMES; +static const char *float_reg_names[] = FLOAT_REGISTER_NAMES; /* Array of the smallest class containing reg number REGNO, indexed by REGNO. Used by REGNO_REG_CLASS in c4x.h. We assume that all these @@ -161,6 +161,27 @@ static tree pure_tree = NULL_TREE; static tree noreturn_tree = NULL_TREE; static tree interrupt_tree = NULL_TREE; +/* Forward declarations */ +static void c4x_add_gc_roots PARAMS ((void)); +static int c4x_isr_reg_used_p PARAMS ((unsigned int)); +static int c4x_leaf_function_p PARAMS ((void)); +static int c4x_assembler_function_p PARAMS ((void)); +static int c4x_immed_float_p PARAMS ((rtx)); +static int c4x_a_register PARAMS ((rtx)); +static int c4x_x_register PARAMS ((rtx)); +static int c4x_immed_int_constant PARAMS ((rtx)); +static int c4x_immed_float_constant PARAMS ((rtx)); +static int c4x_K_constant PARAMS ((rtx)); +static int c4x_N_constant PARAMS ((rtx)); +static int c4x_O_constant PARAMS ((rtx)); +static int c4x_R_indirect PARAMS ((rtx)); +static int c4x_S_indirect PARAMS ((rtx)); +static void c4x_S_address_parse PARAMS ((rtx , int *, int *, int *, int *)); +static int c4x_valid_operands PARAMS ((enum rtx_code, rtx *, + enum machine_mode, int)); +static int c4x_arn_reg_operand PARAMS ((rtx, enum machine_mode, unsigned int)); +static int c4x_arn_mem_operand PARAMS ((rtx, enum machine_mode, unsigned int)); +static void c4x_check_attribute PARAMS ((const char *, tree, tree, tree *)); /* Called to register all of our global variables with the garbage collector. */ @@ -374,7 +395,7 @@ c4x_output_ascii (stream, ptr, len) int c4x_hard_regno_mode_ok (regno, mode) - int regno; + unsigned int regno; enum machine_mode mode; { switch (mode) @@ -688,7 +709,7 @@ c4x_va_arg (valist, type) static int c4x_isr_reg_used_p (regno) - int regno; + unsigned int regno; { /* Don't save/restore FP or ST, we handle them separately. */ if (regno == FRAME_POINTER_REGNUM @@ -752,7 +773,7 @@ c4x_assembler_function_p () } -static int +int c4x_interrupt_function_p () { if (lookup_attribute ("interrupt", @@ -769,55 +790,75 @@ c4x_interrupt_function_p () && ISDIGIT (current_function_name[6]); } - -/* Write function prologue. */ - void -c4x_function_prologue (file, size) - FILE *file; - int size; +c4x_expand_prologue () { - int regno; + unsigned int regno; + int size = get_frame_size (); + rtx insn; -/* In functions where ar3 is not used but frame pointers are still - specified, frame pointers are not adjusted (if >= -O2) and this is - used so it won't be needlessly push the frame pointer. */ + /* In functions where ar3 is not used but frame pointers are still + specified, frame pointers are not adjusted (if >= -O2) and this + is used so it won't needlessly push the frame pointer. */ int dont_push_ar3; /* For __assembler__ function don't build a prologue. */ if (c4x_assembler_function_p ()) { - fprintf (file, "; *** Assembler Function ***\n"); return; } + +#ifdef FUNCTION_BLOCK_PROFILER_EXIT + if (profile_block_flag == 2) + { + FUNCTION_BLOCK_PROFILER_EXIT + } +#endif /* For __interrupt__ function build specific prologue. */ if (c4x_interrupt_function_p ()) { c4x_leaf_function = c4x_leaf_function_p (); - fprintf (file, "; *** Interrupt Entry %s ***\n", - c4x_leaf_function ? "(leaf)" : ""); - - fprintf (file, "\tpush\tst\n"); + + insn = emit_insn (gen_push_st ()); + RTX_FRAME_RELATED_P (insn) = 1; if (size) { - fprintf (file, "\tpush\tar3\n\tldi\tsp,ar3\n"); + insn = emit_insn (gen_pushqi ( gen_rtx_REG (QImode, AR3_REGNO))); + RTX_FRAME_RELATED_P (insn) = 1; + insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, AR3_REGNO), + gen_rtx_REG (QImode, SP_REGNO))); + RTX_FRAME_RELATED_P (insn) = 1; /* FIXME: Assume ISR doesn't require more than 32767 words of local variables. */ if (size > 32767) error ("ISR %s requires %d words of local variables, " "maximum is 32767.", current_function_name, size); - fprintf (file, "\taddi\t%d,sp\n", size); + insn = emit_insn (gen_addqi3 (gen_rtx_REG (QImode, SP_REGNO), + gen_rtx_REG (QImode, SP_REGNO), + GEN_INT(size))); + RTX_FRAME_RELATED_P (insn) = 1; } for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) { if (c4x_isr_reg_used_p (regno)) { - fprintf (file, "\tpush\t%s\n", reg_names[regno]); - if (IS_EXT_REGNO (regno)) /* Save 32MSB of R0--R11. */ - fprintf (file, "\tpushf\t%s\n", - TARGET_TI ? reg_names[regno] - : float_reg_names[regno]); + if (regno == DP_REGNO) + { + insn = emit_insn (gen_push_dp ()); + RTX_FRAME_RELATED_P (insn) = 1; + } + else + { + insn = emit_insn (gen_pushqi (gen_rtx_REG (QImode, regno))); + RTX_FRAME_RELATED_P (insn) = 1; + if (IS_EXT_REGNO (regno)) + { + insn = emit_insn (gen_pushqf + (gen_rtx_REG (QFmode, regno))); + RTX_FRAME_RELATED_P (insn) = 1; + } + } } } /* We need to clear the repeat mode flag if the ISR is @@ -826,14 +867,20 @@ c4x_function_prologue (file, size) if (regs_ever_live[RC_REGNO] || regs_ever_live[RS_REGNO] || regs_ever_live[RE_REGNO]) - fprintf (file, "\tandn\t0100h,st\n"); + { + insn = emit_insn (gen_andn_st (GEN_INT(~0x100))); + RTX_FRAME_RELATED_P (insn) = 1; + } /* Reload DP reg if we are paranoid about some turkey violating small memory model rules. */ if (TARGET_SMALL && TARGET_PARANOID) - fprintf (file, TARGET_C3X ? - "\tldp\t@data_sec\n" : - "\tldpk\t@data_sec\n"); + { + insn = emit_insn (gen_set_ldp_prologue + (gen_rtx_REG (QImode, DP_REGNO), + gen_rtx_SYMBOL_REF (QImode, "data_sec"))); + RTX_FRAME_RELATED_P (insn) = 1; + } } else { @@ -843,8 +890,11 @@ c4x_function_prologue (file, size) || (current_function_args_size != 0) || (optimize < 2)) { - fprintf (file, "\tpush\tar3\n"); - fprintf (file, "\tldi\tsp,ar3\n"); + insn = emit_insn (gen_pushqi ( gen_rtx_REG (QImode, AR3_REGNO))); + RTX_FRAME_RELATED_P (insn) = 1; + insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, AR3_REGNO), + gen_rtx_REG (QImode, SP_REGNO))); + RTX_FRAME_RELATED_P (insn) = 1; dont_push_ar3 = 1; } else @@ -865,28 +915,46 @@ c4x_function_prologue (file, size) size += 1; } } - + if (size > 32767) { /* Local vars are too big, it will take multiple operations to increment SP. */ if (TARGET_C3X) { - fprintf (file, "\tldi\t%d,r1\n", size >> 16); - fprintf (file, "\tlsh\t16,r1\n"); + insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, R1_REGNO), + GEN_INT(size >> 16))); + RTX_FRAME_RELATED_P (insn) = 1; + insn = emit_insn (gen_lshrqi3 (gen_rtx_REG (QImode, R1_REGNO), + gen_rtx_REG (QImode, R1_REGNO), + GEN_INT(-16))); + RTX_FRAME_RELATED_P (insn) = 1; } else - fprintf (file, "\tldhi\t%d,r1\n", size >> 16); - fprintf (file, "\tor\t%d,r1\n", size & 0xffff); - fprintf (file, "\taddi\tr1,sp\n"); + { + insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, R1_REGNO), + GEN_INT(size & ~0xffff))); + RTX_FRAME_RELATED_P (insn) = 1; + } + insn = emit_insn (gen_iorqi3 (gen_rtx_REG (QImode, R1_REGNO), + gen_rtx_REG (QImode, R1_REGNO), + GEN_INT(size & 0xffff))); + RTX_FRAME_RELATED_P (insn) = 1; + insn = emit_insn (gen_addqi3 (gen_rtx_REG (QImode, SP_REGNO), + gen_rtx_REG (QImode, SP_REGNO), + gen_rtx_REG (QImode, R1_REGNO))); + RTX_FRAME_RELATED_P (insn) = 1; } else if (size != 0) { /* Local vars take up less than 32767 words, so we can directly add the number. */ - fprintf (file, "\taddi\t%d,sp\n", size); + insn = emit_insn (gen_addqi3 (gen_rtx_REG (QImode, SP_REGNO), + gen_rtx_REG (QImode, SP_REGNO), + GEN_INT (size))); + RTX_FRAME_RELATED_P (insn) = 1; } - + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) { if (regs_ever_live[regno] && ! call_used_regs[regno]) @@ -895,14 +963,18 @@ c4x_function_prologue (file, size) { /* R6 and R7 are saved as floating point. */ if (TARGET_PRESERVE_FLOAT) - fprintf (file, "\tpush\t%s\n", reg_names[regno]); - fprintf (file, "\tpushf\t%s\n", - TARGET_TI ? reg_names[regno] - : float_reg_names[regno]); + { + insn = emit_insn (gen_pushqi + (gen_rtx_REG (QImode, regno))); + RTX_FRAME_RELATED_P (insn) = 1; + } + insn = emit_insn (gen_pushqf (gen_rtx_REG (QFmode, regno))); + RTX_FRAME_RELATED_P (insn) = 1; } else if ((! dont_push_ar3) || (regno != AR3_REGNO)) { - fprintf (file, "\tpush\t%s\n", reg_names[regno]); + insn = emit_insn (gen_pushqi ( gen_rtx_REG (QImode, regno))); + RTX_FRAME_RELATED_P (insn) = 1; } } } @@ -910,40 +982,23 @@ c4x_function_prologue (file, size) } -/* Write function epilogue. */ - void -c4x_function_epilogue (file, size) - FILE *file; - int size; +c4x_expand_epilogue() { int regno; - int restore_count = 0; - int delayed_jump = 0; + int jump = 0; int dont_pop_ar3; rtx insn; - - insn = get_last_insn (); - if (insn && GET_CODE (insn) == NOTE) - insn = prev_nonnote_insn (insn); - - if (insn && GET_CODE (insn) == BARRIER) - return; - + int size = get_frame_size (); + /* For __assembler__ function build no epilogue. */ if (c4x_assembler_function_p ()) { - fprintf (file, "\trets\n"); /* Play it safe. */ + insn = emit_jump_insn (gen_return_from_epilogue ()); + RTX_FRAME_RELATED_P (insn) = 1; return; } -#ifdef FUNCTION_BLOCK_PROFILER_EXIT - if (profile_block_flag == 2) - { - FUNCTION_BLOCK_PROFILER_EXIT (file); - } -#endif - /* For __interrupt__ function build specific epilogue. */ if (c4x_interrupt_function_p ()) { @@ -951,19 +1006,39 @@ c4x_function_epilogue (file, size) { if (! c4x_isr_reg_used_p (regno)) continue; - if (IS_EXT_REGNO (regno)) - fprintf (file, "\tpopf\t%s\n", - TARGET_TI ? reg_names[regno] - : float_reg_names[regno]); - fprintf (file, "\tpop\t%s\n", reg_names[regno]); + if (regno == DP_REGNO) + { + insn = emit_insn (gen_pop_dp ()); + RTX_FRAME_RELATED_P (insn) = 1; + } + else + { + /* We have to use unspec because the compiler will delete insns + that are not call-saved. */ + if (IS_EXT_REGNO (regno)) + { + insn = emit_insn (gen_popqf_unspec + (gen_rtx_REG (QFmode, regno))); + RTX_FRAME_RELATED_P (insn) = 1; + } + insn = emit_insn (gen_popqi_unspec (gen_rtx_REG (QImode, regno))); + RTX_FRAME_RELATED_P (insn) = 1; + } } if (size) { - fprintf (file, "\tsubi\t%d,sp\n", size); - fprintf (file, "\tpop\tar3\n"); + insn = emit_insn (gen_subqi3 (gen_rtx_REG (QImode, SP_REGNO), + gen_rtx_REG (QImode, SP_REGNO), + GEN_INT(size))); + RTX_FRAME_RELATED_P (insn) = 1; + insn = emit_insn (gen_popqi + (gen_rtx_REG (QImode, AR3_REGNO))); + RTX_FRAME_RELATED_P (insn) = 1; } - fprintf (file, "\tpop\tst\n"); - fprintf (file, "\treti\n"); + insn = emit_insn (gen_pop_st ()); + RTX_FRAME_RELATED_P (insn) = 1; + insn = emit_jump_insn (gen_return_from_interrupt_epilogue ()); + RTX_FRAME_RELATED_P (insn) = 1; } else { @@ -973,14 +1048,19 @@ c4x_function_epilogue (file, size) || (current_function_args_size != 0) || (optimize < 2)) { - /* R2 holds the return value. */ - fprintf (file, "\tldi\t*-ar3(1),r2\n"); - + insn = emit_insn + (gen_movqi (gen_rtx_REG (QImode, R2_REGNO), + gen_rtx_MEM (QImode, + gen_rtx_PLUS + (QImode, gen_rtx_REG (QImode, + AR3_REGNO), + GEN_INT(-1))))); + RTX_FRAME_RELATED_P (insn) = 1; + /* We already have the return value and the fp, so we need to add those to the stack. */ size += 2; - delayed_jump = 1; - restore_count = 1; + jump = 1; dont_pop_ar3 = 1; } else @@ -1001,41 +1081,7 @@ c4x_function_epilogue (file, size) size += 1; } } - - /* Now get the number of instructions required to restore the - registers. */ - for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--) - { - if ((regs_ever_live[regno] && ! call_used_regs[regno]) - && ((! dont_pop_ar3) || (regno != AR3_REGNO))) - { - restore_count++; - if (TARGET_PRESERVE_FLOAT - && ((regno == R6_REGNO) || (regno == R7_REGNO))) - restore_count++; - } - } - - /* Get the number of instructions required to restore the stack. */ - if (size > 32767) - restore_count += (TARGET_C3X ? 4 : 3); - else if (size != 0) - restore_count += 1; - - if (delayed_jump && (restore_count < 3)) - { - /* We don't have enough instructions to account for the delayed - branch, so put some nops in. */ - - fprintf (file, "\tbud\tr2\n"); - while (restore_count < 3) - { - fprintf (file, "\tnop\n"); - restore_count++; - } - restore_count = 0; - } - + /* Now restore the saved registers, putting in the delayed branch where required. */ for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--) @@ -1044,33 +1090,28 @@ c4x_function_epilogue (file, size) { if (regno == AR3_REGNO && dont_pop_ar3) continue; - - if (delayed_jump && (restore_count == 3)) - fprintf (file, "\tbud\tr2\n"); - + /* R6 and R7 are saved as floating point. */ if ((regno == R6_REGNO) || (regno == R7_REGNO)) { - fprintf (file, "\tpopf\t%s\n", - TARGET_TI ? reg_names[regno] - : float_reg_names[regno]); + insn = emit_insn (gen_popqf_unspec + (gen_rtx_REG (QFmode, regno))); + RTX_FRAME_RELATED_P (insn) = 1; if (TARGET_PRESERVE_FLOAT) { - restore_count--; - if (delayed_jump && (restore_count == 3)) - fprintf (file, "\tbud\tr2\n"); - fprintf (file, "\tpop\t%s\n", reg_names[regno]); + insn = emit_insn (gen_popqi_unspec + (gen_rtx_REG (QImode, regno))); + RTX_FRAME_RELATED_P (insn) = 1; } } else - fprintf (file, "\tpop\t%s\n", reg_names[regno]); - restore_count--; + { + insn = emit_insn (gen_popqi (gen_rtx_REG (QImode, regno))); + RTX_FRAME_RELATED_P (insn) = 1; + } } } - - if (delayed_jump && (restore_count == 3)) - fprintf (file, "\tbud\tr2\n"); - + if (frame_pointer_needed) { if ((size != 0) @@ -1078,42 +1119,69 @@ c4x_function_epilogue (file, size) || (optimize < 2)) { /* Restore the old FP. */ - fprintf (file, "\tldi\t*ar3,ar3\n"); - restore_count--; - - if (delayed_jump && (restore_count == 3)) - fprintf (file, "\tbud\tr2\n"); + insn = emit_insn + (gen_movqi + (gen_rtx_REG (QImode, AR3_REGNO), + gen_rtx_MEM (QImode, gen_rtx_REG (QImode, AR3_REGNO)))); + + RTX_FRAME_RELATED_P (insn) = 1; } } - + if (size > 32767) { /* Local vars are too big, it will take multiple operations to decrement SP. */ if (TARGET_C3X) { - fprintf (file, "\tldi\t%d,r3\n", size >> 16); - if (delayed_jump) - fprintf (file, "\tbud\tr2\n"); - fprintf (file, "\tlsh\t16,r3\n"); + insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, R3_REGNO), + GEN_INT(size >> 16))); + RTX_FRAME_RELATED_P (insn) = 1; + insn = emit_insn (gen_lshrqi3 (gen_rtx_REG (QImode, R3_REGNO), + gen_rtx_REG (QImode, R3_REGNO), + GEN_INT(-16))); + RTX_FRAME_RELATED_P (insn) = 1; } else - fprintf (file, "\tldhi\t%d,r3\n", size >> 16); - fprintf (file, "\tor\t%d,r3\n", size & 0xffff); - fprintf (file, "\tsubi\tr3,sp\n"); + { + insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, R3_REGNO), + GEN_INT(size & ~0xffff))); + RTX_FRAME_RELATED_P (insn) = 1; + } + insn = emit_insn (gen_iorqi3 (gen_rtx_REG (QImode, R3_REGNO), + gen_rtx_REG (QImode, R3_REGNO), + GEN_INT(size & 0xffff))); + RTX_FRAME_RELATED_P (insn) = 1; + insn = emit_insn (gen_subqi3 (gen_rtx_REG (QImode, SP_REGNO), + gen_rtx_REG (QImode, SP_REGNO), + gen_rtx_REG (QImode, R3_REGNO))); + RTX_FRAME_RELATED_P (insn) = 1; } else if (size != 0) { /* Local vars take up less than 32768 words, so we can directly subtract the number. */ - fprintf (file, "\tsubi\t%d,sp\n", size); + insn = emit_insn (gen_subqi3 (gen_rtx_REG (QImode, SP_REGNO), + gen_rtx_REG (QImode, SP_REGNO), + GEN_INT(size))); + RTX_FRAME_RELATED_P (insn) = 1; + } + + if (jump) + { + insn = emit_insn (gen_indirect_jump ( + gen_rtx_REG (QImode, R2_REGNO))); + RTX_FRAME_RELATED_P (insn) = 1; + } + else + { + insn = emit_jump_insn (gen_return_from_epilogue ()); + RTX_FRAME_RELATED_P (insn) = 1; } - - if (! delayed_jump) - fprintf (file, "\trets\n"); } } + int c4x_null_epilogue_p () { @@ -1137,6 +1205,7 @@ c4x_null_epilogue_p () return 0; } + int c4x_emit_move_sequence (operands, mode) rtx *operands; @@ -1259,6 +1328,42 @@ c4x_emit_move_sequence (operands, mode) return 1; } + if (mode == QImode + && reg_operand (op0, mode) + && const_int_operand (op1, mode) + && ! IS_INT16_CONST (INTVAL (op1)) + && ! IS_HIGH_CONST (INTVAL (op1))) + { + emit_insn (gen_loadqi_big_constant (op0, op1)); + return 1; + } + + if (mode == HImode + && reg_operand (op0, mode) + && const_int_operand (op1, mode)) + { + emit_insn (gen_loadhi_big_constant (op0, op1)); + return 1; + } + + if (mode == QImode + && reg_operand (op0, mode) + && const_int_operand (op1, mode) + && ! IS_INT16_CONST (INTVAL (op1)) + && ! IS_HIGH_CONST (INTVAL (op1))) + { + emit_insn (gen_loadqi_big_constant (op0, op1)); + return 1; + } + + if (mode == HImode + && reg_operand (op0, mode) + && const_int_operand (op1, mode)) + { + emit_insn (gen_loadhi_big_constant (op0, op1)); + return 1; + } + /* Adjust operands in case we have modified them. */ operands[0] = op0; operands[1] = op1; @@ -1313,7 +1418,7 @@ c4x_emit_libcall3 (libcall, code, mode, operands) enum machine_mode mode; rtx *operands; { - return c4x_emit_libcall (libcall, code, mode, mode, 3, operands); + c4x_emit_libcall (libcall, code, mode, mode, 3, operands); } @@ -1738,7 +1843,7 @@ c4x_gen_compare_reg (code, x, y) char * c4x_output_cbranch (form, seq) - char *form; + const char *form; rtx seq; { int delayed = 0; @@ -3684,7 +3789,7 @@ static int c4x_valid_operands (code, operands, mode, force) enum rtx_code code; rtx *operands; - enum machine_mode mode; + enum machine_mode mode ATTRIBUTE_UNUSED; int force; { rtx op1; @@ -3716,9 +3821,9 @@ c4x_valid_operands (code, operands, mode, force) if (code1 == MEM && code2 == MEM) { - if (c4x_S_indirect (op1, mode) && c4x_S_indirect (op2, mode)) + if (c4x_S_indirect (op1) && c4x_S_indirect (op2)) return 1; - return c4x_R_indirect (op1, mode) && c4x_R_indirect (op2, mode); + return c4x_R_indirect (op1) && c4x_R_indirect (op2); } if (code1 == code2) @@ -3972,7 +4077,7 @@ static int c4x_arn_reg_operand (op, mode, regno) rtx op; enum machine_mode mode; - int regno; + unsigned int regno; { if (mode != VOIDmode && mode != GET_MODE (op)) return 0; @@ -3986,7 +4091,7 @@ static int c4x_arn_mem_operand (op, mode, regno) rtx op; enum machine_mode mode; - int regno; + unsigned int regno; { if (mode != VOIDmode && mode != GET_MODE (op)) return 0; @@ -4523,7 +4628,7 @@ c4x_file_end (fp) static void c4x_check_attribute (attrib, list, decl, attributes) - char *attrib; + const char *attrib; tree list, decl, *attributes; { while (list != NULL_TREE diff --git a/gcc/config/c4x/c4x.md b/gcc/config/c4x/c4x.md index 89fe2d0bb16..12da60ed0a9 100644 --- a/gcc/config/c4x/c4x.md +++ b/gcc/config/c4x/c4x.md @@ -1131,6 +1131,23 @@ (set (match_dup 0) (lo_sum:QI (match_dup 0) (match_dup 1)))] "") +(define_split + [(set (match_operand:QI 0 "reg_operand" "") + (match_operand:QI 1 "const_int_operand" "")) + (clobber (reg:QI 16))] + "! TARGET_C3X + && ! IS_INT16_CONST (INTVAL (operands[1])) + && ! IS_HIGH_CONST (INTVAL (operands[1])) + && reload_completed + && std_reg_operand (operands[0], QImode)" + [(set (match_dup 0) (match_dup 2)) + (set (match_dup 0) (ior:QI (match_dup 0) (match_dup 3)))] + " +{ + operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & ~0xffff); + operands[3] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 0xffff); +}") + (define_split [(set (match_operand:QI 0 "reg_operand" "") (match_operand:QI 1 "const_int_operand" ""))] @@ -1147,6 +1164,28 @@ operands[3] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 0xffff); }") +(define_split + [(set (match_operand:QI 0 "reg_operand" "") + (match_operand:QI 1 "const_int_operand" "")) + (clobber (reg:QI 16))] + "TARGET_C3X && ! TARGET_SMALL + && ! IS_INT16_CONST (INTVAL (operands[1])) + && reload_completed + && std_reg_operand (operands[0], QImode) + && c4x_shiftable_constant (operands[1]) < 0" + [(set (match_dup 0) (match_dup 2)) + (set (match_dup 0) (ashift:QI (match_dup 0) (match_dup 4))) + (set (match_dup 0) (ior:QI (match_dup 0) (match_dup 3)))] + " +{ + /* Generate two's complement value of 16 MSBs. */ + operands[2] = gen_rtx (CONST_INT, VOIDmode, + (((INTVAL (operands[1]) >> 16) & 0xffff) + - 0x8000) ^ ~0x7fff); + operands[3] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 0xffff); + operands[4] = gen_rtx (CONST_INT, VOIDmode, 16); +}") + (define_split [(set (match_operand:QI 0 "reg_operand" "") (match_operand:QI 1 "const_int_operand" ""))] @@ -1168,6 +1207,28 @@ operands[4] = gen_rtx (CONST_INT, VOIDmode, 16); }") +(define_split + [(set (match_operand:QI 0 "reg_operand" "") + (match_operand:QI 1 "const_int_operand" "")) + (clobber (reg:QI 16))] + "TARGET_C3X + && ! IS_INT16_CONST (INTVAL (operands[1])) + && reload_completed + && std_reg_operand (operands[0], QImode) + && c4x_shiftable_constant (operands[1]) >= 0" + [(set (match_dup 0) (match_dup 2)) + (set (match_dup 0) (ashift:QI (match_dup 0) (match_dup 3)))] + " +{ + /* Generate two's complement value of MSBs. */ + int shift = c4x_shiftable_constant (operands[1]); + + operands[2] = gen_rtx (CONST_INT, VOIDmode, + (((INTVAL (operands[1]) >> shift) & 0xffff) + - 0x8000) ^ ~0x7fff); + operands[3] = gen_rtx (CONST_INT, VOIDmode, shift); +}") + (define_split [(set (match_operand:QI 0 "reg_operand" "") (match_operand:QI 1 "const_int_operand" ""))] @@ -1189,6 +1250,29 @@ operands[3] = gen_rtx (CONST_INT, VOIDmode, shift); }") +(define_split + [(set (match_operand:QI 0 "reg_operand" "") + (match_operand:QI 1 "const_int_operand" "")) + (clobber (reg:QI 16))] + "! TARGET_SMALL + && ! IS_INT16_CONST (INTVAL (operands[1])) + && ! IS_HIGH_CONST (INTVAL (operands[1])) + && reload_completed + && ! std_reg_operand (operands[0], QImode)" + [(set (match_dup 2) (high:QI (match_dup 3))) + (set (match_dup 0) (match_dup 4)) + (use (match_dup 1))] + " +{ + rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO); + operands[2] = dp_reg; + operands[3] = force_const_mem (Pmode, operands[1]); + operands[4] = change_address (operands[3], QImode, + gen_rtx_LO_SUM (Pmode, dp_reg, + XEXP (operands[3], 0))); + operands[3] = XEXP (operands[3], 0); +}") + (define_split [(set (match_operand:QI 0 "reg_operand" "") (match_operand:QI 1 "const_int_operand" ""))] @@ -1211,6 +1295,27 @@ operands[3] = XEXP (operands[3], 0); }") +(define_split + [(set (match_operand:QI 0 "reg_operand" "") + (match_operand:QI 1 "const_int_operand" "")) + (clobber (reg:QI 16))] + "TARGET_SMALL + && ! IS_INT16_CONST (INTVAL (operands[1])) + && ! IS_HIGH_CONST (INTVAL (operands[1])) + && reload_completed + && ((TARGET_C3X && c4x_shiftable_constant (operands[1]) < 0) + || ! std_reg_operand (operands[0], QImode))" + [(set (match_dup 0) (match_dup 2)) + (use (match_dup 1))] + " +{ + rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO); + operands[2] = force_const_mem (Pmode, operands[1]); + operands[2] = change_address (operands[2], QImode, + gen_rtx_LO_SUM (Pmode, dp_reg, + XEXP (operands[2], 0))); +}") + (define_split [(set (match_operand:QI 0 "reg_operand" "") (match_operand:QI 1 "const_int_operand" ""))] @@ -1233,7 +1338,8 @@ (define_split [(set (match_operand:HI 0 "reg_operand" "") - (match_operand:HI 1 "const_int_operand" ""))] + (match_operand:HI 1 "const_int_operand" "")) + (clobber (reg:QI 16))] "reload_completed" [(set (match_dup 2) (match_dup 4)) (set (match_dup 3) (match_dup 5))] @@ -1315,7 +1421,8 @@ (define_insn "loadhi_big_constant" [(set (match_operand:HI 0 "reg_operand" "=c*d") - (match_operand:HI 1 "const_int_operand" ""))] + (match_operand:HI 1 "const_int_operand" "")) + (clobber (reg:QI 16))] "" "#" [(set_attr "type" "multi")]) @@ -1336,7 +1443,8 @@ (define_insn "loadqi_big_constant" [(set (match_operand:QI 0 "reg_operand" "=c*d") - (match_operand:QI 1 "const_int_operand" ""))] + (match_operand:QI 1 "const_int_operand" "")) + (clobber (reg:QI 16))] "! IS_INT16_CONST (INTVAL (operands[1])) && ! IS_HIGH_CONST (INTVAL (operands[1]))" "#"