diff options
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/sh/sh.c | 8 | ||||
-rw-r--r-- | gcc/config/sh/sh.md | 18 |
2 files changed, 24 insertions, 2 deletions
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 67215029155..d727a678638 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -346,7 +346,8 @@ print_operand (stream, x, code) { case '.': if (final_sequence - && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))) + && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)) + && get_attr_length (XVECEXP (final_sequence, 0, 1))) fprintf (stream, ASSEMBLER_DIALECT ? "/s" : ".s"); break; case ',': @@ -3212,6 +3213,11 @@ gen_far_branch (bp) JUMP_LABEL (jump) = bp->far_label; if (! invert_jump (insn, label, 1)) abort (); + (emit_insn_after + (gen_stuff_delay_slot + (GEN_INT (INSN_UID (XEXP (SET_SRC (PATTERN (jump)), 0))), + GEN_INT (recog_memoized (insn) == CODE_FOR_branch_false)), + insn)); /* Prevent reorg from undoing our splits. */ gen_block_redirect (jump, bp->address += 2, 2); } diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index aa64bf5cb81..7016e74ec48 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -696,6 +696,10 @@ (eq_attr "length" "2") (const_string "yes") ] (const_string "no"))) +(define_attr "cond_delay_slot" "yes,no" + (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes") + ] (const_string "no"))) + (define_attr "is_sfunc" "" (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0))) @@ -738,7 +742,7 @@ (define_delay (and (eq_attr "type" "cbranch") (ne (symbol_ref "TARGET_SH2") (const_int 0))) - [(eq_attr "in_delay_slot" "yes") (eq_attr "in_delay_slot" "yes") (nil)]) + [(eq_attr "in_delay_slot" "yes") (eq_attr "cond_delay_slot" "yes") (nil)]) ;; ------------------------------------------------------------------------- ;; SImode signed integer comparisons @@ -5141,6 +5145,18 @@ "TARGET_SH1" "" [(set_attr "length" "0")]) + +;; This one is used to preemt an insn from beyond the bra / braf / jmp +;; being pulled into the delay slot of a condbranch that has been made to +;; jump around the unconditional jump because it was out of range. +(define_insn "stuff_delay_slot" + [(set (pc) + (unspec [(match_operand 0 "const_int_operand" "") (pc)] UNSPEC_BBR)) + (set (reg:SI T_REG) (match_operand 1 "const_int_operand" ""))] + "TARGET_SH1" + "" + [(set_attr "length" "0") + (set_attr "cond_delay_slot" "yes")]) ;; Conditional branch insns |