static bool thumb_force_lr_save (void);
static int const_ok_for_op (HOST_WIDE_INT, enum rtx_code);
static rtx emit_sfm (int, int);
+static int arm_size_return_regs (void);
#ifndef AOF_ASSEMBLER
static bool arm_assemble_integer (rtx, unsigned int, int);
#endif
/* Which ABI to use. */
enum arm_abi_type arm_abi;
-/* Set by the -mfpu=... option. */
-static const char * target_fpu_name = NULL;
-
-/* Set by the -mfpe=... option. */
-static const char * target_fpe_name = NULL;
-
-/* Set by the -mfloat-abi=... option. */
-static const char * target_float_abi_name = NULL;
-
-/* Set by the -mabi=... option. */
-static const char * target_abi_name = NULL;
-
/* Used to parse -mstructure_size_boundary command line option. */
-static const char * structure_size_string = NULL;
int arm_structure_size_boundary = DEFAULT_STRUCTURE_SIZE_BOUNDARY;
/* Used for Thumb call_via trampolines. */
enum machine_mode output_memory_reference_mode;
/* The register number to be used for the PIC offset register. */
-static const char * arm_pic_register_string = NULL;
int arm_pic_register = INVALID_REGNUM;
/* Set to 1 when a return insn is output, this means that the epilogue
{
switch (code)
{
- case OPT_mabi_:
- target_abi_name = arg;
- return true;
-
case OPT_march_:
arm_select[1].string = arg;
return true;
arm_select[0].string = arg;
return true;
- case OPT_mfloat_abi_:
- target_float_abi_name = arg;
- return true;
-
- case OPT_mfp_:
- case OPT_mfpe_:
- target_fpe_name = arg;
- return true;
-
- case OPT_mfpu_:
- target_fpu_name = arg;
- return true;
-
case OPT_mhard_float:
target_float_abi_name = "hard";
return true;
- case OPT_mpic_register_:
- arm_pic_register_string = arg;
- return true;
-
case OPT_msoft_float:
target_float_abi_name = "soft";
return true;
- case OPT_mstructure_size_boundary_:
- structure_size_string = arg;
- return true;
-
case OPT_mtune_:
arm_select[2].string = arg;
return true;
if (!call_used_regs[3])
return 0;
- /* ... that it isn't being used for a return value (always true
- until we implement return-in-regs), or for a tail-call
- argument ... */
+ /* ... that it isn't being used for a return value ... */
+ if (arm_size_return_regs () >= (4 * UNITS_PER_WORD))
+ return 0;
+
+ /* ... or for a tail-call argument ... */
if (sibling)
{
gcc_assert (GET_CODE (sibling) == CALL_INSN);
}
}
+ /* See if we can calculate the value as the difference between two
+ valid immediates. */
+ if (clear_sign_bit_copies + clear_zero_bit_copies <= 16)
+ {
+ int topshift = clear_sign_bit_copies & ~1;
+
+ temp1 = ARM_SIGN_EXTEND ((remainder + (0x00800000 >> topshift))
+ & (0xff000000 >> topshift));
+
+ /* If temp1 is zero, then that means the 9 most significant
+ bits of remainder were 1 and we've caused it to overflow.
+ When topshift is 0 we don't need to do anything since we
+ can borrow from 'bit 32'. */
+ if (temp1 == 0 && topshift != 0)
+ temp1 = 0x80000000 >> (topshift - 1);
+
+ temp2 = ARM_SIGN_EXTEND (temp1 - remainder);
+
+ if (const_ok_for_arm (temp2))
+ {
+ if (generate)
+ {
+ rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
+ emit_constant_insn (cond,
+ gen_rtx_SET (VOIDmode, new_src,
+ GEN_INT (temp1)));
+ emit_constant_insn (cond,
+ gen_addsi3 (target, new_src,
+ GEN_INT (-temp2)));
+ }
+
+ return 2;
+ }
+ }
+
/* See if we can generate this by setting the bottom (or the top)
16 bits, and then shifting these into the other half of the
word. We only look for the simplest cases, to do more would cost
HOST_WIDE_INT size;
if (!AGGREGATE_TYPE_P (type) &&
+ (TREE_CODE (type) != VECTOR_TYPE) &&
!(TARGET_AAPCS_BASED && TREE_CODE (type) == COMPLEX_TYPE))
/* All simple types are returned in registers.
For AAPCS, complex types are treated the same as aggregates. */
return (size < 0 || size > UNITS_PER_WORD);
}
+ /* To maximize backwards compatibility with previous versions of gcc,
+ return vectors up to 4 words in registers. */
+ if (TREE_CODE (type) == VECTOR_TYPE)
+ return (size < 0 || size > (4 * UNITS_PER_WORD));
+
/* For the arm-wince targets we choose to be compatible with Microsoft's
ARM and Thumb compilers, which always return aggregates in memory. */
#ifndef ARM_WINCE
{
if (TREE_CODE (*node) != FUNCTION_DECL)
{
- warning (0, "%qs attribute only applies to functions",
+ warning (OPT_Wattributes, "%qs attribute only applies to functions",
IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
{
if (TREE_CODE (*node) != FUNCTION_DECL)
{
- warning (0, "%qs attribute only applies to functions",
+ warning (OPT_Wattributes, "%qs attribute only applies to functions",
IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
{
if (arm_isr_value (args) == ARM_FT_UNKNOWN)
{
- warning (0, "%qs attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qs attribute ignored",
+ IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
}
}
else
{
- warning (0, "%qs attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qs attribute ignored",
+ IDENTIFIER_POINTER (name));
}
}
}
/* If this fix's address is greater than the address of the first
entry, then we can't put the fix in this pool. We subtract the
size of the current fix to ensure that if the table is fully
- packed we still have enough room to insert this value by suffling
+ packed we still have enough room to insert this value by shuffling
the other fixes forwards. */
if (minipool_vector_head &&
fix->address >= minipool_vector_head->max_address - fix->fix_size)
return par;
}
+/* Calculate the size of the return value that is passed in registers. */
+static int
+arm_size_return_regs (void)
+{
+ enum machine_mode mode;
+
+ if (current_function_return_rtx != 0)
+ mode = GET_MODE (current_function_return_rtx);
+ else
+ mode = DECL_MODE (DECL_RESULT (current_function_decl));
+
+ return GET_MODE_SIZE (mode);
+}
+
static rtx
emit_sfm (int base_reg, int count)
{
int high_regs_pushed = 0;
int had_to_push_lr;
int size;
- int mode;
if (return_used_this_function)
return "";
This is more reliable that examining regs_ever_live[] because that
will be set if the register is ever used in the function, not just if
the register is used to hold a return value. */
-
- if (current_function_return_rtx != 0)
- mode = GET_MODE (current_function_return_rtx);
- else
- mode = DECL_MODE (DECL_RESULT (current_function_decl));
-
- size = GET_MODE_SIZE (mode);
+ size = arm_size_return_regs ();
/* The prolog may have pushed some high registers to use as
work registers. e.g. the testsuite file:
asm_fprintf (f, "\tmov\t%r, %r\t\t%@ Backtrace structure created\n",
ARM_HARD_FRAME_POINTER_REGNUM, work_register);
}
- /* Optimisation: If we are not pushing any low registers but we are going
+ /* Optimization: If we are not pushing any low registers but we are going
to push some high registers then delay our first push. This will just
be a push of LR and we can combine it with the push of the first high
register. */
}
-/* The EABI says test the least significan bit of a guard variable. */
+/* The EABI says test the least significant bit of a guard variable. */
static bool
arm_cxx_guard_mask_bit (void)