aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/v850/v850.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2012-11-20 13:12:16 +0000
committerNick Clifton <nickc@gcc.gnu.org>2012-11-20 13:12:16 +0000
commitb84d824df416552f65fb541138b49764ad8718df (patch)
tree198b86948cadcabe4eac22fa19035f2e16be7042 /gcc/config/v850/v850.c
parentaef5ffaaabf541543a2b027254bc44490c1dead3 (diff)
downloadgcc-b84d824df416552f65fb541138b49764ad8718df.zip
gcc-b84d824df416552f65fb541138b49764ad8718df.tar.gz
gcc-b84d824df416552f65fb541138b49764ad8718df.tar.bz2
v850.c (F): New function.
* config/v850/v850.c (F): New function. Mark the given insn as being frame related. (v850_all_frame_related): New function. Mark the given push insn as being frame related. (v850_pass_by_reference): When using the RH850 ABI do not pass arguments by reference. (v850_strict_argument_naming): Delete function. (v850_function_arg): Use word alignment with the RH850 ABI. (v850_arg_partial_bytes): Likewise. (v850_function_arg_advance): Likewise. (v850_print_operand): Handle CONST_INT and CONST_DOUBLE. (compute_register_save_size): Use df_regs_ever_live_p. (increment_stack): Mark prologue adjustments as being frame related. (expand_prologue): Handle pretend args. Mark insns generated as being frame related. (expand_epilogue): Likewise. (v850_return_in_memory): When using the RH850 ABI return aggregates in memory. (v850_setup_incoming_varargs): Delete function. (v850_option_override): New function. (TARGET_DEBUG_UNWIND_INFO): Delete definition. (TARGET_SETUP_INCOMING_VARARGS): Likewise. (TARGET_STRICT_ARGUMENT_NAMING): Likewise. (TARGET_OPTION_OVERRIDE): Define. * config/v850/v850.h (ASM_SPEC): Pass 8byte-align and gcc-abi options on to assembler. (LINK_SPEC): Likewise. (TARGET_CPU_CPP_BUILTINS): Define __V850_8BYTE_ALIGN__ and __V850_GCC_ABI__. (STACK_BOUNDARY): Set to BIGGEST_ALIGNMENT. (FUNCTION_BOUNDARY): With the RH850 ABI always 32-bit alignment. (BIGGEST_ALIGNMENT): With -8byte-align set to 64-bits. (BIGGEST_FIELD_ALIGNMENT): Likewise. (enum reg_class): Swap EVEN_REGS and GENERAL_REGS. (REG_CLASS_NAMES): Likewise. (REG_CLASS_CONTENTS): Likewise. (struct cum_arg): Delete anonymous_args field. (INIT_CUMULATIVE_ARGS): Update. (PREFERRED_DEBUG): Set to DWARF2_DEBUG. (DWARF2_FRAME_INFO): Define. (DWARF2_UNWIND_INFO): Define. (INCOMING_RETURN_ADDR_RTX): Define. (DWARF_FRAME_RETURN_COLUMN): Define. (TARGET_USE_FPU): Define. * config/v850/v850.md: Replace TARGET_V850E2V3 in floating point insns with TARGET_USE_FPU. (fixuns_truncsfsi2): New pattern. (fixuns_truncdfsi2): New pattern. (fix_truncsfdi2): New pattern. (fixuns_truncsfdi2): New pattern. (fix_truncdfdi2): New pattern. (fixuns_truncdfdi2): New pattern. (unsfloatsisf2): New pattern. (unsfloatsidf2): New pattern. (floatdisf2): New pattern. (unsfloatdisf2): New pattern. (floatdidf2): New pattern. (unsfloatdidf2): New pattern. (fnmasf4): Fix RTl description. (fnmssf4): Likewise. * config/v850/v850.opt (mrelax): New option. (mlong-jumps): Likewise. (msoft-float): Likewise. (mhard-float): Likewise. (mrh850-abi): Likewise. (mgcc-abi): Likewise. (m8byte-align): Likewise. * config/v850/t-v850 (MULTILIB_OPTIONS): Update multilib options. (MULTILIB_DIRNAMES): Likewise. From-SVN: r193661
Diffstat (limited to 'gcc/config/v850/v850.c')
-rw-r--r--gcc/config/v850/v850.c257
1 files changed, 174 insertions, 83 deletions
diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c
index 5d297cf..e1570c3 100644
--- a/gcc/config/v850/v850.c
+++ b/gcc/config/v850/v850.c
@@ -72,6 +72,35 @@ static GTY(()) section * tdata_section;
static GTY(()) section * zdata_section;
static GTY(()) section * zbss_section;
+/* We use this to wrap all emitted insns in the prologue. */
+static rtx
+F (rtx x)
+{
+ if (GET_CODE (x) != CLOBBER)
+ RTX_FRAME_RELATED_P (x) = 1;
+ return x;
+}
+
+/* Mark all the subexpressions of the PARALLEL rtx PAR as
+ frame-related. Return PAR.
+
+ dwarf2out.c:dwarf2out_frame_debug_expr ignores sub-expressions of a
+ PARALLEL rtx other than the first if they do not have the
+ FRAME_RELATED flag set on them. */
+
+static rtx
+v850_all_frame_related (rtx par)
+{
+ int len = XVECLEN (par, 0);
+ int i;
+
+ gcc_assert (GET_CODE (par) == PARALLEL);
+ for (i = 0; i < len; i++)
+ F (XVECEXP (par, 0, i));
+
+ return par;
+}
+
/* Handle the TARGET_PASS_BY_REFERENCE target hook.
Specify whether to pass the argument by reference. */
@@ -82,6 +111,9 @@ v850_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
{
unsigned HOST_WIDE_INT size;
+ if (!TARGET_GCC_ABI)
+ return 0;
+
if (type)
size = int_size_in_bytes (type);
else
@@ -90,14 +122,6 @@ v850_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
return size > 8;
}
-/* Implementing the Varargs Macros. */
-
-static bool
-v850_strict_argument_naming (cumulative_args_t ca ATTRIBUTE_UNUSED)
-{
- return !TARGET_GHS ? true : false;
-}
-
/* Return an RTX to represent where an argument with mode MODE
and type TYPE will be passed to a function. If the result
is NULL_RTX, the argument will be pushed. */
@@ -127,7 +151,9 @@ v850_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
return NULL_RTX;
}
- if (size <= UNITS_PER_WORD && type)
+ if (!TARGET_GCC_ABI)
+ align = UNITS_PER_WORD;
+ else if (size <= UNITS_PER_WORD && type)
align = TYPE_ALIGN (type) / BITS_PER_UNIT;
else
align = size;
@@ -171,7 +197,7 @@ v850_arg_partial_bytes (cumulative_args_t cum_v, enum machine_mode mode,
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
int size, align;
- if (TARGET_GHS && !named)
+ if (!named)
return 0;
if (mode == BLKmode)
@@ -182,7 +208,9 @@ v850_arg_partial_bytes (cumulative_args_t cum_v, enum machine_mode mode,
if (size < 1)
size = 1;
- if (type)
+ if (!TARGET_GCC_ABI)
+ align = UNITS_PER_WORD;
+ else if (type)
align = TYPE_ALIGN (type) / BITS_PER_UNIT;
else
align = size;
@@ -212,12 +240,18 @@ v850_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
- cum->nbytes += (((type && int_size_in_bytes (type) > 8
- ? GET_MODE_SIZE (Pmode)
- : (mode != BLKmode
- ? GET_MODE_SIZE (mode)
- : int_size_in_bytes (type))) + UNITS_PER_WORD - 1)
- & -UNITS_PER_WORD);
+ if (!TARGET_GCC_ABI)
+ cum->nbytes += (((mode != BLKmode
+ ? GET_MODE_SIZE (mode)
+ : int_size_in_bytes (type)) + UNITS_PER_WORD - 1)
+ & -UNITS_PER_WORD);
+ else
+ cum->nbytes += (((type && int_size_in_bytes (type) > 8
+ ? GET_MODE_SIZE (Pmode)
+ : (mode != BLKmode
+ ? GET_MODE_SIZE (mode)
+ : int_size_in_bytes (type))) + UNITS_PER_WORD - 1)
+ & -UNITS_PER_WORD);
}
/* Return the high and low words of a CONST_DOUBLE */
@@ -517,8 +551,25 @@ v850_print_operand (FILE * file, rtx x, int code)
fprintf (file, "[r0]");
break;
- default:
+ case CONST_INT:
+ {
+ unsigned HOST_WIDE_INT v = INTVAL (x);
+
+ /* Trickery to avoid problems with shifting
+ 32-bits at a time on a 32-bit host. */
+ v = v >> 16;
+ v = v >> 16;
+ fprintf (file, HOST_WIDE_INT_PRINT_HEX, v);
+ break;
+ }
+
+ case CONST_DOUBLE:
+ fprintf (file, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_HIGH (x));
break;
+
+ default:
+ debug_rtx (x);
+ gcc_unreachable ();
}
break;
case 'S':
@@ -583,6 +634,10 @@ v850_print_operand (FILE * file, rtx x, int code)
case SUBREG:
fputs (reg_names[subreg_regno (x)], file);
break;
+ case CONST_DOUBLE:
+ fprintf (file, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x));
+ break;
+
case CONST_INT:
case SYMBOL_REF:
case CONST:
@@ -895,7 +950,7 @@ v850_float_nz_comparison_operator (rtx op, enum machine_mode mode)
if (GET_MODE (XEXP (op, 0)) == CC_FPU_NEmode)
return code == NE;
- return 0;
+ return code == GT || code == GE || code == NE;
}
enum machine_mode
@@ -1287,7 +1342,7 @@ v850_reorg (void)
case INSN:
pattern = single_set (insn);
- /* See if there are any memory references we can shorten */
+ /* See if there are any memory references we can shorten. */
if (pattern)
{
rtx src = SET_SRC (pattern);
@@ -1301,11 +1356,11 @@ v850_reorg (void)
if (GET_CODE (dest) == SUBREG
&& (GET_CODE (SUBREG_REG (dest)) == MEM
|| GET_CODE (SUBREG_REG (dest)) == REG))
- alter_subreg (&dest, true);
+ alter_subreg (&dest, false);
if (GET_CODE (src) == SUBREG
&& (GET_CODE (SUBREG_REG (src)) == MEM
|| GET_CODE (SUBREG_REG (src)) == REG))
- alter_subreg (&src, true);
+ alter_subreg (&src, false);
if (GET_CODE (dest) == MEM && GET_CODE (src) == MEM)
mem = NULL_RTX;
@@ -1448,13 +1503,6 @@ compute_register_save_size (long * p_reg_saved)
int call_p = df_regs_ever_live_p (LINK_POINTER_REGNUM);
long reg_saved = 0;
- /* Always save the link pointer - we cannot rely upon df_regs_ever_live_p. */
- if (!call_p)
- {
- df_set_regs_ever_live (LINK_POINTER_REGNUM, true);
- call_p = 1;
- }
-
/* Count space for the register saves. */
if (interrupt_handler)
{
@@ -1547,6 +1595,34 @@ compute_register_save_size (long * p_reg_saved)
return size;
}
+/* Typical stack layout should looks like this after the function's prologue:
+
+ | |
+ -- ^
+ | | \ |
+ | | arguments saved | Increasing
+ | | on the stack | addresses
+ PARENT arg pointer -> | | /
+ -------------------------- ---- -------------------
+ | | - space for argument split between regs & stack
+ --
+ CHILD | | \ <-- (return address here)
+ | | other call
+ | | saved registers
+ | | /
+ --
+ frame pointer -> | | \ ___
+ | | local |
+ | | variables |f
+ | | / |r
+ -- |a
+ | | \ |m
+ | | outgoing |e
+ | | arguments | | Decreasing
+ (hard) frame pointer | | / | | addresses
+ and stack pointer -> | | / _|_ |
+ -------------------------- ---- ------------------ V */
+
int
compute_frame_size (int size, long * p_reg_saved)
{
@@ -1590,7 +1666,7 @@ use_prolog_function (int num_save, int frame_size)
}
static void
-increment_stack (unsigned int amount)
+increment_stack (signed int amount, bool in_prologue)
{
rtx inc;
@@ -1603,11 +1679,15 @@ increment_stack (unsigned int amount)
{
rtx reg = gen_rtx_REG (Pmode, 12);
- emit_move_insn (reg, inc);
+ inc = emit_move_insn (reg, inc);
+ if (in_prologue)
+ F (inc);
inc = reg;
}
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, inc));
+ inc = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, inc));
+ if (in_prologue)
+ F (inc);
}
void
@@ -1641,6 +1721,10 @@ expand_prologue (void)
if (((1L << LINK_POINTER_REGNUM) & reg_saved) != 0)
actual_fsize -= INTERRUPT_ALL_SAVE_SIZE;
+
+ /* Interrupt functions are not passed arguments, so no need to
+ allocate space for split structure arguments. */
+ gcc_assert (crtl->args.pretend_args_size == 0);
}
/* Identify all of the saved registers. */
@@ -1651,10 +1735,25 @@ expand_prologue (void)
save_regs[num_save++] = gen_rtx_REG (Pmode, i);
}
+ if (crtl->args.pretend_args_size)
+ {
+ if (num_save == 0)
+ {
+ increment_stack (- (actual_fsize + crtl->args.pretend_args_size), true);
+ actual_fsize = 0;
+ }
+ else
+ increment_stack (- crtl->args.pretend_args_size, true);
+ }
+
/* See if we have an insn that allocates stack space and saves the particular
- registers we want to. */
+ registers we want to. Note that the helpers won't
+ allocate additional space for registers GCC saves to complete a
+ "split" structure argument. */
save_all = NULL_RTX;
- if (TARGET_PROLOG_FUNCTION && num_save > 0)
+ if (TARGET_PROLOG_FUNCTION
+ && !crtl->args.pretend_args_size
+ && num_save > 0)
{
if (use_prolog_function (num_save, actual_fsize))
{
@@ -1694,6 +1793,8 @@ expand_prologue (void)
= gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 11));
}
+ v850_all_frame_related (save_all);
+
code = recog (save_all, NULL_RTX, NULL);
if (code >= 0)
{
@@ -1734,26 +1835,26 @@ expand_prologue (void)
offset = init_stack_alloc - 4;
if (init_stack_alloc)
- increment_stack (- (signed) init_stack_alloc);
+ increment_stack (- (signed) init_stack_alloc, true);
/* Save the return pointer first. */
if (num_save > 0 && REGNO (save_regs[num_save-1]) == LINK_POINTER_REGNUM)
{
- emit_move_insn (gen_rtx_MEM (SImode,
- plus_constant (Pmode,
- stack_pointer_rtx,
- offset)),
- save_regs[--num_save]);
+ F (emit_move_insn (gen_rtx_MEM (SImode,
+ plus_constant (Pmode,
+ stack_pointer_rtx,
+ offset)),
+ save_regs[--num_save]));
offset -= 4;
}
for (i = 0; i < num_save; i++)
{
- emit_move_insn (gen_rtx_MEM (SImode,
- plus_constant (Pmode,
- stack_pointer_rtx,
- offset)),
- save_regs[i]);
+ F (emit_move_insn (gen_rtx_MEM (SImode,
+ plus_constant (Pmode,
+ stack_pointer_rtx,
+ offset)),
+ save_regs[i]));
offset -= 4;
}
}
@@ -1763,15 +1864,11 @@ expand_prologue (void)
> 32K or we just called a function to save the registers and needed more
stack. */
if (actual_fsize > init_stack_alloc)
- {
- int diff = actual_fsize - init_stack_alloc;
-
- increment_stack (- diff);
- }
+ increment_stack (init_stack_alloc - actual_fsize, true);
/* If we need a frame pointer, set it up now. */
if (frame_pointer_needed)
- emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
+ F (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx));
}
@@ -1814,6 +1911,7 @@ expand_epilogue (void)
if (TARGET_PROLOG_FUNCTION
&& num_restore > 0
+ && !crtl->args.pretend_args_size
&& !interrupt_handler)
{
int alloc_stack = (4 * num_restore);
@@ -1851,7 +1949,7 @@ expand_epilogue (void)
rtx insn;
actual_fsize -= alloc_stack;
- increment_stack (actual_fsize);
+ increment_stack (actual_fsize, false);
insn = emit_jump_insn (restore_all);
INSN_CODE (insn) = code;
@@ -1877,7 +1975,7 @@ expand_epilogue (void)
/* Deallocate the rest of the stack if it is > 32K. */
if ((unsigned int) actual_fsize > init_stack_free)
- increment_stack (actual_fsize - init_stack_free);
+ increment_stack (actual_fsize - init_stack_free, false);
/* Special case interrupt functions that save all registers
for a call. */
@@ -1918,7 +2016,8 @@ expand_epilogue (void)
}
/* Cut back the remainder of the stack. */
- increment_stack (init_stack_free);
+ increment_stack (init_stack_free + crtl->args.pretend_args_size,
+ false);
}
/* And return or use reti for interrupt handlers. */
@@ -2931,7 +3030,11 @@ static bool
v850_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
{
/* Return values > 8 bytes in length in memory. */
- return int_size_in_bytes (type) > 8 || TYPE_MODE (type) == BLKmode;
+ return int_size_in_bytes (type) > 8
+ || TYPE_MODE (type) == BLKmode
+ /* With the rh850 ABI return all aggregates in memory. */
+ || ((! TARGET_GCC_ABI) && AGGREGATE_TYPE_P (type))
+ ;
}
/* Worker function for TARGET_FUNCTION_VALUE. */
@@ -2945,18 +3048,6 @@ v850_function_value (const_tree valtype,
}
-/* Worker function for TARGET_SETUP_INCOMING_VARARGS. */
-
-static void
-v850_setup_incoming_varargs (cumulative_args_t ca,
- enum machine_mode mode ATTRIBUTE_UNUSED,
- tree type ATTRIBUTE_UNUSED,
- int *pretend_arg_size ATTRIBUTE_UNUSED,
- int second_time ATTRIBUTE_UNUSED)
-{
- get_cumulative_args (ca)->anonymous_args = (!TARGET_GHS ? 1 : 0);
-}
-
/* Worker function for TARGET_CAN_ELIMINATE. */
static bool
@@ -3067,29 +3158,35 @@ static const struct attribute_spec v850_attribute_table[] =
{ NULL, 0, 0, false, false, false, NULL, false }
};
-static enum unwind_info_type
-v850_debug_unwind_info (void)
+
+static void
+v850_option_override (void)
{
- return UI_NONE;
-}
+ if (flag_exceptions || flag_non_call_exceptions)
+ flag_omit_frame_pointer = 0;
-#undef TARGET_DEBUG_UNWIND_INFO
-#define TARGET_DEBUG_UNWIND_INFO v850_debug_unwind_info
+ /* The RH850 ABI does not (currently) support the use of the CALLT instruction. */
+ if (! TARGET_GCC_ABI)
+ target_flags |= MASK_DISABLE_CALLT;
+}
/* Initialize the GCC target structure. */
+#undef TARGET_OPTION_OVERRIDE
+#define TARGET_OPTION_OVERRIDE v850_option_override
+
#undef TARGET_MEMORY_MOVE_COST
-#define TARGET_MEMORY_MOVE_COST v850_memory_move_cost
+#define TARGET_MEMORY_MOVE_COST v850_memory_move_cost
#undef TARGET_ASM_ALIGNED_HI_OP
#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
#undef TARGET_PRINT_OPERAND
-#define TARGET_PRINT_OPERAND v850_print_operand
+#define TARGET_PRINT_OPERAND v850_print_operand
#undef TARGET_PRINT_OPERAND_ADDRESS
-#define TARGET_PRINT_OPERAND_ADDRESS v850_print_operand_address
+#define TARGET_PRINT_OPERAND_ADDRESS v850_print_operand_address
#undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
-#define TARGET_PRINT_OPERAND_PUNCT_VALID_P v850_print_operand_punct_valid_p
+#define TARGET_PRINT_OPERAND_PUNCT_VALID_P v850_print_operand_punct_valid_p
#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA v850_output_addr_const_extra
@@ -3143,9 +3240,6 @@ v850_debug_unwind_info (void)
#undef TARGET_CALLEE_COPIES
#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true
-#undef TARGET_SETUP_INCOMING_VARARGS
-#define TARGET_SETUP_INCOMING_VARARGS v850_setup_incoming_varargs
-
#undef TARGET_ARG_PARTIAL_BYTES
#define TARGET_ARG_PARTIAL_BYTES v850_arg_partial_bytes
@@ -3166,9 +3260,6 @@ v850_debug_unwind_info (void)
#undef TARGET_TRAMPOLINE_INIT
#define TARGET_TRAMPOLINE_INIT v850_trampoline_init
-#undef TARGET_STRICT_ARGUMENT_NAMING
-#define TARGET_STRICT_ARGUMENT_NAMING v850_strict_argument_naming
-
#undef TARGET_LEGITIMATE_CONSTANT_P
#define TARGET_LEGITIMATE_CONSTANT_P v850_legitimate_constant_p