From 1ec0eb08cebf52b464c2f1da505b41858cde8bcf Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Wed, 27 Jun 2018 12:31:10 -0600 Subject: [PATCH] v850-protos.h (notice_update_cc): Remove. * config/v850/v850-protos.h (notice_update_cc): Remove. * config/v850/v850.c (v850_compare_op0, v850_compare_op1): Remove. (v850_print_operand): Handle 'D' and "d". (v850_select_cc_mode): Remove ATTRIBUTE_UNUSED for last argument. Add handling of arithmetic/logical operations compared against zero. (v850_gen_float_compare): Remove ATTRIBUTE_UNUSED for last argument. Do not look at v850_compare_op, instead get mode from last argument. (v850_gen_compare): Remove (increment_stack): Use addsi3_clobber_flags to avoid splitting failure after reload for prologue insns. (expand_prologue): Account for CLOBBER of CC_REGNUM in various patterns. (construct_save_jarl): Likewise. (TARGET_FLAGS_REGNUM): Define. * config/v850/v850.h (v850_compare_op0, v850_compare_op1): Remove. (NOTICE_UPDATE_CC): Remove. * config/v850/v850.md (v850_tst1): Use (reg:CCZ CC_REGNUM) rather than cc0. Conditionalize on reload_completed. (cmpsi_insn, setfcc_insn): Likewise. (tst1 splitter): Turn into define_and_split which sets the flags after reload. (cstoresi4, cbranchsf4, cbranchdf4, cbranchsi4_insn): Likewise. (cbranchsi4, branch_normal, branch_invert): Do not expose cc0 here. (cstoresf4, cstoredf4): Clobber the flags. (cmpsi, cmpsf, cmpdf): Remove expanders. (setf_insn): Remove pattern. (addsi3): Turn into define_and_split which clobbers the flags after reload and a suitable pattern (addsi3_clobber_flags) for use after reload. (subsi3, negsi2, andsi3, iorsi3, xorsi3, one_cmplsi2) Likewise. (ashlsi3, ashlsi3_v850e2, lshrsi3, lsh4si3_v850e2): Likewise. (ashrsi3, ashrsi3_v850e2): Likewise. (bins): Clobber the flags. (movsicc_normal_cc, movsicc_normal, movsicc_tst1): Likewise. (movsicc_tst1_revesed, sasf, swap and rotate patterns): Likewise. (fix_loop_counter, call_internal_short, call_internal_long): Likewise. (call_value_internal_short, call_value_internal_long): Likewise. (callt_save_interrupt, callt_return_interrupt): Likewise. (save_interrupt, return_interrupt): Likewise. (callt_save_all_interrupt, save_all_interrupt): Likewise. (_save_all_interrupt, callt_restore_all_interrupt): Likewise. (restore_all_interrupt, _restore_all_interrupt): Likewise. (All FP comparisons): Only allow after reload has completed. (trfsr): Likewise. (divh, divhu): Tweak output template. (branch_z_normal, branch_z_invert): Remove (branch_nz_normal, branch_nz_invert): Likewise. (extendhisi_insn, extendqisi_insn): Do not clobber flags. Co-Authored-By: Austin Law From-SVN: r262190 --- gcc/ChangeLog | 49 +++ gcc/config/v850/v850-protos.h | 1 - gcc/config/v850/v850.c | 68 ++-- gcc/config/v850/v850.h | 5 - gcc/config/v850/v850.md | 706 ++++++++++++++++++++-------------- 5 files changed, 493 insertions(+), 336 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d9abfff5d0c..9cd59b27236 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,6 +1,55 @@ 2018-06-27 Jeff Law Austin Law + * config/v850/v850-protos.h (notice_update_cc): Remove. + * config/v850/v850.c (v850_compare_op0, v850_compare_op1): Remove. + (v850_print_operand): Handle 'D' and "d". + (v850_select_cc_mode): Remove ATTRIBUTE_UNUSED for last argument. + Add handling of arithmetic/logical operations compared against zero. + (v850_gen_float_compare): Remove ATTRIBUTE_UNUSED for last argument. + Do not look at v850_compare_op, instead get mode from last argument. + (v850_gen_compare): Remove + (increment_stack): Use addsi3_clobber_flags to avoid splitting failure + after reload for prologue insns. + (expand_prologue): Account for CLOBBER of CC_REGNUM in various + patterns. + (construct_save_jarl): Likewise. + (TARGET_FLAGS_REGNUM): Define. + * config/v850/v850.h (v850_compare_op0, v850_compare_op1): Remove. + (NOTICE_UPDATE_CC): Remove. + * config/v850/v850.md (v850_tst1): Use (reg:CCZ CC_REGNUM) rather + than cc0. Conditionalize on reload_completed. + (cmpsi_insn, setfcc_insn): Likewise. + (tst1 splitter): Turn into define_and_split which sets the flags + after reload. + (cstoresi4, cbranchsf4, cbranchdf4, cbranchsi4_insn): Likewise. + (cbranchsi4, branch_normal, branch_invert): Do not expose cc0 here. + (cstoresf4, cstoredf4): Clobber the flags. + (cmpsi, cmpsf, cmpdf): Remove expanders. + (setf_insn): Remove pattern. + (addsi3): Turn into define_and_split which clobbers the flags after + reload and a suitable pattern (addsi3_clobber_flags) for use after + reload. + (subsi3, negsi2, andsi3, iorsi3, xorsi3, one_cmplsi2) Likewise. + (ashlsi3, ashlsi3_v850e2, lshrsi3, lsh4si3_v850e2): Likewise. + (ashrsi3, ashrsi3_v850e2): Likewise. + (bins): Clobber the flags. + (movsicc_normal_cc, movsicc_normal, movsicc_tst1): Likewise. + (movsicc_tst1_revesed, sasf, swap and rotate patterns): Likewise. + (fix_loop_counter, call_internal_short, call_internal_long): Likewise. + (call_value_internal_short, call_value_internal_long): Likewise. + (callt_save_interrupt, callt_return_interrupt): Likewise. + (save_interrupt, return_interrupt): Likewise. + (callt_save_all_interrupt, save_all_interrupt): Likewise. + (_save_all_interrupt, callt_restore_all_interrupt): Likewise. + (restore_all_interrupt, _restore_all_interrupt): Likewise. + (All FP comparisons): Only allow after reload has completed. + (trfsr): Likewise. + (divh, divhu): Tweak output template. + (branch_z_normal, branch_z_invert): Remove + (branch_nz_normal, branch_nz_invert): Likewise. + (extendhisi_insn, extendqisi_insn): Do not clobber flags. + * config/v850/v850-modes.def (CCZ, CCNZ): Add new modes. * config/v850/v850.c (notice_update_cc): Remove. * config/v850/v850.h (CC_OVERFLOW_UNUSABLE): Remove diff --git a/gcc/config/v850/v850-protos.h b/gcc/config/v850/v850-protos.h index e8ff280f83d..ca99703248b 100644 --- a/gcc/config/v850/v850-protos.h +++ b/gcc/config/v850/v850-protos.h @@ -32,7 +32,6 @@ extern void v850_init_expanders (void); #ifdef RTX_CODE extern rtx v850_return_addr (int); extern const char *output_move_single (rtx *); -extern void notice_update_cc (rtx, rtx_insn *); extern char * construct_save_jarl (rtx); extern char * construct_restore_jr (rtx); #ifdef HAVE_MACHINE_MODES diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c index e184718e1ef..cb2debf46f1 100644 --- a/gcc/config/v850/v850.c +++ b/gcc/config/v850/v850.c @@ -68,8 +68,6 @@ data_area_stack_element * data_area_stack = NULL; function is an interrupt handler. */ static int v850_interrupt_cache_p = FALSE; -rtx v850_compare_op0, v850_compare_op1; - /* Whether current function is an interrupt handler. */ static int v850_interrupt_p = FALSE; @@ -418,7 +416,9 @@ v850_print_operand (FILE * file, rtx x, int code) case 'b': case 'B': case 'C': - switch ((code == 'B' || code == 'C') + case 'd': + case 'D': + switch ((code == 'B' || code == 'C' || code == 'D') ? reverse_condition (GET_CODE (x)) : GET_CODE (x)) { case NE: @@ -434,7 +434,10 @@ v850_print_operand (FILE * file, rtx x, int code) fprintf (file, "e"); break; case GE: - fprintf (file, "ge"); + if (code == 'D' || code == 'd') + fprintf (file, "p"); + else + fprintf (file, "ge"); break; case GT: fprintf (file, "gt"); @@ -443,7 +446,10 @@ v850_print_operand (FILE * file, rtx x, int code) fprintf (file, "le"); break; case LT: - fprintf (file, "lt"); + if (code == 'D' || code == 'd') + fprintf (file, "n"); + else + fprintf (file, "lt"); break; case GEU: fprintf (file, "nl"); @@ -905,7 +911,7 @@ output_move_single (rtx * operands) } machine_mode -v850_select_cc_mode (enum rtx_code cond, rtx op0, rtx op1 ATTRIBUTE_UNUSED) +v850_select_cc_mode (enum rtx_code cond, rtx op0, rtx op1) { if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT) { @@ -927,11 +933,20 @@ v850_select_cc_mode (enum rtx_code cond, rtx op0, rtx op1 ATTRIBUTE_UNUSED) gcc_unreachable (); } } + + if (op1 == const0_rtx + && (cond == EQ || cond == NE || cond == LT || cond == GE) + && (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS + || GET_CODE (op0) == NEG || GET_CODE (op0) == AND + || GET_CODE (op0) == IOR || GET_CODE (op0) == XOR + || GET_CODE (op0) == NOT || GET_CODE (op0) == ASHIFT)) + return CCNZmode; + return CCmode; } machine_mode -v850_gen_float_compare (enum rtx_code cond, machine_mode mode ATTRIBUTE_UNUSED, rtx op0, rtx op1) +v850_gen_float_compare (enum rtx_code cond, machine_mode mode, rtx op0, rtx op1) { if (GET_MODE (op0) == DFmode) { @@ -960,7 +975,7 @@ v850_gen_float_compare (enum rtx_code cond, machine_mode mode ATTRIBUTE_UNUSED, gcc_unreachable (); } } - else if (GET_MODE (v850_compare_op0) == SFmode) + else if (mode == SFmode) { switch (cond) { @@ -993,25 +1008,6 @@ v850_gen_float_compare (enum rtx_code cond, machine_mode mode ATTRIBUTE_UNUSED, return v850_select_cc_mode (cond, op0, op1); } -rtx -v850_gen_compare (enum rtx_code cond, machine_mode mode, rtx op0, rtx op1) -{ - if (GET_MODE_CLASS(GET_MODE (op0)) != MODE_FLOAT) - { - emit_insn (gen_cmpsi_insn (op0, op1)); - return gen_rtx_fmt_ee (cond, mode, gen_rtx_REG(CCmode, CC_REGNUM), const0_rtx); - } - else - { - rtx cc_reg; - mode = v850_gen_float_compare (cond, mode, op0, op1); - cc_reg = gen_rtx_REG (mode, CC_REGNUM); - emit_insn (gen_rtx_SET (cc_reg, gen_rtx_REG (mode, FCC_REGNUM))); - - return gen_rtx_fmt_ee (cond, mode, cc_reg, const0_rtx); - } -} - /* Return maximum offset supported for a short EP memory reference of mode MODE and signedness UNSIGNEDP. */ @@ -1635,7 +1631,7 @@ increment_stack (signed int amount, bool in_prologue) inc = reg; } - inc = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, inc)); + inc = emit_insn (gen_addsi3_clobber_flags (stack_pointer_rtx, stack_pointer_rtx, inc)); if (in_prologue) F (inc); } @@ -1712,7 +1708,7 @@ expand_prologue (void) save_all = gen_rtx_PARALLEL (VOIDmode, - rtvec_alloc (num_save + 1 + rtvec_alloc (num_save + 2 + (TARGET_DISABLE_CALLT ? (TARGET_LONG_CALLS ? 2 : 1) : 0))); XVECEXP (save_all, 0, 0) @@ -1731,13 +1727,16 @@ expand_prologue (void) save_regs[i]); } + XVECEXP (save_all, 0, num_save + 1) + = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, CC_REGNUM)); + if (TARGET_DISABLE_CALLT) { - XVECEXP (save_all, 0, num_save + 1) + XVECEXP (save_all, 0, num_save + 2) = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 10)); if (TARGET_LONG_CALLS) - XVECEXP (save_all, 0, num_save + 2) + XVECEXP (save_all, 0, num_save + 3) = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 11)); } @@ -2330,7 +2329,7 @@ construct_save_jarl (rtx op) stack_bytes = INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)); /* Each push will put 4 bytes from the stack.... */ - stack_bytes += (count - (TARGET_LONG_CALLS ? 3 : 2)) * 4; + stack_bytes += (count - (TARGET_LONG_CALLS ? 4 : 3)) * 4; /* Make sure that the amount we are popping either 0 or 16 bytes. */ if (stack_bytes != 0) @@ -2341,7 +2340,7 @@ construct_save_jarl (rtx op) /* Now compute the bit mask of registers to push. */ mask = 0; - for (i = 1; i < count - (TARGET_LONG_CALLS ? 2 : 1); i++) + for (i = 1; i < count - (TARGET_LONG_CALLS ? 3 : 2); i++) { rtx vector_element = XVECEXP (op, 0, i); @@ -3325,6 +3324,9 @@ v850_modes_tieable_p (machine_mode mode1, machine_mode mode2) #undef TARGET_MODES_TIEABLE_P #define TARGET_MODES_TIEABLE_P v850_modes_tieable_p +#undef TARGET_FLAGS_REGNUM +#define TARGET_FLAGS_REGNUM 32 + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-v850.h" diff --git a/gcc/config/v850/v850.h b/gcc/config/v850/v850.h index 96bddc25801..04d226a8e05 100644 --- a/gcc/config/v850/v850.h +++ b/gcc/config/v850/v850.h @@ -26,9 +26,6 @@ #ifndef GCC_V850_H #define GCC_V850_H -extern GTY(()) rtx v850_compare_op0; -extern GTY(()) rtx v850_compare_op1; - #undef LIB_SPEC #define LIB_SPEC "%{!shared:%{!symbolic:--start-group -lc -lgcc --end-group}}" @@ -567,8 +564,6 @@ struct cum_arg { int nbytes; }; #define SELECT_CC_MODE(OP, X, Y) v850_select_cc_mode (OP, X, Y) -#define NOTICE_UPDATE_CC(EXP, INSN) - /* Nonzero if access to memory by bytes or half words is no faster than accessing full words. */ #define SLOW_BYTE_ACCESS 1 diff --git a/gcc/config/v850/v850.md b/gcc/config/v850/v850.md index 0fad9ea501d..3cfec74324f 100644 --- a/gcc/config/v850/v850.md +++ b/gcc/config/v850/v850.md @@ -28,6 +28,42 @@ ;; ;; One day we'll probably need to handle calls to targets more than 4M ;; away. +;; + +;; Condition codes +;; +;; Data movement (load, store, register copy) does not modify condition +;; codes. But there is no way to add two registers together without +;; modifying the condition codes. +;; +;; So we do not expose the condition codes until after reload. The +;; general approach is to have a define_insn_and_split for the basic +;; operation with no condition codes in the pattern (to give the +;; optimizers maximal freedom). The splitter adds a clobber of the +;; condition codes after reload. There is a distinct pattern which +;; sets the condition codes. +;; +;; As noted, data movement does not affect condition codes. +;; +;; Arithmetic generally set the codes in the expected ways, with mul +;; instructions being a notable outlier. div instructions generally +;; do the right thing, except when the output registers are the same +;; when the flags do not get set. We just assume they're clobbered +;; for div instructions to avoid MD bloat with marginal benefit +;; +;; The bit manipulation instructions (clr1, not1, set1) set condition +;; codes, but not in a useful way (they're set to the prior status of +;; the bit). So we just model those as clobbers. tst1 does set the +;; condition codes in a useful way. We could perhaps do better with +;; these by noting they only modify the Z flag, it doesn't seem worth +;; the effort. +;; +;; Byte swaps seem to change the condition codes, but I haven't tried +;; to describe how. +;; +;; I have no documentation on the rotate instructions. They likely +;; set the condition codes, but I've left them as clobbers for now. + ;; The size of instructions in bytes. @@ -352,110 +388,90 @@ ;; ---------------------------------------------------------------------- (define_insn "*v850_tst1" - [(set (cc0) + [(set (reg:CCZ CC_REGNUM) (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "m") (const_int 1) (match_operand:QI 1 "const_int_operand" "n")) (const_int 0)))] - "" + "reload_completed" "tst1 %1,%0" [(set_attr "length" "4")]) ;; This replaces ld.b;sar;andi with tst1;setf nz. +;; Should there be variants for HI or SI modes? -(define_split +(define_insn_and_split "" [(set (match_operand:SI 0 "register_operand" "") (compare (zero_extract:SI (match_operand:QI 1 "memory_operand" "") (const_int 1) (match_operand 2 "const_int_operand" "")) (const_int 0)))] "" - [(set (cc0) (compare (zero_extract:SI (match_dup 1) - (const_int 1) - (match_dup 2)) - (const_int 0))) - (set (match_dup 0) (ne:SI (cc0) (const_int 0)))]) + "#" + "reload_completed" + [(set (reg:CCZ CC_REGNUM) (compare (zero_extract:SI (match_dup 1) + (const_int 1) + (match_dup 2)) + (const_int 0))) + (set (match_dup 0) (ne:SI (reg:CCZ CC_REGNUM) (const_int 0)))]) (define_expand "cbranchsi4" - [(set (cc0) - (compare (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "reg_or_int5_operand" ""))) - (set (pc) + [(set (pc) (if_then_else - (match_operator 0 "ordered_comparison_operator" [(cc0) - (const_int 0)]) + (match_operator 0 "comparison_operator" + [(match_operand:SI 1 "register_operand") + (match_operand:SI 2 "reg_or_int5_operand")]) (label_ref (match_operand 3 "" "")) (pc)))] "") -(define_expand "cstoresi4" - [(set (cc0) - (compare (match_operand:SI 2 "register_operand" "") - (match_operand:SI 3 "reg_or_int5_operand" ""))) - (set (match_operand:SI 0 "register_operand") - (match_operator:SI 1 "ordered_comparison_operator" [(cc0) - (const_int 0)]))] - "") - -(define_expand "cmpsi" - [(set (cc0) - (compare (match_operand:SI 0 "register_operand" "r,r") - (match_operand:SI 1 "reg_or_int5_operand" "r,J")))] - "" - { - v850_compare_op0 = operands[0]; - v850_compare_op1 = operands[1]; - DONE; - }) - (define_insn "cmpsi_insn" - [(set (cc0) + [(set (reg:CC CC_REGNUM) (compare (match_operand:SI 0 "register_operand" "r,r") (match_operand:SI 1 "reg_or_int5_operand" "r,J")))] - "" - "@ - cmp %1,%0 - cmp %1,%0" + "reload_completed" + "cmp %1,%0" [(set_attr "length" "2,2")]) -(define_expand "cbranchsf4" +(define_insn_and_split "cbranchsf4" [(set (pc) (if_then_else (match_operator 0 "ordered_comparison_operator" - [(match_operand:SF 1 "register_operand") - (match_operand:SF 2 "register_operand")]) + [(match_operand:SF 1 "register_operand" "r") + (match_operand:SF 2 "register_operand" "r")]) (label_ref (match_operand 3 "")) - (pc))) - (clobber (cc0))] + (pc)))] "TARGET_USE_FPU" -{ - enum rtx_code cond = GET_CODE (operands[0]); - machine_mode mode; - rtx fcc_reg; - rtx cc_reg; - rtx tmp; - - v850_compare_op0 = operands[1]; - v850_compare_op1 = operands[2]; - - if (GET_MODE_CLASS (GET_MODE (v850_compare_op0)) != MODE_FLOAT) - FAIL; - - mode = v850_gen_float_compare (cond, VOIDmode, v850_compare_op0, v850_compare_op1); - fcc_reg = gen_rtx_REG (mode, FCC_REGNUM); - cc_reg = gen_rtx_REG (mode, CC_REGNUM); - emit_insn (gen_rtx_SET (cc_reg, fcc_reg)); - tmp = gen_rtx_fmt_ee (cond, mode, cc_reg, const0_rtx); - tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, - gen_rtx_LABEL_REF (VOIDmode, operands[3]), pc_rtx); - emit_jump_insn (gen_rtx_SET (pc_rtx, tmp)); - DONE; -}) + "#" + "reload_completed" + [(set (match_dup 4) (match_dup 5)) + (set (pc) + (if_then_else (match_dup 6) + (label_ref (match_dup 3)) + (pc)))] + "{ + /* This will generate the comparison insn at the start of + the sequence and get us the right mode to use for our + condition code registers. */ + enum machine_mode mode + = v850_gen_float_compare (GET_CODE (operands[0]), + GET_MODE (operands[1]), + operands[1], operands[2]); + /* We want operands referring to CC_REGNUM and FCC_REGNUM + in mode MODE. */ + operands[4] = gen_rtx_REG (mode, CC_REGNUM); + operands[5] = gen_rtx_REG (mode, FCC_REGNUM); + if (mode == CC_FPU_NEmode) + operands[6] = gen_rtx_NE (mode, operands[4], const0_rtx); + else + operands[6] = gen_rtx_EQ (mode, operands[4], const0_rtx); +}") (define_insn "cstoresf4" [(set (match_operand:SI 0 "register_operand" "=r") (match_operator:SI 1 "ordered_comparison_operator" [(match_operand:SF 2 "register_operand" "r") - (match_operand:SF 3 "register_operand" "r")]))] + (match_operand:SF 3 "register_operand" "r")])) + (clobber (reg:CC CC_REGNUM))] "TARGET_USE_FPU" { if (GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE) @@ -471,44 +487,47 @@ [(set_attr "length" "12") (set_attr "type" "fpu")]) -(define_expand "cbranchdf4" +(define_insn_and_split "cbranchdf4" [(set (pc) (if_then_else (match_operator 0 "ordered_comparison_operator" - [(match_operand:DF 1 "even_reg_operand") - (match_operand:DF 2 "even_reg_operand")]) + [(match_operand:DF 1 "even_reg_operand" "r") + (match_operand:DF 2 "even_reg_operand" "r")]) (label_ref (match_operand 3 "")) - (pc))) - (clobber (cc0))] + (pc)))] "TARGET_USE_FPU" -{ - enum rtx_code cond = GET_CODE (operands[0]); - machine_mode mode; - rtx fcc_reg; - rtx cc_reg; - rtx tmp; - - v850_compare_op0 = operands[1]; - v850_compare_op1 = operands[2]; - - if (GET_MODE_CLASS (GET_MODE (v850_compare_op0)) != MODE_FLOAT) - FAIL; - - mode = v850_gen_float_compare (cond, VOIDmode, v850_compare_op0, v850_compare_op1); - fcc_reg = gen_rtx_REG (mode, FCC_REGNUM); - cc_reg = gen_rtx_REG (mode, CC_REGNUM); - emit_insn (gen_rtx_SET (cc_reg, fcc_reg)); - tmp = gen_rtx_fmt_ee (cond, mode, cc_reg, const0_rtx); - tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, - gen_rtx_LABEL_REF (VOIDmode, operands[3]), pc_rtx); - emit_jump_insn (gen_rtx_SET (pc_rtx, tmp)); - DONE; -}) + "#" + "reload_completed" +;; How to get the mode here? + [(set (match_dup 4) (match_dup 5)) + (set (pc) + (if_then_else (match_dup 6) + (label_ref (match_dup 3)) + (pc)))] + "{ + /* This will generate the comparison insn at the start of + the sequence and get us the right mode to use for our + condition code registers. */ + enum machine_mode mode + = v850_gen_float_compare (GET_CODE (operands[0]), + GET_MODE (operands[1]), + operands[1], operands[2]); + PUT_MODE (operands[0], mode); + /* We want operands referring to CC_REGNUM and FCC_REGNUM + in mode MODE. */ + operands[4] = gen_rtx_REG (mode, CC_REGNUM); + operands[5] = gen_rtx_REG (mode, FCC_REGNUM); + if (mode == CC_FPU_NEmode) + operands[6] = gen_rtx_NE (mode, operands[4], const0_rtx); + else + operands[6] = gen_rtx_EQ (mode, operands[4], const0_rtx); +}") (define_insn "cstoredf4" [(set (match_operand:SI 0 "register_operand" "=r") (match_operator:SI 1 "ordered_comparison_operator" [(match_operand:DF 2 "even_reg_operand" "r") - (match_operand:DF 3 "even_reg_operand" "r")]))] + (match_operand:DF 3 "even_reg_operand" "r")])) + (clobber (reg:CC CC_REGNUM))] "TARGET_USE_FPU" { if (GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE) @@ -524,38 +543,25 @@ [(set_attr "length" "12") (set_attr "type" "fpu")]) -(define_expand "cmpsf" - [(set (reg:CC CC_REGNUM) - (compare (match_operand:SF 0 "register_operand" "r") - (match_operand:SF 1 "register_operand" "r")))] - "TARGET_USE_FPU" - { - v850_compare_op0 = operands[0]; - v850_compare_op1 = operands[1]; - DONE; - }) - -(define_expand "cmpdf" - [(set (reg:CC CC_REGNUM) - (compare (match_operand:DF 0 "even_reg_operand" "r") - (match_operand:DF 1 "even_reg_operand" "r")))] - "TARGET_USE_FPU" - { - v850_compare_op0 = operands[0]; - v850_compare_op1 = operands[1]; - DONE; - }) - ;; ---------------------------------------------------------------------- ;; ADD INSTRUCTIONS ;; ---------------------------------------------------------------------- -(define_insn "addsi3" +(define_insn_and_split "addsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (plus:SI (match_operand:SI 1 "register_operand" "%0,r,r") + (match_operand:SI 2 "nonmemory_operand" "rJ,K,U")))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])]) + +(define_insn "addsi3_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (plus:SI (match_operand:SI 1 "register_operand" "%0,r,r") (match_operand:SI 2 "nonmemory_operand" "rJ,K,U"))) (clobber (reg:CC CC_REGNUM))] - "" "@ add %2,%0 @@ -566,8 +572,17 @@ ;; ---------------------------------------------------------------------- ;; SUBTRACT INSTRUCTIONS ;; ---------------------------------------------------------------------- +(define_insn_and_split "subsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (minus:SI (match_operand:SI 1 "register_operand" "0,r") + (match_operand:SI 2 "register_operand" "r,0")))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])]) -(define_insn "subsi3" +(define_insn "subsi3_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r,r") (minus:SI (match_operand:SI 1 "register_operand" "0,r") (match_operand:SI 2 "register_operand" "r,0"))) @@ -578,7 +593,16 @@ subr %1,%0" [(set_attr "length" "2,2")]) -(define_insn "negsi2" +(define_insn_and_split "negsi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (neg:SI (match_operand:SI 1 "register_operand" "0")))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (neg:SI (match_dup 1))) + (clobber (reg:CC CC_REGNUM))])]) + +(define_insn "negsi2_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r") (neg:SI (match_operand:SI 1 "register_operand" "0"))) (clobber (reg:CC CC_REGNUM))] @@ -703,7 +727,7 @@ (match_dup 2))) (clobber (reg:CC CC_REGNUM))] "TARGET_V850E_UP" - "sxh %0\n\tdivh %2,%0,%3" + "sxh %0\\n\\tdivh %2,%0,%3" [(set_attr "length" "6") (set_attr "type" "div")]) @@ -719,7 +743,7 @@ (match_dup 2))) (clobber (reg:CC CC_REGNUM))] "TARGET_V850E_UP" - "zxh %0\n\tdivhu %2,%0,%3" + "zxh %0\\n\\ndivhu %2,%0,%3" [(set_attr "length" "6") (set_attr "type" "div")]) @@ -785,12 +809,22 @@ [(set_attr "length" "4") (set_attr "type" "bit1")]) -(define_insn "andsi3" +(define_insn_and_split "andsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (and:SI (match_operand:SI 1 "register_operand" "%0,0,r") + (match_operand:SI 2 "nonmemory_operand" "r,I,M")))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])]) + +(define_insn "andsi3_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (and:SI (match_operand:SI 1 "register_operand" "%0,0,r") (match_operand:SI 2 "nonmemory_operand" "r,I,M"))) (clobber (reg:CC CC_REGNUM))] - "" + "reload_completed" "@ and %2,%0 and %.,%0 @@ -860,7 +894,17 @@ [(set_attr "length" "4") (set_attr "type" "bit1")]) -(define_insn "iorsi3" +(define_insn_and_split "iorsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (ior:SI (match_operand:SI 1 "register_operand" "%0,0,r") + (match_operand:SI 2 "nonmemory_operand" "r,I,M")))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])]) + +(define_insn "iorsi3_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (ior:SI (match_operand:SI 1 "register_operand" "%0,0,r") (match_operand:SI 2 "nonmemory_operand" "r,I,M"))) @@ -935,7 +979,17 @@ [(set_attr "length" "4") (set_attr "type" "bit1")]) -(define_insn "xorsi3" +(define_insn_and_split "xorsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (xor:SI (match_operand:SI 1 "register_operand" "%0,0,r") + (match_operand:SI 2 "nonmemory_operand" "r,I,M")))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])]) + +(define_insn "xorsi3_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (xor:SI (match_operand:SI 1 "register_operand" "%0,0,r") (match_operand:SI 2 "nonmemory_operand" "r,I,M"))) @@ -946,12 +1000,23 @@ xor %.,%0 xori %2,%1,%0" [(set_attr "length" "2,2,4")]) + ;; ---------------------------------------------------------------------- ;; NOT INSTRUCTIONS ;; ---------------------------------------------------------------------- -(define_insn "one_cmplsi2" +(define_insn_and_split "one_cmplsi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (not:SI (match_operand:SI 1 "register_operand" "r")))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (not:SI (match_dup 1))) + (clobber (reg:CC CC_REGNUM))])]) + + +(define_insn "one_cmplsi2_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r") (not:SI (match_operand:SI 1 "register_operand" "r"))) (clobber (reg:CC CC_REGNUM))] @@ -977,7 +1042,8 @@ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") (match_operand:SI 1 "immediate_operand" "n") (match_operand:SI 2 "immediate_operand" "n")) - (match_operand:SI 3 "register_operand" "r"))] + (match_operand:SI 3 "register_operand" "r")) + (clobber (reg:CC CC_REGNUM))] "TARGET_V850E3V5_UP" "bins %3, %2, %1, %0" [(set_attr "length" "4")]) @@ -986,20 +1052,46 @@ ;; Scc INSTRUCTIONS ;; ----------------------------------------------------------------- -(define_insn "*setcc" +(define_insn_and_split "*cbranchsi4_insn" + [(set (pc) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "reg_or_int5_operand" "rJ")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" + "#" + "reload_completed" + [(set (reg:CC CC_REGNUM) + (compare:CC (match_dup 1) (match_dup 2))) + (set (pc) + (if_then_else (match_op_dup 0 + [(reg:CC CC_REGNUM) (const_int 0)]) + (label_ref (match_dup 3)) + (pc)))] + "") + + +(define_insn_and_split "cstoresi4" [(set (match_operand:SI 0 "register_operand" "=r") (match_operator:SI 1 "comparison_operator" - [(cc0) (const_int 0)]))] + [(match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "reg_or_int5_operand" "rJ")]))] "" - "setf %c1,%0" - [(set_attr "length" "4")]) + "#" + "reload_completed" + [(set (reg:CC CC_REGNUM) + (compare:CC (match_dup 2) (match_dup 3))) + (set (match_dup 0) (match_op_dup 1 + [(reg:CC CC_REGNUM) (const_int 0)]))] + "") -(define_insn "setf_insn" +(define_insn "*setcc_insn" [(set (match_operand:SI 0 "register_operand" "=r") - (match_operator:SI 1 "comparison_operator" - [(reg:CC CC_REGNUM) (const_int 0)]))] - "" - "setf %b1,%0" + (match_operator:SI 1 "comparison_operator" + [(reg:CC CC_REGNUM) (const_int 0)]))] + "reload_completed" + "setf %c1,%0" [(set_attr "length" "4")]) (define_insn "set_z_insn" @@ -1065,12 +1157,6 @@ } }) -;; ??? Clobbering the condition codes is overkill. - -;; ??? We sometimes emit an unnecessary compare instruction because the -;; condition codes may have already been set by an earlier instruction, -;; but we have no code here to avoid the compare if it is unnecessary. - (define_insn "movsicc_normal_cc" [(set (match_operand:SI 0 "register_operand" "=r") (if_then_else:SI @@ -1078,7 +1164,7 @@ [(reg:CC CC_REGNUM) (const_int 0)]) (match_operand:SI 2 "reg_or_int5_operand" "rJ") (match_operand:SI 3 "reg_or_0_operand" "rI")))] - "(TARGET_V850E_UP)" + "reload_completed && (TARGET_V850E_UP)" "cmov %c1,%2,%z3,%0"; [(set_attr "length" "6")]) @@ -1089,11 +1175,11 @@ [(reg:CC CC_REGNUM) (const_int 0)]) (match_operand:SI 2 "reg_or_0_operand" "rI") (match_operand:SI 3 "reg_or_int5_operand" "rJ")))] - "(TARGET_V850E_UP)" + "reload_completed && (TARGET_V850E_UP)" "cmov %C1,%3,%z2,%0" [(set_attr "length" "6")]) -(define_insn "*movsicc_normal" +(define_insn_and_split "*movsicc_normal" [(set (match_operand:SI 0 "register_operand" "=r") (if_then_else:SI (match_operator 1 "comparison_operator" @@ -1102,21 +1188,35 @@ (match_operand:SI 2 "reg_or_int5_operand" "rJ") (match_operand:SI 3 "reg_or_0_operand" "rI")))] "(TARGET_V850E_UP)" - "cmp %5,%4 ; cmov %c1,%2,%z3,%0" - [(set_attr "length" "6")]) + "#" + "reload_completed" + [(set (reg:CC CC_REGNUM) + (compare:CC (match_dup 4) (match_dup 5))) + (set (match_dup 0) + (if_then_else:SI (match_op_dup 1 + [(reg:CC CC_REGNUM) (const_int 0)]) + (match_dup 2) (match_dup 3)))]) -(define_insn "*movsicc_reversed" + +(define_insn_and_split "*movsicc_reversed" [(set (match_operand:SI 0 "register_operand" "=r") (if_then_else:SI (match_operator 1 "comparison_operator" [(match_operand:SI 4 "register_operand" "r") (match_operand:SI 5 "reg_or_int5_operand" "rJ")]) - (match_operand:SI 2 "reg_or_0_operand" "rI") - (match_operand:SI 3 "reg_or_int5_operand" "rJ")))] + (match_operand:SI 2 "reg_or_int5_operand" "rI") + (match_operand:SI 3 "reg_or_0_operand" "rJ")))] "(TARGET_V850E_UP)" - "cmp %5,%4 ; cmov %C1,%3,%z2,%0" - [(set_attr "length" "6")]) + "#" + "reload_completed" + [(set (reg:CC CC_REGNUM) + (compare:CC (match_dup 4) (match_dup 5))) + (set (match_dup 0) + (if_then_else:SI (match_op_dup 1 + [(reg:CC CC_REGNUM) (const_int 0)]) + (match_dup 2) (match_dup 3)))]) +;; We could expose the setting of the condition codes here. (define_insn "*movsicc_tst1" [(set (match_operand:SI 0 "register_operand" "=r") (if_then_else:SI @@ -1127,11 +1227,13 @@ (match_operand 3 "const_int_operand" "n")) (const_int 0)]) (match_operand:SI 4 "reg_or_int5_operand" "rJ") - (match_operand:SI 5 "reg_or_0_operand" "rI")))] + (match_operand:SI 5 "reg_or_0_operand" "rI"))) + (clobber (reg:CC CC_REGNUM))] "(TARGET_V850E_UP)" "tst1 %3,%2 ; cmov %c1,%4,%z5,%0" [(set_attr "length" "8")]) +;; We could expose the setting of the condition codes here. (define_insn "*movsicc_tst1_reversed" [(set (match_operand:SI 0 "register_operand" "=r") (if_then_else:SI @@ -1142,7 +1244,8 @@ (match_operand 3 "const_int_operand" "n")) (const_int 0)]) (match_operand:SI 4 "reg_or_0_operand" "rI") - (match_operand:SI 5 "reg_or_int5_operand" "rJ")))] + (match_operand:SI 5 "reg_or_int5_operand" "rJ"))) + (clobber (reg:CC CC_REGNUM))] "(TARGET_V850E_UP)" "tst1 %3,%2 ; cmov %C1,%5,%z4,%0" [(set_attr "length" "8")]) @@ -1152,6 +1255,9 @@ ;; second pattern by subsequent combining. As above, we must include the ;; comparison to avoid input reloads in an insn using cc0. +;; We could expose the setting of the condition codes here. +;; However, I haven't seen this pattern used, so I'm not going +;; to bother. (define_insn "*sasf" [(set (match_operand:SI 0 "register_operand" "=r") (ior:SI @@ -1235,7 +1341,8 @@ [(ashift:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "const_int_operand" "n")) (lshiftrt:SI (match_dup 1) - (match_operand:SI 3 "const_int_operand" "n"))]))] + (match_operand:SI 3 "const_int_operand" "n"))])) + (clobber (reg:CC CC_REGNUM))] "TARGET_V850E3V5_UP && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32)" "rotl %2, %1, %0" [(set_attr "length" "4")]) @@ -1246,7 +1353,8 @@ [(lshiftrt:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 3 "const_int_operand" "n")) (ashift:SI (match_dup 1) - (match_operand:SI 2 "const_int_operand" "n"))]))] + (match_operand:SI 2 "const_int_operand" "n"))])) + (clobber (reg:CC CC_REGNUM))] "TARGET_V850E3V5_UP && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32)" "rotl %2, %1, %0" [(set_attr "length" "4")]) @@ -1287,9 +1395,11 @@ } ) +;; Note the embedded arithmetic. That affects the condition codes! (define_insn "fix_loop_counter" [(unspec:SI [(match_operand:SI 0 "register_operand" "+r,!m") - (clobber (match_scratch:SI 1 "=X,r"))] UNSPEC_LOOP)] + (clobber (match_scratch:SI 1 "=X,r"))] UNSPEC_LOOP) + (clobber (reg:CC CC_REGNUM))] "TARGET_V850E3V5_UP && TARGET_LOOP" { switch (which_alternative) @@ -1349,68 +1459,52 @@ ;; Conditional jump instructions -(define_insn "*branch_normal" +(define_insn_and_split "*cbranchsi4_insn" [(set (pc) - (if_then_else (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 0 "" "")) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "reg_or_int5_operand" "rJ")]) + (label_ref (match_operand 3 "" "")) (pc)))] "" -{ - if (get_attr_length (insn) == 2) - return "b%b1 %l0"; - if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4) - return "b%b1 %l0"; - return "b%B1 .+6 ; jr %l0"; -} - [(set (attr "length") - (if_then_else (lt (abs (minus (match_dup 0) (pc))) - (const_int 256)) - (const_int 2) - (if_then_else (lt (abs (minus (match_dup 0) (pc))) - (const_int 65536)) - (const_int 4) - (const_int 6))))]) + "#" + "reload_completed" + [(set (reg:CC CC_REGNUM) + (compare:CC (match_dup 1) (match_dup 2))) + (set (pc) + (if_then_else (match_op_dup 0 + [(reg:CC CC_REGNUM) (const_int 0)]) + (label_ref (match_dup 3)) + (pc)))] + "") -(define_insn "*branch_invert" +(define_insn "*branch_normal" [(set (pc) (if_then_else (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" -{ - if (get_attr_length (insn) == 2) - return "b%B1 %l0"; - - if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4) - return "b%B1 %l0"; - - return "b%b1 .+6 ; jr %l0"; -} - [(set (attr "length") - (if_then_else (lt (abs (minus (match_dup 0) (pc))) - (const_int 256)) - (const_int 2) - (if_then_else (lt (abs (minus (match_dup 0) (pc))) - (const_int 65536)) - (const_int 4) - (const_int 6))))]) - -(define_insn "branch_z_normal" - [(set (pc) - (if_then_else (match_operand 1 "v850_float_z_comparison_operator" "") + [(reg CC_REGNUM) (const_int 0)]) (label_ref (match_operand 0 "" "")) (pc)))] - "TARGET_V850E2V3_UP" + "reload_completed" { + bool nzmode = GET_MODE (XEXP (operands[1], 0)) == CCNZmode; if (get_attr_length (insn) == 2) - return "bz %l0"; - + { + if (nzmode) + return "b%d1 %l0"; + else + return "b%b1 %l0"; + } if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4) - return "bz %l0"; - - return "bnz 1f ; jr %l0 ; 1:"; + { + if (nzmode) + return "b%d1 %l0"; + else + return "b%b1 %l0"; + } + if (nzmode) + return "b%D1 .+6 ; jr %l0"; + else + return "b%B1 .+6 ; jr %l0"; } [(set (attr "length") (if_then_else (lt (abs (minus (match_dup 0) (pc))) @@ -1421,68 +1515,36 @@ (const_int 4) (const_int 6))))]) -(define_insn "*branch_z_invert" +(define_insn "*branch_invert" [(set (pc) - (if_then_else (match_operand 1 "v850_float_z_comparison_operator" "") + (if_then_else (match_operator 1 "comparison_operator" + [(reg CC_REGNUM) (const_int 0)]) (pc) (label_ref (match_operand 0 "" ""))))] - "TARGET_V850E2V3_UP" + "reload_completed" { - if (get_attr_length (insn) == 2) - return "bnz %l0"; - - if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4) - return "bnz %l0"; - - return "bz 1f ; jr %l0 ; 1:"; -} - [(set (attr "length") - (if_then_else (lt (abs (minus (match_dup 0) (pc))) - (const_int 256)) - (const_int 2) - (if_then_else (lt (abs (minus (match_dup 0) (pc))) - (const_int 65536)) - (const_int 4) - (const_int 6))))]) + bool nzmode = GET_MODE (XEXP (operands[1], 0)) == CCNZmode; -(define_insn "branch_nz_normal" - [(set (pc) - (if_then_else (match_operand 1 "v850_float_nz_comparison_operator" "") - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_V850E2V3_UP" -{ if (get_attr_length (insn) == 2) - return "bnz %l0"; - - if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4) - return "bnz %l0"; - - return "bz 1f ; jr %l0 ; 1:"; -} -[(set (attr "length") - (if_then_else (lt (abs (minus (match_dup 0) (pc))) - (const_int 256)) - (const_int 2) - (if_then_else (lt (abs (minus (match_dup 0) (pc))) - (const_int 65536)) - (const_int 4) - (const_int 6))))]) - -(define_insn "*branch_nz_invert" - [(set (pc) - (if_then_else (match_operand 1 "v850_float_nz_comparison_operator" "") - (pc) - (label_ref (match_operand 0 "" ""))))] - "TARGET_V850E2V3_UP" -{ - if (get_attr_length (insn) == 2) - return "bz %l0"; + { + if (nzmode) + return "b%D1 %l0"; + else + return "b%B1 %l0"; + } if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4) - return "bz %l0"; + { + if (nzmode) + return "b%D1 %l0"; + else + return "b%B1 %l0"; + } - return "bnz 1f ; jr %l0 ; 1:"; + if (nzmode) + return "b%d1 .+6 ; jr %l0"; + else + return "b%b1 .+6 ; jr %l0"; } [(set (attr "length") (if_then_else (lt (abs (minus (match_dup 0) (pc))) @@ -1602,6 +1664,7 @@ (define_insn "call_internal_short" [(call (mem:QI (match_operand:SI 0 "call_address_operand" "S,r")) (match_operand:SI 1 "general_operand" "g,g")) + (clobber (reg:CC CC_REGNUM)) (clobber (reg:SI 31))] "! TARGET_LONG_CALLS" { @@ -1620,6 +1683,7 @@ (define_insn "call_internal_long" [(call (mem:QI (match_operand:SI 0 "call_address_operand" "S,r")) (match_operand:SI 1 "general_operand" "g,g")) + (clobber (reg:CC CC_REGNUM)) (clobber (reg:SI 31))] "TARGET_LONG_CALLS" { @@ -1668,6 +1732,7 @@ [(set (match_operand 0 "" "=r,r") (call (mem:QI (match_operand:SI 1 "call_address_operand" "S,r")) (match_operand:SI 2 "general_operand" "g,g"))) + (clobber (reg:CC CC_REGNUM)) (clobber (reg:SI 31))] "! TARGET_LONG_CALLS" { @@ -1687,6 +1752,7 @@ [(set (match_operand 0 "" "=r,r") (call (mem:QI (match_operand:SI 1 "call_address_operand" "S,r")) (match_operand:SI 2 "general_operand" "g,g"))) + (clobber (reg:CC CC_REGNUM)) (clobber (reg:SI 31))] "TARGET_LONG_CALLS" { @@ -1719,6 +1785,7 @@ ;; EXTEND INSTRUCTIONS ;; ---------------------------------------------------------------------- +;; We only need the CC clobber because of the andi alternative (define_insn "*zero_extendhisi2_v850e" [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") (zero_extend:SI @@ -1791,8 +1858,7 @@ (define_insn "*extendhisi_insn" [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,Q,m"))) - (clobber (reg:CC CC_REGNUM))] + (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,Q,m")))] "(TARGET_V850E_UP)" "@ sxh %0 @@ -1822,8 +1888,7 @@ (define_insn "*extendqisi_insn" [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,Q,m"))) - (clobber (reg:CC CC_REGNUM))] + (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,Q,m")))] "(TARGET_V850E_UP)" "@ sxb %0 @@ -1853,7 +1918,18 @@ ;; SHIFTS ;; ---------------------------------------------------------------------- -(define_insn "ashlsi3" +(define_insn_and_split "ashlsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (ashift:SI + (match_operand:SI 1 "register_operand" "0,0") + (match_operand:SI 2 "nonmemory_operand" "r,N")))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])]) + +(define_insn "ashlsi3_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r,r") (ashift:SI (match_operand:SI 1 "register_operand" "0,0") @@ -1865,7 +1941,7 @@ shl %2,%0" [(set_attr "length" "4,2")]) -(define_insn "ashlsi3_v850e2" +(define_insn "ashlsi3_v850e2_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r") (ashift:SI (match_operand:SI 1 "register_operand" "r") @@ -1875,7 +1951,18 @@ "shl %2,%1,%0" [(set_attr "length" "4")]) -(define_insn "lshrsi3" +(define_insn_and_split "lshrsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (lshiftrt:SI + (match_operand:SI 1 "register_operand" "0,0") + (match_operand:SI 2 "nonmemory_operand" "r,N")))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])]) + +(define_insn "lshrsi3_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r,r") (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0") @@ -1887,7 +1974,7 @@ shr %2,%0" [(set_attr "length" "4,2")]) -(define_insn "lshrsi3_v850e2" +(define_insn "lshrsi3_v850e2_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r") (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") @@ -1897,7 +1984,18 @@ "shr %2,%1,%0" [(set_attr "length" "4")]) -(define_insn "ashrsi3" +(define_insn_and_split "ashrsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (ashiftrt:SI + (match_operand:SI 1 "register_operand" "0,0") + (match_operand:SI 2 "nonmemory_operand" "r,N")))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])]) + +(define_insn "ashrsi3_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r,r") (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0") @@ -1909,7 +2007,7 @@ sar %2,%0" [(set_attr "length" "4,2")]) -(define_insn "ashrsi3_v850e2" +(define_insn "ashrsi3_v850e2_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r") (ashiftrt:SI (match_operand:SI 1 "register_operand" "r") @@ -2279,6 +2377,8 @@ ;; ---------------- special insns ;; +;; reciprocal + ;; Generic code demands that the recip and rsqrt named patterns ;; have precisely one operand. So that's what we expose in the ;; expander via the strange UNSPEC. However, those expanders @@ -2417,7 +2517,7 @@ [(set (reg:CC_FPU_LE FCC_REGNUM) (compare:CC_FPU_LE (match_operand:SF 0 "register_operand" "r") (match_operand:SF 1 "register_operand" "r")))] - "TARGET_USE_FPU" + "reload_completed && TARGET_USE_FPU" "cmpf.s le, %z0, %z1" [(set_attr "length" "4") (set_attr "type" "fpu")]) @@ -2426,7 +2526,7 @@ [(set (reg:CC_FPU_LT FCC_REGNUM) (compare:CC_FPU_LT (match_operand:SF 0 "register_operand" "r") (match_operand:SF 1 "register_operand" "r")))] - "TARGET_USE_FPU" + "reload_completed && TARGET_USE_FPU" "cmpf.s lt, %z0, %z1" [(set_attr "length" "4") (set_attr "type" "fpu")]) @@ -2435,7 +2535,7 @@ [(set (reg:CC_FPU_GE FCC_REGNUM) (compare:CC_FPU_GE (match_operand:SF 0 "register_operand" "r") (match_operand:SF 1 "register_operand" "r")))] - "TARGET_USE_FPU" + "reload_completed && TARGET_USE_FPU" "cmpf.s le, %z1, %z0" [(set_attr "length" "4") (set_attr "type" "fpu")]) @@ -2444,7 +2544,7 @@ [(set (reg:CC_FPU_GT FCC_REGNUM) (compare:CC_FPU_GT (match_operand:SF 0 "register_operand" "r") (match_operand:SF 1 "register_operand" "r")))] - "TARGET_USE_FPU" + "reload_completed && TARGET_USE_FPU" "cmpf.s lt, %z1, %z0" [(set_attr "length" "4") (set_attr "type" "fpu")]) @@ -2453,7 +2553,7 @@ [(set (reg:CC_FPU_EQ FCC_REGNUM) (compare:CC_FPU_EQ (match_operand:SF 0 "register_operand" "r") (match_operand:SF 1 "register_operand" "r")))] - "TARGET_USE_FPU" + "reload_completed && TARGET_USE_FPU" "cmpf.s eq, %z0, %z1" [(set_attr "length" "4") (set_attr "type" "fpu")]) @@ -2464,7 +2564,7 @@ [(set (reg:CC_FPU_LE FCC_REGNUM) (compare:CC_FPU_LE (match_operand:DF 0 "even_reg_operand" "r") (match_operand:DF 1 "even_reg_operand" "r")))] - "TARGET_USE_FPU" + "reload_completed && TARGET_USE_FPU" "cmpf.d le, %z0, %z1" [(set_attr "length" "4") (set_attr "type" "fpu")]) @@ -2473,7 +2573,7 @@ [(set (reg:CC_FPU_LT FCC_REGNUM) (compare:CC_FPU_LT (match_operand:DF 0 "even_reg_operand" "r") (match_operand:DF 1 "even_reg_operand" "r")))] - "TARGET_USE_FPU" + "reload_completed && TARGET_USE_FPU" "cmpf.d lt, %z0, %z1" [(set_attr "length" "4") (set_attr "type" "fpu")]) @@ -2482,7 +2582,7 @@ [(set (reg:CC_FPU_GE FCC_REGNUM) (compare:CC_FPU_GE (match_operand:DF 0 "even_reg_operand" "r") (match_operand:DF 1 "even_reg_operand" "r")))] - "TARGET_USE_FPU" + "reload_completed && TARGET_USE_FPU" "cmpf.d le, %z1, %z0" [(set_attr "length" "4") (set_attr "type" "fpu")]) @@ -2491,7 +2591,7 @@ [(set (reg:CC_FPU_GT FCC_REGNUM) (compare:CC_FPU_GT (match_operand:DF 0 "even_reg_operand" "r") (match_operand:DF 1 "even_reg_operand" "r")))] - "TARGET_USE_FPU" + "reload_completed && TARGET_USE_FPU" "cmpf.d lt, %z1, %z0" [(set_attr "length" "4") (set_attr "type" "fpu")]) @@ -2500,7 +2600,7 @@ [(set (reg:CC_FPU_EQ FCC_REGNUM) (compare:CC_FPU_EQ (match_operand:DF 0 "even_reg_operand" "r") (match_operand:DF 1 "even_reg_operand" "r")))] - "TARGET_USE_FPU" + "reload_completed && TARGET_USE_FPU" "cmpf.d eq, %z0, %z1" [(set_attr "length" "4") (set_attr "type" "fpu")]) @@ -2512,7 +2612,8 @@ (define_insn "trfsr" [(set (match_operand 0 "" "") (match_operand 1 "" ""))] - "TARGET_USE_FPU + "reload_completed + && TARGET_USE_FPU && GET_MODE(operands[0]) == GET_MODE(operands[1]) && GET_CODE(operands[0]) == REG && REGNO (operands[0]) == CC_REGNUM && GET_CODE(operands[1]) == REG && REGNO (operands[1]) == FCC_REGNUM @@ -2668,7 +2769,8 @@ ;; Initialize an interrupt function. Do not depend on TARGET_PROLOG_FUNCTION. (define_insn "callt_save_interrupt" - [(unspec_volatile [(const_int 0)] 2)] + [(unspec_volatile [(const_int 0)] 2) + (clobber (reg:CC CC_REGNUM))] "(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT" ;; The CALLT instruction stores the next address of CALLT to CTPC register ;; without saving its previous value. So if the interrupt handler @@ -2689,7 +2791,8 @@ [(set_attr "length" "26")]) (define_insn "callt_return_interrupt" - [(unspec_volatile [(const_int 0)] 3)] + [(unspec_volatile [(const_int 0)] 3) + (clobber (reg:CC CC_REGNUM))] "(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT" "callt ctoff(__callt_return_interrupt)" [(set_attr "length" "2")]) @@ -2700,7 +2803,8 @@ (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 4)) (set (mem:SI (plus:SI (reg:SI 3) (const_int -12))) (reg:SI 1)) (set (mem:SI (plus:SI (reg:SI 3) (const_int -8))) (reg:SI 10)) - (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 11))] + (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 11)) + (clobber (reg:CC CC_REGNUM))] "" { if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS) @@ -2733,7 +2837,8 @@ (set (reg:SI 10) (mem:SI (plus:SI (reg:SI 3) (const_int 12)))) (set (reg:SI 1) (mem:SI (plus:SI (reg:SI 3) (const_int 8)))) (set (reg:SI 4) (mem:SI (plus:SI (reg:SI 3) (const_int 4)))) - (set (reg:SI 30) (mem:SI (reg:SI 3)))] + (set (reg:SI 30) (mem:SI (reg:SI 3))) + (clobber (reg:CC CC_REGNUM))] "" { if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS) @@ -2763,13 +2868,15 @@ ;; insns this complicated. (define_insn "callt_save_all_interrupt" - [(unspec_volatile [(const_int 0)] 0)] + [(unspec_volatile [(const_int 0)] 0) + (clobber (reg:CC CC_REGNUM))] "(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT" "callt ctoff(__callt_save_all_interrupt)" [(set_attr "length" "2")]) (define_insn "save_all_interrupt" - [(unspec_volatile [(const_int 0)] 0)] + [(unspec_volatile [(const_int 0)] 0) + (clobber (reg:CC CC_REGNUM))] "" { if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS) @@ -2844,10 +2951,12 @@ [(set (attr "length") (if_then_else (match_test "TARGET_LONG_CALLS") (const_int 4) - (const_int 62)))]) + (const_int 62) + ))]) (define_insn "_save_all_interrupt" - [(unspec_volatile [(const_int 0)] 0)] + [(unspec_volatile [(const_int 0)] 0) + (clobber (reg:CC CC_REGNUM))] "TARGET_V850 && ! TARGET_LONG_CALLS" "jarl __save_all_interrupt,r10" [(set_attr "length" "4")]) @@ -2859,13 +2968,15 @@ ;; insns this complicated. (define_insn "callt_restore_all_interrupt" - [(unspec_volatile [(const_int 0)] 1)] + [(unspec_volatile [(const_int 0)] 1) + (clobber (reg:CC CC_REGNUM))] "(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT" "callt ctoff(__callt_restore_all_interrupt)" [(set_attr "length" "2")]) (define_insn "restore_all_interrupt" - [(unspec_volatile [(const_int 0)] 1)] + [(unspec_volatile [(const_int 0)] 1) + (clobber (reg:CC CC_REGNUM))] "" { if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS) @@ -2942,7 +3053,8 @@ ))]) (define_insn "_restore_all_interrupt" - [(unspec_volatile [(const_int 0)] 1)] + [(unspec_volatile [(const_int 0)] 1) + (clobber (reg:CC CC_REGNUM))] "TARGET_V850 && ! TARGET_LONG_CALLS" "jarl __restore_all_interrupt,r10" [(set_attr "length" "4")]) -- 2.30.2