On 04/19/2011 02:52 AM, Denis Chertykov wrote:
> 2011/4/19 Georg-Johann Lay <a...@gjlay.de>:
>> How can add, sub etc. be split? This would need an explicit
>> representation of carry.
> 
> Yes.
> 
> Look at http://gcc.gnu.org/ml/gcc/2005-03/msg00871.html

Well, sort-of, but not really.

It gets a tad ugly, but have a look at the adddi3* patterns in
the mn10300 and rx ports.

In particular note how both the inputs and outputs to the insn
(not the expander) are all SImode, allowing for lower_subreg to
do its job.  The patterns are split post-reload -- some of that
is for scheduling, some of that simply makes computing the 
individual insn lengths significantly easier -- but you wouldn't
really have to do that for AVR.

For AVR things would become even trickier.  You might consider

(define_predicate "concat_operator"
  (match_code "concat"))

(define_insn "addsi3_qqqq"
  [(set (match_operand:QI 0 "register_operand" "=r")
        (truncate:QI
          (plus:SI
            (match_operator:SI 12 "concat_operator"
               [(match_operand:QI  4 "register_operand" "0")
                (match_operand:QI  5 "register_operand" "1")
                (match_operand:QI  6 "register_operand" "2")
                (match_operand:QI  7 "register_operand" "3")])
            (match_operator:SI 13 "concat_operator"
               [(match_operand:QI  8 "reg_or_0_operand" "rL")
                (match_operand:QI  9 "reg_or_0_operand" "rL")
                (match_operand:QI 10 "reg_or_0_operand" "rL")
                (match_operand:QI 11 "reg_or_0_operand" "rL")])))
   (set (match_operand:QI 1 "register_operand" "=r")
        (truncate:QI
          (lshiftrt:SI
            (plus:SI (match_dup 24) (match_dup 25))
            (const_int 8))))
   (set (match_operand:QI 2 "register_operand" "=r")
        (truncate:QI
          (lshiftrt:SI
            (plus:SI (match_dup 24) (match_dup 25))
            (const_int 16))))
   (set (match_operand:QI 3 "register_operand" "=r")
        (truncate:QI
          (lshiftrt:SI
            (plus:SI (match_dup 24) (match_dup 25))
            (const_int 24))))]
  ""
  "add %0,%Z8\;adc %1,%Z9\;adc %2,%Z10\;adc %3,%Z11"
  [(set_attr "length" "4")]
)

This may require a little bit of code inside combine to handle
CONCAT in a reasonable way, but that should be fairly minimal.

It may also want some more special case patterns and/or peep2s
to more efficiently handle constants, particularly considering
adiw and subic.  But I think it's at least worth investigating.


r~

Reply via email to