aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhp <hp@138bc75d-0d04-0410-961f-82ee72b054a4>2002-07-07 17:13:14 +0000
committerhp <hp@138bc75d-0d04-0410-961f-82ee72b054a4>2002-07-07 17:13:14 +0000
commitd33107045bbd0b2ced761435480bf2e2775879fc (patch)
tree7360583492a7eea5f3ca793f548aa470e505136f
parent547309503c706e536c65f4fbf7e0eb6aff9b1c79 (diff)
Emit MMIX function prologue and epilogue as rtl.
* config/mmix/mmix.md ("call"): Use mmix_get_hard_reg_initial_val, not unprototyped get_hard_reg_initial_val. ("call_value", "nonlocal_goto_receiver"): Ditto. ("return"): Make define_expand. Move real insn to... ("*expanded_return"): New pattern. ("prologue", "epilogue"): New define_expands. * config/mmix/mmix.h (MMIX_rO_REGNUM): New macro. (struct machine_function): New member in_prologue. (FIRST_PSEUDO_REGISTER): Adjust for including rO as register. (FIXED_REGISTERS, CALL_USED_REGISTERS): Ditto. (MMIX_MMIXWARE_ABI_REG_ALLOC_ORDER): Ditto. (MMIX_GNU_ABI_REG_ALLOC_ORDER, REG_CLASS_CONTENTS): Ditto. (REGISTER_NAMES, ADDITIONAL_REGISTER_NAMES): Ditto. (LOCAL_REGNO): Define. Adjust comment. * config/mmix/mmix.c (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS): Consider regs_ever_live[MMIX_rJ_REGNUM], not just leaf_function_p. (MMIX_OUTPUT_REGNO): Don't translate registers while outputting the prologue. (mmix_target_asm_function_prologue): Make static. Just mark that the prologue is being emitted. Move guts to... (mmix_expand_prologue): New function. Adjust for emitting prologue as rtl. For sizes, use HOST_WIDE_INT only. (mmix_target_asm_function_epilogue): Make static. Simply emit a \n. Move guts to... (mmix_expand_epilogue): New function. Adjust for emitting epilogue as rtl. For sizes, use HOST_WIDE_INT only. (mmix_target_asm_function_end_prologue): Mark that the prologue has ended. (TARGET_ASM_FUNCTION_END_PROLOGUE): Define. (mmix_conditional_register_usage): Improve comments. (mmix_local_regno): New function. (mmix_emit_sp_add, mmix_get_hard_reg_initial_val): Ditto. * config/mmix/mmix-protos.h (mmix_local_regno): Prototype. (mmix_expand_prologue, mmix_expand_epilogue): Ditto. (mmix_get_hard_reg_initial_val): Ditto. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@55302 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog40
-rw-r--r--gcc/config/mmix/mmix-protos.h4
-rw-r--r--gcc/config/mmix/mmix.c976
-rw-r--r--gcc/config/mmix/mmix.h38
-rw-r--r--gcc/config/mmix/mmix.md30
5 files changed, 558 insertions, 530 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4367e6966a9..2a1b68300a4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,43 @@
+2002-07-07 Hans-Peter Nilsson <hp@bitrange.com>
+
+ Emit MMIX function prologue and epilogue as rtl.
+ * config/mmix/mmix.md ("call"): Use mmix_get_hard_reg_initial_val,
+ not unprototyped get_hard_reg_initial_val.
+ ("call_value", "nonlocal_goto_receiver"): Ditto.
+ ("return"): Make define_expand. Move real insn to...
+ ("*expanded_return"): New pattern.
+ ("prologue", "epilogue"): New define_expands.
+ * config/mmix/mmix.h (MMIX_rO_REGNUM): New macro.
+ (struct machine_function): New member in_prologue.
+ (FIRST_PSEUDO_REGISTER): Adjust for including rO as register.
+ (FIXED_REGISTERS, CALL_USED_REGISTERS): Ditto.
+ (MMIX_MMIXWARE_ABI_REG_ALLOC_ORDER): Ditto.
+ (MMIX_GNU_ABI_REG_ALLOC_ORDER, REG_CLASS_CONTENTS): Ditto.
+ (REGISTER_NAMES, ADDITIONAL_REGISTER_NAMES): Ditto.
+ (LOCAL_REGNO): Define. Adjust comment.
+ * config/mmix/mmix.c (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS):
+ Consider regs_ever_live[MMIX_rJ_REGNUM], not just
+ leaf_function_p.
+ (MMIX_OUTPUT_REGNO): Don't translate registers while outputting
+ the prologue.
+ (mmix_target_asm_function_prologue): Make static. Just mark that
+ the prologue is being emitted. Move guts to...
+ (mmix_expand_prologue): New function. Adjust for emitting
+ prologue as rtl. For sizes, use HOST_WIDE_INT only.
+ (mmix_target_asm_function_epilogue): Make static. Simply emit a
+ \n. Move guts to...
+ (mmix_expand_epilogue): New function. Adjust for emitting
+ epilogue as rtl. For sizes, use HOST_WIDE_INT only.
+ (mmix_target_asm_function_end_prologue): Mark that the prologue
+ has ended.
+ (TARGET_ASM_FUNCTION_END_PROLOGUE): Define.
+ (mmix_conditional_register_usage): Improve comments.
+ (mmix_local_regno): New function.
+ (mmix_emit_sp_add, mmix_get_hard_reg_initial_val): Ditto.
+ * config/mmix/mmix-protos.h (mmix_local_regno): Prototype.
+ (mmix_expand_prologue, mmix_expand_epilogue): Ditto.
+ (mmix_get_hard_reg_initial_val): Ditto.
+
2002-07-06 Andreas Jaeger <aj@suse.de>
* toplev.c (set_fast_math_flags): Don't use ISO C style function
diff --git a/gcc/config/mmix/mmix-protos.h b/gcc/config/mmix/mmix-protos.h
index 5cfe561d3d3..f13a179e13f 100644
--- a/gcc/config/mmix/mmix-protos.h
+++ b/gcc/config/mmix/mmix-protos.h
@@ -57,6 +57,7 @@ extern int mmix_shiftable_wyde_value PARAMS ((unsigned HOST_WIDEST_INT));
extern void mmix_output_register_setting
PARAMS ((FILE *, int, HOST_WIDEST_INT, int));
extern void mmix_conditional_register_usage PARAMS ((void));
+extern int mmix_local_regno PARAMS ((int));
extern int mmix_dbx_register_number PARAMS ((int));
/* Things that need rtl.h, tree.h or real.h included, or in combination. */
@@ -123,6 +124,9 @@ extern void mmix_print_operand_address PARAMS ((FILE *, rtx));
extern int mmix_valid_comparison PARAMS ((RTX_CODE, enum machine_mode, rtx));
extern rtx mmix_gen_compare_reg PARAMS ((enum rtx_code, rtx, rtx));
extern void mmix_machine_dependent_reorg PARAMS ((rtx));
+extern void mmix_expand_prologue PARAMS ((void));
+extern void mmix_expand_epilogue PARAMS ((void));
+extern rtx mmix_get_hard_reg_initial_val PARAMS ((enum machine_mode, int));
#endif /* RTX_CODE */
extern int mmix_asm_preferred_eh_data_format PARAMS ((int, int));
diff --git a/gcc/config/mmix/mmix.c b/gcc/config/mmix/mmix.c
index 7dbfb2e879d..c3c4d985c05 100644
--- a/gcc/config/mmix/mmix.c
+++ b/gcc/config/mmix/mmix.c
@@ -52,9 +52,19 @@ Boston, MA 02111-1307, USA. */
/* We have no means to tell DWARF 2 about the register stack, so we need
to store the return address on the stack if an exception can get into
- this function. FIXME: Narrow condition. */
-#define MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS \
- (flag_exceptions && ! leaf_function_p ())
+ this function. FIXME: Narrow condition. Before any whole-function
+ analysis, regs_ever_live[] isn't initialized. We know it's up-to-date
+ after reload_completed; it may contain incorrect information some time
+ before that. Within a RTL sequence (after a call to start_sequence,
+ such as in RTL expanders), leaf_function_p doesn't see all insns
+ (perhaps any insn). But regs_ever_live is up-to-date when
+ leaf_function_p () isn't, so we "or" them together to get accurate
+ information. FIXME: Some tweak to leaf_function_p might be
+ preferrable. */
+#define MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS \
+ (flag_exceptions \
+ && ((reload_completed && regs_ever_live[MMIX_rJ_REGNUM]) \
+ || !leaf_function_p ()))
#define IS_MMIX_EH_RETURN_DATA_REG(REGNO) \
(current_function_calls_eh_return \
@@ -68,11 +78,15 @@ Boston, MA 02111-1307, USA. */
registers. In effect this makes unused call-saved registers to be used
as call-clobbered registers. The benefit comes from keeping the number
of local registers (value of rL) low, since there's a cost of
- increasing rL and clearing unused (unset) registers with lower numbers. */
+ increasing rL and clearing unused (unset) registers with lower numbers.
+ Don't translate while outputting the prologue. */
#define MMIX_OUTPUT_REGNO(N) \
(TARGET_ABI_GNU \
|| (int) (N) < MMIX_RETURN_VALUE_REGNUM \
|| (int) (N) > MMIX_LAST_STACK_REGISTER_REGNUM \
+ || cfun == NULL \
+ || cfun->machine == NULL \
+ || cfun->machine->in_prologue \
? (N) : ((N) - MMIX_RETURN_VALUE_REGNUM \
+ cfun->machine->highest_saved_stack_register + 1))
@@ -110,10 +124,11 @@ static bool mmix_assemble_integer PARAMS ((rtx, unsigned int, int));
static struct machine_function * mmix_init_machine_status PARAMS ((void));
static void mmix_encode_section_info PARAMS ((tree, int));
static const char *mmix_strip_name_encoding PARAMS ((const char *));
-
-extern void mmix_target_asm_function_prologue
+static void mmix_emit_sp_add PARAMS ((HOST_WIDE_INT offset));
+static void mmix_target_asm_function_prologue
PARAMS ((FILE *, HOST_WIDE_INT));
-extern void mmix_target_asm_function_epilogue
+static void mmix_target_asm_function_end_prologue PARAMS ((FILE *));
+static void mmix_target_asm_function_epilogue
PARAMS ((FILE *, HOST_WIDE_INT));
@@ -136,6 +151,9 @@ extern void mmix_target_asm_function_epilogue
#undef TARGET_ASM_FUNCTION_PROLOGUE
#define TARGET_ASM_FUNCTION_PROLOGUE mmix_target_asm_function_prologue
+#undef TARGET_ASM_FUNCTION_END_PROLOGUE
+#define TARGET_ASM_FUNCTION_END_PROLOGUE mmix_target_asm_function_end_prologue
+
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE mmix_target_asm_function_epilogue
@@ -241,11 +259,11 @@ mmix_conditional_register_usage ()
/* Change the default from the mmixware ABI. For the GNU ABI,
$15..$30 are call-saved just as $0..$14. There must be one
- call-clobbered local register for the "hole" describing number of
- saved local registers saved by PUSHJ/PUSHGO during the function
- call, receiving the return value at return. So best is to use
- the highest, $31. It's already marked call-clobbered for the
- mmixware ABI. */
+ call-clobbered local register for the "hole" that holds the
+ number of saved local registers saved by PUSHJ/PUSHGO during the
+ function call, receiving the return value at return. So best is
+ to use the highest, $31. It's already marked call-clobbered for
+ the mmixware ABI. */
for (i = 15; i <= 30; i++)
call_used_regs[i] = 0;
@@ -263,6 +281,17 @@ mmix_conditional_register_usage ()
reg_names[i]++;
}
+/* LOCAL_REGNO.
+ All registers that are part of the register stack and that will be
+ saved are local. */
+
+int
+mmix_local_regno (regno)
+ int regno;
+{
+ return regno <= MMIX_LAST_STACK_REGISTER_REGNUM && !call_used_regs[regno];
+}
+
/* PREFERRED_RELOAD_CLASS.
We need to extend the reload class of REMAINDER_REG and HIMULT_REG. */
@@ -672,335 +701,25 @@ mmix_asm_preferred_eh_data_format (code, global)
return DW_EH_PE_absptr;
}
-/* Emit the function prologue. For simplicity while the port is still
- in a flux, we do it as text rather than the now preferred RTL way,
- as (define_insn "function_prologue").
+/* Make a note that we've seen the beginning of of the prologue. This
+ matters to whether we'll translate register numbers as calculated by
+ mmix_machine_dependent_reorg. */
- FIXME: Translate to RTL and/or optimize some of the DWARF 2 stuff. */
-
-void
-mmix_target_asm_function_prologue (stream, locals_size)
- FILE *stream;
- HOST_WIDE_INT locals_size;
+static void
+mmix_target_asm_function_prologue (stream, framesize)
+ FILE *stream ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT framesize ATTRIBUTE_UNUSED;
{
- int regno;
- int stack_space_to_allocate
- = (current_function_outgoing_args_size
- + current_function_pretend_args_size
- + (int) locals_size + 7) & ~7;
- int offset = -8;
- int doing_dwarf = dwarf2out_do_frame ();
- long cfa_offset = 0;
-
- /* Guard our assumptions. Very low priority FIXME. */
- if (locals_size != (int) locals_size)
- error ("stack frame too big");
-
- /* Add room needed to save global non-register-stack registers. */
- for (regno = 255;
- regno >= MMIX_FIRST_GLOBAL_REGNUM;
- regno--)
- /* Note that we assume that the frame-pointer-register is one of these
- registers, in which case we don't count it here. */
- if ((((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
- && regs_ever_live[regno] && !call_used_regs[regno]))
- || IS_MMIX_EH_RETURN_DATA_REG (regno))
- stack_space_to_allocate += 8;
-
- /* If we do have a frame-pointer, add room for it. */
- if (frame_pointer_needed)
- stack_space_to_allocate += 8;
-
- /* If we have a non-local label, we need to be able to unwind to it, so
- store the current register stack pointer. Also store the return
- address if we do that. */
- if (MMIX_CFUN_HAS_LANDING_PAD)
- stack_space_to_allocate += 16;
- else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
- /* If we do have a saved return-address slot, add room for it. */
- stack_space_to_allocate += 8;
-
- /* Make sure we don't get an unaligned stack. */
- if ((stack_space_to_allocate % 8) != 0)
- internal_error ("stack frame not a multiple of 8 bytes: %d",
- stack_space_to_allocate);
-
- if (current_function_pretend_args_size)
- {
- int mmix_first_vararg_reg
- = (MMIX_FIRST_INCOMING_ARG_REGNUM
- + (MMIX_MAX_ARGS_IN_REGS
- - current_function_pretend_args_size / 8));
-
- for (regno
- = MMIX_FIRST_INCOMING_ARG_REGNUM + MMIX_MAX_ARGS_IN_REGS - 1;
- regno >= mmix_first_vararg_reg;
- regno--)
- {
- if (offset < 0)
- {
- int stack_chunk
- = stack_space_to_allocate > (256 - 8)
- ? (256 - 8) : stack_space_to_allocate;
-
- fprintf (stream, "\tSUBU %s,%s,%d\n",
- reg_names[MMIX_STACK_POINTER_REGNUM],
- reg_names[MMIX_STACK_POINTER_REGNUM],
- stack_chunk);
-
- if (doing_dwarf)
- {
- /* Each call to dwarf2out_def_cfa overrides the previous
- setting; they don't accumulate. We must keep track
- of the offset ourselves. */
- cfa_offset += stack_chunk;
- if (!frame_pointer_needed)
- dwarf2out_def_cfa ("", MMIX_STACK_POINTER_REGNUM,
- cfa_offset);
- }
- offset += stack_chunk;
- stack_space_to_allocate -= stack_chunk;
- }
-
- fprintf (stream, "\tSTOU %s,%s,%d\n", reg_names[regno],
- reg_names[MMIX_STACK_POINTER_REGNUM],
- offset);
-
- /* These registers aren't actually saved (as in "will be
- restored"), so don't tell DWARF2 they're saved. */
-
- offset -= 8;
- }
- }
-
- /* Store the frame-pointer. */
-
- if (frame_pointer_needed)
- {
- if (offset < 0)
- {
- /* Get 8 less than otherwise, since we need to reach offset + 8. */
- int stack_chunk
- = stack_space_to_allocate > (256 - 8 - 8)
- ? (256 - 8 - 8) : stack_space_to_allocate;
-
- fprintf (stream, "\tSUBU %s,%s,%d\n",
- reg_names[MMIX_STACK_POINTER_REGNUM],
- reg_names[MMIX_STACK_POINTER_REGNUM],
- stack_chunk);
- if (doing_dwarf)
- cfa_offset += stack_chunk;
- offset += stack_chunk;
- stack_space_to_allocate -= stack_chunk;
- }
-
- fprintf (stream, "\tSTOU %s,%s,%d\n\tADDU %s,%s,%d\n",
- reg_names[MMIX_FRAME_POINTER_REGNUM],
- reg_names[MMIX_STACK_POINTER_REGNUM],
- offset,
- reg_names[MMIX_FRAME_POINTER_REGNUM],
- reg_names[MMIX_STACK_POINTER_REGNUM],
- offset + 8);
- if (doing_dwarf)
- {
- /* If we're using the frame-pointer, then we just need this CFA
- definition basing on that value (often equal to the CFA).
- Further changes to the stack-pointer do not affect the
- frame-pointer, so we conditionalize them below on
- !frame_pointer_needed. */
- dwarf2out_def_cfa ("", MMIX_FRAME_POINTER_REGNUM,
- -cfa_offset + offset + 8);
-
- dwarf2out_reg_save ("", MMIX_FRAME_POINTER_REGNUM,
- -cfa_offset + offset);
- }
-
- offset -= 8;
- }
-
- if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
- {
- /* Store the return-address, if one is needed on the stack. We
- usually store it in a register when needed, but that doesn't work
- with -fexceptions. */
-
- if (offset < 0)
- {
- /* Get 8 less than otherwise, since we need to reach offset + 8. */
- int stack_chunk
- = stack_space_to_allocate > (256 - 8 - 8)
- ? (256 - 8 - 8) : stack_space_to_allocate;
-
- fprintf (stream, "\tSUBU %s,%s,%d\n",
- reg_names[MMIX_STACK_POINTER_REGNUM],
- reg_names[MMIX_STACK_POINTER_REGNUM],
- stack_chunk);
- if (doing_dwarf)
- {
- cfa_offset += stack_chunk;
- if (!frame_pointer_needed)
- dwarf2out_def_cfa ("", MMIX_STACK_POINTER_REGNUM,
- cfa_offset);
- }
- offset += stack_chunk;
- stack_space_to_allocate -= stack_chunk;
- }
-
- fprintf (stream, "\tGET $255,rJ\n\tSTOU $255,%s,%d\n",
- reg_names[MMIX_STACK_POINTER_REGNUM],
- offset);
- if (doing_dwarf)
- dwarf2out_return_save ("", -cfa_offset + offset);
- offset -= 8;
- }
- else if (MMIX_CFUN_HAS_LANDING_PAD)
- offset -= 8;
-
- if (MMIX_CFUN_HAS_LANDING_PAD)
- {
- /* Store the register defining the numbering of local registers, so
- we know how long to unwind the register stack. */
-
- if (offset < 0)
- {
- /* Get 8 less than otherwise, since we need to reach offset + 8. */
- int stack_chunk
- = stack_space_to_allocate > (256 - 8 - 8)
- ? (256 - 8 - 8) : stack_space_to_allocate;
-
- fprintf (stream, "\tSUBU %s,%s,%d\n",
- reg_names[MMIX_STACK_POINTER_REGNUM],
- reg_names[MMIX_STACK_POINTER_REGNUM],
- stack_chunk);
- offset += stack_chunk;
- stack_space_to_allocate -= stack_chunk;
-
- if (doing_dwarf)
- {
- cfa_offset += stack_chunk;
- if (!frame_pointer_needed)
- dwarf2out_def_cfa ("", MMIX_STACK_POINTER_REGNUM,
- cfa_offset);
- }
- }
-
- /* We don't tell dwarf2 about this one; we just have it to unwind
- the register stack at landing pads. FIXME: It's a kludge because
- we can't describe the effect of the PUSHJ and PUSHGO insns on the
- register stack at the moment. Best thing would be to handle it
- like stack-pointer offsets. Better: some hook into dwarf2out.c
- to produce DW_CFA_expression:s that specify the increment of rO,
- and unwind it at eh_return (preferred) or at the landing pad.
- Then saves to $0..$G-1 could be specified through that register. */
-
- fprintf (stream, "\tGET $255,rO\n\tSTOU $255,%s,%d\n",
- reg_names[MMIX_STACK_POINTER_REGNUM], offset);
-
- offset -= 8;
- }
-
- /* After the return-address and the frame-pointer, we have the local
- variables. They're the ones that may have an "unaligned" size. */
- offset -= (locals_size + 7) & ~7;
-
- /* Now store all registers that are global, i.e. not saved by the
- register file machinery.
-
- It is assumed that the frame-pointer is one of these registers, so it
- is explicitly excluded in the count. */
-
- for (regno = 255;
- regno >= MMIX_FIRST_GLOBAL_REGNUM;
- regno--)
- if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
- && regs_ever_live[regno] && ! call_used_regs[regno])
- || IS_MMIX_EH_RETURN_DATA_REG (regno))
- {
- if (offset < 0)
- {
- int stack_chunk;
-
- /* Since the local variables go above, we may get a large
- offset here. */
- if (offset < -248)
- {
- /* We're not going to access the locals area in the
- prologue, so we'll just silently subtract the slab we
- will not access. */
- stack_chunk =
- stack_space_to_allocate > (256 - offset - 8)
- ? (256 - offset - 8) : stack_space_to_allocate;
-
- mmix_output_register_setting (stream, 255, stack_chunk, 1);
- fprintf (stream, "\tSUBU %s,%s,$255\n",
- reg_names[MMIX_STACK_POINTER_REGNUM],
- reg_names[MMIX_STACK_POINTER_REGNUM]);
-
- if (doing_dwarf)
- {
- cfa_offset += stack_chunk;
- if (!frame_pointer_needed)
- dwarf2out_def_cfa ("", MMIX_STACK_POINTER_REGNUM,
- cfa_offset);
- }
- }
- else
- {
- stack_chunk = stack_space_to_allocate > (256 - 8)
- ? (256 - 8) : stack_space_to_allocate;
-
- fprintf (stream, "\tSUBU %s,%s,%d\n",
- reg_names[MMIX_STACK_POINTER_REGNUM],
- reg_names[MMIX_STACK_POINTER_REGNUM], stack_chunk);
- if (doing_dwarf)
- {
- cfa_offset += stack_chunk;
- if (!frame_pointer_needed)
- dwarf2out_def_cfa ("", MMIX_STACK_POINTER_REGNUM,
- cfa_offset);
- }
- }
-
- offset += stack_chunk;
- stack_space_to_allocate -= stack_chunk;
- }
-
- fprintf (stream, "\tSTOU %s,%s,%d\n", reg_names[regno],
- reg_names[MMIX_STACK_POINTER_REGNUM], offset);
- if (doing_dwarf)
- dwarf2out_reg_save ("", regno, -cfa_offset + offset);
- offset -= 8;
- }
+ cfun->machine->in_prologue = 1;
+}
- /* Finally, allocate room for outgoing args and local vars if room
- wasn't allocated above. This might be any number of bytes (well, we
- assume it fits in a host-int). */
- if (stack_space_to_allocate)
- {
- if (stack_space_to_allocate < 256)
- {
- fprintf (stream, "\tSUBU %s,%s,%d\n",
- reg_names[MMIX_STACK_POINTER_REGNUM],
- reg_names[MMIX_STACK_POINTER_REGNUM],
- stack_space_to_allocate);
- }
- else
- {
- mmix_output_register_setting (stream, 255,
- stack_space_to_allocate, 1);
- fprintf (stream, "\tSUBU %s,%s,$255\n",
- reg_names[MMIX_STACK_POINTER_REGNUM],
- reg_names[MMIX_STACK_POINTER_REGNUM]);
- }
+/* Make a note that we've seen the end of the prologue. */
- if (doing_dwarf)
- {
- cfa_offset += stack_space_to_allocate;
- if (!frame_pointer_needed)
- dwarf2out_def_cfa ("", MMIX_STACK_POINTER_REGNUM,
- cfa_offset);
- }
- }
+static void
+mmix_target_asm_function_end_prologue (stream)
+ FILE *stream ATTRIBUTE_UNUSED;
+{
+ cfun->machine->in_prologue = 0;
}
/* MACHINE_DEPENDENT_REORG.
@@ -1055,178 +774,8 @@ mmix_target_asm_function_epilogue (stream, locals_size)
HOST_WIDE_INT locals_size;
{
- int regno;
- int stack_space_to_deallocate
- = (current_function_outgoing_args_size
- + current_function_pretend_args_size
- + (int) locals_size + 7) & ~7;
-
- /* The assumption that locals_size fits in an int is asserted in
- mmix_target_asm_function_prologue. */
-
- /* The first address to access is beyond the outgoing_args area. */
- int offset = current_function_outgoing_args_size;
-
- rtx insn = get_last_insn ();
-
- /* If the last insn was a BARRIER, we don't have to write any code,
- then all returns were covered by "return" insns. */
- if (GET_CODE (insn) == NOTE)
- insn = prev_nonnote_insn (insn);
- if (insn
- && (GET_CODE (insn) == BARRIER
- /* We must make sure that the insn really is a "return" and
- not a conditional branch. Try to match the return exactly,
- and if it doesn't match, assume it is a conditional branch
- (and output an epilogue). */
- || (GET_CODE (insn) == JUMP_INSN
- && GET_CODE (PATTERN (insn)) == RETURN)))
- {
- /* Emit an extra \n as is done with the normal epilogue. */
- fputc ('\n', stream);
- return;
- }
-
- /* Add the space for global non-register-stack registers.
- It is assumed that the frame-pointer register can be one of these
- registers, in which case it is excluded from the count when needed. */
- for (regno = 255;
- regno >= MMIX_FIRST_GLOBAL_REGNUM;
- regno--)
- if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
- && regs_ever_live[regno] && !call_used_regs[regno])
- || IS_MMIX_EH_RETURN_DATA_REG (regno))
- stack_space_to_deallocate += 8;
-
- /* Add in the space for register stack-pointer. If so, always add room
- for the saved PC. */
- if (MMIX_CFUN_HAS_LANDING_PAD)
- stack_space_to_deallocate += 16;
- else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
- /* If we have a saved return-address slot, add it in. */
- stack_space_to_deallocate += 8;
-
- /* Add in the frame-pointer. */
- if (frame_pointer_needed)
- stack_space_to_deallocate += 8;
-
- /* Make sure we don't get an unaligned stack. */
- if ((stack_space_to_deallocate % 8) != 0)
- internal_error ("stack frame not a multiple of octabyte: %d",
- stack_space_to_deallocate);
-
- /* We will add back small offsets to the stack pointer as we go.
- First, we restore all registers that are global, i.e. not saved by
- the register file machinery. */
-
- for (regno = MMIX_FIRST_GLOBAL_REGNUM;
- regno <= 255;
- regno++)
- if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
- && regs_ever_live[regno] && !call_used_regs[regno])
- || IS_MMIX_EH_RETURN_DATA_REG (regno))
- {
- if (offset > 255)
- {
- if (offset > 65535)
- {
- /* There's better support for incrementing than
- decrementing, so we might be able to optimize this as
- we see a need. */
- mmix_output_register_setting (stream, 255, offset, 1);
- fprintf (stream, "\tADDU %s,%s,$255\n",
- reg_names[MMIX_STACK_POINTER_REGNUM],
- reg_names[MMIX_STACK_POINTER_REGNUM]);
- }
- else
- fprintf (stream, "\tINCL %s,%d\n",
- reg_names[MMIX_STACK_POINTER_REGNUM], offset);
-
- stack_space_to_deallocate -= offset;
- offset = 0;
- }
-
- fprintf (stream, "\tLDOU %s,%s,%d\n",
- reg_names[regno],
- reg_names[MMIX_STACK_POINTER_REGNUM],
- offset);
- offset += 8;
- }
-
- /* Here is where the local variables were. As in the prologue, they
- might be of an unaligned size. */
- offset += (locals_size + 7) & ~7;
-
-
- /* The saved register stack pointer is just below the frame-pointer
- register. We don't need to restore it "manually"; the POP
- instruction does that. */
- if (MMIX_CFUN_HAS_LANDING_PAD)
- offset += 16;
- else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
- /* The return-address slot is just below the frame-pointer register.
- We don't need to restore it because we don't really use it. */
- offset += 8;
-
- /* Get back the old frame-pointer-value. */
- if (frame_pointer_needed)
- {
- if (offset > 255)
- {
- if (offset > 65535)
- {
- /* There's better support for incrementing than
- decrementing, so we might be able to optimize this as
- we see a need. */
- mmix_output_register_setting (stream, 255, offset, 1);
- fprintf (stream, "\tADDU %s,%s,$255\n",
- reg_names[MMIX_STACK_POINTER_REGNUM],
- reg_names[MMIX_STACK_POINTER_REGNUM]);
- }
- else
- fprintf (stream, "\tINCL %s,%d\n",
- reg_names[MMIX_STACK_POINTER_REGNUM], offset);
-
- stack_space_to_deallocate -= offset;
- offset = 0;
- }
-
- fprintf (stream, "\tLDOU %s,%s,%d\n",
- reg_names[MMIX_FRAME_POINTER_REGNUM],
- reg_names[MMIX_STACK_POINTER_REGNUM],
- offset);
- offset += 8;
- }
-
- /* We do not need to restore pretended incoming args, just add back
- offset to sp. */
- if (stack_space_to_deallocate > 65535)
- {
- /* There's better support for incrementing than decrementing, so
- we might be able to optimize this as we see a need. */
- mmix_output_register_setting (stream, 255,
- stack_space_to_deallocate, 1);
- fprintf (stream, "\tADDU %s,%s,$255\n",
- reg_names[MMIX_STACK_POINTER_REGNUM],
- reg_names[MMIX_STACK_POINTER_REGNUM]);
- }
- else if (stack_space_to_deallocate != 0)
- fprintf (stream, "\tINCL %s,%d\n",
- reg_names[MMIX_STACK_POINTER_REGNUM],
- stack_space_to_deallocate);
-
- if (current_function_calls_eh_return)
- /* Adjustment the (normal) stack-pointer to that of the receiver.
- FIXME: It would be nice if we could also adjust the register stack
- here, but we need to express it through DWARF 2 too. */
- fprintf (stream, "\tADDU %s,%s,%s\n",
- reg_names [MMIX_STACK_POINTER_REGNUM],
- reg_names [MMIX_STACK_POINTER_REGNUM],
- reg_names [MMIX_EH_RETURN_STACKADJ_REGNUM]);
-
- /* The extra \n is so we have a blank line between the assembly code of
- separate functions. */
- fprintf (stream, "\tPOP %d,0\n\n", MMIX_POP_ARGUMENT ());
+ /* Emit an \n for readability of the generated assembly. */
+ fputc ('\n', stream);
}
/* ASM_OUTPUT_MI_THUNK. */
@@ -2483,8 +2032,19 @@ mmix_dbx_register_number (regno)
Now MMIX's own functions. First the exported ones. */
+/* Wrapper for get_hard_reg_initial_val since integrate.h isn't included
+ from insn-emit.c. */
+
+rtx
+mmix_get_hard_reg_initial_val (mode, regno)
+ enum machine_mode mode;
+ int regno;
+{
+ return get_hard_reg_initial_val (mode, regno);
+}
+
/* Non-zero when the function epilogue is simple enough that a single
- "POP %d,0" should be used. */
+ "POP %d,0" should be used even within the function. */
int
mmix_use_simple_return ()
@@ -2520,6 +2080,360 @@ mmix_use_simple_return ()
return stack_space_to_allocate == 0;
}
+
+/* Expands the function prologue into RTX. */
+
+void
+mmix_expand_prologue ()
+{
+ HOST_WIDE_INT locals_size = get_frame_size ();
+ int regno;
+ HOST_WIDE_INT stack_space_to_allocate
+ = (current_function_outgoing_args_size
+ + current_function_pretend_args_size
+ + locals_size + 7) & ~7;
+ HOST_WIDE_INT offset = -8;
+
+ /* Add room needed to save global non-register-stack registers. */
+ for (regno = 255;
+ regno >= MMIX_FIRST_GLOBAL_REGNUM;
+ regno--)
+ /* Note that we assume that the frame-pointer-register is one of these
+ registers, in which case we don't count it here. */
+ if ((((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
+ && regs_ever_live[regno] && !call_used_regs[regno]))
+ || IS_MMIX_EH_RETURN_DATA_REG (regno))
+ stack_space_to_allocate += 8;
+
+ /* If we do have a frame-pointer, add room for it. */
+ if (frame_pointer_needed)
+ stack_space_to_allocate += 8;
+
+ /* If we have a non-local label, we need to be able to unwind to it, so
+ store the current register stack pointer. Also store the return
+ address if we do that. */
+ if (MMIX_CFUN_HAS_LANDING_PAD)
+ stack_space_to_allocate += 16;
+ else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
+ /* If we do have a saved return-address slot, add room for it. */
+ stack_space_to_allocate += 8;
+
+ /* Make sure we don't get an unaligned stack. */
+ if ((stack_space_to_allocate % 8) != 0)
+ internal_error ("stack frame not a multiple of 8 bytes: %d",
+ stack_space_to_allocate);
+
+ if (current_function_pretend_args_size)
+ {
+ int mmix_first_vararg_reg
+ = (MMIX_FIRST_INCOMING_ARG_REGNUM
+ + (MMIX_MAX_ARGS_IN_REGS
+ - current_function_pretend_args_size / 8));
+
+ for (regno
+ = MMIX_FIRST_INCOMING_ARG_REGNUM + MMIX_MAX_ARGS_IN_REGS - 1;
+ regno >= mmix_first_vararg_reg;
+ regno--)
+ {
+ if (offset < 0)
+ {
+ HOST_WIDE_INT stack_chunk
+ = stack_space_to_allocate > (256 - 8)
+ ? (256 - 8) : stack_space_to_allocate;
+
+ mmix_emit_sp_add (-stack_chunk);
+ offset += stack_chunk;
+ stack_space_to_allocate -= stack_chunk;
+ }
+
+ /* These registers aren't actually saved (as in "will be
+ restored"), so don't tell DWARF2 they're saved. */
+ emit_move_insn (gen_rtx_MEM (DImode,
+ plus_constant (stack_pointer_rtx,
+ offset)),
+ gen_rtx_REG (DImode, regno));
+ offset -= 8;
+ }
+ }
+
+ /* Store the frame-pointer. */
+
+ if (frame_pointer_needed)
+ {
+ rtx insn;
+
+ if (offset < 0)
+ {
+ /* Get 8 less than otherwise, since we need to reach offset + 8. */
+ HOST_WIDE_INT stack_chunk
+ = stack_space_to_allocate > (256 - 8 - 8)
+ ? (256 - 8 - 8) : stack_space_to_allocate;
+
+ mmix_emit_sp_add (-stack_chunk);
+
+ offset += stack_chunk;
+ stack_space_to_allocate -= stack_chunk;
+ }
+
+ insn = emit_move_insn (gen_rtx_MEM (DImode,
+ plus_constant (stack_pointer_rtx,
+ offset)),
+ hard_frame_pointer_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ insn = emit_insn (gen_adddi3 (hard_frame_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (offset + 8)));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ offset -= 8;
+ }
+
+ if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
+ {
+ rtx tmpreg, retreg;
+ rtx insn;
+
+ /* Store the return-address, if one is needed on the stack. We
+ usually store it in a register when needed, but that doesn't work
+ with -fexceptions. */
+
+ if (offset < 0)
+ {
+ /* Get 8 less than otherwise, since we need to reach offset + 8. */
+ HOST_WIDE_INT stack_chunk
+ = stack_space_to_allocate > (256 - 8 - 8)
+ ? (256 - 8 - 8) : stack_space_to_allocate;
+
+ mmix_emit_sp_add (-stack_chunk);
+
+ offset += stack_chunk;
+ stack_space_to_allocate -= stack_chunk;
+ }
+
+ tmpreg = gen_rtx_REG (DImode, 255);
+ retreg = gen_rtx_REG (DImode, MMIX_rJ_REGNUM);
+
+ /* Dwarf2 code is confused by the use of a temporary register for
+ storing the return address, so we have to express it as a note,
+ which we attach to the actual store insn. */
+ emit_move_insn (tmpreg, retreg);
+
+ insn = emit_move_insn (gen_rtx_MEM (DImode,
+ plus_constant (stack_pointer_rtx,
+ offset)),
+ tmpreg);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ REG_NOTES (insn)
+ = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
+ gen_rtx_SET (VOIDmode,
+ gen_rtx_MEM (DImode,
+ plus_constant (stack_pointer_rtx,
+ offset)),
+ retreg),
+ REG_NOTES (insn));
+
+ offset -= 8;
+ }
+ else if (MMIX_CFUN_HAS_LANDING_PAD)
+ offset -= 8;
+
+ if (MMIX_CFUN_HAS_LANDING_PAD)
+ {
+ /* Store the register defining the numbering of local registers, so
+ we know how long to unwind the register stack. */
+
+ if (offset < 0)
+ {
+ /* Get 8 less than otherwise, since we need to reach offset + 8. */
+ HOST_WIDE_INT stack_chunk
+ = stack_space_to_allocate > (256 - 8 - 8)
+ ? (256 - 8 - 8) : stack_space_to_allocate;
+
+ mmix_emit_sp_add (-stack_chunk);
+
+ offset += stack_chunk;
+ stack_space_to_allocate -= stack_chunk;
+ }
+
+ /* We don't tell dwarf2 about this one; we just have it to unwind
+ the register stack at landing pads. FIXME: It's a kludge because
+ we can't describe the effect of the PUSHJ and PUSHGO insns on the
+ register stack at the moment. Best thing would be to handle it
+ like stack-pointer offsets. Better: some hook into dwarf2out.c
+ to produce DW_CFA_expression:s that specify the increment of rO,
+ and unwind it at eh_return (preferred) or at the landing pad.
+ Then saves to $0..$G-1 could be specified through that register. */
+
+ emit_move_insn (gen_rtx_REG (DImode, 255),
+ gen_rtx_REG (DImode,
+ MMIX_rO_REGNUM));
+ emit_move_insn (gen_rtx_MEM (DImode,
+ plus_constant (stack_pointer_rtx, offset)),
+ gen_rtx_REG (DImode, 255));
+ offset -= 8;
+ }
+
+ /* After the return-address and the frame-pointer, we have the local
+ variables. They're the ones that may have an "unaligned" size. */
+ offset -= (locals_size + 7) & ~7;
+
+ /* Now store all registers that are global, i.e. not saved by the
+ register file machinery.
+
+ It is assumed that the frame-pointer is one of these registers, so it
+ is explicitly excluded in the count. */
+
+ for (regno = 255;
+ regno >= MMIX_FIRST_GLOBAL_REGNUM;
+ regno--)
+ if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
+ && regs_ever_live[regno] && ! call_used_regs[regno])
+ || IS_MMIX_EH_RETURN_DATA_REG (regno))
+ {
+ rtx insn;
+
+ if (offset < 0)
+ {
+ HOST_WIDE_INT stack_chunk
+ = (stack_space_to_allocate > (256 - offset - 8)
+ ? (256 - offset - 8) : stack_space_to_allocate);
+
+ mmix_emit_sp_add (-stack_chunk);
+ offset += stack_chunk;
+ stack_space_to_allocate -= stack_chunk;
+ }
+
+ insn = emit_move_insn (gen_rtx_MEM (DImode,
+ plus_constant (stack_pointer_rtx,
+ offset)),
+ gen_rtx_REG (DImode, regno));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ offset -= 8;
+ }
+
+ /* Finally, allocate room for outgoing args and local vars if room
+ wasn't allocated above. */
+ if (stack_space_to_allocate)
+ mmix_emit_sp_add (-stack_space_to_allocate);
+}
+
+/* Expands the function epilogue into RTX. */
+
+void
+mmix_expand_epilogue ()
+{
+ HOST_WIDE_INT locals_size = get_frame_size ();
+ int regno;
+ HOST_WIDE_INT stack_space_to_deallocate
+ = (current_function_outgoing_args_size
+ + current_function_pretend_args_size
+ + locals_size + 7) & ~7;
+
+ /* The assumption that locals_size fits in an int is asserted in
+ mmix_expand_prologue. */
+
+ /* The first address to access is beyond the outgoing_args area. */
+ int offset = current_function_outgoing_args_size;
+
+ /* Add the space for global non-register-stack registers.
+ It is assumed that the frame-pointer register can be one of these
+ registers, in which case it is excluded from the count when needed. */
+ for (regno = 255;
+ regno >= MMIX_FIRST_GLOBAL_REGNUM;
+ regno--)
+ if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
+ && regs_ever_live[regno] && !call_used_regs[regno])
+ || IS_MMIX_EH_RETURN_DATA_REG (regno))
+ stack_space_to_deallocate += 8;
+
+ /* Add in the space for register stack-pointer. If so, always add room
+ for the saved PC. */
+ if (MMIX_CFUN_HAS_LANDING_PAD)
+ stack_space_to_deallocate += 16;
+ else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
+ /* If we have a saved return-address slot, add it in. */
+ stack_space_to_deallocate += 8;
+
+ /* Add in the frame-pointer. */
+ if (frame_pointer_needed)
+ stack_space_to_deallocate += 8;
+
+ /* Make sure we don't get an unaligned stack. */
+ if ((stack_space_to_deallocate % 8) != 0)
+ internal_error ("stack frame not a multiple of octabyte: %d",
+ stack_space_to_deallocate);
+
+ /* We will add back small offsets to the stack pointer as we go.
+ First, we restore all registers that are global, i.e. not saved by
+ the register file machinery. */
+
+ for (regno = MMIX_FIRST_GLOBAL_REGNUM;
+ regno <= 255;
+ regno++)
+ if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
+ && regs_ever_live[regno] && !call_used_regs[regno])
+ || IS_MMIX_EH_RETURN_DATA_REG (regno))
+ {
+ if (offset > 255)
+ {
+ mmix_emit_sp_add (offset);
+ stack_space_to_deallocate -= offset;
+ offset = 0;
+ }
+
+ emit_move_insn (gen_rtx_REG (DImode, regno),
+ gen_rtx_MEM (DImode,
+ plus_constant (stack_pointer_rtx,
+ offset)));
+ offset += 8;
+ }
+
+ /* Here is where the local variables were. As in the prologue, they
+ might be of an unaligned size. */
+ offset += (locals_size + 7) & ~7;
+
+
+ /* The saved register stack pointer is just below the frame-pointer
+ register. We don't need to restore it "manually"; the POP
+ instruction does that. */
+ if (MMIX_CFUN_HAS_LANDING_PAD)
+ offset += 16;
+ else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
+ /* The return-address slot is just below the frame-pointer register.
+ We don't need to restore it because we don't really use it. */
+ offset += 8;
+
+ /* Get back the old frame-pointer-value. */
+ if (frame_pointer_needed)
+ {
+ if (offset > 255)
+ {
+ mmix_emit_sp_add (offset);
+
+ stack_space_to_deallocate -= offset;
+ offset = 0;
+ }
+
+ emit_move_insn (hard_frame_pointer_rtx,
+ gen_rtx_MEM (DImode,
+ plus_constant (stack_pointer_rtx,
+ offset)));
+ offset += 8;
+ }
+
+ /* We do not need to restore pretended incoming args, just add back
+ offset to sp. */
+ if (stack_space_to_deallocate != 0)
+ mmix_emit_sp_add (stack_space_to_deallocate);
+
+ if (current_function_calls_eh_return)
+ /* Adjust the (normal) stack-pointer to that of the receiver.
+ FIXME: It would be nice if we could also adjust the register stack
+ here, but we need to express it through DWARF 2 too. */
+ emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
+ gen_rtx_REG (DImode,
+ MMIX_EH_RETURN_STACKADJ_REGNUM)));
+}
+
/* Output an optimal sequence for setting a register to a specific
constant. Used in an alternative for const_ints in movdi, and when
using large stack-frame offsets.
@@ -2884,6 +2798,48 @@ mmix_gen_compare_reg (code, x, y)
/* Local (static) helper functions. */
+static void
+mmix_emit_sp_add (offset)
+ HOST_WIDE_INT offset;
+{
+ rtx insn;
+
+ if (offset < 0)
+ {
+ /* Negative stack-pointer adjustments are allocations and appear in
+ the prologue only. We mark them as frame-related so unwind and
+ debug info is properly emitted for them. */
+ if (offset > -255)
+ insn = emit_insn (gen_adddi3 (stack_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (offset)));
+ else
+ {
+ rtx tmpr = gen_rtx_REG (DImode, 255);
+ RTX_FRAME_RELATED_P (emit_move_insn (tmpr, GEN_INT (offset))) = 1;
+ insn = emit_insn (gen_adddi3 (stack_pointer_rtx,
+ stack_pointer_rtx, tmpr));
+ }
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ else
+ {
+ /* Positive adjustments are in the epilogue only. Don't mark them
+ as "frame-related" for unwind info. */
+ if (CONST_OK_FOR_LETTER_P (offset, 'L'))
+ emit_insn (gen_adddi3 (stack_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (offset)));
+ else
+ {
+ rtx tmpr = gen_rtx_REG (DImode, 255);
+ emit_move_insn (tmpr, GEN_INT (offset));
+ insn = emit_insn (gen_adddi3 (stack_pointer_rtx,
+ stack_pointer_rtx, tmpr));
+ }
+ }
+}
+
/* Print operator suitable for doing something with a shiftable
wyde. The type of operator is passed as an asm output modifier. */
diff --git a/gcc/config/mmix/mmix.h b/gcc/config/mmix/mmix.h
index 7280a3e2904..d3dad13fe9e 100644
--- a/gcc/config/mmix/mmix.h
+++ b/gcc/config/mmix/mmix.h
@@ -49,6 +49,7 @@ Boston, MA 02111-1307, USA. */
#define MMIX_HIMULT_REGNUM 258
#define MMIX_REMAINDER_REGNUM 260
#define MMIX_ARG_POINTER_REGNUM 261
+#define MMIX_rO_REGNUM 262
#define MMIX_LAST_STACK_REGISTER_REGNUM 31
/* Four registers; "ideally, these registers should be call-clobbered", so
@@ -92,6 +93,7 @@ struct machine_function GTY(())
{
int has_landing_pad;
int highest_saved_stack_register;
+ int in_prologue;
};
/* For these target macros, there is no generic documentation here. You
@@ -360,13 +362,13 @@ extern int target_flags;
/* Node: Register Basics */
/* We tell GCC about all 256 general registers, and we also include
- rD, rE, rH, rJ and rR (in that order) so we can describe what insns
+ rD, rE, rH, rJ, rR and rO (in that order) so we can describe what insns
clobber them. We use a faked register for the argument pointer. It is
always eliminated towards the frame-pointer or the stack-pointer, never
output in assembly. Any fixed register would do for this, like $255,
but future debugging is easier when using a separate register. It
counts as a global register for pseudorandom reasons. */
-#define FIRST_PSEUDO_REGISTER 262
+#define FIRST_PSEUDO_REGISTER 263
/* We treat general registers with no assigned purpose as fixed. The
stack pointer, $254, is also fixed. Register $255 is referred to as a
@@ -390,7 +392,7 @@ extern int target_flags;
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, \
- 1, 1, 0, 0, 0, 1 \
+ 1, 1, 0, 0, 0, 1, 1 \
}
/* General registers are fixed and therefore "historically" marked
@@ -414,19 +416,23 @@ extern int target_flags;
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, \
- 1, 1, 1, 1, 1, 1 \
+ 1, 1, 1, 1, 1, 1, 1 \
}
#define CONDITIONAL_REGISTER_USAGE mmix_conditional_register_usage ()
-/* No LOCAL_REGNO, INCOMING_REGNO or OUTGOING_REGNO, since those macros
- are not usable for MMIX: it doesn't have a fixed register window size.
- FIXME: Perhaps we should say something about $0..$15 may sometimes be
- the incoming $16..$31. Those macros need better documentation; it
- looks like they're just bogus and that FUNCTION_INCOMING_ARG_REGNO_P
- and FUNCTION_OUTGOING_VALUE should be used where they're used. For the
+/* No INCOMING_REGNO or OUTGOING_REGNO, since those macros are not usable
+ for MMIX: it doesn't have a fixed register window size. FIXME: Perhaps
+ we should say something about $0..$15 may sometimes be the incoming
+ $16..$31. Those macros need better documentation; it looks like
+ they're just bogus and that FUNCTION_INCOMING_ARG_REGNO_P and
+ FUNCTION_OUTGOING_VALUE should be used where they're used. For the
moment, do nothing; things seem to work anyway. */
+/* Defining LOCAL_REGNO is necessary in presence of prologue/epilogue,
+ else GCC will be confused that those registers aren't saved and
+ restored. */
+#define LOCAL_REGNO(REGNO) mmix_local_regno (REGNO)
/* Node: Allocation Order */
@@ -474,7 +480,7 @@ extern int target_flags;
232, 233, 234, 235, 236, 237, 238, 239, \
240, 241, 242, 243, 244, 245, 246, \
\
- 254, 255, 256, 257, 261 \
+ 254, 255, 256, 257, 261, 262 \
}
/* As a convenience, we put this nearby, for ease of comparison.
@@ -529,7 +535,7 @@ extern int target_flags;
216, 217, 218, 219, 220, 221, 222, 223, \
224, 225, 226, 227, 228, 229, 230, \
\
- 254, 255, 256, 257, 261 \
+ 254, 255, 256, 257, 261, 262 \
}
/* The default one. */
@@ -573,8 +579,8 @@ enum reg_class
{~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, 0x20}, \
{0, 0, 0, 0, 0, 0, 0, 0, 0x10}, \
{0, 0, 0, 0, 0, 0, 0, 0, 4}, \
- {0, 0, 0, 0, 0, 0, 0, 0, 0x3f}, \
- {~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, 0x3f}}
+ {0, 0, 0, 0, 0, 0, 0, 0, 0x7f}, \
+ {~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, 0x7f}}
#define REGNO_REG_CLASS(REGNO) \
((REGNO) <= MMIX_LAST_GENERAL_REGISTER \
@@ -1058,11 +1064,11 @@ typedef struct { int regs; int lib; int now_varargs; } CUMULATIVE_ARGS;
"$232", "$233", "$234", "$235", "$236", "$237", "$238", "$239", \
"$240", "$241", "$242", "$243", "$244", "$245", "$246", "$247", \
"$248", "$249", "$250", "$251", "$252", "$253", "$254", "$255", \
- ":rD", ":rE", ":rH", ":rJ", ":rR", "ap_!BAD!"}
+ ":rD", ":rE", ":rH", ":rJ", ":rR", "ap_!BAD!", ":rO"}
#define ADDITIONAL_REGISTER_NAMES \
{{"sp", 254}, {":sp", 254}, {"rD", 256}, {"rE", 257}, \
- {"rH", 258}, {"rJ", MMIX_rJ_REGNUM}}
+ {"rH", 258}, {"rJ", MMIX_rJ_REGNUM}, {"rO", MMIX_rO_REGNUM}}
#define PRINT_OPERAND(STREAM, X, CODE) \
mmix_print_operand (STREAM, X, CODE)
diff --git a/gcc/config/mmix/mmix.md b/gcc/config/mmix/mmix.md
index 024395b7a15..88ae51445d6 100644
--- a/gcc/config/mmix/mmix.md
+++ b/gcc/config/mmix/mmix.md
@@ -988,7 +988,8 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
in the call, and we set it back after every call (all but one setting
will be optimized away), integrity is maintained. */
operands[3]
- = get_hard_reg_initial_val (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
+ = mmix_get_hard_reg_initial_val (Pmode,
+ MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
/* FIXME: There's a bug in gcc which causes NULL to be passed as
operand[2] when we get out of registers, which later confuses gcc.
@@ -1014,7 +1015,8 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
in the call, and we set it back after every call (all but one setting
will be optimized away), integrity is maintained. */
operands[4]
- = get_hard_reg_initial_val (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
+ = mmix_get_hard_reg_initial_val (Pmode,
+ MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
/* FIXME: See 'call'. */
if (operands[3] == NULL_RTX)
@@ -1067,11 +1069,30 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
;; I hope untyped_call and untyped_return are not needed for MMIX.
;; Users of Objective C will notice.
-(define_insn "return"
+; Generated by GCC.
+(define_expand "return"
[(return)]
"mmix_use_simple_return ()"
+ "")
+
+; Generated by the epilogue expander.
+(define_insn "*expanded_return"
+ [(return)]
+ ""
"POP %.,0")
+(define_expand "prologue"
+ [(const_int 0)]
+ ""
+ "mmix_expand_prologue (); DONE;")
+
+; Note that the (return) from the expander itself is always the last insn
+; in the epilogue.
+(define_expand "epilogue"
+ [(return)]
+ ""
+ "mmix_expand_epilogue ();")
+
(define_insn "nop"
[(const_int 0)]
""
@@ -1111,7 +1132,8 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
"
{
operands[0]
- = get_hard_reg_initial_val (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
+ = mmix_get_hard_reg_initial_val (Pmode,
+ MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
/* Mark this function as containing a landing-pad. */
cfun->machine->has_landing_pad = 1;