/* Subroutines for insn-output.c for SPARC.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
64-bit SPARC-V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
const struct cpu_table *cpu;
const struct sparc_cpu_select *sel;
int fpu;
-
+
#ifndef SPARC_BI_ARCH
/* Check for unsupported architecture size. */
if (! TARGET_64BIT != DEFAULT_ARCH32_P)
/* Code model selection. */
sparc_cmodel = SPARC_DEFAULT_CMODEL;
-
+
#ifdef SPARC_BI_ARCH
if (TARGET_ARCH32)
sparc_cmodel = CM_32;
/* Don't use stack biasing in 32 bit mode. */
if (TARGET_ARCH32)
target_flags &= ~MASK_STACK_BIAS;
-
+
/* Supply a default value for align_functions. */
if (align_functions == 0
&& (sparc_cpu == PROCESSOR_ULTRASPARC
: (sparc_cpu == PROCESSOR_ULTRASPARC3
? 8 : 3)));
if (!PARAM_SET_P (PARAM_L1_CACHE_LINE_SIZE))
- set_param_value ("l1-cache-line-size",
+ set_param_value ("l1-cache-line-size",
((sparc_cpu == PROCESSOR_ULTRASPARC
|| sparc_cpu == PROCESSOR_ULTRASPARC3
|| sparc_cpu == PROCESSOR_NIAGARA
}
operands[1] = sym;
}
-
+
/* Fixup PIC cases. */
if (flag_pic && CONSTANT_P (operands[1]))
{
/* input_operand should have filtered out 32-bit mode. */
sparc_emit_set_const64 (operands[0], operands[1]);
return true;
-
+
default:
gcc_unreachable ();
}
if (code == LTU || code == GEU)
{
emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_fmt_ee (code, SImode,
+ gen_rtx_fmt_ee (code, SImode,
gen_compare_reg_1 (code, x, y),
const0_rtx)));
return true;
}
}
-/* Return true if X is an address which needs a temporary register when
+/* Return true if X is an address which needs a temporary register when
reloaded while generating PIC code. */
int
/* Return nonzero if ADDR is a valid memory address.
STRICT specifies whether strict register checking applies. */
-
+
static bool
sparc_legitimate_address_p (enum machine_mode mode, rtx addr, bool strict)
{
it is to a constant address, or the address involves a LO_SUM. */
return 1;
}
-
+
/* An obviously unaligned address. */
return 0;
}
sparc_mode_class[i] = 1 << (int) T_MODE;
else if (GET_MODE_SIZE (i) == 32)
sparc_mode_class[i] = 1 << (int) O_MODE;
- else
+ else
sparc_mode_class[i] = 0;
break;
case MODE_VECTOR_INT:
sparc_mode_class[i] = 1 << (int) TF_MODE;
else if (GET_MODE_SIZE (i) == 32)
sparc_mode_class[i] = 1 << (int) OF_MODE;
- else
+ else
sparc_mode_class[i] = 0;
break;
case MODE_CC:
if (flag_pic && crtl->uses_pic_offset_table)
load_pic_register (false);
}
-
+
/* This function generates the assembly code for function entry, which boils
down to emitting the necessary .register directives. */
return sparc_prologue_data_valid_p
&& (actual_fsize == 0 || !sparc_leaf_function_p);
}
-
+
/* This function generates the assembly code for function exit. */
-
+
static void
sparc_asm_function_epilogue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
{
sparc_output_deferred_case_vectors ();
}
-
+
/* Output a 'restore' instruction. */
-
+
static void
output_restore (rtx pat)
{
break;
}
}
-
+
/* Output a return. */
const char *
the appropriate fp reg and in memory.
- Summary of the calling conventions implemented by GCC on SPARC:
+ Summary of the calling conventions implemented by GCC on the SPARC:
32-bit ABI:
size argument return value
Note #2: integral vector types follow the scalar floating-point types
conventions to match what is implemented by the Sun VIS SDK.
-Note #3: floating-point vector types follow the aggregate types
+Note #3: floating-point vector types follow the aggregate types
conventions. */
for arithmetic operations which do zero/sign extension at the same time,
so without this we end up with a srl/sra after every assignment to an
user variable, which means very very bad code. */
-
if (TARGET_ARCH64
&& GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_SIZE (mode) < UNITS_PER_WORD)
return mode;
}
-
-
/* Handle the TARGET_STRICT_ARGUMENT_NAMING target hook. */
static bool
/* A subroutine of function_arg_record_value. Assign the bits of the
structure between parms->intoffset and bitpos to integer registers. */
-static void
+static void
function_arg_record_value_3 (HOST_WIDE_INT bitpos,
struct function_arg_record_value_parms *parms)
{
NAMED is nonzero if this argument is a named parameter
(otherwise it is an extra parameter matching an ellipsis).
REGBASE is the regno of the base register for the parameter array. */
-
+
static rtx
function_arg_record_value (const_tree type, enum machine_mode mode,
int slotno, int named, int regbase)
/* Original SPARC 64-bit ABI says that structures and unions
smaller than 16 bytes are passed in registers, as well as
all other base types.
-
+
Extended ABI (as implemented by the Sun compiler) says that
complex floats are passed in registers up to 16 bytes. Pass
all complex integers in registers up to 16 bytes. More generally,
/* Original SPARC 64-bit ABI says that structures and unions
smaller than 32 bytes are returned in registers, as well as
all other base types.
-
+
Extended ABI (as implemented by the Sun compiler) says that all
complex floats are returned in registers (8 FP registers at most
for '_Complex long double'). Return all complex integers in
mem = gen_rtx_MEM (Pmode, plus_constant (stack_pointer_rtx,
STRUCT_VALUE_OFFSET));
- /* Only follow the SPARC ABI for fixed-size structure returns.
- Variable size structure returns are handled per the normal
+ /* Only follow the SPARC ABI for fixed-size structure returns.
+ Variable size structure returns are handled per the normal
procedures in GCC. This is enabled by -mstd-struct-return */
- if (incoming == 2
+ if (incoming == 2
&& sparc_std_struct_return
&& TYPE_SIZE_UNIT (TREE_TYPE (fndecl))
&& TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (fndecl))) == INTEGER_CST)
provided. */
rtx ret_rtx = gen_rtx_REG (Pmode, 31);
rtx scratch = gen_reg_rtx (SImode);
- rtx endlab = gen_label_rtx ();
+ rtx endlab = gen_label_rtx ();
/* Calculate the return object size */
tree size = TYPE_SIZE_UNIT (TREE_TYPE (fndecl));
rtx temp_val = assign_stack_local (Pmode, TREE_INT_CST_LOW (size), 0);
/* Implement SPARC 32-bit psABI callee returns struck checking
- requirements:
-
+ requirements:
+
Fetch the instruction where we will return to and see if
it's an unimp instruction (the most significant 10 bits
will be zero). */
emit_insn (gen_add3_insn (ret_rtx, ret_rtx, GEN_INT (4)));
emit_cmp_and_jump_insns (scratch, size_rtx, EQ, const0_rtx, SImode, 0, endlab);
emit_insn (gen_sub3_insn (ret_rtx, ret_rtx, GEN_INT (4)));
- /* Assign stack temp:
+ /* Assign stack temp:
Write the address of the memory pointed to by temp_val into
the memory pointed to by mem */
emit_move_insn (mem, XEXP (temp_val, 0));
/* branch on register are limited to +-128KB. If it is too far away,
change
-
+
brnz,pt %g1, .LC30
-
+
to
-
+
brz,pn %g1, .+12
nop
ba,pt %xcc, .LC30
-
+
and
-
+
brgez,a,pn %o1, .LC29
-
+
to
-
+
brlz,pt %o1, .+16
nop
ba,pt %xcc, .LC29 */
}
/* Return 1 if REGNO (reg1) is even and REGNO (reg1) == REGNO (reg2) - 1.
- This makes them candidates for using ldd and std insns.
+ This makes them candidates for using ldd and std insns.
Note reg1 and reg2 *must* be hard registers. */
registers_ok_for_ldd_peep (rtx reg1, rtx reg2)
{
/* We might have been passed a SUBREG. */
- if (GET_CODE (reg1) != REG || GET_CODE (reg2) != REG)
+ if (GET_CODE (reg1) != REG || GET_CODE (reg2) != REG)
return 0;
if (REGNO (reg1) % 2 != 0)
return 0;
- /* Integer ldd is deprecated in SPARC V9 */
- if (TARGET_V9 && REGNO (reg1) < 32)
- return 0;
+ /* Integer ldd is deprecated in SPARC V9 */
+ if (TARGET_V9 && REGNO (reg1) < 32)
+ return 0;
return (REGNO (reg1) == REGNO (reg2) - 1);
}
/* Return 1 if the addresses in mem1 and mem2 are suitable for use in
an ldd or std insn.
-
+
This can only happen when addr1 and addr2, the addresses in mem1
and mem2, are consecutive memory locations (addr1 + 4 == addr2).
addr1 must also be aligned on a 64-bit boundary.
/* MEM1 should be aligned on a 64-bit boundary. */
if (MEM_ALIGN (mem1) < 64)
return 0;
-
+
addr1 = XEXP (mem1, 0);
addr2 = XEXP (mem2, 0);
-
+
/* Extract a register number and offset (if used) from the first addr. */
if (GET_CODE (addr1) == PLUS)
{
if (dependent_reg_rtx != NULL_RTX && reg1 == REGNO (dependent_reg_rtx))
return 0;
-
- /* The first offset must be evenly divisible by 8 to ensure the
+
+ /* The first offset must be evenly divisible by 8 to ensure the
address is 64 bit aligned. */
if (offset1 % 8 != 0)
return 0;
{
case ERROR_MARK:
return qualifiers;
-
+
case ARRAY_TYPE:
qualifiers |= (3 << shift);
break;
if (TYPE_PRECISION (type) <= CHAR_TYPE_SIZE)
return (qualifiers | (TYPE_UNSIGNED (type) ? 12 : 2));
-
+
else if (TYPE_PRECISION (type) <= SHORT_TYPE_SIZE)
return (qualifiers | (TYPE_UNSIGNED (type) ? 13 : 3));
-
+
else if (TYPE_PRECISION (type) <= INT_TYPE_SIZE)
return (qualifiers | (TYPE_UNSIGNED (type) ? 14 : 4));
-
+
else
return (qualifiers | (TYPE_UNSIGNED (type) ? 15 : 5));
-
+
case REAL_TYPE:
/* If this is a range type, consider it to be the underlying
type. */
if (TYPE_PRECISION (type) == FLOAT_TYPE_SIZE)
return (qualifiers | 6);
- else
+ else
return (qualifiers | 7);
-
+
case COMPLEX_TYPE: /* GNU Fortran COMPLEX type. */
/* ??? We need to distinguish between double and float complex types,
but I don't know how yet because I can't reach this code from
case BOOLEAN_TYPE: /* Boolean truth value type. */
case LANG_TYPE: /* ? */
return qualifiers;
-
+
default:
gcc_unreachable (); /* Not a type! */
}
if (dep_type == TYPE_STORE || dep_type == TYPE_FPSTORE)
{
if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET
- || GET_CODE (SET_DEST (dep_pat)) != MEM
+ || GET_CODE (SET_DEST (dep_pat)) != MEM
|| GET_CODE (SET_SRC (pat)) != MEM
|| ! rtx_equal_p (XEXP (SET_DEST (dep_pat), 0),
XEXP (SET_SRC (pat), 0)))
return cost + 2;
- return cost + 8;
+ return cost + 8;
}
break;
default:
break;
- }
+ }
return cost;
}
sparc_sched_init (FILE *dump ATTRIBUTE_UNUSED,
int sched_verbose ATTRIBUTE_UNUSED,
int max_ready ATTRIBUTE_UNUSED)
-{
-}
-
+{}
+
static int
sparc_use_sched_lookahead (void)
{
sparc_addr_list = gen_rtx_EXPR_LIST (VOIDmode, vec, sparc_addr_list);
}
-static void
+static void
sparc_output_addr_vec (rtx vec)
{
rtx lab = XEXP (vec, 0), body = XEXP (vec, 1);
int idx, vlen = XVECLEN (body, 0);
-#ifdef ASM_OUTPUT_ADDR_VEC_START
+#ifdef ASM_OUTPUT_ADDR_VEC_START
ASM_OUTPUT_ADDR_VEC_START (asm_out_file);
#endif
ASM_OUTPUT_ADDR_VEC_ELT
(asm_out_file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0)));
}
-
+
#ifdef ASM_OUTPUT_ADDR_VEC_END
ASM_OUTPUT_ADDR_VEC_END (asm_out_file);
#endif
}
-static void
+static void
sparc_output_addr_diff_vec (rtx vec)
{
rtx lab = XEXP (vec, 0), body = XEXP (vec, 1);
rtx base = XEXP (XEXP (body, 0), 0);
int idx, vlen = XVECLEN (body, 1);
-#ifdef ASM_OUTPUT_ADDR_VEC_START
+#ifdef ASM_OUTPUT_ADDR_VEC_START
ASM_OUTPUT_ADDR_VEC_START (asm_out_file);
#endif
CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)),
CODE_LABEL_NUMBER (base));
}
-
+
#ifdef ASM_OUTPUT_ADDR_VEC_END
ASM_OUTPUT_ADDR_VEC_END (asm_out_file);
#endif
align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
if (align > 0)
ASM_OUTPUT_ALIGN (asm_out_file, align);
-
+
for (t = sparc_addr_list; t ; t = XEXP (t, 1))
sparc_output_addr_vec (XEXP (t, 0));
for (t = sparc_addr_diff_list; t ; t = XEXP (t, 1))
/* Find the "this" pointer. Normally in %o0, but in ARCH64 if the function
returns a structure, the structure return pointer is there instead. */
- if (TARGET_ARCH64 && aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
+ if (TARGET_ARCH64
+ && aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
this_rtx = gen_rtx_REG (Pmode, int_arg_first + 1);
else
this_rtx = gen_rtx_REG (Pmode, int_arg_first);
bool
sparc_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
{
- return (to == HARD_FRAME_POINTER_REGNUM
+ return (to == HARD_FRAME_POINTER_REGNUM
|| !targetm.frame_pointer_required ());
}