Richard Sandiford <richard.sandif...@arm.com> writes:
>> @@ -758,6 +781,58 @@ (define_expand "cbranchcc4"
>>    ""
>>  )
>>  
>> +;; Emit a `CB<cond> (register)` or `CB<cond> (immediate)` instruction.
>> +(define_insn "aarch64_cb<GPI:mode>"
>> +  [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
>> +                        [(match_operand:GPI 1 "register_operand")
>> +                         (match_operand:GPI 2 "aarch64_cb_operand")])
>> +                       (label_ref (match_operand 3))
>> +                       (pc)))]
>> +  "TARGET_CMPBR"
>> +  "cb%m0\\t%<w>1, %<w>2, %l3";
>> +  [(set_attr "type" "branch")
>> +   (set (attr "length")
>> +    (if_then_else (and (ge (minus (match_dup 3) (pc))
>> +                           (const_int BRANCH_LEN_N_1Kib))
>> +                       (lt (minus (match_dup 3) (pc))
>> +                           (const_int BRANCH_LEN_P_1Kib)))
>> +                  (const_int 4)
>> +                  (const_int 8)))
>> +   (set (attr "far_branch")
>> +    (if_then_else (and (ge (minus (match_dup 3) (pc))
>> +                           (const_int BRANCH_LEN_N_1Kib))
>> +                       (lt (minus (match_dup 3) (pc))
>> +                           (const_int BRANCH_LEN_P_1Kib)))
>> +                  (const_string "no")
>> +                  (const_string "yes")))]
>> +)
>> +
>> +;; Emit a `CBB<cond> (register)` or `CBH<cond> (register)` instruction.
>> +(define_insn "aarch64_cb<SHORT:mode>"
>> +  [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
>> +                        [(match_operand:SHORT 1 "register_operand")
>> +                         (match_operand:SHORT 2 
>> "aarch64_cb_short_operand")])
>> +                       (label_ref (match_operand 3))
>> +                       (pc)))]
>> +  "TARGET_CMPBR"
>> +  "cb<SHORT:cmpbr_suffix>%m0\\t%<w>1, %<w>2, %l3";
>> +  [(set_attr "type" "branch")
>> +   (set (attr "length")
>> +    (if_then_else (and (ge (minus (match_dup 3) (pc))
>> +                           (const_int BRANCH_LEN_N_1Kib))
>> +                       (lt (minus (match_dup 3) (pc))
>> +                           (const_int BRANCH_LEN_P_1Kib)))
>> +                  (const_int 4)
>> +                  (const_int 8)))
>> +   (set (attr "far_branch")
>> +    (if_then_else (and (ge (minus (match_dup 3) (pc))
>> +                           (const_int BRANCH_LEN_N_1Kib))
>> +                       (lt (minus (match_dup 3) (pc))
>> +                           (const_int BRANCH_LEN_P_1Kib)))
>> +                  (const_string "no")
>> +                  (const_string "yes")))]
>> +)
>> +
>
> [...]
>
> A slight wrinkle is that the CB<cc> immediate instruction requires CBLT
> rather than CBLE, etc.  IIRC, GCC canonicalises in the opposite
> direction, preferring LEU over LTU, etc.
>
> So I think we might need a custom version of aarch64_comparison_operator
> that checks whether the immediate is in the range [0, 63] for the "native"
> cmoparisons and an appropriate variant for the "non-native" comparisons
> (LE, GE, LEU, GEU).  The output asm section would then need to adjust
> the instruction accordingly before printing it out.

Sorry, I realised later than a match_operator along the lines I suggested
wouldn't work well in combination with the constraints.  We'd need to use
one constraint for the native operations and another constraint for the
emulated ones.

So perhaps the define_insns will need to use a code iterator instead
of a match_operator.  With a code iterator, the constraint string can
use a code attribute to choose the appropriate range.

Thanks,
Richard

Reply via email to