Mercurial > hg > CbC > CbC_gcc
diff gcc/config/m68k/m68k.c @ 67:f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Mar 2011 17:18:12 +0900 |
parents | b7f97abdc517 |
children | 04ced10e8804 |
line wrap: on
line diff
--- a/gcc/config/m68k/m68k.c Tue May 25 18:58:51 2010 +0900 +++ b/gcc/config/m68k/m68k.c Tue Mar 22 17:18:12 2011 +0900 @@ -33,7 +33,7 @@ #include "output.h" #include "insn-attr.h" #include "recog.h" -#include "toplev.h" +#include "diagnostic-core.h" #include "expr.h" #include "reload.h" #include "tm_p.h" @@ -132,8 +132,10 @@ static int m68k_sched_first_cycle_multipass_dfa_lookahead (void); static bool m68k_can_eliminate (const int, const int); +static void m68k_conditional_register_usage (void); static bool m68k_legitimate_address_p (enum machine_mode, rtx, bool); static bool m68k_handle_option (size_t, const char *, int); +static void m68k_option_override (void); static rtx find_addr_reg (rtx); static const char *singlemove_string (rtx *); static void m68k_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, @@ -153,7 +155,12 @@ #endif static void m68k_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED; static void m68k_trampoline_init (rtx, tree, rtx); +static int m68k_return_pops_args (tree, tree, int); static rtx m68k_delegitimize_address (rtx); +static void m68k_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, + const_tree, bool); +static rtx m68k_function_arg (CUMULATIVE_ARGS *, enum machine_mode, + const_tree, bool); /* Specify the identification number of the library being built */ @@ -231,6 +238,9 @@ #undef TARGET_HANDLE_OPTION #define TARGET_HANDLE_OPTION m68k_handle_option +#undef TARGET_OPTION_OVERRIDE +#define TARGET_OPTION_OVERRIDE m68k_option_override + #undef TARGET_RTX_COSTS #define TARGET_RTX_COSTS m68k_rtx_costs @@ -268,12 +278,24 @@ #undef TARGET_CAN_ELIMINATE #define TARGET_CAN_ELIMINATE m68k_can_eliminate +#undef TARGET_CONDITIONAL_REGISTER_USAGE +#define TARGET_CONDITIONAL_REGISTER_USAGE m68k_conditional_register_usage + #undef TARGET_TRAMPOLINE_INIT #define TARGET_TRAMPOLINE_INIT m68k_trampoline_init +#undef TARGET_RETURN_POPS_ARGS +#define TARGET_RETURN_POPS_ARGS m68k_return_pops_args + #undef TARGET_DELEGITIMIZE_ADDRESS #define TARGET_DELEGITIMIZE_ADDRESS m68k_delegitimize_address +#undef TARGET_FUNCTION_ARG +#define TARGET_FUNCTION_ARG m68k_function_arg + +#undef TARGET_FUNCTION_ARG_ADVANCE +#define TARGET_FUNCTION_ARG_ADVANCE m68k_function_arg_advance + static const struct attribute_spec m68k_attribute_table[] = { /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ @@ -534,17 +556,10 @@ } } -/* Sometimes certain combinations of command options do not make - sense on a particular target machine. You can define a macro - `OVERRIDE_OPTIONS' to take account of this. This macro, if - defined, is executed once just after all the command options have - been parsed. - - Don't use this macro to turn on various extra optimizations for - `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */ - -void -override_options (void) +/* Implement TARGET_OPTION_OVERRIDE. */ + +static void +m68k_option_override (void) { const struct m68k_target_selection *entry; unsigned long target_mask; @@ -1038,7 +1053,7 @@ m68k_expand_prologue (void) { HOST_WIDE_INT fsize_with_regs; - rtx limit, src, dest, insn; + rtx limit, src, dest; m68k_compute_frame_layout (); @@ -1181,7 +1196,7 @@ if (!TARGET_SEP_DATA && crtl->uses_pic_offset_table) - insn = emit_insn (gen_load_got (pic_offset_table_rtx)); + emit_insn (gen_load_got (pic_offset_table_rtx)); } /* Return true if a simple (return) instruction is sufficient for this @@ -1472,6 +1487,26 @@ return false; } +/* On the m68k all args are always pushed. */ + +static rtx +m68k_function_arg (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED, + enum machine_mode mode ATTRIBUTE_UNUSED, + const_tree type ATTRIBUTE_UNUSED, + bool named ATTRIBUTE_UNUSED) +{ + return NULL_RTX; +} + +static void +m68k_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, + const_tree type, bool named ATTRIBUTE_UNUSED) +{ + *cum += (mode != BLKmode + ? (GET_MODE_SIZE (mode) + 3) & ~3 + : (int_size_in_bytes (type) + 3) & ~3); +} + /* Convert X to a legitimate function call memory reference and return the result. */ @@ -3477,6 +3512,7 @@ /* Normal case: do the two words, low-numbered first. */ + m68k_final_prescan_insn (NULL, operands, 2); handle_movsi (operands); /* Do the middle one of the three words for long double */ @@ -3487,6 +3523,7 @@ if (addreg1) handle_reg_adjust (addreg1, 4); + m68k_final_prescan_insn (NULL, middlehalf, 2); handle_movsi (middlehalf); } @@ -3497,6 +3534,7 @@ handle_reg_adjust (addreg1, 4); /* Do that word. */ + m68k_final_prescan_insn (NULL, latehalf, 2); handle_movsi (latehalf); /* Undo the adds we just did. */ @@ -4597,7 +4635,8 @@ case UNSPEC_RELOC16: case UNSPEC_RELOC32: output_addr_const (file, XVECEXP (x, 0, 0)); - fputs (m68k_get_reloc_decoration (INTVAL (XVECEXP (x, 0, 1))), file); + fputs (m68k_get_reloc_decoration + ((enum m68k_reloc) INTVAL (XVECEXP (x, 0, 1))), file); return true; default: @@ -4624,50 +4663,48 @@ and turn them back into a direct symbol reference. */ static rtx -m68k_delegitimize_address (rtx x) +m68k_delegitimize_address (rtx orig_x) { - rtx orig_x = delegitimize_mem_from_attrs (x); - rtx y; - rtx addend = NULL_RTX; - rtx result; - + rtx x; + struct m68k_address addr; + rtx unspec; + + orig_x = delegitimize_mem_from_attrs (orig_x); x = orig_x; if (MEM_P (x)) x = XEXP (x, 0); - if (GET_CODE (x) == PLUS - && GET_CODE (XEXP (x, 1)) == CONST - && REG_P (XEXP (x, 0)) - && REGNO (XEXP (x, 0)) == PIC_REG) - { - y = x = XEXP (XEXP (x, 1), 0); - - /* Handle an addend. */ - if ((GET_CODE (x) == PLUS || GET_CODE (x) == MINUS) - && CONST_INT_P (XEXP (x, 1))) - { - addend = XEXP (x, 1); - x = XEXP (x, 0); - } - - if (GET_CODE (x) == UNSPEC - && (XINT (x, 1) == UNSPEC_RELOC16 - || XINT (x, 1) == UNSPEC_RELOC32)) - { - result = XVECEXP (x, 0, 0); - if (addend) - { - if (GET_CODE (y) == PLUS) - result = gen_rtx_PLUS (Pmode, result, addend); - else - result = gen_rtx_MINUS (Pmode, result, addend); - result = gen_rtx_CONST (Pmode, result); - } - return result; - } - } - - return orig_x; + if (GET_CODE (x) != PLUS || GET_MODE (x) != Pmode) + return orig_x; + + if (!m68k_decompose_address (GET_MODE (x), x, false, &addr) + || addr.offset == NULL_RTX + || GET_CODE (addr.offset) != CONST) + return orig_x; + + unspec = XEXP (addr.offset, 0); + if (GET_CODE (unspec) == PLUS && CONST_INT_P (XEXP (unspec, 1))) + unspec = XEXP (unspec, 0); + if (GET_CODE (unspec) != UNSPEC + || (XINT (unspec, 1) != UNSPEC_RELOC16 + && XINT (unspec, 1) != UNSPEC_RELOC32)) + return orig_x; + x = XVECEXP (unspec, 0, 0); + gcc_assert (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF); + if (unspec != XEXP (addr.offset, 0)) + x = gen_rtx_PLUS (Pmode, x, XEXP (XEXP (addr.offset, 0), 1)); + if (addr.index) + { + rtx idx = addr.index; + if (addr.scale != 1) + idx = gen_rtx_MULT (Pmode, idx, GEN_INT (addr.scale)); + x = gen_rtx_PLUS (Pmode, idx, x); + } + if (addr.base) + x = gen_rtx_PLUS (Pmode, addr.base, x); + if (MEM_P (orig_x)) + x = replace_equiv_address_nv (orig_x, x); + return x; } @@ -5608,7 +5645,6 @@ default: gcc_unreachable (); - return 0; } } @@ -5652,7 +5688,6 @@ default: gcc_unreachable (); - return 0; } } @@ -5758,7 +5793,6 @@ default: gcc_unreachable (); - return 0; } } @@ -5790,7 +5824,6 @@ default: gcc_unreachable (); - return 0; } } else @@ -5816,7 +5849,6 @@ default: gcc_unreachable (); - return 0; } } } @@ -5849,7 +5881,6 @@ default: gcc_unreachable (); - return 0; } } @@ -5868,7 +5899,6 @@ default: gcc_unreachable (); - return 0; } } @@ -6150,7 +6180,7 @@ return m68k_sched_issue_rate () - 1; } -/* Implementation of targetm.sched.md_init_global () hook. +/* Implementation of targetm.sched.init_global () hook. It is invoked once per scheduling pass and is used here to initialize scheduler constants. */ static void @@ -6258,7 +6288,7 @@ sched_branch_type = NULL; } -/* Implementation of targetm.sched.md_init () hook. +/* Implementation of targetm.sched.init () hook. It is invoked each time scheduler starts on the new block (basic block or extended basic block). */ static void @@ -6525,4 +6555,44 @@ FINALIZE_TRAMPOLINE (XEXP (m_tramp, 0)); } +/* On the 68000, the RTS insn cannot pop anything. + On the 68010, the RTD insn may be used to pop them if the number + of args is fixed, but if the number is variable then the caller + must pop them all. RTD can't be used for library calls now + because the library is compiled with the Unix compiler. + Use of RTD is a selectable option, since it is incompatible with + standard Unix calling sequences. If the option is not selected, + the caller must always pop the args. */ + +static int +m68k_return_pops_args (tree fundecl, tree funtype, int size) +{ + return ((TARGET_RTD + && (!fundecl + || TREE_CODE (fundecl) != IDENTIFIER_NODE) + && (!stdarg_p (funtype))) + ? size : 0); +} + +/* Make sure everything's fine if we *don't* have a given processor. + This assumes that putting a register in fixed_regs will keep the + compiler's mitts completely off it. We don't bother to zero it out + of register classes. */ + +static void +m68k_conditional_register_usage (void) +{ + int i; + HARD_REG_SET x; + if (!TARGET_HARD_FLOAT) + { + COPY_HARD_REG_SET (x, reg_class_contents[(int)FP_REGS]); + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (TEST_HARD_REG_BIT (x, i)) + fixed_regs[i] = call_used_regs[i] = 1; + } + if (flag_pic) + fixed_regs[PIC_REG] = call_used_regs[PIC_REG] = 1; +} + #include "gt-m68k.h"