Commit 60b85c4c by Eric Botcazou Committed by Eric Botcazou

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
parent e57e265b
2004-02-03 Eric Botcazou <ebotcazou@libertysurf.fr>
* 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.
2004-02-03 Paolo Bonzini <bonzini@gnu.org> 2004-02-03 Paolo Bonzini <bonzini@gnu.org>
PR c/11658 PR c/11658
......
...@@ -48,12 +48,6 @@ do { \ ...@@ -48,12 +48,6 @@ do { \
#define DATA_SECTION_ASM_OP "\t.data" #define DATA_SECTION_ASM_OP "\t.data"
/* How to renumber registers for dbx and gdb. In the flat model, the frame
pointer is really %i7. */
#define DBX_REGISTER_NUMBER(REGNO) \
(TARGET_FLAT && (REGNO) == HARD_FRAME_POINTER_REGNUM ? 31 : REGNO)
/* This is how to output a note to DBX telling it the line number /* This is how to output a note to DBX telling it the line number
to which the following sequence of instructions corresponds. to which the following sequence of instructions corresponds.
......
...@@ -61,9 +61,3 @@ do { \ ...@@ -61,9 +61,3 @@ do { \
/* Output before writable data. */ /* Output before writable data. */
#define DATA_SECTION_ASM_OP "\t.data" #define DATA_SECTION_ASM_OP "\t.data"
/* How to renumber registers for dbx and gdb. In the flat model, the frame
pointer is really %i7. */
#define DBX_REGISTER_NUMBER(REGNO) \
(TARGET_FLAT && (REGNO) == HARD_FRAME_POINTER_REGNUM ? 31 : REGNO)
...@@ -59,10 +59,6 @@ Boston, MA 02111-1307, USA. */ ...@@ -59,10 +59,6 @@ Boston, MA 02111-1307, USA. */
#undef DBX_CONTIN_CHAR #undef DBX_CONTIN_CHAR
#define DBX_CONTIN_CHAR '?' #define DBX_CONTIN_CHAR '?'
#undef DBX_REGISTER_NUMBER
#define DBX_REGISTER_NUMBER(REGNO) \
(TARGET_FLAT && REGNO == HARD_FRAME_POINTER_REGNUM ? 31 : REGNO)
#undef LOCAL_LABEL_PREFIX #undef LOCAL_LABEL_PREFIX
#define LOCAL_LABEL_PREFIX "." #define LOCAL_LABEL_PREFIX "."
......
...@@ -57,11 +57,6 @@ Boston, MA 02111-1307, USA. */ ...@@ -57,11 +57,6 @@ Boston, MA 02111-1307, USA. */
/* However it appears that Solaris 2.0 uses the same reg numbering as /* However it appears that Solaris 2.0 uses the same reg numbering as
the old BSD-style system did. */ the old BSD-style system did. */
/* Same as sparc.h */
#undef DBX_REGISTER_NUMBER
#define DBX_REGISTER_NUMBER(REGNO) \
(TARGET_FLAT && (REGNO) == HARD_FRAME_POINTER_REGNUM ? 31 : REGNO)
/* The Solaris 2 assembler uses .skip, not .zero, so put this back. */ /* The Solaris 2 assembler uses .skip, not .zero, so put this back. */
#undef ASM_OUTPUT_SKIP #undef ASM_OUTPUT_SKIP
#define ASM_OUTPUT_SKIP(FILE,SIZE) \ #define ASM_OUTPUT_SKIP(FILE,SIZE) \
......
...@@ -53,8 +53,6 @@ extern void order_regs_for_local_alloc (void); ...@@ -53,8 +53,6 @@ extern void order_regs_for_local_alloc (void);
extern HOST_WIDE_INT compute_frame_size (HOST_WIDE_INT, int); extern HOST_WIDE_INT compute_frame_size (HOST_WIDE_INT, int);
extern int check_pic (int); extern int check_pic (int);
extern int short_branch (int, int); extern int short_branch (int, int);
extern int sparc_flat_epilogue_delay_slots (void);
extern HOST_WIDE_INT sparc_flat_compute_frame_size (HOST_WIDE_INT);
extern void sparc_profile_hook (int); extern void sparc_profile_hook (int);
extern void sparc_override_options (void); extern void sparc_override_options (void);
extern int leaf_return_peephole_ok (void); extern int leaf_return_peephole_ok (void);
...@@ -111,7 +109,6 @@ extern int pic_address_needs_scratch (rtx); ...@@ -111,7 +109,6 @@ extern int pic_address_needs_scratch (rtx);
extern int reg_unused_after (rtx, rtx); extern int reg_unused_after (rtx, rtx);
extern int register_ok_for_ldd (rtx); extern int register_ok_for_ldd (rtx);
extern int registers_ok_for_ldd_peep (rtx, rtx); extern int registers_ok_for_ldd_peep (rtx, rtx);
extern int sparc_flat_eligible_for_epilogue_delay (rtx, int);
extern int v9_regcmp_p (enum rtx_code); extern int v9_regcmp_p (enum rtx_code);
extern char *sparc_v8plus_shift (rtx *, rtx, const char *); extern char *sparc_v8plus_shift (rtx *, rtx, const char *);
/* Function used for V8+ code generation. Returns 1 if the high /* Function used for V8+ code generation. Returns 1 if the high
......
...@@ -79,7 +79,7 @@ static int num_gfregs; ...@@ -79,7 +79,7 @@ static int num_gfregs;
rtx sparc_compare_op0, sparc_compare_op1; rtx sparc_compare_op0, sparc_compare_op1;
/* Coordinate with the md file wrt special insns created by /* Coordinate with the md file wrt special insns created by
sparc_nonflat_function_epilogue. */ sparc_function_epilogue. */
bool sparc_emitting_epilogue; bool sparc_emitting_epilogue;
/* Vector to say how input registers are mapped to output registers. /* Vector to say how input registers are mapped to output registers.
...@@ -155,14 +155,8 @@ static int set_extends (rtx); ...@@ -155,14 +155,8 @@ static int set_extends (rtx);
static void output_restore_regs (FILE *, int); static void output_restore_regs (FILE *, int);
static void sparc_output_function_prologue (FILE *, HOST_WIDE_INT); static void sparc_output_function_prologue (FILE *, HOST_WIDE_INT);
static void sparc_output_function_epilogue (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_function_epilogue (FILE *, HOST_WIDE_INT, int);
static void sparc_flat_function_prologue (FILE *, HOST_WIDE_INT); static void sparc_function_prologue (FILE *, HOST_WIDE_INT, 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);
#ifdef OBJECT_FORMAT_ELF #ifdef OBJECT_FORMAT_ELF
static void sparc_elf_asm_named_section (const char *, unsigned int); static void sparc_elf_asm_named_section (const char *, unsigned int);
#endif #endif
...@@ -4333,18 +4327,14 @@ sparc_output_scratch_registers (FILE *file ATTRIBUTE_UNUSED) ...@@ -4333,18 +4327,14 @@ sparc_output_scratch_registers (FILE *file ATTRIBUTE_UNUSED)
static void static void
sparc_output_function_prologue (FILE *file, HOST_WIDE_INT size) sparc_output_function_prologue (FILE *file, HOST_WIDE_INT size)
{ {
if (TARGET_FLAT) sparc_function_prologue (file, size,
sparc_flat_function_prologue (file, size); current_function_uses_only_leaf_regs);
else
sparc_nonflat_function_prologue (file, size,
current_function_uses_only_leaf_regs);
} }
/* Output code for the function prologue. */ /* Output code for the function prologue. */
static void static void
sparc_nonflat_function_prologue (FILE *file, HOST_WIDE_INT size, sparc_function_prologue (FILE *file, HOST_WIDE_INT size, int leaf_function)
int leaf_function)
{ {
sparc_output_scratch_registers (file); sparc_output_scratch_registers (file);
...@@ -4498,19 +4488,16 @@ output_restore_regs (FILE *file, int leaf_function ATTRIBUTE_UNUSED) ...@@ -4498,19 +4488,16 @@ output_restore_regs (FILE *file, int leaf_function ATTRIBUTE_UNUSED)
static void static void
sparc_output_function_epilogue (FILE *file, HOST_WIDE_INT size) sparc_output_function_epilogue (FILE *file, HOST_WIDE_INT size)
{ {
if (TARGET_FLAT) sparc_function_epilogue (file, size,
sparc_flat_function_epilogue (file, size); current_function_uses_only_leaf_regs);
else
sparc_nonflat_function_epilogue (file, size,
current_function_uses_only_leaf_regs);
} }
/* Output code for the function epilogue. */ /* Output code for the function epilogue. */
static void static void
sparc_nonflat_function_epilogue (FILE *file, sparc_function_epilogue (FILE *file,
HOST_WIDE_INT size ATTRIBUTE_UNUSED, HOST_WIDE_INT size ATTRIBUTE_UNUSED,
int leaf_function) int leaf_function)
{ {
const char *ret; const char *ret;
...@@ -7405,724 +7392,6 @@ sparc64_initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt) ...@@ -7405,724 +7392,6 @@ sparc64_initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt)
#endif #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 /* 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. */ 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) ...@@ -8640,10 +7909,9 @@ sparc_elf_asm_named_section (const char *name, unsigned int flags)
} }
#endif /* OBJECT_FORMAT_ELF */ #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 current function returns a structure. This is because the "unimp
after call" convention would cause the callee to return to the after call" convention would cause the callee to return to the
wrong place. The generic code already disallows cases where 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) ...@@ -8659,9 +7927,7 @@ sparc_elf_asm_named_section (const char *name, unsigned int flags)
static bool static bool
sparc_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED) sparc_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
{ {
return (decl return (decl && (TARGET_ARCH64 || ! current_function_returns_struct));
&& ! TARGET_FLAT
&& (TARGET_ARCH64 || ! current_function_returns_struct));
} }
/* libfunc renaming. */ /* libfunc renaming. */
......
...@@ -442,12 +442,7 @@ extern int target_flags; ...@@ -442,12 +442,7 @@ extern int target_flags;
#define MASK_IMPURE_TEXT 0x100 #define MASK_IMPURE_TEXT 0x100
#define TARGET_IMPURE_TEXT (target_flags & MASK_IMPURE_TEXT) #define TARGET_IMPURE_TEXT (target_flags & MASK_IMPURE_TEXT)
/* Nonzero means that we should generate code using a flat register window /* 0x200 is unused */
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)
/* Nonzero means use the registers that the SPARC ABI reserves for /* Nonzero means use the registers that the SPARC ABI reserves for
application software. This must be the default to coincide with the application software. This must be the default to coincide with the
...@@ -551,10 +546,6 @@ extern int target_flags; ...@@ -551,10 +546,6 @@ extern int target_flags;
N_("Pass -assert pure-text to linker") }, \ N_("Pass -assert pure-text to linker") }, \
{"no-impure-text", -MASK_IMPURE_TEXT, \ {"no-impure-text", -MASK_IMPURE_TEXT, \
N_("Do not pass -assert pure-text to linker") }, \ 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, \ {"app-regs", MASK_APP_REGS, \
N_("Use ABI reserved registers") }, \ N_("Use ABI reserved registers") }, \
{"no-app-regs", -MASK_APP_REGS, \ {"no-app-regs", -MASK_APP_REGS, \
...@@ -571,20 +562,6 @@ extern int target_flags; ...@@ -571,20 +562,6 @@ extern int target_flags;
N_("Utilize Visual Instruction Set") }, \ N_("Utilize Visual Instruction Set") }, \
{"no-vis", -MASK_VIS, \ {"no-vis", -MASK_VIS, \
N_("Do not utilize Visual Instruction Set") }, \ 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, \ {"ptr64", MASK_PTR64, \
N_("Pointers are 64-bit") }, \ N_("Pointers are 64-bit") }, \
{"ptr32", -MASK_PTR64, \ {"ptr32", -MASK_PTR64, \
...@@ -874,7 +851,7 @@ if (TARGET_ARCH64 \ ...@@ -874,7 +851,7 @@ if (TARGET_ARCH64 \
/* Argument passing regs. */ /* Argument passing regs. */
#define SPARC_OUTGOING_INT_ARG_FIRST 8 #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 #define SPARC_FP_ARG_FIRST 32
/* 1 for registers that have pervasive standard uses /* 1 for registers that have pervasive standard uses
...@@ -995,19 +972,6 @@ do \ ...@@ -995,19 +972,6 @@ do \
fixed_regs[4] = 1; \ fixed_regs[4] = 1; \
else if (fixed_regs[4] == 2) \ else if (fixed_regs[4] == 2) \
fixed_regs[4] = 0; \ 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) while (0)
...@@ -1100,16 +1064,9 @@ extern int sparc_mode_class[]; ...@@ -1100,16 +1064,9 @@ extern int sparc_mode_class[];
Zero means the frame pointer need not be set up (and parms Zero means the frame pointer need not be set up (and parms
may be accessed via the stack pointer) in functions that seem suitable. may be accessed via the stack pointer) in functions that seem suitable.
This is computed in `reload', in reload1.c. This is computed in `reload', in reload1.c.
Used in flow.c, global.c, and reload1.c. Used in flow.c, global.c, and reload1.c. */
#define FRAME_POINTER_REQUIRED \
Being a non-leaf function does not mean a frame pointer is needed in the (! (leaf_function_p () && only_leaf_regs_used ()))
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 ()))
/* Base register for access to arguments of the function. */ /* Base register for access to arguments of the function. */
#define ARG_POINTER_REGNUM FRAME_POINTER_REGNUM #define ARG_POINTER_REGNUM FRAME_POINTER_REGNUM
...@@ -1573,7 +1530,6 @@ extern char leaf_reg_remap[]; ...@@ -1573,7 +1530,6 @@ extern char leaf_reg_remap[];
#define REG_PARM_STACK_SPACE(DECL) (6 * UNITS_PER_WORD) #define REG_PARM_STACK_SPACE(DECL) (6 * UNITS_PER_WORD)
/* Definitions for register elimination. */ /* Definitions for register elimination. */
/* ??? In TARGET_FLAT mode we needn't have a hard frame pointer. */
#define ELIMINABLE_REGS \ #define ELIMINABLE_REGS \
{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ {{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
...@@ -1590,17 +1546,11 @@ extern char leaf_reg_remap[]; ...@@ -1590,17 +1546,11 @@ extern char leaf_reg_remap[];
do { \ do { \
(OFFSET) = 0; \ (OFFSET) = 0; \
if ((TO) == STACK_POINTER_REGNUM) \ if ((TO) == STACK_POINTER_REGNUM) \
{ \ /* Note, we always pretend that this is a leaf function \
/* Note, we always pretend that this is a leaf function \ because if it's not, there's no point in trying to \
because if it's not, there's no point in trying to \ eliminate the frame pointer. If it is a leaf \
eliminate the frame pointer. If it is a leaf \ function, we guessed right! */ \
function, we guessed right! */ \ (OFFSET) = compute_frame_size (get_frame_size (), 1); \
if (TARGET_FLAT) \
(OFFSET) = \
sparc_flat_compute_frame_size (get_frame_size ()); \
else \
(OFFSET) = compute_frame_size (get_frame_size (), 1); \
} \
(OFFSET) += SPARC_STACK_BIAS; \ (OFFSET) += SPARC_STACK_BIAS; \
} while (0) } while (0)
...@@ -1622,29 +1572,18 @@ extern char leaf_reg_remap[]; ...@@ -1622,29 +1572,18 @@ extern char leaf_reg_remap[];
/* Some subroutine macros specific to this machine. /* Some subroutine macros specific to this machine.
When !TARGET_FPU, put float return values in the general registers, When !TARGET_FPU, put float return values in the general registers,
since we don't have any fp registers. */ since we don't have any fp registers. */
#define BASE_RETURN_VALUE_REG(MODE) \ #define BASE_RETURN_VALUE_REG(MODE) \
(TARGET_ARCH64 \ (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 : 8)
? (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 : 8) \
: (TARGET_FPU && FLOAT_MODE_P (MODE) && (MODE) != TFmode ? 32 : 8))
#define BASE_OUTGOING_VALUE_REG(MODE) \ #define BASE_OUTGOING_VALUE_REG(MODE) \
(TARGET_ARCH64 \ (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 : 24)
? (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_PASSING_ARG_REG(MODE) \ #define BASE_PASSING_ARG_REG(MODE) \
(TARGET_ARCH64 \ (TARGET_ARCH64 && TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 : 8)
? (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 : 8) \
: 8)
/* ??? FIXME -- seems wrong for v9 structure passing... */ /* ??? FIXME -- seems wrong for v9 structure passing... */
#define BASE_INCOMING_ARG_REG(MODE) \ #define BASE_INCOMING_ARG_REG(MODE) \
(TARGET_ARCH64 \ (TARGET_ARCH64 && TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 : 24)
? (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 \
: TARGET_FLAT ? 8 : 24) \
: (TARGET_FLAT ? 8 : 24))
/* Define this macro if the target machine has "register windows". This /* Define this macro if the target machine has "register windows". This
C expression returns the register number as seen by the called function C expression returns the register number as seen by the called function
...@@ -1652,7 +1591,7 @@ extern char leaf_reg_remap[]; ...@@ -1652,7 +1591,7 @@ extern char leaf_reg_remap[];
Return OUT if register number OUT is not an outbound register. */ Return OUT if register number OUT is not an outbound register. */
#define INCOMING_REGNO(OUT) \ #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 /* Define this macro if the target machine has "register windows". This
C expression returns the register number as seen by the calling function C expression returns the register number as seen by the calling function
...@@ -1660,14 +1599,14 @@ extern char leaf_reg_remap[]; ...@@ -1660,14 +1599,14 @@ extern char leaf_reg_remap[];
Return IN if register number IN is not an inbound register. */ Return IN if register number IN is not an inbound register. */
#define OUTGOING_REGNO(IN) \ #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 /* 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 C expression returns true if the register is call-saved but is in the
register window. */ register window. */
#define LOCAL_REGNO(REGNO) \ #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. /* Define how to find the value returned by a function.
VALTYPE is the data type of the value (as a tree). VALTYPE is the data type of the value (as a tree).
...@@ -1883,15 +1822,13 @@ do { \ ...@@ -1883,15 +1822,13 @@ do { \
(get_frame_size () != 0 \ (get_frame_size () != 0 \
|| current_function_calls_alloca || current_function_outgoing_args_size) || current_function_calls_alloca || current_function_outgoing_args_size)
#define DELAY_SLOTS_FOR_EPILOGUE \ #define DELAY_SLOTS_FOR_EPILOGUE 1
(TARGET_FLAT ? sparc_flat_epilogue_delay_slots () : 1)
#define ELIGIBLE_FOR_EPILOGUE_DELAY(trial, slots_filled) \ #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 registers used by the epilogue and return instruction. */
#define EPILOGUE_USES(REGNO) \ #define EPILOGUE_USES(REGNO) (REGNO == 31)
(!TARGET_FLAT && REGNO == 31)
/* Length in units of the trampoline for entering a nested function. */ /* Length in units of the trampoline for entering a nested function. */
...@@ -1924,8 +1861,7 @@ do { \ ...@@ -1924,8 +1861,7 @@ do { \
/* Given an rtx for the address of a frame, /* Given an rtx for the address of a frame,
return an rtx for the address of the word in the frame return an rtx for the address of the word in the frame
that holds the dynamic chain--the previous frame's address. that holds the dynamic chain--the previous frame's address. */
??? -mflat support? */
#define DYNAMIC_CHAIN_ADDRESS(frame) \ #define DYNAMIC_CHAIN_ADDRESS(frame) \
plus_constant (frame, 14 * UNITS_PER_WORD + SPARC_STACK_BIAS) plus_constant (frame, 14 * UNITS_PER_WORD + SPARC_STACK_BIAS)
......
...@@ -80,12 +80,12 @@ ...@@ -80,12 +80,12 @@
;; Attribute for the instruction set. ;; Attribute for the instruction set.
;; At present we only need to distinguish v9/!v9, but for clarity we ;; At present we only need to distinguish v9/!v9, but for clarity we
;; test TARGET_V8 too. ;; test TARGET_V8 too.
(define_attr "isa" "v6,v8,v9,sparclet" (define_attr "isa" "v7,v8,v9,sparclet"
(const (const
(cond [(symbol_ref "TARGET_V9") (const_string "v9") (cond [(symbol_ref "TARGET_V9") (const_string "v9")
(symbol_ref "TARGET_V8") (const_string "v8") (symbol_ref "TARGET_V8") (const_string "v8")
(symbol_ref "TARGET_SPARCLET") (const_string "sparclet")] (symbol_ref "TARGET_SPARCLET") (const_string "sparclet")]
(const_string "v6")))) (const_string "v7"))))
;; Architecture size. ;; Architecture size.
(define_attr "arch" "arch32bit,arch64bit" (define_attr "arch" "arch32bit,arch64bit"
...@@ -124,9 +124,6 @@ ...@@ -124,9 +124,6 @@
(define_attr "current_function_calls_alloca" "false,true" (define_attr "current_function_calls_alloca" "false,true"
(symbol_ref "current_function_calls_alloca != 0")) (symbol_ref "current_function_calls_alloca != 0"))
(define_attr "flat" "false,true"
(symbol_ref "TARGET_FLAT != 0"))
;; Length (in # of insns). ;; Length (in # of insns).
(define_attr "length" "" (define_attr "length" ""
(cond [(eq_attr "type" "uncond_branch,call,sibcall") (cond [(eq_attr "type" "uncond_branch,call,sibcall")
...@@ -7724,7 +7721,6 @@ ...@@ -7724,7 +7721,6 @@
"jmp\t%a0%#" "jmp\t%a0%#"
[(set_attr "type" "uncond_branch")]) [(set_attr "type" "uncond_branch")])
;; ??? Doesn't work with -mflat.
(define_expand "nonlocal_goto" (define_expand "nonlocal_goto"
[(match_operand:SI 0 "general_operand" "") [(match_operand:SI 0 "general_operand" "")
(match_operand:SI 1 "general_operand" "") (match_operand:SI 1 "general_operand" "")
...@@ -7839,7 +7835,7 @@ ...@@ -7839,7 +7835,7 @@
{ {
if (! current_function_calls_alloca) if (! current_function_calls_alloca)
return ""; return "";
if (! TARGET_V9 || TARGET_FLAT) if (! TARGET_V9)
return "\tta\t3\n"; return "\tta\t3\n";
fputs ("\tflushw\n", asm_out_file); fputs ("\tflushw\n", asm_out_file);
if (flag_pic) if (flag_pic)
...@@ -7858,8 +7854,6 @@ ...@@ -7858,8 +7854,6 @@
(set (attr "length") (set (attr "length")
(cond [(eq_attr "current_function_calls_alloca" "false") (cond [(eq_attr "current_function_calls_alloca" "false")
(const_int 0) (const_int 0)
(eq_attr "flat" "true")
(const_int 1)
(eq_attr "isa" "!v9") (eq_attr "isa" "!v9")
(const_int 1) (const_int 1)
(eq_attr "pic" "true") (eq_attr "pic" "true")
...@@ -8107,7 +8101,7 @@ ...@@ -8107,7 +8101,7 @@
(compare:CCX (match_dup 1) (const_int 0)))])] (compare:CCX (match_dup 1) (const_int 0)))])]
"") "")
;; Return peepholes. These are generated by sparc_nonflat_function_epilogue ;; Return peepholes. These are generated by sparc_function_epilogue
;; who then immediately calls final_scan_insn. ;; who then immediately calls final_scan_insn.
(define_insn "*return_qi" (define_insn "*return_qi"
...@@ -8267,31 +8261,6 @@ ...@@ -8267,31 +8261,6 @@
[(set_attr "type" "multi") [(set_attr "type" "multi")
(set_attr "length" "2")]) (set_attr "length" "2")])
;; Now peepholes to do a call followed by a jump.
(define_peephole
[(parallel [(set (match_operand 0 "" "")
(call (mem:SI (match_operand:SI 1 "call_operand_address" "ps"))
(match_operand 2 "" "")))
(clobber (reg:SI 15))])
(set (pc) (label_ref (match_operand 3 "" "")))]
"short_branch (INSN_UID (insn), INSN_UID (operands[3]))
&& (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))
&& sparc_cpu != PROCESSOR_ULTRASPARC
&& sparc_cpu != PROCESSOR_ULTRASPARC3"
"call\t%a1, %2\n\tadd\t%%o7, (%l3-.-4), %%o7")
(define_peephole
[(parallel [(call (mem:SI (match_operand:SI 0 "call_operand_address" "ps"))
(match_operand 1 "" ""))
(clobber (reg:SI 15))])
(set (pc) (label_ref (match_operand 2 "" "")))]
"short_branch (INSN_UID (insn), INSN_UID (operands[2]))
&& (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))
&& sparc_cpu != PROCESSOR_ULTRASPARC
&& sparc_cpu != PROCESSOR_ULTRASPARC3"
"call\t%a0, %1\n\tadd\t%%o7, (%l2-.-4), %%o7")
;; ??? UltraSPARC-III note: A memory operation loading into the floating point register ;; ??? UltraSPARC-III note: A memory operation loading into the floating point register
;; ??? file, if it hits the prefetch cache, has a chance to dual-issue with other memory ;; ??? file, if it hits the prefetch cache, has a chance to dual-issue with other memory
;; ??? operations. With DFA we might be able to model this, but it requires a lot of ;; ??? operations. With DFA we might be able to model this, but it requires a lot of
...@@ -8370,26 +8339,6 @@ ...@@ -8370,26 +8339,6 @@
load_pic_register (); load_pic_register ();
DONE; DONE;
}) })
;; We need to reload %l7 for -mflat -fpic,
;; otherwise %l7 should be preserved simply
;; by loading the function's register window
(define_expand "exception_receiver"
[(const_int 0)]
"TARGET_FLAT && flag_pic"
{
load_pic_register ();
DONE;
})
;; Likewise
(define_expand "builtin_setjmp_receiver"
[(label_ref (match_operand 0 "" ""))]
"TARGET_FLAT && flag_pic"
{
load_pic_register ();
DONE;
})
(define_insn "trap" (define_insn "trap"
[(trap_if (const_int 1) (const_int 5))] [(trap_if (const_int 1) (const_int 5))]
......
...@@ -15,7 +15,7 @@ fp-bit.c: $(srcdir)/config/fp-bit.c ...@@ -15,7 +15,7 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
echo '#define US_SOFTWARE_GOFAST' >> fp-bit.c echo '#define US_SOFTWARE_GOFAST' >> fp-bit.c
cat $(srcdir)/config/fp-bit.c >> fp-bit.c cat $(srcdir)/config/fp-bit.c >> fp-bit.c
MULTILIB_OPTIONS = mfpu mflat MULTILIB_OPTIONS = mfpu
MULTILIB_DIRNAMES = MULTILIB_DIRNAMES =
MULTILIB_MATCHES = mfpu=mhard-float mfpu=mcpu?f934 MULTILIB_MATCHES = mfpu=mhard-float mfpu=mcpu?f934
......
...@@ -359,15 +359,12 @@ in the following sections. ...@@ -359,15 +359,12 @@ in the following sections.
-mcmodel=@var{code-model} @gol -mcmodel=@var{code-model} @gol
-m32 -m64 -mapp-regs -mno-app-regs @gol -m32 -m64 -mapp-regs -mno-app-regs @gol
-mfaster-structs -mno-faster-structs @gol -mfaster-structs -mno-faster-structs @gol
-mflat -mno-flat -mfpu -mno-fpu @gol -mfpu -mno-fpu -mhard-float -msoft-float @gol
-mhard-float -msoft-float @gol
-mhard-quad-float -msoft-quad-float @gol -mhard-quad-float -msoft-quad-float @gol
-mimpure-text -mno-impure-text -mlittle-endian @gol -mimpure-text -mno-impure-text -mlittle-endian @gol
-mstack-bias -mno-stack-bias @gol -mstack-bias -mno-stack-bias @gol
-munaligned-doubles -mno-unaligned-doubles @gol -munaligned-doubles -mno-unaligned-doubles @gol
-mv8plus -mno-v8plus -mvis -mno-vis @gol -mv8plus -mno-v8plus -mvis -mno-vis}
-mcypress -mf930 -mf934 @gol
-msparclite -msupersparc -mv8}
@emph{ARM Options} @emph{ARM Options}
@gccoptlist{-mapcs-frame -mno-apcs-frame @gol @gccoptlist{-mapcs-frame -mno-apcs-frame @gol
...@@ -6212,22 +6209,6 @@ emulates the effect of the instruction. Because of the trap handler overhead, ...@@ -6212,22 +6209,6 @@ emulates the effect of the instruction. Because of the trap handler overhead,
this is much slower than calling the ABI library routines. Thus the this is much slower than calling the ABI library routines. Thus the
@option{-msoft-quad-float} option is the default. @option{-msoft-quad-float} option is the default.
@item -mno-flat
@itemx -mflat
@opindex mno-flat
@opindex mflat
With @option{-mflat}, the compiler does not generate save/restore instructions
and will use a ``flat'' or single register window calling convention.
This model uses %i7 as the frame pointer and is compatible with the normal
register window model. Code from either may be intermixed.
The local registers and the input registers (0--5) are still treated as
``call saved'' registers and will be saved on the stack as necessary.
With @option{-mno-flat} (the default), the compiler emits save/restore
instructions (except for leaf functions) and is the normal mode of operation.
These options are deprecated and will be deleted in a future GCC release.
@item -mno-unaligned-doubles @item -mno-unaligned-doubles
@itemx -munaligned-doubles @itemx -munaligned-doubles
@opindex mno-unaligned-doubles @opindex mno-unaligned-doubles
...@@ -6270,26 +6251,6 @@ using @option{-mimpure-text}, you should compile all source code with ...@@ -6270,26 +6251,6 @@ using @option{-mimpure-text}, you should compile all source code with
This option is only available on SunOS and Solaris. This option is only available on SunOS and Solaris.
@item -mv8
@itemx -msparclite
@opindex mv8
@opindex msparclite
These two options select variations on the SPARC architecture.
These options are deprecated and will be deleted in a future GCC release.
They have been replaced with @option{-mcpu=xxx}.
@item -mcypress
@itemx -msupersparc
@itemx -mf930
@itemx -mf934
@opindex mcypress
@opindex msupersparc
@opindex -mf930
@opindex -mf934
These four options select the processor for which the code is optimized.
These options are deprecated and will be deleted in a future GCC release.
They have been replaced with @option{-mcpu=xxx}.
@item -mcpu=@var{cpu_type} @item -mcpu=@var{cpu_type}
@opindex mcpu @opindex mcpu
Set the instruction set, register set, and instruction scheduling parameters Set the instruction set, register set, and instruction scheduling parameters
......
2004-02-03 Eric Botcazou <ebotcazou@libertysurf.fr>
* gcc.dg/20020503-1.c: Remove -mflat dg-options.
2004-02-03 Paolo Bonzini <bonzini@gnu.org> 2004-02-03 Paolo Bonzini <bonzini@gnu.org>
PR c/11658 PR c/11658
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
returned -1 for some registers (like %o0). */ returned -1 for some registers (like %o0). */
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O2 -g" } */ /* { dg-options "-O2 -g" } */
/* { dg-options "-O2 -g -mflat" { target sparc*-*-* } } */
void foo (char *a, char *b, char *c, char *d) void foo (char *a, char *b, char *c, char *d)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment