diff options
author | hp <hp@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-07-07 17:13:14 +0000 |
---|---|---|
committer | hp <hp@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-07-07 17:13:14 +0000 |
commit | d33107045bbd0b2ced761435480bf2e2775879fc (patch) | |
tree | 7360583492a7eea5f3ca793f548aa470e505136f /gcc/config/mmix | |
parent | 547309503c706e536c65f4fbf7e0eb6aff9b1c79 (diff) | |
download | gcc-d33107045bbd0b2ced761435480bf2e2775879fc.tar.gz |
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
Diffstat (limited to 'gcc/config/mmix')
-rw-r--r-- | gcc/config/mmix/mmix-protos.h | 4 | ||||
-rw-r--r-- | gcc/config/mmix/mmix.c | 976 | ||||
-rw-r--r-- | gcc/config/mmix/mmix.h | 38 | ||||
-rw-r--r-- | gcc/config/mmix/mmix.md | 30 |
4 files changed, 518 insertions, 530 deletions
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; |