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
This commit is contained in:
Doug Evans 1997-09-25 01:09:41 +00:00
parent 5d4f5e8767
commit bf62bbf1bc

View File

@ -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);
/* 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. */
emit_insn (gen_rtx (SET, VOIDmode, pic_offset_table_rtx,
gen_rtx (HIGH, Pmode, pic_pc_rtx)));
l2 = gen_label_rtx ();
emit_label (l1);
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))));
/* 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)));
/* 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)));
/* Note that we pun calls and jumps here! */
emit_jump_insn (gen_get_pc_via_call (l2, l1));
/* Don't let the scheduler separate the previous insn from `l1'. */
emit_insn (gen_blockage ());
emit_label (l2);
emit_insn (gen_rtx (SET, VOIDmode, pic_offset_table_rtx,
gen_rtx (HIGH, Pmode, pic_pc_rtx)));
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, 1))));
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;
}
/* 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). */
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));
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? */