From 4e5b002baa5ce9097e3a1a4798b31c83f0e2ef56 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Wed, 8 Sep 2004 21:17:53 +0200 Subject: [PATCH] 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 --- gcc/ChangeLog | 27 ++++ gcc/config/sparc/sparc-protos.h | 4 +- gcc/config/sparc/sparc.c | 220 ++++++++++++-------------------- gcc/config/sparc/sparc.h | 17 ++- gcc/config/sparc/sparc.md | 16 +-- 5 files changed, 132 insertions(+), 152 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ce2df35771c..063bcfffaaf 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,30 @@ +2004-09-08 Eric Botcazou + + * 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 * 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 bc4d6ac5c28..71599c96223 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 ac1a4345a07..336d832e61a 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 719900b14d7..562a10d28c6 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 9446cbef168..886d190d16a 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")]) -- 2.30.2