diff options
author | Nick Clifton <nickc@redhat.com> | 2012-11-20 13:12:16 +0000 |
---|---|---|
committer | Nick Clifton <nickc@gcc.gnu.org> | 2012-11-20 13:12:16 +0000 |
commit | b84d824df416552f65fb541138b49764ad8718df (patch) | |
tree | 198b86948cadcabe4eac22fa19035f2e16be7042 /gcc/config/v850/v850.c | |
parent | aef5ffaaabf541543a2b027254bc44490c1dead3 (diff) | |
download | gcc-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.c | 257 |
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 |