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.
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
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);
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;
#endif
}
\f
-/* 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))
-\f
-/* 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;
-}
-\f
-/* 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;
-}
-\f
-/* 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;
- }
- }
- }
-}
-\f
-/* 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);
-}
-\f
-/* 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 ();
-}
-\f
-/* 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;
-}
-\f
/* 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. */
}
#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
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));
}
\f
/* libfunc renaming. */
#define MASK_IMPURE_TEXT 0x100
#define TARGET_IMPURE_TEXT (target_flags & MASK_IMPURE_TEXT)
-/* Nonzero means that we should generate code using a flat register window
- model, i.e. no save/restore instructions are generated, which is
- compatible with normal sparc code.
- The frame pointer is %i7 instead of %fp. */
-#define MASK_FLAT 0x200
-#define TARGET_FLAT (target_flags & MASK_FLAT)
+/* 0x200 is unused */
/* Nonzero means use the registers that the SPARC ABI reserves for
application software. This must be the default to coincide with the
N_("Pass -assert pure-text to linker") }, \
{"no-impure-text", -MASK_IMPURE_TEXT, \
N_("Do not pass -assert pure-text to linker") }, \
- {"flat", MASK_FLAT, \
- N_("Use flat register window model") }, \
- {"no-flat", -MASK_FLAT, \
- N_("Do not use flat register window model") }, \
{"app-regs", MASK_APP_REGS, \
N_("Use ABI reserved registers") }, \
{"no-app-regs", -MASK_APP_REGS, \
N_("Utilize Visual Instruction Set") }, \
{"no-vis", -MASK_VIS, \
N_("Do not utilize Visual Instruction Set") }, \
- /* ??? These are deprecated, coerced to -mcpu=. Delete in 2.9. */ \
- {"cypress", 0, \
- N_("Optimize for Cypress processors") }, \
- {"sparclite", 0, \
- N_("Optimize for SPARCLite processors") }, \
- {"f930", 0, \
- N_("Optimize for F930 processors") }, \
- {"f934", 0, \
- N_("Optimize for F934 processors") }, \
- {"v8", 0, \
- N_("Use V8 SPARC ISA") }, \
- {"supersparc", 0, \
- N_("Optimize for SuperSPARC processors") }, \
- /* End of deprecated options. */ \
{"ptr64", MASK_PTR64, \
N_("Pointers are 64-bit") }, \
{"ptr32", -MASK_PTR64, \
/* Argument passing regs. */
#define SPARC_OUTGOING_INT_ARG_FIRST 8
-#define SPARC_INCOMING_INT_ARG_FIRST (TARGET_FLAT ? 8 : 24)
+#define SPARC_INCOMING_INT_ARG_FIRST 24
#define SPARC_FP_ARG_FIRST 32
/* 1 for registers that have pervasive standard uses
fixed_regs[4] = 1; \
else if (fixed_regs[4] == 2) \
fixed_regs[4] = 0; \
- if (TARGET_FLAT) \
- { \
- int regno; \
- /* Let the compiler believe the frame pointer is still \
- %fp, but output it as %i7. */ \
- fixed_regs[31] = 1; \
- reg_names[HARD_FRAME_POINTER_REGNUM] = "%i7"; \
- /* Disable leaf functions */ \
- memset (sparc_leaf_regs, 0, FIRST_PSEUDO_REGISTER); \
- /* Make LEAF_REG_REMAP a noop. */ \
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \
- leaf_reg_remap [regno] = regno; \
- } \
} \
while (0)
Zero means the frame pointer need not be set up (and parms
may be accessed via the stack pointer) in functions that seem suitable.
This is computed in `reload', in reload1.c.
- Used in flow.c, global.c, and reload1.c.
-
- Being a non-leaf function does not mean a frame pointer is needed in the
- flat window model. However, the debugger won't be able to backtrace through
- us with out it. */
-#define FRAME_POINTER_REQUIRED \
- (TARGET_FLAT \
- ? (current_function_calls_alloca \
- || !leaf_function_p ()) \
- : ! (leaf_function_p () && only_leaf_regs_used ()))
+ Used in flow.c, global.c, and reload1.c. */
+#define FRAME_POINTER_REQUIRED \
+ (! (leaf_function_p () && only_leaf_regs_used ()))
/* Base register for access to arguments of the function. */
#define ARG_POINTER_REGNUM FRAME_POINTER_REGNUM
#define REG_PARM_STACK_SPACE(DECL) (6 * UNITS_PER_WORD)
/* Definitions for register elimination. */
-/* ??? In TARGET_FLAT mode we needn't have a hard frame pointer. */
#define ELIMINABLE_REGS \
{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
do { \
(OFFSET) = 0; \
if ((TO) == STACK_POINTER_REGNUM) \
- { \
- /* Note, we always pretend that this is a leaf function \
- because if it's not, there's no point in trying to \
- eliminate the frame pointer. If it is a leaf \
- function, we guessed right! */ \
- if (TARGET_FLAT) \
- (OFFSET) = \
- sparc_flat_compute_frame_size (get_frame_size ()); \
- else \
- (OFFSET) = compute_frame_size (get_frame_size (), 1); \
- } \
+ /* Note, we always pretend that this is a leaf function \
+ because if it's not, there's no point in trying to \
+ eliminate the frame pointer. If it is a leaf \
+ function, we guessed right! */ \
+ (OFFSET) = compute_frame_size (get_frame_size (), 1); \
(OFFSET) += SPARC_STACK_BIAS; \
} while (0)
/* Some subroutine macros specific to this machine.
When !TARGET_FPU, put float return values in the general registers,
since we don't have any fp registers. */
-#define BASE_RETURN_VALUE_REG(MODE) \
- (TARGET_ARCH64 \
- ? (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 : 8) \
- : (TARGET_FPU && FLOAT_MODE_P (MODE) && (MODE) != TFmode ? 32 : 8))
+#define BASE_RETURN_VALUE_REG(MODE) \
+ (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 : 8)
-#define BASE_OUTGOING_VALUE_REG(MODE) \
- (TARGET_ARCH64 \
- ? (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 \
- : TARGET_FLAT ? 8 : 24) \
- : (TARGET_FPU && FLOAT_MODE_P (MODE) && (MODE) != TFmode ? 32\
- : (TARGET_FLAT ? 8 : 24)))
+#define BASE_OUTGOING_VALUE_REG(MODE) \
+ (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 : 24)
#define BASE_PASSING_ARG_REG(MODE) \
- (TARGET_ARCH64 \
- ? (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 : 8) \
- : 8)
+ (TARGET_ARCH64 && TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 : 8)
/* ??? FIXME -- seems wrong for v9 structure passing... */
#define BASE_INCOMING_ARG_REG(MODE) \
- (TARGET_ARCH64 \
- ? (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 \
- : TARGET_FLAT ? 8 : 24) \
- : (TARGET_FLAT ? 8 : 24))
+ (TARGET_ARCH64 && TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 : 24)
/* Define this macro if the target machine has "register windows". This
C expression returns the register number as seen by the called function
Return OUT if register number OUT is not an outbound register. */
#define INCOMING_REGNO(OUT) \
- ((TARGET_FLAT || (OUT) < 8 || (OUT) > 15) ? (OUT) : (OUT) + 16)
+ (((OUT) < 8 || (OUT) > 15) ? (OUT) : (OUT) + 16)
/* Define this macro if the target machine has "register windows". This
C expression returns the register number as seen by the calling function
Return IN if register number IN is not an inbound register. */
#define OUTGOING_REGNO(IN) \
- ((TARGET_FLAT || (IN) < 24 || (IN) > 31) ? (IN) : (IN) - 16)
+ (((IN) < 24 || (IN) > 31) ? (IN) : (IN) - 16)
/* Define this macro if the target machine has register windows. This
C expression returns true if the register is call-saved but is in the
register window. */
#define LOCAL_REGNO(REGNO) \
- (TARGET_FLAT ? 0 : (REGNO) >= 16 && (REGNO) <= 31)
+ ((REGNO) >= 16 && (REGNO) <= 31)
/* Define how to find the value returned by a function.
VALTYPE is the data type of the value (as a tree).
(get_frame_size () != 0 \
|| current_function_calls_alloca || current_function_outgoing_args_size)
-#define DELAY_SLOTS_FOR_EPILOGUE \
- (TARGET_FLAT ? sparc_flat_epilogue_delay_slots () : 1)
+#define DELAY_SLOTS_FOR_EPILOGUE 1
+
#define ELIGIBLE_FOR_EPILOGUE_DELAY(trial, slots_filled) \
- (TARGET_FLAT ? sparc_flat_eligible_for_epilogue_delay (trial, slots_filled) \
- : eligible_for_epilogue_delay (trial, slots_filled))
+ eligible_for_epilogue_delay (trial, slots_filled)
/* Define registers used by the epilogue and return instruction. */
-#define EPILOGUE_USES(REGNO) \
- (!TARGET_FLAT && REGNO == 31)
+#define EPILOGUE_USES(REGNO) (REGNO == 31)
\f
/* Length in units of the trampoline for entering a nested function. */
/* Given an rtx for the address of a frame,
return an rtx for the address of the word in the frame
- that holds the dynamic chain--the previous frame's address.
- ??? -mflat support? */
+ that holds the dynamic chain--the previous frame's address. */
#define DYNAMIC_CHAIN_ADDRESS(frame) \
plus_constant (frame, 14 * UNITS_PER_WORD + SPARC_STACK_BIAS)