aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@libertysurf.fr>2004-09-08 21:17:53 +0200
committerEric Botcazou <ebotcazou@gcc.gnu.org>2004-09-08 19:17:53 +0000
commit4e5b002baa5ce9097e3a1a4798b31c83f0e2ef56 (patch)
treea9321393d72a1201f896606a77956af853d6274c
parent5826770c628d6e527ac774243d3632ad44ed49ce (diff)
downloadgcc-4e5b002baa5ce9097e3a1a4798b31c83f0e2ef56.zip
gcc-4e5b002baa5ce9097e3a1a4798b31c83f0e2ef56.tar.gz
gcc-4e5b002baa5ce9097e3a1a4798b31c83f0e2ef56.tar.bz2
sparc.c (sparc_indent_opcode): New variable.
* config/sparc/sparc.c (sparc_indent_opcode): New variable. (output_return): Do not test for the presence of the 'unimp' insn. Use 'current_function_uses_only_leaf_regs' and 'final_sequence' as predicates instead of custom ones. Return raw strings when possible. (output_sibcall): Likewise. Concatenate strings. (output_ubranch): Remove kludge for TurboSPARC. (output_cbranch): Remove 'noop' parameter. Do not output 'nop'. (output_v9branch): Likewise. (print_operand): Use 'final_sequence' instead of 'dbr_sequence_length'. <#>: Set sparc_indent_opcode if the delay slot is filled. <(>: Likewise. <)>: New operand to emit the displacement from the saved PC on return. <@>: Remove. * config/sparc/sparc.h (sparc_indent_opcode): Declare it. (ASM_OUTPUT_OPCODE): New macro. (PRINT_OPERAND_PUNCT_VALID_P): Remove '^' and add ')'. * config/sparc/sparc.md (normal_branch, inverted_branch, normal_fp_branch, inverted_fp_branch, normal_fpe_branch, inverted_fpe_branch): Adjust call to output_cbranch. (normal_int_branch_sp64, inverted_int_branch_sp64): Adjust call to output_v9branch. * config/sparc/sparc-protos.h (output_cbranch): Adjust. (output_v9branch): Likewise. From-SVN: r87198
-rw-r--r--gcc/ChangeLog27
-rw-r--r--gcc/config/sparc/sparc-protos.h4
-rw-r--r--gcc/config/sparc/sparc.c220
-rw-r--r--gcc/config/sparc/sparc.h17
-rw-r--r--gcc/config/sparc/sparc.md16
5 files changed, 132 insertions, 152 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ce2df35..063bcff 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,30 @@
+2004-09-08 Eric Botcazou <ebotcazou@libertysurf.fr>
+
+ * config/sparc/sparc.c (sparc_indent_opcode): New variable.
+ (output_return): Do not test for the presence of the 'unimp' insn.
+ Use 'current_function_uses_only_leaf_regs' and 'final_sequence'
+ as predicates instead of custom ones. Return raw strings when
+ possible.
+ (output_sibcall): Likewise. Concatenate strings.
+ (output_ubranch): Remove kludge for TurboSPARC.
+ (output_cbranch): Remove 'noop' parameter. Do not output 'nop'.
+ (output_v9branch): Likewise.
+ (print_operand): Use 'final_sequence' instead of 'dbr_sequence_length'.
+ <#>: Set sparc_indent_opcode if the delay slot is filled.
+ <(>: Likewise.
+ <)>: New operand to emit the displacement from the saved PC on return.
+ <@>: Remove.
+ * config/sparc/sparc.h (sparc_indent_opcode): Declare it.
+ (ASM_OUTPUT_OPCODE): New macro.
+ (PRINT_OPERAND_PUNCT_VALID_P): Remove '^' and add ')'.
+ * config/sparc/sparc.md (normal_branch, inverted_branch,
+ normal_fp_branch, inverted_fp_branch, normal_fpe_branch,
+ inverted_fpe_branch): Adjust call to output_cbranch.
+ (normal_int_branch_sp64, inverted_int_branch_sp64): Adjust
+ call to output_v9branch.
+ * config/sparc/sparc-protos.h (output_cbranch): Adjust.
+ (output_v9branch): Likewise.
+
2004-09-08 Devang Patel <dpatel@apple.com>
* config/darwin.h (TARGET_OPTION_TRANSLATE_TABLE): Add -segaddr,
diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h
index bc4d6ac..71599c9 100644
--- a/gcc/config/sparc/sparc-protos.h
+++ b/gcc/config/sparc/sparc-protos.h
@@ -81,11 +81,11 @@ extern void sparc_emit_set_symbolic_const64 (rtx, rtx, rtx);
extern int sparc_splitdi_legitimate (rtx, rtx);
extern int sparc_absnegfloat_split_legitimate (rtx, rtx);
extern const char *output_ubranch (rtx, int, rtx);
-extern const char *output_cbranch (rtx, rtx, int, int, int, int, rtx);
+extern const char *output_cbranch (rtx, rtx, int, int, int, rtx);
extern const char *output_return (rtx);
extern const char *output_sibcall (rtx, rtx);
extern const char *output_v8plus_shift (rtx *, rtx, const char *);
-extern const char *output_v9branch (rtx, rtx, int, int, int, int, int, rtx);
+extern const char *output_v9branch (rtx, rtx, int, int, int, int, rtx);
extern void emit_v9_brxx_insn (enum rtx_code, rtx, rtx);
extern void print_operand (FILE *, rtx, int);
extern int mems_ok_for_ldd_peep (rtx, rtx, rtx);
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index ac1a434..336d832 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -276,10 +276,12 @@ struct machine_function GTY(())
Normally, this is %fp, but if we are in a leaf procedure, this
is %sp+"something". We record "something" separately as it may
be too big for reg+constant addressing. */
-
static rtx frame_base_reg;
static HOST_WIDE_INT frame_base_offset;
+/* 1 if the next opcode is to be specially indented. */
+int sparc_indent_opcode = 0;
+
static void sparc_init_modes (void);
static void scan_record_type (tree, int *, int *, int *);
static int function_arg_slotno (const CUMULATIVE_ARGS *, enum machine_mode,
@@ -4675,44 +4677,17 @@ output_restore (rtx pat)
const char *
output_return (rtx insn)
{
- int leaf_function_p = current_function_uses_only_leaf_regs;
- bool delay_slot_filled_p = dbr_sequence_length () > 0;
- /* True if the caller has placed an "unimp" insn immediately after the call.
- This insn is used in the 32-bit ABI when calling a function that returns
- a non zero-sized structure. The 64-bit ABI doesn't have it. Be careful
- to have this test be the same as that used on the call. */
- bool sparc_skip_caller_unimp
- = ! TARGET_ARCH64
- && current_function_returns_struct
- && (TREE_CODE (DECL_SIZE (DECL_RESULT (current_function_decl)))
- == INTEGER_CST)
- && ! integer_zerop (DECL_SIZE (DECL_RESULT (current_function_decl)));
-
- if (leaf_function_p)
+ if (current_function_uses_only_leaf_regs)
{
/* This is a leaf function so we don't have to bother restoring the
register window, which frees us from dealing with the convoluted
semantics of restore/return. We simply output the jump to the
- return address and the insn in the delay slot, which usually is
- the substraction restoring the stack pointer %sp. */
+ return address and the insn in the delay slot (if any). */
if (current_function_calls_eh_return)
abort ();
- fprintf (asm_out_file, "\tjmp\t%%o7+%d\n", sparc_skip_caller_unimp ? 12 : 8);
-
- if (delay_slot_filled_p)
- {
- rtx delay = NEXT_INSN (insn);
- if (! delay)
- abort ();
-
- final_scan_insn (delay, asm_out_file, 1, 0, 1, NULL);
- PATTERN (delay) = gen_blockage ();
- INSN_CODE (delay) = -1;
- }
- else
- fputs ("\t nop\n", asm_out_file);
+ return "jmp\t%%o7+%)%#";
}
else
{
@@ -4725,7 +4700,7 @@ output_return (rtx insn)
{
/* If the function uses __builtin_eh_return, the eh_return
machinery occupies the delay slot. */
- if (delay_slot_filled_p || sparc_skip_caller_unimp)
+ if (final_sequence)
abort ();
if (! flag_delayed_branch)
@@ -4741,7 +4716,7 @@ output_return (rtx insn)
else
fputs ("\t nop\n", asm_out_file);
}
- else if (delay_slot_filled_p)
+ else if (final_sequence)
{
rtx delay, pat;
@@ -4754,32 +4729,25 @@ output_return (rtx insn)
if (TARGET_V9 && ! epilogue_renumber (&pat, 1))
{
epilogue_renumber (&pat, 0);
- fprintf (asm_out_file, "\treturn\t%%i7+%d\n",
- sparc_skip_caller_unimp ? 12 : 8);
- final_scan_insn (delay, asm_out_file, 1, 0, 1, NULL);
+ return "return\t%%i7+%)%#";
}
else
{
- fprintf (asm_out_file, "\tjmp\t%%i7+%d\n",
- sparc_skip_caller_unimp ? 12 : 8);
+ output_asm_insn ("jmp\t%%i7+%)", NULL);
output_restore (pat);
+ PATTERN (delay) = gen_blockage ();
+ INSN_CODE (delay) = -1;
}
-
- PATTERN (delay) = gen_blockage ();
- INSN_CODE (delay) = -1;
}
else
{
/* The delay slot is empty. */
if (TARGET_V9)
- fprintf (asm_out_file, "\treturn\t%%i7+%d\n\t nop\n",
- sparc_skip_caller_unimp ? 12 : 8);
+ return "return\t%%i7+%)\n\t nop";
else if (flag_delayed_branch)
- fprintf (asm_out_file, "\tjmp\t%%i7+%d\n\t restore\n",
- sparc_skip_caller_unimp ? 12 : 8);
+ return "jmp\t%%i7+%)\n\t restore";
else
- fprintf (asm_out_file, "\trestore\n\tjmp\t%%o7+%d\n\t nop\n",
- sparc_skip_caller_unimp ? 12 : 8);
+ return "restore\n\tjmp\t%%o7+%)\n\t nop";
}
}
@@ -4791,8 +4759,6 @@ output_return (rtx insn)
const char *
output_sibcall (rtx insn, rtx call_operand)
{
- int leaf_function_p = current_function_uses_only_leaf_regs;
- bool delay_slot_filled_p = dbr_sequence_length () > 0;
rtx operands[1];
if (! flag_delayed_branch)
@@ -4800,36 +4766,23 @@ output_sibcall (rtx insn, rtx call_operand)
operands[0] = call_operand;
- if (leaf_function_p)
+ if (current_function_uses_only_leaf_regs)
{
/* This is a leaf function so we don't have to bother restoring the
register window. We simply output the jump to the function and
the insn in the delay slot (if any). */
- if (LEAF_SIBCALL_SLOT_RESERVED_P && delay_slot_filled_p)
+ if (LEAF_SIBCALL_SLOT_RESERVED_P && final_sequence)
abort();
- if (delay_slot_filled_p)
- {
- rtx delay = NEXT_INSN (insn);
- if (! delay)
- abort ();
-
- output_asm_insn ("sethi\t%%hi(%a0), %%g1", operands);
- output_asm_insn ("jmp\t%%g1 + %%lo(%a0)", operands);
- final_scan_insn (delay, asm_out_file, 1, 0, 1, NULL);
-
- PATTERN (delay) = gen_blockage ();
- INSN_CODE (delay) = -1;
- }
+ if (final_sequence)
+ output_asm_insn ("sethi\t%%hi(%a0), %%g1\n\tjmp\t%%g1 + %%lo(%a0)%#",
+ operands);
else
- {
- /* Use or with rs2 %%g0 instead of mov, so that as/ld can optimize
- it into branch if possible. */
- output_asm_insn ("or\t%%o7, %%g0, %%g1", operands);
- output_asm_insn ("call\t%a0, 0", operands);
- output_asm_insn (" or\t%%g1, %%g0, %%o7", operands);
- }
+ /* Use or with rs2 %%g0 instead of mov, so that as/ld can optimize
+ it into branch if possible. */
+ output_asm_insn ("or\t%%o7, %%g0, %%g1\n\tcall\t%a0, 0\n\t or\t%%g1, %%g0, %%o7",
+ operands);
}
else
{
@@ -4839,7 +4792,7 @@ output_sibcall (rtx insn, rtx call_operand)
output_asm_insn ("call\t%a0, 0", operands);
- if (delay_slot_filled_p)
+ if (final_sequence)
{
rtx delay = NEXT_INSN (insn);
if (! delay)
@@ -6118,51 +6071,29 @@ const char *
output_ubranch (rtx dest, int label, rtx insn)
{
static char string[64];
- bool noop = false;
+ bool v9_form = false;
char *p;
- /* TurboSPARC is reported to have problems with
- with
- foo: b,a foo
- i.e. an empty loop with the annul bit set. The workaround is to use
- foo: b foo; nop
- instead. */
-
- if (! TARGET_V9 && flag_delayed_branch
- && (INSN_ADDRESSES (INSN_UID (dest))
- == INSN_ADDRESSES (INSN_UID (insn))))
+ if (TARGET_V9 && INSN_ADDRESSES_SET_P ())
{
- strcpy (string, "b\t");
- noop = true;
+ int delta = (INSN_ADDRESSES (INSN_UID (dest))
+ - INSN_ADDRESSES (INSN_UID (insn)));
+ /* Leave some instructions for "slop". */
+ if (delta >= -260000 && delta < 260000)
+ v9_form = true;
}
- else
- {
- bool v9_form = false;
-
- if (TARGET_V9 && INSN_ADDRESSES_SET_P ())
- {
- int delta = (INSN_ADDRESSES (INSN_UID (dest))
- - INSN_ADDRESSES (INSN_UID (insn)));
- /* Leave some instructions for "slop". */
- if (delta >= -260000 && delta < 260000)
- v9_form = true;
- }
- if (v9_form)
- strcpy (string, "ba%*,pt\t%%xcc, ");
- else
- strcpy (string, "b%*\t");
- }
+ if (v9_form)
+ strcpy (string, "ba%*,pt\t%%xcc, ");
+ else
+ strcpy (string, "b%*\t");
p = strchr (string, '\0');
*p++ = '%';
*p++ = 'l';
*p++ = '0' + label;
*p++ = '%';
- if (noop)
- *p++ = '#';
- else
- *p++ = '(';
+ *p++ = '(';
*p = '\0';
return string;
@@ -6177,13 +6108,11 @@ output_ubranch (rtx dest, int label, rtx insn)
REVERSED is nonzero if we should reverse the sense of the comparison.
- ANNUL is nonzero if we should generate an annulling branch.
-
- NOOP is nonzero if we have to follow this branch by a noop. */
+ ANNUL is nonzero if we should generate an annulling branch. */
const char *
output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
- int noop, rtx insn)
+ rtx insn)
{
static char string[64];
enum rtx_code code = GET_CODE (op);
@@ -6406,18 +6335,18 @@ output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
if (far)
{
strcpy (p, ".+12\n\t nop\n\tb\t");
- if (annul || noop)
+ /* Skip the next insn if requested or
+ if we know that it will be a nop. */
+ if (annul || ! final_sequence)
p[3] = '6';
p += 14;
}
*p++ = '%';
*p++ = 'l';
- /* Set the char indicating the number of the operand containing the
- label_ref. */
*p++ = label + '0';
+ *p++ = '%';
+ *p++ = '#';
*p = '\0';
- if (noop)
- strcpy (p, "\n\t nop");
return string;
}
@@ -6644,13 +6573,11 @@ sparc_emit_fixunsdi (rtx *operands, enum machine_mode mode)
REVERSED is nonzero if we should reverse the sense of the comparison.
- ANNUL is nonzero if we should generate an annulling branch.
-
- NOOP is nonzero if we have to follow this branch by a noop. */
+ ANNUL is nonzero if we should generate an annulling branch. */
const char *
output_v9branch (rtx op, rtx dest, int reg, int label, int reversed,
- int annul, int noop, rtx insn)
+ int annul, rtx insn)
{
static char string[64];
enum rtx_code code = GET_CODE (op);
@@ -6759,7 +6686,9 @@ output_v9branch (rtx op, rtx dest, int reg, int label, int reversed,
}
strcpy (p, ".+12\n\t nop\n\t");
- if (annul || noop)
+ /* Skip the next insn if requested or
+ if we know that it will be a nop. */
+ if (annul || ! final_sequence)
p[3] = '6';
p += 12;
if (veryfar)
@@ -6776,11 +6705,10 @@ output_v9branch (rtx op, rtx dest, int reg, int label, int reversed,
*p++ = '%';
*p++ = 'l';
*p++ = '0' + label;
+ *p++ = '%';
+ *p++ = '#';
*p = '\0';
- if (noop)
- strcpy (p, "\n\t nop");
-
return string;
}
@@ -7077,43 +7005,55 @@ print_operand (FILE *file, rtx x, int code)
switch (code)
{
case '#':
- /* Output a 'nop' if there's nothing for the delay slot. */
- if (dbr_sequence_length () == 0)
+ /* Output an insn in a delay slot. */
+ if (final_sequence)
+ sparc_indent_opcode = 1;
+ else
fputs ("\n\t nop", file);
return;
case '*':
/* Output an annul flag if there's nothing for the delay slot and we
- are optimizing. This is always used with '(' below. */
- /* Sun OS 4.1.1 dbx can't handle an annulled unconditional branch;
- this is a dbx bug. So, we only do this when optimizing. */
- /* On UltraSPARC, a branch in a delay slot causes a pipeline flush.
+ are optimizing. This is always used with '(' below.
+ Sun OS 4.1.1 dbx can't handle an annulled unconditional branch;
+ this is a dbx bug. So, we only do this when optimizing.
+ On UltraSPARC, a branch in a delay slot causes a pipeline flush.
Always emit a nop in case the next instruction is a branch. */
- if (dbr_sequence_length () == 0
- && (optimize && (int)sparc_cpu < PROCESSOR_V9))
+ if (! final_sequence && (optimize && (int)sparc_cpu < PROCESSOR_V9))
fputs (",a", file);
return;
case '(':
/* Output a 'nop' if there's nothing for the delay slot and we are
not optimizing. This is always used with '*' above. */
- if (dbr_sequence_length () == 0
- && ! (optimize && (int)sparc_cpu < PROCESSOR_V9))
+ if (! final_sequence && ! (optimize && (int)sparc_cpu < PROCESSOR_V9))
fputs ("\n\t nop", file);
+ else if (final_sequence)
+ sparc_indent_opcode = 1;
+ return;
+ case ')':
+ /* Output the right displacement from the saved PC on function return.
+ The caller may have placed an "unimp" insn immediately after the call
+ so we have to account for it. This insn is used in the 32-bit ABI
+ when calling a function that returns a non zero-sized structure. The
+ 64-bit ABI doesn't have it. Be careful to have this test be the same
+ as that used on the call. */
+ if (! TARGET_ARCH64
+ && current_function_returns_struct
+ && (TREE_CODE (DECL_SIZE (DECL_RESULT (current_function_decl)))
+ == INTEGER_CST)
+ && ! integer_zerop (DECL_SIZE (DECL_RESULT (current_function_decl))))
+ fputs ("12", file);
+ else
+ fputc ('8', file);
return;
case '_':
/* Output the Embedded Medium/Anywhere code model base register. */
fputs (EMBMEDANY_BASE_REG, file);
return;
- case '@':
- /* Print out what we are using as the frame pointer. This might
- be %fp, or might be %sp+offset. */
- /* ??? What if offset is too big? Perhaps the caller knows it isn't? */
- fprintf (file, "%s+"HOST_WIDE_INT_PRINT_DEC,
- reg_names[REGNO (frame_base_reg)], frame_base_offset);
- return;
case '&':
/* Print some local dynamic TLS name. */
assemble_name (file, get_some_local_dynamic_name ());
return;
+
case 'Y':
/* Adjust the operand to take into account a RESTORE operation. */
if (GET_CODE (x) == CONST_INT)
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index 719900b..562a10d 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -2517,6 +2517,19 @@ do { \
#define ASM_OUTPUT_IDENT(FILE, NAME) \
fprintf (FILE, "%s\"%s\"\n", IDENT_ASM_OP, NAME);
+/* Prettify the assembly. */
+
+extern int sparc_indent_opcode;
+
+#define ASM_OUTPUT_OPCODE(FILE, PTR) \
+ do { \
+ if (sparc_indent_opcode) \
+ { \
+ putc (' ', FILE); \
+ sparc_indent_opcode = 0; \
+ } \
+ } while (0)
+
/* Emit a dtp-relative reference to a TLS variable. */
#ifdef HAVE_AS_TLS
@@ -2525,8 +2538,8 @@ do { \
#endif
#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
- ((CHAR) == '#' || (CHAR) == '*' || (CHAR) == '^' \
- || (CHAR) == '(' || (CHAR) == '_' || (CHAR) == '&')
+ ((CHAR) == '#' || (CHAR) == '*' || (CHAR) == '(' \
+ || (CHAR) == ')' || (CHAR) == '_' || (CHAR) == '&')
/* Print operand X (an rtx) in assembler syntax to file FILE.
CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 9446cbe..886d190 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -1549,7 +1549,7 @@
{
return output_cbranch (operands[0], operands[1], 1, 0,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
- ! final_sequence, insn);
+ insn);
}
[(set_attr "type" "branch")
(set_attr "branch_type" "icc")])
@@ -1565,7 +1565,7 @@
{
return output_cbranch (operands[0], operands[1], 1, 1,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
- ! final_sequence, insn);
+ insn);
}
[(set_attr "type" "branch")
(set_attr "branch_type" "icc")])
@@ -1582,7 +1582,7 @@
{
return output_cbranch (operands[1], operands[2], 2, 0,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
- ! final_sequence, insn);
+ insn);
}
[(set_attr "type" "branch")
(set_attr "branch_type" "fcc")])
@@ -1599,7 +1599,7 @@
{
return output_cbranch (operands[1], operands[2], 2, 1,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
- ! final_sequence, insn);
+ insn);
}
[(set_attr "type" "branch")
(set_attr "branch_type" "fcc")])
@@ -1616,7 +1616,7 @@
{
return output_cbranch (operands[1], operands[2], 2, 0,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
- ! final_sequence, insn);
+ insn);
}
[(set_attr "type" "branch")
(set_attr "branch_type" "fcc")])
@@ -1633,7 +1633,7 @@
{
return output_cbranch (operands[1], operands[2], 2, 1,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
- ! final_sequence, insn);
+ insn);
}
[(set_attr "type" "branch")
(set_attr "branch_type" "fcc")])
@@ -1655,7 +1655,7 @@
{
return output_v9branch (operands[0], operands[2], 1, 2, 0,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
- ! final_sequence, insn);
+ insn);
}
[(set_attr "type" "branch")
(set_attr "branch_type" "reg")])
@@ -1672,7 +1672,7 @@
{
return output_v9branch (operands[0], operands[2], 1, 2, 1,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
- ! final_sequence, insn);
+ insn);
}
[(set_attr "type" "branch")
(set_attr "branch_type" "reg")])