Daniel Towner <[EMAIL PROTECTED]> writes:
> Am I doing something fundamentally wrong with the way I am defining the
> length attribute, or the delay slot attribute?
No, I think this just The Way Things Are. I had a similar problem
with the h8sx delayed branch, and ended up reversing the delay slot
and branch if the branch turned out to be too long. Maybe a similar
thing will work for your port?
The full code is in config/h8300, but I've snipped the most relevant
parts below. And no, it's not pretty. ;) I don't think it's too bad
conceptually though. There was never any guarantee that the delay slot
insn would be emitted at the very end; if the target has a limited range
of conditional branch (as MIPS does) then we generate a branch around an
unconditional jump, and the delay slot goes in the branch-around instead.
Richard
(define_attr "length" ""
(cond [(eq_attr "type" "branch")
;; In a forward delayed branch, (pc) represents the end of the
;; delay sequence, not the end of the branch itself.
(if_then_else (and (ge (minus (match_dup 0) (pc))
(const_int -126))
(le (plus (minus (match_dup 0) (pc))
(symbol_ref "DELAY_SLOT_LENGTH (insn)"))
(const_int 126)))
(const_int 2)
...
;; Only allow jumps to have a delay slot if we think they might
;; be short enough. This is just an optimization: we don't know
;; for certain whether they will be or not.
(define_delay (and (eq_attr "delay_slot" "jump")
(eq (symbol_ref "get_attr_length (insn)") (const_int 2)))
[(eq_attr "can_delay" "yes")
(nil)
(nil)])
(define_insn "jump"
[(set (pc)
(label_ref (match_operand 0 "" "")))]
""
"*
{
if (final_sequence != 0)
{
if (get_attr_length (insn) == 2)
return \"bra/s %l0\";
else
{
/* The branch isn't short enough to use bra/s. Output the
branch and delay slot in their normal order.
If this is a backward branch, it will now be branching two
bytes further than previously thought. The length-based
test for bra vs. jump is very conservative though, so the
branch will still be within range. */
rtvec vec;
int seen;
vec = XVEC (final_sequence, 0);
final_sequence = 0;
final_scan_insn (RTVEC_ELT (vec, 1), asm_out_file, optimize, 1, &
seen);
final_scan_insn (RTVEC_ELT (vec, 0), asm_out_file, optimize, 1, &
seen);
INSN_DELETED_P (RTVEC_ELT (vec, 1)) = 1;
return \"\";
}
}
...
}"
[(set_attr "type" "branch")
(set (attr "delay_slot")
(if_then_else (ne (symbol_ref "TARGET_H8300SX") (const_int 0))
(const_string "jump")
(const_string "none")))
(set_attr "cc" "none")])