From bf62bbf1bc2f110fd887c6ea4f900b5cf75b294a Mon Sep 17 00:00:00 2001 From: Doug Evans Date: Thu, 25 Sep 1997 01:09:41 +0000 Subject: [PATCH] sparc.c (finalize_pic): Update call to gen_get_pc_via_call. * sparc/sparc.c (finalize_pic): Update call to gen_get_pc_via_call. * sparc/sparc.c (sparc_align_{loops,jumps,funcs}_string): New globals. (sparc_align_{loops,jumps,funcs}): New globals. (sparc_override_options): Handle -malign-loops=, -malign-jumps=, -malign-functions=. (move_operand): Use SPARC_SETHI_P. (arith_double_operand): Cast to unsigned HOST_WIDE_INT first, then perform test. (arith11_double_operand): Likewise. (arith10_double_operand): Likewise. (finalize_pic): Finish sparc64 support. (emit_move_sequence): Use SPARC_SETHI_P. Simplify low part of 64 bit constants if able. (output_fp_move_quad): Don't use fmovq unless TARGET_HARD_QUAD. (sparc_builtin_saveregs, sparc64 case): Don't save fp regs if ! TARGET_FPU. * sparc.h (ASM_COMMENT_START): Define. * sparc.c (output_function_prologue): Use it. (sparc_flat_output_function_{epi,pro}logue): Likewise. From-SVN: r15706 --- gcc/config/sparc/sparc.c | 247 +++++++++++++++++++++++---------------- 1 file changed, 146 insertions(+), 101 deletions(-) diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index f040aa7608e..75a9eb5a181 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -116,6 +116,16 @@ static void sparc_init_modes (); /* Option handling. */ +/* Record options as passed by user. */ +char *sparc_align_loops_string; +char *sparc_align_jumps_string; +char *sparc_align_funcs_string; + +/* Parsed values, as a power of two. */ +int sparc_align_loops; +int sparc_align_jumps; +int sparc_align_funcs; + struct sparc_cpu_select sparc_select[] = { /* switch name, tune arch */ @@ -223,6 +233,47 @@ sparc_override_options () if (TARGET_V9 && TARGET_ARCH32) target_flags |= MASK_DEPRECATED_V8_INSNS; + /* Validate -malign-loops= value, or provide default. */ + if (sparc_align_loops_string) + { + sparc_align_loops = exact_log2 (atoi (sparc_align_loops_string)); + if (sparc_align_loops < 2 || sparc_align_loops > 7) + fatal ("-malign-loops=%s is not between 4 and 128 or is not a power of two", + sparc_align_loops_string); + } + else + { + /* ??? This relies on ASM_OUTPUT_ALIGN to not emit the alignment if + its 0. This sounds a bit kludgey. */ + sparc_align_loops = 0; + } + + /* Validate -malign-jumps= value, or provide default. */ + if (sparc_align_jumps_string) + { + sparc_align_jumps = exact_log2 (atoi (sparc_align_jumps_string)); + if (sparc_align_jumps < 2 || sparc_align_loops > 7) + fatal ("-malign-jumps=%s is not between 4 and 128 or is not a power of two", + sparc_align_jumps_string); + } + else + { + /* ??? This relies on ASM_OUTPUT_ALIGN to not emit the alignment if + its 0. This sounds a bit kludgey. */ + sparc_align_jumps = 0; + } + + /* Validate -malign-functions= value, or provide default. */ + if (sparc_align_funcs_string) + { + sparc_align_funcs = exact_log2 (atoi (sparc_align_funcs_string)); + if (sparc_align_funcs < 2 || sparc_align_loops > 7) + fatal ("-malign-functions=%s is not between 4 and 128 or is not a power of two", + sparc_align_funcs_string); + } + else + sparc_align_funcs = DEFAULT_SPARC_ALIGN_FUNCS; + /* Do various machine dependent initializations. */ sparc_init_modes (); } @@ -587,7 +638,7 @@ move_operand (op, mode) if (register_operand (op, mode)) return 1; if (GET_CODE (op) == CONST_INT) - return (SMALL_INT (op) || (INTVAL (op) & 0x3ff) == 0); + return SMALL_INT (op) || SPARC_SETHI_P (INTVAL (op)); if (GET_MODE (op) != mode) return 0; @@ -787,11 +838,11 @@ arith_double_operand (op, mode) || (GET_CODE (op) == CONST_INT && SMALL_INT (op)) || (! TARGET_ARCH64 && GET_CODE (op) == CONST_DOUBLE - && (unsigned) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000 - && (unsigned) (CONST_DOUBLE_HIGH (op) + 0x1000) < 0x2000) + && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000 + && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_HIGH (op) + 0x1000) < 0x2000) || (TARGET_ARCH64 && GET_CODE (op) == CONST_DOUBLE - && (unsigned) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000 + && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000 && ((CONST_DOUBLE_HIGH (op) == -1 && (CONST_DOUBLE_LOW (op) & 0x1000) == 0x1000) || (CONST_DOUBLE_HIGH (op) == 0 @@ -811,14 +862,14 @@ arith11_double_operand (op, mode) return (register_operand (op, mode) || (GET_CODE (op) == CONST_DOUBLE && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode) - && (unsigned) (CONST_DOUBLE_LOW (op) + 0x400) < 0x800 + && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_LOW (op) + 0x400) < 0x800 && ((CONST_DOUBLE_HIGH (op) == -1 && (CONST_DOUBLE_LOW (op) & 0x400) == 0x400) || (CONST_DOUBLE_HIGH (op) == 0 && (CONST_DOUBLE_LOW (op) & 0x400) == 0))) || (GET_CODE (op) == CONST_INT && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode) - && (unsigned) (INTVAL (op) + 0x400) < 0x800)); + && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x400) < 0x800)); } /* Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that @@ -841,7 +892,7 @@ arith10_double_operand (op, mode) && (CONST_DOUBLE_LOW (op) & 0x200) == 0))) || (GET_CODE (op) == CONST_INT && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode) - && (unsigned) (INTVAL (op) + 0x200) < 0x400)); + && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x200) < 0x400)); } /* Return truth value of whether OP is a integer which fits the @@ -1404,8 +1455,6 @@ finalize_pic () flag_pic = 0; - /* ??? sparc64 pic currently under construction. */ - start_sequence (); l1 = gen_label_rtx (); @@ -1421,56 +1470,41 @@ finalize_pic () gen_rtx (LABEL_REF, VOIDmode, l1), pc_rtx)))); - if (! TARGET_ARCH64) - { - l2 = gen_label_rtx (); - emit_label (l1); - /* Note that we pun calls and jumps here! */ - emit_jump_insn (gen_get_pc_sp32 (l2)); - emit_label (l2); - - emit_insn (gen_rtx (SET, VOIDmode, pic_offset_table_rtx, - gen_rtx (HIGH, Pmode, pic_pc_rtx))); - - emit_insn (gen_rtx (SET, VOIDmode, - pic_offset_table_rtx, - gen_rtx (LO_SUM, Pmode, - pic_offset_table_rtx, pic_pc_rtx))); - emit_insn (gen_rtx (SET, VOIDmode, - pic_offset_table_rtx, - gen_rtx (PLUS, Pmode, - pic_offset_table_rtx, - gen_rtx (REG, Pmode, 15)))); - - /* emit_insn (gen_rtx (ASM_INPUT, VOIDmode, "!#PROLOGUE# 1")); */ - LABEL_PRESERVE_P (l1) = 1; - LABEL_PRESERVE_P (l2) = 1; - } - else - { - /* ??? This definately isn't right for -mfullany. */ - /* ??? And it doesn't quite seem right for the others either. */ - emit_label (l1); - emit_insn (gen_get_pc_sp64 (gen_rtx (REG, Pmode, 1))); - - /* Don't let the scheduler separate the previous insn from `l1'. */ - emit_insn (gen_blockage ()); - - emit_insn (gen_rtx (SET, VOIDmode, pic_offset_table_rtx, - gen_rtx (HIGH, Pmode, pic_pc_rtx))); - - emit_insn (gen_rtx (SET, VOIDmode, - pic_offset_table_rtx, - gen_rtx (LO_SUM, Pmode, - pic_offset_table_rtx, pic_pc_rtx))); - emit_insn (gen_rtx (SET, VOIDmode, - pic_offset_table_rtx, - gen_rtx (PLUS, Pmode, - pic_offset_table_rtx, gen_rtx (REG, Pmode, 1)))); - - /* emit_insn (gen_rtx (ASM_INPUT, VOIDmode, "!#PROLOGUE# 1")); */ - LABEL_PRESERVE_P (l1) = 1; - } + /* sparc64: the RDPC instruction doesn't pair, and puts 4 bubbles in the + pipe to boot. So don't use it here, especially when we're + doing a save anyway because of %l7. */ + + l2 = gen_label_rtx (); + emit_label (l1); + + /* Iff we are doing delay branch optimization, slot the sethi up + here so that it will fill the delay slot of the call. */ + if (flag_delayed_branch) + emit_insn (gen_rtx (SET, VOIDmode, pic_offset_table_rtx, + gen_rtx (HIGH, Pmode, pic_pc_rtx))); + + /* Note that we pun calls and jumps here! */ + emit_jump_insn (gen_get_pc_via_call (l2, l1)); + + emit_label (l2); + + if (!flag_delayed_branch) + emit_insn (gen_rtx (SET, VOIDmode, pic_offset_table_rtx, + gen_rtx (HIGH, Pmode, pic_pc_rtx))); + + emit_insn (gen_rtx (SET, VOIDmode, + pic_offset_table_rtx, + gen_rtx (LO_SUM, Pmode, + pic_offset_table_rtx, pic_pc_rtx))); + emit_insn (gen_rtx (SET, VOIDmode, + pic_offset_table_rtx, + gen_rtx (PLUS, Pmode, + pic_offset_table_rtx, + gen_rtx (REG, Pmode, 15)))); + + /* emit_insn (gen_rtx (ASM_INPUT, VOIDmode, "!#PROLOGUE# 1")); */ + LABEL_PRESERVE_P (l1) = 1; + LABEL_PRESERVE_P (l2) = 1; flag_pic = orig_flag_pic; @@ -1569,10 +1603,10 @@ emit_move_sequence (operands, mode) } else if (GET_CODE (operand1) == CONST_INT ? (! SMALL_INT (operand1) - && (INTVAL (operand1) & 0x3ff) != 0) - : (GET_CODE (operand1) == CONST_DOUBLE - ? ! arith_double_operand (operand1, DImode) - : 1)) + && ! SPARC_SETHI_P (INTVAL (operand1))) + : GET_CODE (operand1) == CONST_DOUBLE + ? ! arith_double_operand (operand1, DImode) + : 1) { /* For DImode values, temp must be operand0 because of the way HI and LO_SUM work. The LO_SUM operator only copies half of @@ -1596,6 +1630,10 @@ emit_move_sequence (operands, mode) emit_insn (gen_rtx (SET, VOIDmode, temp, gen_rtx (HIGH, mode, operand1))); + if (GET_CODE (operand1) == CONST_INT) + operand1 = GEN_INT (INTVAL (operand1) & 0xffffffff); + else if (GET_CODE (operand1) == CONST_DOUBLE) + operand1 = GEN_INT (CONST_DOUBLE_LOW (operand1) & 0xffffffff); operands[1] = gen_rtx (LO_SUM, mode, temp, operand1); } } @@ -2207,7 +2245,7 @@ output_fp_move_quad (operands) { if (FP_REG_P (op1)) { - if (TARGET_V9) + if (TARGET_V9 && TARGET_HARD_QUAD) return "fmovq %1,%0"; else return "fmovs %1,%0\n\tfmovs %R1,%R0\n\tfmovs %S1,%S0\n\tfmovs %T1,%T0"; @@ -3133,7 +3171,7 @@ output_function_prologue (file, size, leaf_function) } /* This is only for the human reader. */ - fprintf (file, "\t!#PROLOGUE# 0\n"); + fprintf (file, "\t%s#PROLOGUE# 0\n", ASM_COMMENT_START); if (actual_fsize == 0) /* do nothing. */ ; @@ -3211,7 +3249,7 @@ output_function_prologue (file, size, leaf_function) /* If doing anything with PIC, do it now. */ if (! flag_pic) - fprintf (file, "\t!#PROLOGUE# 1\n"); + fprintf (file, "\t%s#PROLOGUE# 1\n", ASM_COMMENT_START); /* Call saved registers are saved just above the outgoing argument area. */ if (num_gfregs) @@ -3405,10 +3443,11 @@ sparc_builtin_saveregs (arglist) /* ??? If n_intregs + n_floatregs == 0, should we allocate at least 1 byte? Or can assign_stack_local accept a 0 SIZE argument? */ - bufsize = (n_intregs * UNITS_PER_WORD) + (n_floatregs * (UNITS_PER_WORD / 2)); + bufsize = (n_intregs * UNITS_PER_WORD) + + (TARGET_FPU ? (n_floatregs * (UNITS_PER_WORD / 2)) : 0); /* Add space in front of the int regs to ensure proper alignment of quadword fp regs. We must add the space in front because va_start assumes this. */ - if (n_floatregs >= 4) + if (TARGET_FPU && n_floatregs >= 4) adjust = ((n_intregs + first_floatreg / 2) % 2) * UNITS_PER_WORD; else adjust = 0; @@ -3426,23 +3465,26 @@ sparc_builtin_saveregs (arglist) move_block_from_reg (BASE_INCOMING_ARG_REG (SImode) + first_intreg, regbuf, n_intregs, n_intregs * UNITS_PER_WORD); - /* Save float args. - This is optimized to only save the regs that are necessary. Explicitly - named args need not be saved. - We explicitly build a pointer to the buffer because it halves the insn - count when not optimizing (otherwise the pointer is built for each reg - saved). */ - - fpregs = gen_reg_rtx (Pmode); - emit_move_insn (fpregs, plus_constant (XEXP (regbuf, 0), - n_intregs * UNITS_PER_WORD)); - for (regno = first_floatreg; regno < NPARM_REGS (SFmode); regno += 2) - emit_move_insn (gen_rtx (MEM, DFmode, - plus_constant (fpregs, - GET_MODE_SIZE (SFmode) - * (regno - first_floatreg))), - gen_rtx (REG, DFmode, - BASE_INCOMING_ARG_REG (DFmode) + regno)); + if (TARGET_FPU) + { + /* Save float args. + This is optimized to only save the regs that are necessary. + Explicitly named args need not be saved. + We explicitly build a pointer to the buffer because it halves the insn + count when not optimizing (otherwise the pointer is built for each reg + saved). */ + + fpregs = gen_reg_rtx (Pmode); + emit_move_insn (fpregs, plus_constant (XEXP (regbuf, 0), + n_intregs * UNITS_PER_WORD)); + for (regno = first_floatreg; regno < NPARM_REGS (SFmode); regno += 2) + emit_move_insn (gen_rtx (MEM, DFmode, + plus_constant (fpregs, + GET_MODE_SIZE (SFmode) + * (regno - first_floatreg))), + gen_rtx (REG, DFmode, + BASE_INCOMING_ARG_REG (DFmode) + regno)); + } if (flag_check_memory_usage) { @@ -4800,8 +4842,9 @@ sparc_flat_output_function_prologue (file, size) unsigned long gmask = current_frame_info.gmask; /* This is only for the human reader. */ - fprintf (file, "\t!#PROLOGUE# 0\n"); - fprintf (file, "\t!# vars= %d, regs= %d/%d, args= %d, extra= %d\n", + fprintf (file, "\t%s#PROLOGUE# 0\n", ASM_COMMENT_START); + fprintf (file, "\t%s# vars= %d, 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, @@ -4857,8 +4900,8 @@ sparc_flat_output_function_prologue (file, size) { fprintf (file, "\tst %s,[%s+%d]\n", fp_str, sp_str, reg_offset); - fprintf (file, "\tsub %s,%d,%s\t!# set up frame pointer\n", - sp_str, -size, fp_str); + fprintf (file, "\tsub %s,%d,%s\t%s# set up frame pointer\n", + sp_str, -size, fp_str, ASM_COMMENT_START); reg_offset += 4; } } @@ -4870,8 +4913,8 @@ sparc_flat_output_function_prologue (file, size) { fprintf (file, "\tst %s,[%s+%d]\n", fp_str, sp_str, reg_offset); - fprintf (file, "\tadd %s,%s,%s\t!# set up frame pointer\n", - sp_str, t1_str, fp_str); + fprintf (file, "\tadd %s,%s,%s\t%s# set up frame pointer\n", + sp_str, t1_str, fp_str, ASM_COMMENT_START); reg_offset += 4; } } @@ -4915,8 +4958,9 @@ sparc_flat_output_function_prologue (file, size) sp_str, -size1, sp_str); if (gmask & FRAME_POINTER_MASK) { - fprintf (file, "\tst %s,[%s+%d]\n\tsub %s,%d,%s\t!# set up frame pointer\n", - fp_str, sp_str, offset, sp_str, -size1, fp_str); + fprintf (file, "\tst %s,[%s+%d]\n\tsub %s,%d,%s\t%s# set up frame pointer\n", + fp_str, sp_str, offset, sp_str, -size1, fp_str, + ASM_COMMENT_START); offset += 4; } } @@ -4926,8 +4970,9 @@ sparc_flat_output_function_prologue (file, size) size1, t1_str, sp_str, t1_str, sp_str); if (gmask & FRAME_POINTER_MASK) { - fprintf (file, "\tst %s,[%s+%d]\n\tadd %s,%s,%s\t!# set up frame pointer\n", - fp_str, sp_str, offset, sp_str, t1_str, fp_str); + fprintf (file, "\tst %s,[%s+%d]\n\tadd %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; } } @@ -4965,7 +5010,7 @@ sparc_flat_output_function_prologue (file, size) } } - fprintf (file, "\t!#PROLOGUE# 1\n"); + fprintf (file, "\t%s#PROLOGUE# 1\n", ASM_COMMENT_START); } /* Do any necessary cleanup after a function to restore stack, frame, @@ -4980,7 +5025,7 @@ sparc_flat_output_function_epilogue (file, size) int noepilogue = FALSE; /* This is only for the human reader. */ - fprintf (file, "\t!#EPILOGUE#\n"); + 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 @@ -5022,11 +5067,11 @@ sparc_flat_output_function_epilogue (file, size) if (frame_pointer_needed) { if (size > 4095) - fprintf (file,"\tsub %s,%s,%s\t\t!# sp not trusted here\n", - fp_str, t1_str, sp_str); + fprintf (file,"\tsub %s,%s,%s\t\t%s# sp not trusted here\n", + fp_str, t1_str, sp_str, ASM_COMMENT_START); else - fprintf (file,"\tsub %s,%d,%s\t\t!# sp not trusted here\n", - fp_str, size, sp_str); + fprintf (file,"\tsub %s,%d,%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? */ -- 2.30.2