#define SPLIT_STACK_AVAILABLE 1024
+/* Emit the parmblock for __morestack into .rodata section. It
+ consists of 3 pointer size entries:
+ - frame size
+ - size of stack arguments
+ - offset between parm block and __morestack return label */
+
+void
+s390_output_split_stack_data (rtx parm_block, rtx call_done,
+ rtx frame_size, rtx args_size)
+{
+ rtx ops[] = { parm_block, call_done };
+
+ switch_to_section (targetm.asm_out.function_rodata_section
+ (current_function_decl));
+
+ if (TARGET_64BIT)
+ output_asm_insn (".align\t8", NULL);
+ else
+ output_asm_insn (".align\t4", NULL);
+
+ (*targetm.asm_out.internal_label) (asm_out_file, "L",
+ CODE_LABEL_NUMBER (parm_block));
+ if (TARGET_64BIT)
+ {
+ output_asm_insn (".quad\t%0", &frame_size);
+ output_asm_insn (".quad\t%0", &args_size);
+ output_asm_insn (".quad\t%1-%0", ops);
+ }
+ else
+ {
+ output_asm_insn (".long\t%0", &frame_size);
+ output_asm_insn (".long\t%0", &args_size);
+ output_asm_insn (".long\t%1-%0", ops);
+ }
+
+ switch_to_section (current_function_section ());
+}
+
/* Emit -fsplit-stack prologue, which goes before the regular function
prologue. */
call_done = gen_label_rtx ();
parm_base = gen_label_rtx ();
-
- /* Emit the parameter block. */
- tmp = gen_split_stack_data (parm_base, call_done,
- GEN_INT (frame_size),
- GEN_INT (args_size));
- insn = emit_insn (tmp);
- add_reg_note (insn, REG_LABEL_OPERAND, call_done);
- LABEL_NUSES (call_done)++;
- add_reg_note (insn, REG_LABEL_OPERAND, parm_base);
LABEL_NUSES (parm_base)++;
+ LABEL_NUSES (call_done)++;
/* %r1 = litbase. */
insn = emit_move_insn (r1, gen_rtx_LABEL_REF (VOIDmode, parm_base));
/* Now, we need to call __morestack. It has very special calling
conventions: it preserves param/return/static chain registers for
calling main function body, and looks for its own parameters at %r1. */
+ if (cc != NULL)
+ tmp = gen_split_stack_cond_call (Pmode,
+ morestack_ref,
+ parm_base,
+ call_done,
+ GEN_INT (frame_size),
+ GEN_INT (args_size),
+ cc);
+ else
+ tmp = gen_split_stack_call (Pmode,
+ morestack_ref,
+ parm_base,
+ call_done,
+ GEN_INT (frame_size),
+ GEN_INT (args_size));
+
+ insn = emit_jump_insn (tmp);
+ JUMP_LABEL (insn) = call_done;
+ add_reg_note (insn, REG_LABEL_OPERAND, parm_base);
+ add_reg_note (insn, REG_LABEL_OPERAND, call_done);
if (cc != NULL)
{
- tmp = gen_split_stack_cond_call (morestack_ref, cc, call_done);
-
- insn = emit_jump_insn (tmp);
- JUMP_LABEL (insn) = call_done;
- LABEL_NUSES (call_done)++;
-
/* Mark the jump as very unlikely to be taken. */
add_reg_br_prob_note (insn,
profile_probability::very_unlikely ());
}
else
{
- tmp = gen_split_stack_call (morestack_ref, call_done);
- insn = emit_jump_insn (tmp);
- JUMP_LABEL (insn) = call_done;
- LABEL_NUSES (call_done)++;
emit_barrier ();
}
; Split stack support
UNSPECV_SPLIT_STACK_CALL
- UNSPECV_SPLIT_STACK_DATA
UNSPECV_OSC_BREAK
])
DONE;
})
-;; __morestack parameter block for split stack prologue. Parameters are:
-;; parameter block label, label to be called by __morestack, frame size,
-;; stack parameter size.
+;; Call to __morestack used by the split stack support
-(define_insn "split_stack_data"
- [(unspec_volatile [(match_operand 0 "" "X")
- (match_operand 1 "" "X")
- (match_operand 2 "const_int_operand" "X")
- (match_operand 3 "const_int_operand" "X")]
- UNSPECV_SPLIT_STACK_DATA)]
- ""
-{
- switch_to_section (targetm.asm_out.function_rodata_section
- (current_function_decl));
+; The insn has 3 parts:
+; 1. A jump to the call done label. The jump will be done as part of
+; __morestack and will not be explicitly emitted to the insn stream.
+; 2. The call of __morestack including a use for r1 which is supposed to
+; point to the parameter block for __morestack.
+; 3. 3 USES whose values together with the call done label will be
+; used to emit the parameter block to the .rodata section. This
+; needs to be tied into the same insn as 1. since the call done
+; label is emitted also as part of the parm block. In order to
+; allow the edge to the BB with the call done label to be
+; redirected both need to make use of the same label_ref.
- if (TARGET_64BIT)
- output_asm_insn (".align\t8", operands);
- else
- output_asm_insn (".align\t4", operands);
- (*targetm.asm_out.internal_label) (asm_out_file, "L",
- CODE_LABEL_NUMBER (operands[0]));
- if (TARGET_64BIT)
- {
- output_asm_insn (".quad\t%2", operands);
- output_asm_insn (".quad\t%3", operands);
- output_asm_insn (".quad\t%1-%0", operands);
- }
- else
- {
- output_asm_insn (".long\t%2", operands);
- output_asm_insn (".long\t%3", operands);
- output_asm_insn (".long\t%1-%0", operands);
- }
-
- switch_to_section (current_function_section ());
- return "";
-}
- [(set_attr "length" "0")])
-
-
-;; A jg with minimal fuss for use in split stack prologue.
-
-(define_expand "split_stack_call"
- [(match_operand 0 "bras_sym_operand" "X")
- (match_operand 1 "" "")]
- ""
-{
- if (TARGET_64BIT)
- emit_jump_insn (gen_split_stack_call_di (operands[0], operands[1]));
- else
- emit_jump_insn (gen_split_stack_call_si (operands[0], operands[1]));
- DONE;
-})
-
-(define_insn "split_stack_call_<mode>"
- [(set (pc) (label_ref (match_operand 1 "" "")))
+(define_insn "@split_stack_call<mode>"
+ [(set (pc) (label_ref (match_operand 2 "" ""))) ; call done label
(set (reg:P 1) (unspec_volatile [(match_operand 0 "bras_sym_operand" "X")
(reg:P 1)]
- UNSPECV_SPLIT_STACK_CALL))]
+ UNSPECV_SPLIT_STACK_CALL))
+ (use (label_ref (match_operand 1 "" "X"))) ; parm block label
+ (use (match_operand 3 "const_int_operand" "X")) ; frame size
+ (use (match_operand 4 "const_int_operand" "X"))] ; arg size
""
- "jg\t%0"
+{
+ s390_output_split_stack_data (operands[1], operands[2], operands[3], operands[4]);
+ return "jg\t%0";
+}
[(set_attr "op_type" "RIL")
(set_attr "type" "branch")])
-;; Also a conditional one.
-
-(define_expand "split_stack_cond_call"
- [(match_operand 0 "bras_sym_operand" "X")
- (match_operand 1 "" "")
- (match_operand 2 "" "")]
- ""
-{
- if (TARGET_64BIT)
- emit_jump_insn (gen_split_stack_cond_call_di (operands[0], operands[1], operands[2]));
- else
- emit_jump_insn (gen_split_stack_cond_call_si (operands[0], operands[1], operands[2]));
- DONE;
-})
+; As above but with a conditional jump
-(define_insn "split_stack_cond_call_<mode>"
+(define_insn "@split_stack_cond_call<mode>"
[(set (pc)
(if_then_else
- (match_operand 1 "" "")
- (label_ref (match_operand 2 "" ""))
+ (match_operand 5 "" "") ; condition
+ (label_ref (match_operand 2 "" "")) ; call done label
(pc)))
(set (reg:P 1) (unspec_volatile [(match_operand 0 "bras_sym_operand" "X")
(reg:P 1)]
- UNSPECV_SPLIT_STACK_CALL))]
+ UNSPECV_SPLIT_STACK_CALL))
+ (use (label_ref (match_operand 1 "" "X"))) ; parm block label
+ (use (match_operand 3 "const_int_operand" "X")) ; frame size
+ (use (match_operand 4 "const_int_operand" "X"))] ; arg size
""
- "jg%C1\t%0"
+{
+ s390_output_split_stack_data (operands[1], operands[2], operands[3], operands[4]);
+ return "jg%C5\t%0";
+}
[(set_attr "op_type" "RIL")
(set_attr "type" "branch")])
+
(define_insn "osc_break"
[(unspec_volatile [(const_int 0)] UNSPECV_OSC_BREAK)]
""