+Mon Mar 3 19:47:26 2003 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.h (OVERRIDE_OPTIONS): Set default values for align_loops
+ and align_jumps if not set.
+ Force align_jumps to be at least 2.
+ When relaxing, force align_functions to be at least the maximum of
+ align_loops, align_jumps and 4.
+ * sh.c (find_barrier, barrier_align): Honour align_jumps_log.
+ (sh_loop_align): Honour align_loops_log.
+
+ * sh.md (length attribute): Use prev_nonnote_insn instead of PREV_INSN
+ to check for indirect_jump_scratch.
+ (indirect_jump_scratch): Add second set.
+ * sh.c (output_far_jump): Use prev_nonnote_insn instead of PREV_INSN
+ when looking for indirect_jump_scratch.
+ Extract scratch register taking new structure of indirect_jump_scratch
+ into account.
+ (gen_block_redirect): Set INSN_SCOPE for indirect_jump_scratch.
+
Mon Mar 3 19:07:21 CET 2003 Jan Hubicka <jh@suse.cz>
* calls.c (rtx_for_function_call): Take the address as an argument
const char *jump;
int far;
int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
+ rtx prev;
this.lab = gen_label_rtx ();
jump = "mov.l %O0,%1; jmp @%1";
}
/* If we have a scratch register available, use it. */
- if (GET_CODE (PREV_INSN (insn)) == INSN
- && INSN_CODE (PREV_INSN (insn)) == CODE_FOR_indirect_jump_scratch)
+ if (GET_CODE ((prev = prev_nonnote_insn (insn))) == INSN
+ && INSN_CODE (prev) == CODE_FOR_indirect_jump_scratch)
{
- this.reg = SET_DEST (PATTERN (PREV_INSN (insn)));
+ this.reg = SET_DEST (XVECEXP (PATTERN (prev), 0, 0));
if (REGNO (this.reg) == R0_REG && flag_pic && ! TARGET_SH2)
jump = "mov.l r1,@-r15; mova %O0,r0; mov.l @r0,r1; add r1,r0; mov.l @r15+,r1; jmp @%1";
output_asm_insn (jump, &this.lab);
{
if (num_mova)
num_mova--;
- if (barrier_align (next_real_insn (from)) == CACHE_LOG)
+ if (barrier_align (next_real_insn (from)) == align_jumps_log)
{
/* We have just passed the barrier in front of the
ADDR_DIFF_VEC, which is stored in found_barrier. Since
rtx insn = emit_insn_before (gen_indirect_jump_scratch
(reg, GEN_INT (INSN_UID (JUMP_LABEL (jump))))
, jump);
+ /* ??? We would like this to have the scope of the jump, but that
+ scope will change when a delay slot insn of an inner scope is added.
+ Hence, after delay slot scheduling, we'll have to expect
+ NOTE_INSN_BLOCK_END notes between the indirect_jump_scratch and
+ the jump. */
+
+ INSN_SCOPE (insn) = INSN_SCOPE (jump);
INSN_CODE (insn) = CODE_FOR_indirect_jump_scratch;
return insn;
}
return ((TARGET_SMALLCODE
|| ((unsigned) XVECLEN (pat, 1) * GET_MODE_SIZE (GET_MODE (pat))
<= (unsigned)1 << (CACHE_LOG - 2)))
- ? 1 << TARGET_SHMEDIA : CACHE_LOG);
+ ? 1 << TARGET_SHMEDIA : align_jumps_log);
}
if (TARGET_SMALLCODE)
return 0;
if (! TARGET_SH2 || ! optimize)
- return CACHE_LOG;
+ return align_jumps_log;
/* When fixing up pcloads, a constant table might be inserted just before
the basic block that ends with the barrier. Thus, we can't trust the
}
}
- return CACHE_LOG;
+ return align_jumps_log;
}
/* If we are inside a phony loop, almost any kind of label can turn up as the
|| recog_memoized (next) == CODE_FOR_consttable_2)
return 0;
- if (TARGET_SH5)
- return 3;
-
- return 2;
+ return align_loops_log;
}
/* Exported to toplev.c.
If relaxing, output the label and pseudo-ops used to link together
calls and the instruction which set the registers. */
-/* ??? This is unnecessary, and probably should be deleted. This makes
- the insn_addresses declaration above unnecessary. */
-
/* ??? The addresses printed by this routine for insns are nonsense for
insns which are inside of a sequence where none of the inner insns have
variable length. This is because the second pass of shorten_branches
flag_schedule_insns = 0; \
} \
\
+ if (align_loops == 0) \
+ align_loops = 1 << (TARGET_SH5 ? 3 : 2); \
+ if (align_jumps == 0) \
+ align_jumps = 1 << CACHE_LOG; \
+ else if (align_jumps <= 1) \
+ align_jumps = 2; \
+ \
/* Allocation boundary (in *bytes*) for the code of a function. \
SH1: 32 bit alignment is faster, because instructions are always \
fetched as a pair from a longword boundary. \
if (align_functions == 0) \
align_functions \
= TARGET_SMALLCODE ? FUNCTION_BOUNDARY/8 : (1 << CACHE_LOG); \
+ /* The linker relaxation code breaks when a function contains \
+ alignments that are larger than that at the start of a \
+ compilation unit. */ \
+ if (TARGET_RELAX) \
+ { \
+ int min_align \
+ = align_loops > align_jumps ? align_loops : align_jumps; \
+ \
+ /* Also take possible .long constants / mova tables int account. */\
+ if (min_align < 4) \
+ min_align = 4; \
+ if (align_functions < min_align) \
+ align_functions = min_align; \
+ } \
} while (0)
\f
/* Target machine storage layout. */
(eq_attr "type" "jump")
(cond [(eq_attr "med_branch_p" "yes")
(const_int 2)
- (and (eq (symbol_ref "GET_CODE (PREV_INSN (insn))")
+ (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))")
(symbol_ref "INSN"))
- (eq (symbol_ref "INSN_CODE (PREV_INSN (insn))")
+ (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))")
(symbol_ref "code_for_indirect_jump_scratch")))
(if_then_else (eq_attr "braf_branch_p" "yes")
(const_int 6)
;; This one has the additional purpose to record a possible scratch register
;; for the following branch.
+;; ??? Unfortunately, just setting the scratch register is not good enough,
+;; because the insn then might be deemed dead and deleted. And we can't
+;; make the use in the jump insn explicit because that would disable
+;; delay slot scheduling from the target.
(define_insn "indirect_jump_scratch"
[(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))]
+ (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))
+ (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
"TARGET_SH1"
""
[(set_attr "length" "0")])
[(set_attr "type" "jump")
(set_attr "needs_delay_slot" "yes")])
+;; ??? It would be much saner to explicitly use the scratch register
+;; in the jump insn, and have indirect_jump_scratch only set it,
+;; but fill_simple_delay_slots would refuse to do delay slot filling
+;; from the target then, as it uses simplejump_p.
+;;(define_insn "jump_compact_far"
+;; [(set (pc)
+;; (label_ref (match_operand 0 "" "")))
+;; (use (match_operand 1 "register_operand" "r")]
+;; "TARGET_SH1"
+;; "* return output_far_jump(insn, operands[0], operands[1]);"
+;; [(set_attr "type" "jump")
+;; (set_attr "needs_delay_slot" "yes")])
+
(define_insn "jump_media"
[(set (pc)
(match_operand:DI 0 "target_operand" "b"))]