> On Jun 20, 2018, at 1:16 AM, Jeff Law <l...@redhat.com> wrote:
>
> On 06/19/2018 12:55 PM, Paul Koning wrote:
>> Gentlepeople,
>>
>> I have a two-operand divide instruction that takes a double length dividend
>> in a register pair, and produces the quotient in the first register and
>> remainder in the second.
>>
>> How do I write a divmod pattern for that? The quotient is easy enough, I
>> write a match_operand for that register and a matching constraint ("0") for
>> the input dividend. But what about the remainder? The remainder appears in
>> a register that isn't explicitly mentioned in the RTL (it's the regnum one
>> higher than the quotient, or if you like, the second subreg of the input
>> (dividend) register.
> You can generally allocate double-sized registers with appropriate
> constraints and the like. And you could use matching constraints,
> perhaps with subregs, but in the end, ewwwww.
>
>>
>> I can make it a define_expand that adds a move from the remainder register
>> into a new register which is the output operand, and count on the optimizer
>> to optimize away that move. Is that the best answer? The current "mod"
>> pattern does that, and I could keep that approach.
> But this would generally be better I think. I'd expect the move to be
> optimized away the vast majority of the time.
Thanks. I looked at some others, like M68k, the difference there is that the
mod result goes to an explicitly named register in the machine instruction.
Here's what I ended up with; it seems to work even though it doesn't match
precisely what the documentation seems to call for.
(define_expand "divmodhi4"
[(parallel
[(set (subreg:HI (match_dup 1) 0)
(div:HI (match_operand:SI 1 "register_operand" "0")
(match_operand:HI 2 "general_operand" "g")))
(set (subreg:HI (match_dup 1) 2)
(mod:HI (match_dup 1) (match_dup 2)))])
(set (match_operand:HI 0 "register_operand" "=r")
(subreg:HI (match_dup 1) 0))
(set (match_operand:HI 3 "register_operand" "=r")
(subreg:HI (match_dup 1) 2))]
"TARGET_40_PLUS"
"")
; and then the actual final instruction:
(define_insn "divmodhi4_nocc"
[(set (subreg:HI (match_operand:SI 0 "register_operand" "=r,r") 0)
(div:HI (match_operand:SI 1 "register_operand" "0,0")
(match_operand:HI 2 "general_operand" "rR,Qi")))
(set (subreg:HI (match_dup 1) 2)
(mod:HI (match_dup 1) (match_dup 2)))
(clobber (reg:CC CC_REGNUM))]
"TARGET_40_PLUS"
"div %2,%0"
[(set_attr "length" "2,4")])
paul