diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8683ed3291d..e7f9d749eef 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,16 @@ 2011-01-17 Richard Henderson + * config/rx/predicates.md (rx_constshift_operand): Use match_test. + (rx_restricted_mem_operand): New. + (rx_shift_operand): Use register_operand. + (rx_source_operand, rx_compare_operand): Likewise. + * config/rx/rx.md (addsi3_flags): New expander. + (adddi3): Rewrite as expander. + (adc_internal, *adc_flags, adddi3_internal): New patterns. + (subsi3_flags): New expander. + (subdi3): Rewrite as expander. + (sbb_internal, *sbb_flags, subdi3_internal): New patterns. + * config/rx/rx.c (RX_BUILTIN_SAT): Remove. (rx_init_builtins): Remove sat builtin. (rx_expand_builtin): Likewise. diff --git a/gcc/config/rx/predicates.md b/gcc/config/rx/predicates.md index 5ae5d2220e0..608fca5f925 100644 --- a/gcc/config/rx/predicates.md +++ b/gcc/config/rx/predicates.md @@ -37,19 +37,19 @@ ;; Only small integers or a value in a register are permitted. (define_predicate "rx_shift_operand" - (match_code "const_int,reg") - { - if (CONST_INT_P (op)) - return IN_RANGE (INTVAL (op), 0, 31); - return true; - } + (ior (match_operand 0 "register_operand") + (and (match_code "const_int") + (match_test "IN_RANGE (INTVAL (op), 0, 31)"))) ) (define_predicate "rx_constshift_operand" - (match_code "const_int") - { - return IN_RANGE (INTVAL (op), 0, 31); - } + (and (match_code "const_int") + (match_test "IN_RANGE (INTVAL (op), 0, 31)")) +) + +(define_predicate "rx_restricted_mem_operand" + (and (match_code "mem") + (match_test "rx_is_restricted_memory_address (XEXP (op, 0), mode)")) ) ;; Check that the operand is suitable as the source operand @@ -57,20 +57,9 @@ ;; and a restricted subset of memory addresses are allowed. (define_predicate "rx_source_operand" - (match_code "const_int,const_double,const,symbol_ref,label_ref,reg,mem") - { - if (CONSTANT_P (op)) - return rx_is_legitimate_constant (op); - - if (! MEM_P (op)) - return true; - - /* Do not allow size conversions whilst accessing memory. */ - if (GET_MODE (op) != mode) - return false; - - return rx_is_restricted_memory_address (XEXP (op, 0), mode); - } + (ior (match_operand 0 "register_operand") + (match_operand 0 "immediate_operand") + (match_operand 0 "rx_restricted_mem_operand")) ) ;; Check that the operand is suitable as the source operand @@ -79,16 +68,8 @@ ;; CONST_INTs are not. (define_predicate "rx_compare_operand" - (match_code "subreg,reg,mem") - { - if (GET_CODE (op) == SUBREG) - return REG_P (XEXP (op, 0)); - - if (! MEM_P (op)) - return true; - - return rx_is_restricted_memory_address (XEXP (op, 0), mode); - } + (ior (match_operand 0 "register_operand") + (match_operand 0 "rx_restricted_mem_operand")) ) ;; Return true if OP is a store multiple operation. This looks like: diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md index a3db92c0ad5..d8cd66d63de 100644 --- a/gcc/config/rx/rx.md +++ b/gcc/config/rx/rx.md @@ -988,17 +988,127 @@ (set_attr "length" "2,2,2,3,4,5,6,2,3,3,4,5,6,5")] ) -(define_insn "adddi3" - [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r") - (plus:DI (match_operand:DI 1 "register_operand" "%0,0,0,0,0,0") - (match_operand:DI 2 "rx_source_operand" - "r,Sint08,Sint16,Sint24,i,Q"))) +;; A helper to expand the above with the CC_MODE filled in. +(define_expand "addsi3_flags" + [(parallel [(set (match_operand:SI 0 "register_operand") + (plus:SI (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "rx_source_operand"))) + (set (reg:CC_ZSC CC_REG) + (compare:CC_ZSC (plus:SI (match_dup 1) (match_dup 2)) + (const_int 0)))])] +) + +(define_insn "adc_internal" + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r") + (plus:SI + (plus:SI + (ltu:SI (reg:CC CC_REG) (const_int 0)) + (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")) + (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q"))) + (clobber (reg:CC CC_REG))] + "reload_completed" + "adc %2,%0" + [(set_attr "timings" "11,11,11,11,11,33") + (set_attr "length" "3,4,5,6,7,6")] +) + +(define_insn "*adc_flags" + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r") + (plus:SI + (plus:SI + (ltu:SI (reg:CC CC_REG) (const_int 0)) + (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")) + (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q"))) + (set (reg CC_REG) + (compare + (plus:SI + (plus:SI + (ltu:SI (reg:CC CC_REG) (const_int 0)) + (match_dup 1)) + (match_dup 2)) + (const_int 0)))] + "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)" + "adc %2,%0" + [(set_attr "timings" "11,11,11,11,11,33") + (set_attr "length" "3,4,5,6,7,6")] +) + +(define_expand "adddi3" + [(set (match_operand:DI 0 "register_operand" "") + (plus:DI (match_operand:DI 1 "register_operand" "") + (match_operand:DI 2 "rx_source_operand" "")))] + "" +{ + rtx op0l, op0h, op1l, op1h, op2l, op2h; + + op0l = gen_lowpart (SImode, operands[0]); + op1l = gen_lowpart (SImode, operands[1]); + op2l = gen_lowpart (SImode, operands[2]); + op0h = gen_highpart (SImode, operands[0]); + op1h = gen_highpart (SImode, operands[1]); + op2h = gen_highpart_mode (SImode, DImode, operands[2]); + + emit_insn (gen_adddi3_internal (op0l, op0h, op1l, op2l, op1h, op2h)); + DONE; +}) + +(define_insn_and_split "adddi3_internal" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "rx_source_operand" "riQ"))) + (set (match_operand:SI 1 "register_operand" "=r") + (plus:SI + (plus:SI + (ltu:SI (plus:SI (match_dup 2) (match_dup 3)) (match_dup 2)) + (match_operand:SI 4 "register_operand" "%1")) + (match_operand:SI 5 "rx_source_operand" "riQ"))) + (clobber (match_scratch:SI 6 "=&r")) (clobber (reg:CC CC_REG))] "" - "add\t%L2, %L0\n\tadc\t%H2, %H0" - [(set_attr "timings" "22,22,22,22,22,44") - (set_attr "length" "5,7,9,11,13,11")] -) + "#" + "reload_completed" + [(const_int 0)] +{ + rtx op0l = operands[0]; + rtx op0h = operands[1]; + rtx op1l = operands[2]; + rtx op2l = operands[3]; + rtx op1h = operands[4]; + rtx op2h = operands[5]; + rtx scratch = operands[6]; + rtx x; + + if (reg_overlap_mentioned_p (op0l, op1h)) + { + emit_move_insn (scratch, op0l); + op1h = scratch; + if (reg_overlap_mentioned_p (op0l, op2h)) + op2h = scratch; + } + else if (reg_overlap_mentioned_p (op0l, op2h)) + { + emit_move_insn (scratch, op0l); + op2h = scratch; + } + + if (rtx_equal_p (op0l, op1l)) + ; + else if (rtx_equal_p (op0l, op2l)) + x = op1l, op1l = op2l, op2l = x; + emit_insn (gen_addsi3_flags (op0l, op1l, op2l)); + + if (rtx_equal_p (op0h, op1h)) + ; + else if (rtx_equal_p (op0h, op2h)) + x = op1h, op1h = op2h, op2h = x; + else + { + emit_move_insn (op0h, op1h); + op1h = op0h; + } + emit_insn (gen_adc_internal (op0h, op1h, op2h)); + DONE; +}) (define_insn "andsi3" [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r") @@ -1445,16 +1555,88 @@ (set_attr "length" "2,2,6,3,5")] ) -(define_insn "subdi3" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (minus:DI (match_operand:DI 1 "register_operand" "0,0") - (match_operand:DI 2 "rx_source_operand" "r,Q"))) +;; A helper to expand the above with the CC_MODE filled in. +(define_expand "subsi3_flags" + [(parallel [(set (match_operand:SI 0 "register_operand") + (minus:SI (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "rx_source_operand"))) + (set (reg:CC_ZSC CC_REG) + (compare:CC_ZSC (minus:SI (match_dup 1) (match_dup 2)) + (const_int 0)))])] +) + +(define_insn "sbb_internal" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (minus:SI + (minus:SI + (match_operand:SI 1 "register_operand" " 0,0") + (match_operand:SI 2 "rx_compare_operand" " r,Q")) + (geu:SI (reg:CC CC_REG) (const_int 0)))) + (clobber (reg:CC CC_REG))] + "reload_completed" + "sbb\t%2, %0" + [(set_attr "timings" "11,33") + (set_attr "length" "3,6")] +) + +(define_insn "*sbb_flags" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (minus:SI + (minus:SI + (match_operand:SI 1 "register_operand" " 0,0") + (match_operand:SI 2 "rx_compare_operand" " r,Q")) + (geu:SI (reg:CC CC_REG) (const_int 0)))) + (set (reg CC_REG) + (compare + (minus:SI + (minus:SI (match_dup 1) (match_dup 2)) + (geu:SI (reg:CC CC_REG) (const_int 0))) + (const_int 0)))] + "reload_completed" + "sbb\t%2, %0" + [(set_attr "timings" "11,33") + (set_attr "length" "3,6")] +) + +(define_expand "subdi3" + [(set (match_operand:DI 0 "register_operand" "") + (minus:DI (match_operand:DI 1 "register_operand" "") + (match_operand:DI 2 "rx_source_operand" "")))] + "" +{ + rtx op0l, op0h, op1l, op1h, op2l, op2h; + + op0l = gen_lowpart (SImode, operands[0]); + op1l = gen_lowpart (SImode, operands[1]); + op2l = gen_lowpart (SImode, operands[2]); + op0h = gen_highpart (SImode, operands[0]); + op1h = gen_highpart (SImode, operands[1]); + op2h = gen_highpart_mode (SImode, DImode, operands[2]); + + emit_insn (gen_subdi3_internal (op0l, op0h, op1l, op2l, op1h, op2h)); + DONE; +}) + +(define_insn_and_split "subdi3_internal" + [(set (match_operand:SI 0 "register_operand" "=&r,&r") + (minus:SI (match_operand:SI 2 "register_operand" " 0, r") + (match_operand:SI 3 "rx_source_operand" "rnQ, r"))) + (set (match_operand:SI 1 "register_operand" "= r, r") + (minus:SI + (minus:SI + (match_operand:SI 4 "register_operand" " 1, 1") + (match_operand:SI 5 "rx_compare_operand" " rQ,rQ")) + (geu:SI (match_dup 2) (match_dup 3)))) (clobber (reg:CC CC_REG))] "" - "sub\t%L2, %L0\n\tsbb\t%H2, %H0" - [(set_attr "timings" "22,44") - (set_attr "length" "5,11")] -) + "#" + "reload_completed" + [(const_int 0)] +{ + emit_insn (gen_subsi3_flags (operands[0], operands[2], operands[3])); + emit_insn (gen_sbb_internal (operands[1], operands[4], operands[5])); + DONE; +}) (define_insn "xorsi3" [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")