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")])

Reply via email to