diff options
author | Eric Botcazou <ebotcazou@libertysurf.fr> | 2004-02-03 13:36:23 +0100 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2004-02-03 12:36:23 +0000 |
commit | 60b85c4c0e161c6e2fe58c70454cb46d553dbe83 (patch) | |
tree | c7cad77d1f7f77fb6749da1af269a50ee4cd6ee6 /gcc/config/sparc/sparc.c | |
parent | e57e265ba61a2e07623521dc872a2b7e82e70b37 (diff) | |
download | gcc-60b85c4c0e161c6e2fe58c70454cb46d553dbe83.zip gcc-60b85c4c0e161c6e2fe58c70454cb46d553dbe83.tar.gz gcc-60b85c4c0e161c6e2fe58c70454cb46d553dbe83.tar.bz2 |
invoke.texi (SPARC options): Remove -mflat and all -mxxx (xxx:chip) options.
* doc/invoke.texi (SPARC options): Remove -mflat and
all -mxxx (xxx:chip) options.
* config/sparc/aout.h (DBX_REGISTER_NUMBER): Delete.
* config/sparc/litecoff.h (DBX_REGISTER_NUMBER): Likewise.
* config/sparc/netbsd-elf.h (DBX_REGISTER_NUMBER): Likewise.
* config/sparc/sol2.h (DBX_REGISTER_NUMBER): Likewise.
* config/sparc/sparc-protos.h: Delete sparc_flat_* prototypes.
* config/sparc/sparc.c: Likewise.
(sparc_output_function_prologue): Remove TARGET_FLAT handling.
(sparc_nonflat_function_prologue): Rename into sparc_function_prologue.
(sparc_output_function_epilogue): Remove TARGET_FLAT handling.
(sparc_nonflat_function_epilogue): Rename into sparc_function_epilogue.
(struct sparc_frame_info, current_frame_info, zero_frame_info): Delete.
(sparc_flat_must_save_register_p): Likewise.
(sparc_flat_compute_frame_size): Likewise.
(sparc_flat_save_restore): Likewise.
(sparc_flat_function_prologue): Likewise.
(sparc_flat_function_epilogue): Likewise.
(sparc_flat_epilogue_delay_slots): Likewise.
(sparc_flat_eligible_for_epilogue_delay): Likewise.
(sparc_function_ok_for_sibcall): Remove TARGET_FLAT handling.
* config/sparc/sparc.h (MASK_FLAT, TARGET_FLAT): Delete.
(TARGET_SWITCHES): Remove -mflat and all -mxxx (xxx:chip) options.
(SPARC_INCOMING_INT_ARG_FIRST): Remove TARGET_FLAT handling.
(CONDITIONAL_REGISTER_USAGE): Likewise.
(FRAME_POINTER_REQUIRED): Likewise.
(INITIAL_ELIMINATION_OFFSET): Likewise.
(BASE_RETURN_VALUE_REG): Likewise.
(BASE_OUTGOING_VALUE_REG): Likewise.
(BASE_PASSING_ARG_REG): Likewise.
(BASE_INCOMING_ARG_REG): Likewise.
(INCOMING_REGNO): Likewise.
(OUTGOING_REGNO): Likewise.
(LOCAL_REGNO): Likewise.
(DELAY_SLOTS_FOR_EPILOGUE): Likewise.
(ELIGIBLE_FOR_EPILOGUE_DELAY): Likewise.
(EPILOGUE_USES): Likewise.
* config/sparc/sparc.md ("isa" attribute): Change "v6" into "v7".
("flat" attribute): Delete.
(do_builtin_setjmp_setup): Remove TARGET_FLAT and "flat" attribute
handling.
(call followed by jump define_peephole's): Delete.
(exception_receiver): Likewise.
(builtin_setjmp_receiver): Likewise.
* config/sparc/t-sparclite (MULTILIB_OPTIONS): Remove -mflat.
From-SVN: r77169
Diffstat (limited to 'gcc/config/sparc/sparc.c')
-rw-r--r-- | gcc/config/sparc/sparc.c | 762 |
1 files changed, 14 insertions, 748 deletions
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index e7dd4fa..855fe1d 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -79,7 +79,7 @@ static int num_gfregs; rtx sparc_compare_op0, sparc_compare_op1; /* Coordinate with the md file wrt special insns created by - sparc_nonflat_function_epilogue. */ + sparc_function_epilogue. */ bool sparc_emitting_epilogue; /* Vector to say how input registers are mapped to output registers. @@ -155,14 +155,8 @@ static int set_extends (rtx); static void output_restore_regs (FILE *, int); static void sparc_output_function_prologue (FILE *, HOST_WIDE_INT); static void sparc_output_function_epilogue (FILE *, HOST_WIDE_INT); -static void sparc_flat_function_epilogue (FILE *, HOST_WIDE_INT); -static void sparc_flat_function_prologue (FILE *, HOST_WIDE_INT); -static void sparc_flat_save_restore (FILE *, const char *, int, - unsigned long, unsigned long, - const char *, const char *, - HOST_WIDE_INT); -static void sparc_nonflat_function_epilogue (FILE *, HOST_WIDE_INT, int); -static void sparc_nonflat_function_prologue (FILE *, HOST_WIDE_INT, int); +static void sparc_function_epilogue (FILE *, HOST_WIDE_INT, int); +static void sparc_function_prologue (FILE *, HOST_WIDE_INT, int); #ifdef OBJECT_FORMAT_ELF static void sparc_elf_asm_named_section (const char *, unsigned int); #endif @@ -4333,18 +4327,14 @@ sparc_output_scratch_registers (FILE *file ATTRIBUTE_UNUSED) static void sparc_output_function_prologue (FILE *file, HOST_WIDE_INT size) { - if (TARGET_FLAT) - sparc_flat_function_prologue (file, size); - else - sparc_nonflat_function_prologue (file, size, - current_function_uses_only_leaf_regs); + sparc_function_prologue (file, size, + current_function_uses_only_leaf_regs); } /* Output code for the function prologue. */ static void -sparc_nonflat_function_prologue (FILE *file, HOST_WIDE_INT size, - int leaf_function) +sparc_function_prologue (FILE *file, HOST_WIDE_INT size, int leaf_function) { sparc_output_scratch_registers (file); @@ -4498,19 +4488,16 @@ output_restore_regs (FILE *file, int leaf_function ATTRIBUTE_UNUSED) static void sparc_output_function_epilogue (FILE *file, HOST_WIDE_INT size) { - if (TARGET_FLAT) - sparc_flat_function_epilogue (file, size); - else - sparc_nonflat_function_epilogue (file, size, - current_function_uses_only_leaf_regs); + sparc_function_epilogue (file, size, + current_function_uses_only_leaf_regs); } /* Output code for the function epilogue. */ static void -sparc_nonflat_function_epilogue (FILE *file, - HOST_WIDE_INT size ATTRIBUTE_UNUSED, - int leaf_function) +sparc_function_epilogue (FILE *file, + HOST_WIDE_INT size ATTRIBUTE_UNUSED, + int leaf_function) { const char *ret; @@ -7405,724 +7392,6 @@ sparc64_initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt) #endif } -/* Subroutines to support a flat (single) register window calling - convention. */ - -/* Single-register window sparc stack frames look like: - - Before call After call - +-----------------------+ +-----------------------+ - high | | | | - mem | caller's temps. | | caller's temps. | - | | | | - +-----------------------+ +-----------------------+ - | | | | - | arguments on stack. | | arguments on stack. | - | | | | - +-----------------------+FP+92->+-----------------------+ - | 6 words to save | | 6 words to save | - | arguments passed | | arguments passed | - | in registers, even | | in registers, even | - | if not passed. | | if not passed. | - SP+68->+-----------------------+FP+68->+-----------------------+ - | 1 word struct addr | | 1 word struct addr | - +-----------------------+FP+64->+-----------------------+ - | | | | - | 16 word reg save area | | 16 word reg save area | - | | | | - SP->+-----------------------+ FP->+-----------------------+ - | 4 word area for | - | fp/alu reg moves | - FP-16->+-----------------------+ - | | - | local variables | - | | - +-----------------------+ - | | - | fp register save | - | | - +-----------------------+ - | | - | gp register save | - | | - +-----------------------+ - | | - | alloca allocations | - | | - +-----------------------+ - | | - | arguments on stack | - | | - SP+92->+-----------------------+ - | 6 words to save | - | arguments passed | - | in registers, even | - low | if not passed. | - memory SP+68->+-----------------------+ - | 1 word struct addr | - SP+64->+-----------------------+ - | | - I 16 word reg save area | - | | - SP->+-----------------------+ */ - -/* Structure to be filled in by sparc_flat_compute_frame_size with register - save masks, and offsets for the current function. */ - -struct sparc_frame_info -{ - HOST_WIDE_INT total_size; /* # bytes that the entire frame takes up. */ - HOST_WIDE_INT var_size; /* # bytes that variables take up. */ - int args_size; /* # bytes that outgoing arguments take up. */ - int extra_size; /* # bytes of extra gunk. */ - int gp_reg_size; /* # bytes needed to store gp regs. */ - int fp_reg_size; /* # bytes needed to store fp regs. */ - unsigned long gmask; /* Mask of saved gp registers. */ - unsigned long fmask; /* Mask of saved fp registers. */ - int reg_offset; /* Offset from new sp to store regs. */ - int initialized; /* Nonzero if frame size already calculated. */ -}; - -/* Current frame information calculated by sparc_flat_compute_frame_size. */ -struct sparc_frame_info current_frame_info; - -/* Zero structure to initialize current_frame_info. */ -struct sparc_frame_info zero_frame_info; - -#define RETURN_ADDR_REGNUM 15 -#define HARD_FRAME_POINTER_MASK (1 << (HARD_FRAME_POINTER_REGNUM)) -#define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM)) - -/* Tell prologue and epilogue if register REGNO should be saved / restored. */ - -static bool -sparc_flat_must_save_register_p (int regno) -{ - /* General case: call-saved registers live at some point. */ - if (!call_used_regs[regno] && regs_ever_live[regno]) - return true; - - /* Frame pointer register (%i7) if needed. */ - if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed) - return true; - - /* PIC register (%l7) if needed. */ - if (regno == (int) PIC_OFFSET_TABLE_REGNUM - && flag_pic && current_function_uses_pic_offset_table) - return true; - - /* Return address register (%o7) if needed. */ - if (regno == RETURN_ADDR_REGNUM - && (regs_ever_live[RETURN_ADDR_REGNUM] - /* When the PIC offset table is used, the PIC register - is set by using a bare call that clobbers %o7. */ - || (flag_pic && current_function_uses_pic_offset_table))) - return true; - - return false; -} - -/* Return the bytes needed to compute the frame pointer from the current - stack pointer. */ - -HOST_WIDE_INT -sparc_flat_compute_frame_size (HOST_WIDE_INT size) - /* # of var. bytes allocated. */ -{ - int regno; - HOST_WIDE_INT total_size; /* # bytes that the entire frame takes up. */ - HOST_WIDE_INT var_size; /* # bytes that variables take up. */ - int args_size; /* # bytes that outgoing arguments take up. */ - int extra_size; /* # extra bytes. */ - int gp_reg_size; /* # bytes needed to store gp regs. */ - int fp_reg_size; /* # bytes needed to store fp regs. */ - unsigned long gmask; /* Mask of saved gp registers. */ - unsigned long fmask; /* Mask of saved fp registers. */ - int reg_offset; /* Offset to register save area. */ - int need_aligned_p; /* 1 if need the save area 8 byte aligned. */ - - /* This is the size of the 16 word reg save area, 1 word struct addr - area, and 4 word fp/alu register copy area. */ - extra_size = -STARTING_FRAME_OFFSET + FIRST_PARM_OFFSET(0); - var_size = size; - gp_reg_size = 0; - fp_reg_size = 0; - gmask = 0; - fmask = 0; - reg_offset = 0; - need_aligned_p = 0; - - args_size = 0; - if (!leaf_function_p ()) - { - /* Also include the size needed for the 6 parameter registers. */ - args_size = current_function_outgoing_args_size + 24; - } - total_size = var_size + args_size; - - /* Calculate space needed for gp registers. */ - for (regno = 1; regno <= 31; regno++) - { - if (sparc_flat_must_save_register_p (regno)) - { - /* If we need to save two regs in a row, ensure there's room to bump - up the address to align it to a doubleword boundary. */ - if ((regno & 0x1) == 0 && sparc_flat_must_save_register_p (regno+1)) - { - if (gp_reg_size % 8 != 0) - gp_reg_size += 4; - gp_reg_size += 2 * UNITS_PER_WORD; - gmask |= 3 << regno; - regno++; - need_aligned_p = 1; - } - else - { - gp_reg_size += UNITS_PER_WORD; - gmask |= 1 << regno; - } - } - } - - /* Calculate space needed for fp registers. */ - for (regno = 32; regno <= 63; regno++) - { - if (regs_ever_live[regno] && !call_used_regs[regno]) - { - fp_reg_size += UNITS_PER_WORD; - fmask |= 1 << (regno - 32); - } - } - - if (gmask || fmask) - { - int n; - reg_offset = FIRST_PARM_OFFSET(0) + args_size; - /* Ensure save area is 8 byte aligned if we need it. */ - n = reg_offset % 8; - if (need_aligned_p && n != 0) - { - total_size += 8 - n; - reg_offset += 8 - n; - } - total_size += gp_reg_size + fp_reg_size; - } - - /* If we must allocate a stack frame at all, we must also allocate - room for register window spillage, so as to be binary compatible - with libraries and operating systems that do not use -mflat. */ - if (total_size > 0) - total_size += extra_size; - else - extra_size = 0; - - total_size = SPARC_STACK_ALIGN (total_size); - - /* Save other computed information. */ - current_frame_info.total_size = total_size; - current_frame_info.var_size = var_size; - current_frame_info.args_size = args_size; - current_frame_info.extra_size = extra_size; - current_frame_info.gp_reg_size = gp_reg_size; - current_frame_info.fp_reg_size = fp_reg_size; - current_frame_info.gmask = gmask; - current_frame_info.fmask = fmask; - current_frame_info.reg_offset = reg_offset; - current_frame_info.initialized = reload_completed; - - /* Ok, we're done. */ - return total_size; -} - -/* Save/restore registers in GMASK and FMASK at register BASE_REG plus offset - OFFSET. - - BASE_REG must be 8 byte aligned. This allows us to test OFFSET for - appropriate alignment and use DOUBLEWORD_OP when we can. We assume - [BASE_REG+OFFSET] will always be a valid address. - - WORD_OP is either "st" for save, "ld" for restore. - DOUBLEWORD_OP is either "std" for save, "ldd" for restore. */ - -static void -sparc_flat_save_restore (FILE *file, const char *base_reg, int offset, - unsigned long gmask, unsigned long fmask, - const char *word_op, const char *doubleword_op, - HOST_WIDE_INT base_offset) -{ - int regno; - - if (gmask == 0 && fmask == 0) - return; - - /* Save registers starting from high to low. We've already saved the - previous frame pointer and previous return address for the debugger's - sake. The debugger allows us to not need a nop in the epilog if at least - one register is reloaded in addition to return address. */ - - if (gmask) - { - for (regno = 1; regno <= 31; regno++) - { - if ((gmask & (1L << regno)) != 0) - { - if ((regno & 0x1) == 0 && ((gmask & (1L << (regno+1))) != 0)) - { - /* We can save two registers in a row. If we're not at a - double word boundary, move to one. - sparc_flat_compute_frame_size ensures there's room to do - this. */ - if (offset % 8 != 0) - offset += UNITS_PER_WORD; - - if (word_op[0] == 's') - { - fprintf (file, "\t%s\t%s, [%s+%d]\n", - doubleword_op, reg_names[regno], - base_reg, offset); - if (dwarf2out_do_frame ()) - { - char *l = dwarf2out_cfi_label (); - dwarf2out_reg_save (l, regno, offset + base_offset); - dwarf2out_reg_save - (l, regno+1, offset+base_offset + UNITS_PER_WORD); - } - } - else - fprintf (file, "\t%s\t[%s+%d], %s\n", - doubleword_op, base_reg, offset, - reg_names[regno]); - - offset += 2 * UNITS_PER_WORD; - regno++; - } - else - { - if (word_op[0] == 's') - { - fprintf (file, "\t%s\t%s, [%s+%d]\n", - word_op, reg_names[regno], - base_reg, offset); - if (dwarf2out_do_frame ()) - dwarf2out_reg_save ("", regno, offset + base_offset); - } - else - fprintf (file, "\t%s\t[%s+%d], %s\n", - word_op, base_reg, offset, reg_names[regno]); - - offset += UNITS_PER_WORD; - } - } - } - } - - if (fmask) - { - for (regno = 32; regno <= 63; regno++) - { - if ((fmask & (1L << (regno - 32))) != 0) - { - if (word_op[0] == 's') - { - fprintf (file, "\t%s\t%s, [%s+%d]\n", - word_op, reg_names[regno], - base_reg, offset); - if (dwarf2out_do_frame ()) - dwarf2out_reg_save ("", regno, offset + base_offset); - } - else - fprintf (file, "\t%s\t[%s+%d], %s\n", - word_op, base_reg, offset, reg_names[regno]); - - offset += UNITS_PER_WORD; - } - } - } -} - -/* Set up the stack and frame (if desired) for the function. */ - -static void -sparc_flat_function_prologue (FILE *file, HOST_WIDE_INT size) -{ - const char *sp_str = reg_names[STACK_POINTER_REGNUM]; - unsigned long gmask = current_frame_info.gmask; - - sparc_output_scratch_registers (file); - - /* This is only for the human reader. */ - fprintf (file, "\t%s#PROLOGUE# 0\n", ASM_COMMENT_START); - fprintf (file, "\t%s# vars= "HOST_WIDE_INT_PRINT_DEC", " - "regs= %d/%d, args= %d, extra= %d\n", - ASM_COMMENT_START, - current_frame_info.var_size, - current_frame_info.gp_reg_size / 4, - current_frame_info.fp_reg_size / 4, - current_function_outgoing_args_size, - current_frame_info.extra_size); - - size = SPARC_STACK_ALIGN (size); - size = (! current_frame_info.initialized - ? sparc_flat_compute_frame_size (size) - : current_frame_info.total_size); - - /* These cases shouldn't happen. Catch them now. */ - if (size == 0 && (gmask || current_frame_info.fmask)) - abort (); - - /* Allocate our stack frame by decrementing %sp. - At present, the only algorithm gdb can use to determine if this is a - flat frame is if we always set %i7 if we set %sp. This can be optimized - in the future by putting in some sort of debugging information that says - this is a `flat' function. However, there is still the case of debugging - code without such debugging information (including cases where most fns - have such info, but there is one that doesn't). So, always do this now - so we don't get a lot of code out there that gdb can't handle. - If the frame pointer isn't needn't then that's ok - gdb won't be able to - distinguish us from a non-flat function but there won't (and shouldn't) - be any differences anyway. The return pc is saved (if necessary) right - after %i7 so gdb won't have to look too far to find it. */ - if (size > 0) - { - int reg_offset = current_frame_info.reg_offset; - const char *const fp_str = reg_names[HARD_FRAME_POINTER_REGNUM]; - static const char *const t1_str = "%g1"; - - /* Things get a little tricky if local variables take up more than ~4096 - bytes and outgoing arguments take up more than ~4096 bytes. When that - happens, the register save area can't be accessed from either end of - the frame. Handle this by decrementing %sp to the start of the gp - register save area, save the regs, update %i7, and then set %sp to its - final value. Given that we only have one scratch register to play - with it is the cheapest solution, and it helps gdb out as it won't - slow down recognition of flat functions. - Don't change the order of insns emitted here without checking with - the gdb folk first. */ - - /* Is the entire register save area offsettable from %sp? */ - if (reg_offset < 4096 - 64 * UNITS_PER_WORD) - { - if (size <= 4096) - { - fprintf (file, "\tadd\t%s, -"HOST_WIDE_INT_PRINT_DEC", %s\n", - sp_str, size, sp_str); - if (gmask & HARD_FRAME_POINTER_MASK) - { - fprintf (file, "\tst\t%s, [%s+%d]\n", - fp_str, sp_str, reg_offset); - fprintf (file, "\tsub\t%s, -"HOST_WIDE_INT_PRINT_DEC", %s" - "\t%s# set up frame pointer\n", - sp_str, size, fp_str, ASM_COMMENT_START); - reg_offset += 4; - } - } - else - { - build_big_number (file, size, t1_str); - fprintf (file, "\tsub\t%s, %s, %s\n", sp_str, t1_str, sp_str); - if (gmask & HARD_FRAME_POINTER_MASK) - { - fprintf (file, "\tst\t%s, [%s+%d]\n", - fp_str, sp_str, reg_offset); - fprintf (file, "\tadd\t%s, %s, %s\t%s# set up frame pointer\n", - sp_str, t1_str, fp_str, ASM_COMMENT_START); - reg_offset += 4; - } - } - if (dwarf2out_do_frame ()) - { - char *l = dwarf2out_cfi_label (); - if (gmask & HARD_FRAME_POINTER_MASK) - { - dwarf2out_reg_save (l, HARD_FRAME_POINTER_REGNUM, - reg_offset - 4 - size); - dwarf2out_def_cfa (l, HARD_FRAME_POINTER_REGNUM, 0); - } - else - dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, size); - } - if (gmask & RETURN_ADDR_MASK) - { - fprintf (file, "\tst\t%s, [%s+%d]\n", - reg_names[RETURN_ADDR_REGNUM], sp_str, reg_offset); - if (dwarf2out_do_frame ()) - dwarf2out_return_save ("", reg_offset - size); - reg_offset += 4; - } - sparc_flat_save_restore (file, sp_str, reg_offset, - gmask & ~(HARD_FRAME_POINTER_MASK | RETURN_ADDR_MASK), - current_frame_info.fmask, - "st", "std", -size); - } - else - { - /* Subtract %sp in two steps, but make sure there is always a - 64-byte register save area, and %sp is properly aligned. */ - - /* Amount to decrement %sp by, the first time. */ - HOST_WIDE_INT size1 = ((size - reg_offset + 64) + 15) & -16; - - /* Amount to decrement %sp by, the second time. */ - HOST_WIDE_INT size2 = size - size1; - - /* Offset to register save area from %sp after first decrement. */ - int offset = (int)(size1 - (size - reg_offset)); - - if (size1 <= 4096) - { - fprintf (file, "\tadd\t%s, -"HOST_WIDE_INT_PRINT_DEC", %s\n", - sp_str, size1, sp_str); - if (gmask & HARD_FRAME_POINTER_MASK) - { - fprintf (file, "\tst\t%s, [%s+%d]\n" - "\tsub\t%s, -"HOST_WIDE_INT_PRINT_DEC", %s" - "\t%s# set up frame pointer\n", - fp_str, sp_str, offset, sp_str, size1, - fp_str, ASM_COMMENT_START); - offset += 4; - } - } - else - { - build_big_number (file, size1, t1_str); - fprintf (file, "\tsub\t%s, %s, %s\n", sp_str, t1_str, sp_str); - if (gmask & HARD_FRAME_POINTER_MASK) - { - fprintf (file, "\tst\t%s, [%s+%d]\n" - "\tadd\t%s, %s, %s\t%s# set up frame pointer\n", - fp_str, sp_str, offset, sp_str, t1_str, - fp_str, ASM_COMMENT_START); - offset += 4; - } - } - if (dwarf2out_do_frame ()) - { - char *l = dwarf2out_cfi_label (); - if (gmask & HARD_FRAME_POINTER_MASK) - { - dwarf2out_reg_save (l, HARD_FRAME_POINTER_REGNUM, - offset - 4 - size1); - dwarf2out_def_cfa (l, HARD_FRAME_POINTER_REGNUM, 0); - } - else - dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, size1); - } - if (gmask & RETURN_ADDR_MASK) - { - fprintf (file, "\tst\t%s, [%s+%d]\n", - reg_names[RETURN_ADDR_REGNUM], sp_str, offset); - if (dwarf2out_do_frame ()) - /* offset - size1 == reg_offset - size - if reg_offset were updated above like offset. */ - dwarf2out_return_save ("", offset - size1); - offset += 4; - } - sparc_flat_save_restore (file, sp_str, offset, - gmask & ~(HARD_FRAME_POINTER_MASK | RETURN_ADDR_MASK), - current_frame_info.fmask, - "st", "std", -size1); - if (size2 <= 4096) - fprintf (file, "\tadd\t%s, -"HOST_WIDE_INT_PRINT_DEC", %s\n", - sp_str, size2, sp_str); - else - { - build_big_number (file, size2, t1_str); - fprintf (file, "\tsub\t%s, %s, %s\n", sp_str, t1_str, sp_str); - } - if (dwarf2out_do_frame ()) - if (! (gmask & HARD_FRAME_POINTER_MASK)) - dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, size); - } - } - - fprintf (file, "\t%s#PROLOGUE# 1\n", ASM_COMMENT_START); -} - -/* Do any necessary cleanup after a function to restore stack, frame, - and regs. */ - -static void -sparc_flat_function_epilogue (FILE *file, HOST_WIDE_INT size) -{ - rtx epilogue_delay = current_function_epilogue_delay_list; - int noepilogue = FALSE; - - /* This is only for the human reader. */ - fprintf (file, "\t%s#EPILOGUE#\n", ASM_COMMENT_START); - - /* The epilogue does not depend on any registers, but the stack - registers, so we assume that if we have 1 pending nop, it can be - ignored, and 2 it must be filled (2 nops occur for integer - multiply and divide). */ - - size = SPARC_STACK_ALIGN (size); - size = (!current_frame_info.initialized - ? sparc_flat_compute_frame_size (size) - : current_frame_info.total_size); - - if (size == 0 && epilogue_delay == 0) - { - rtx insn = get_last_insn (); - - /* If the last insn was a BARRIER, we don't have to write any code - because a jump (aka return) was put there. */ - if (GET_CODE (insn) == NOTE) - insn = prev_nonnote_insn (insn); - if (insn && GET_CODE (insn) == BARRIER) - noepilogue = TRUE; - } - - if (!noepilogue) - { - int reg_offset = current_frame_info.reg_offset; - int reg_offset1; - const char *const sp_str = reg_names[STACK_POINTER_REGNUM]; - const char *const fp_str = reg_names[HARD_FRAME_POINTER_REGNUM]; - static const char *const t1_str = "%g1"; - - /* In the reload sequence, we don't need to fill the load delay - slots for most of the loads, also see if we can fill the final - delay slot if not otherwise filled by the reload sequence. */ - - if (size > 4096) - build_big_number (file, size, t1_str); - - if (frame_pointer_needed) - { - if (size > 4096) - fprintf (file,"\tsub\t%s, %s, %s\t\t%s# sp not trusted here\n", - fp_str, t1_str, sp_str, ASM_COMMENT_START); - else - fprintf (file,"\tadd\t%s, -"HOST_WIDE_INT_PRINT_DEC", %s" - "\t\t%s# sp not trusted here\n", - fp_str, size, sp_str, ASM_COMMENT_START); - } - - /* Is the entire register save area offsettable from %sp? */ - if (reg_offset < 4096 - 64 * UNITS_PER_WORD) - { - reg_offset1 = 0; - } - else - { - /* Restore %sp in two steps, but make sure there is always a - 64-byte register save area, and %sp is properly aligned. */ - - /* Amount to increment %sp by, the first time. */ - reg_offset1 = ((reg_offset - 64 - 16) + 15) & -16; - - /* Offset to register save area from %sp. */ - reg_offset = reg_offset1 - reg_offset; - - if (reg_offset1 > 4096) - { - build_big_number (file, reg_offset1, t1_str); - fprintf (file, "\tadd\t%s, %s, %s\n", sp_str, t1_str, sp_str); - } - else - fprintf (file, "\tsub\t%s, -%d, %s\n", sp_str, reg_offset1, sp_str); - } - - /* We must restore the frame pointer and return address reg first - because they are treated specially by the prologue output code. */ - if (current_frame_info.gmask & HARD_FRAME_POINTER_MASK) - { - fprintf (file, "\tld\t[%s+%d], %s\n", - sp_str, reg_offset, fp_str); - reg_offset += 4; - } - if (current_frame_info.gmask & RETURN_ADDR_MASK) - { - fprintf (file, "\tld\t[%s+%d], %s\n", - sp_str, reg_offset, reg_names[RETURN_ADDR_REGNUM]); - reg_offset += 4; - } - - /* Restore any remaining saved registers. */ - sparc_flat_save_restore (file, sp_str, reg_offset, - current_frame_info.gmask & ~(HARD_FRAME_POINTER_MASK | RETURN_ADDR_MASK), - current_frame_info.fmask, - "ld", "ldd", 0); - - /* If we had to increment %sp in two steps, record it so the second - restoration in the epilogue finishes up. */ - if (reg_offset1 > 0) - { - size -= reg_offset1; - if (size > 4096) - build_big_number (file, size, t1_str); - } - - if (current_function_returns_struct) - fprintf (file, "\tjmp\t%%o7+12\n"); - else - fprintf (file, "\tretl\n"); - - /* If the only register saved is the return address, we need a - nop, unless we have an instruction to put into it. Otherwise - we don't since reloading multiple registers doesn't reference - the register being loaded. */ - - if (epilogue_delay) - { - if (size) - abort (); - final_scan_insn (XEXP (epilogue_delay, 0), file, 1, -2, 1, NULL); - } - - else if (size > 4096) - fprintf (file, "\tadd\t%s, %s, %s\n", sp_str, t1_str, sp_str); - - else if (size > 0) - fprintf (file, "\tsub\t%s, -"HOST_WIDE_INT_PRINT_DEC", %s\n", - sp_str, size, sp_str); - - else - fprintf (file, "\tnop\n"); - } - - /* Reset state info for each function. */ - current_frame_info = zero_frame_info; - - sparc_output_deferred_case_vectors (); -} - -/* Define the number of delay slots needed for the function epilogue. - - On the sparc, we need a slot if either no stack has been allocated, - or the only register saved is the return register. */ - -int -sparc_flat_epilogue_delay_slots (void) -{ - if (!current_frame_info.initialized) - (void) sparc_flat_compute_frame_size (get_frame_size ()); - - if (current_frame_info.total_size == 0) - return 1; - - return 0; -} - -/* Return true if TRIAL is a valid insn for the epilogue delay slot. - Any single length instruction which doesn't reference the stack or frame - pointer is OK. */ - -int -sparc_flat_eligible_for_epilogue_delay (rtx trial, int slot ATTRIBUTE_UNUSED) -{ - rtx pat = PATTERN (trial); - - if (get_attr_length (trial) != 1) - return 0; - - if (! reg_mentioned_p (stack_pointer_rtx, pat) - && ! reg_mentioned_p (frame_pointer_rtx, pat)) - return 1; - - return 0; -} - /* Adjust the cost of a scheduling dependency. Return the new cost of a dependency LINK or INSN on DEP_INSN. COST is the current cost. */ @@ -8640,10 +7909,9 @@ sparc_elf_asm_named_section (const char *name, unsigned int flags) } #endif /* OBJECT_FORMAT_ELF */ -/* We do not allow sibling calls if -mflat, nor - we do not allow indirect calls to be optimized into sibling calls. +/* We do not allow indirect calls to be optimized into sibling calls. - Also, on sparc 32-bit we cannot emit a sibling call when the + Also, on SPARC 32-bit we cannot emit a sibling call when the current function returns a structure. This is because the "unimp after call" convention would cause the callee to return to the wrong place. The generic code already disallows cases where the @@ -8659,9 +7927,7 @@ sparc_elf_asm_named_section (const char *name, unsigned int flags) static bool sparc_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED) { - return (decl - && ! TARGET_FLAT - && (TARGET_ARCH64 || ! current_function_returns_struct)); + return (decl && (TARGET_ARCH64 || ! current_function_returns_struct)); } /* libfunc renaming. */ |