diff options
Diffstat (limited to 'm68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k.c.p')
-rw-r--r-- | m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k.c.p | 513 |
1 files changed, 513 insertions, 0 deletions
diff --git a/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k.c.p b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k.c.p new file mode 100644 index 0000000..9ca42a1 --- /dev/null +++ b/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k.c.p @@ -0,0 +1,513 @@ +--- gcc-3.4.6/gcc/config/m68k/m68k.c 2013-05-19 20:09:27.000000000 +0200 ++++ gcc/config/m68k/m68k.c 2013-05-19 20:23:32.000000000 +0200 +@@ -123,6 +123,8 @@ + static tree m68k_handle_fndecl_attribute (tree *node, tree name, + tree args, int flags, + bool *no_add_attrs); ++static tree m68k_handle_type_attribute (tree *, tree, tree, int, bool *); ++static int m68k_comp_type_attributes (tree, tree); + static void m68k_compute_frame_layout (void); + static bool m68k_save_reg (unsigned int regno, bool interrupt_handler); + static int const_int_cost (rtx); +@@ -138,6 +140,8 @@ + const char *m68k_align_funcs_string; + /* Specify the identification number of the library being built */ + const char *m68k_library_id_string; ++/* Specify number of registers for integer, pointer and float arguments. */ ++const char *m68k_regparm_string; + + /* Specify power of two alignment used for loops. */ + int m68k_align_loops; +@@ -145,6 +149,8 @@ + int m68k_align_jumps; + /* Specify power of two alignment used for functions. */ + int m68k_align_funcs; ++/* Specify number of registers for integer, pointer and float arguments. */ ++int m68k_regparm; + + /* Nonzero if the last compare/test insn had FP operands. The + sCC expanders peek at this to determine what to do for the +@@ -208,9 +214,30 @@ + { + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ + { "interrupt_handler", 0, 0, true, false, false, m68k_handle_fndecl_attribute }, ++ ++ /* Stkparm attribute specifies to pass arguments on the stack */ ++ { "stkparm", 0, 0, false, true, true, m68k_handle_type_attribute }, ++ /* Regparm attribute specifies how many integer arguments are to be ++ passed in registers. */ ++ { "regparm", 0, 1, false, true, true, m68k_handle_type_attribute }, ++ ++#ifdef TARGET_AMIGAOS ++ /* Stackext attribute specifies to generate stackextension code */ ++ { "stackext", 0, 0, false, true, true, amigaos_handle_type_attribute }, ++ /* Interrupt attribute specifies to generate a special exit code */ ++ { "interrupt", 0, 0, false, true, true, amigaos_handle_type_attribute }, ++ /* Saveds attribute specifies to generate baserel setup code */ ++ { "saveds", 0, 0, false, true, true, amigaos_handle_type_attribute }, ++ /* Chip attribute specifies to place data in a "special" section */ ++ { "chip", 0, 0, true, false, false, amigaos_handle_decl_attribute }, ++#endif ++ + { NULL, 0, 0, false, false, false, NULL } + }; + ++#undef TARGET_COMP_TYPE_ATTRIBUTES ++#define TARGET_COMP_TYPE_ATTRIBUTES m68k_comp_type_attributes ++ + struct gcc_target targetm = TARGET_INITIALIZER; + + /* Sometimes certain combinations of command options do not make +@@ -296,6 +323,23 @@ + m68k_align_funcs = i; + } + ++ /* Validate -mregparm and -mregparm= value. */ ++ if (m68k_regparm_string) ++ { ++ m68k_regparm = atoi (m68k_regparm_string); ++ if (m68k_regparm < 1 || m68k_regparm > M68K_MAX_REGPARM) ++ error ("-mregparm=%d is not between 1 and %d", ++ m68k_regparm, M68K_MAX_REGPARM); ++ target_flags |= MASK_REGPARM; ++ } ++ else ++ if (TARGET_REGPARM) ++ m68k_regparm = M68K_DEFAULT_REGPARM; ++ ++ /* XXX: FIXME: Workaround for a bug. */ ++ if (flag_pic >= 3) ++ flag_strength_reduce = 0; ++ + /* -fPIC uses 32-bit pc-relative displacements, which don't exist + until the 68020. */ + if (!TARGET_68020 && !TARGET_COLDFIRE && (flag_pic == 2)) +@@ -312,12 +356,14 @@ + the PLT entry for `foo'. Doing function cse will cause the address of + `foo' to be loaded into a register, which is exactly what we want to + avoid when we are doing PIC on svr4 m68k. */ +- if (flag_pic) ++ if (flag_pic && flag_pic < 3) + flag_no_function_cse = 1; + + SUBTARGET_OVERRIDE_OPTIONS; + } + ++/* Attributes support. */ ++ + /* Return nonzero if FUNC is an interrupt function as specified by the + "interrupt_handler" attribute. */ + static bool +@@ -350,6 +396,251 @@ + return NULL_TREE; + } + ++/* Handle a "regparm" or "stkparm" attribute; ++ arguments as in struct attribute_spec.handler. */ ++ ++static tree ++m68k_handle_type_attribute (tree *node, tree name, tree args, ++ int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) ++{ ++ if (TREE_CODE (*node) == FUNCTION_TYPE || TREE_CODE (*node) == METHOD_TYPE) ++ { ++ /* 'regparm' accepts one optional argument - number of registers in ++ single class that should be used to pass arguments. */ ++ if (is_attribute_p ("regparm", name)) ++ { ++ if (lookup_attribute ("stkparm", TYPE_ATTRIBUTES(*node))) ++ { ++ error ("`regparm' and `stkparm' are mutually exclusive"); ++ } ++ if (args && TREE_CODE (args) == TREE_LIST) ++ { ++ tree numofregs = TREE_VALUE (args); ++ if (numofregs) ++ if (TREE_CODE (numofregs) != INTEGER_CST ++/* ++ || compare_tree_int(numofregs, 1) < 0 ++ || compare_tree_int(numofregs, M68K_MAX_REGPARM) > 0) ++*/ ++ || TREE_INT_CST_HIGH (numofregs) ++ || TREE_INT_CST_LOW (numofregs) < 1 ++ || TREE_INT_CST_LOW (numofregs) > M68K_MAX_REGPARM) ++ { ++ error ("invalid argument to `regparm' attribute"); ++ } ++ } ++ } ++ else if (is_attribute_p ("stkparm", name)) ++ { ++ if (lookup_attribute ("regparm", TYPE_ATTRIBUTES(*node))) ++ { ++ error ("`regparm' and `stkparm' are mutually exclusive"); ++ } ++ } ++ } ++ else ++ { ++ warning ("`%s' attribute only applies to functions", ++ IDENTIFIER_POINTER (name)); ++ *no_add_attrs = true; ++ } ++ ++ return NULL_TREE; ++} ++ ++/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible, ++ one if they are compatible, and two if they are nearly compatible ++ (which causes a warning to be generated). */ ++ ++static int ++m68k_comp_type_attributes (tree type1, tree type2) ++{ ++ /* Functions or methods are incompatible if they specify mutually ++ exclusive ways of passing arguments. */ ++ if (TREE_CODE (type1) == FUNCTION_TYPE || TREE_CODE (type1) == METHOD_TYPE) ++ { ++ tree arg1, arg2; ++ if (!! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type1)) != ++ !! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type2)) ++ || !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1)) != ++ !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2))) ++ return 0; /* 'regparm' and 'stkparm' are mutually exclusive. */ ++ ++ arg1 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1)); ++ arg2 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2)); ++ if (arg1 && arg2) ++ { ++ int num1 = 0, num2 = 0; ++ if (TREE_VALUE (arg1) && TREE_CODE (TREE_VALUE (arg1)) == TREE_LIST) ++ { ++ tree numofregs = TREE_VALUE (TREE_VALUE (arg1)); ++ if (numofregs) ++ num1 = TREE_INT_CST_LOW (numofregs); ++ } ++ if (TREE_VALUE (arg2) && TREE_CODE (TREE_VALUE (arg2)) == TREE_LIST) ++ { ++ tree numofregs = TREE_VALUE (TREE_VALUE (arg2)); ++ if (numofregs) ++ num2 = TREE_INT_CST_LOW (numofregs); ++ } ++ if (num1 != num2) ++ return 0; /* Different numbers, or no number in one type. */ ++ } ++ } ++#ifdef TARGET_AMIGAOS ++ return amigaos_comp_type_attributes(type1, type2); ++#else ++ return 1; ++#endif ++} ++ ++/* Argument-passing support functions. */ ++ ++/* Initialize a variable CUM of type CUMULATIVE_ARGS ++ for a call to a function whose data type is FNTYPE. ++ For a library call, FNTYPE is 0. */ ++ ++void ++m68k_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype) ++{ ++ cum->last_arg_reg = -1; ++ cum->regs_already_used = 0; ++ if (fntype) ++ { ++ if (lookup_attribute ("stkparm", TYPE_ATTRIBUTES (fntype))) ++ cum->num_of_regs = 0; ++ else ++ { ++ tree ratree = lookup_attribute ("regparm", TYPE_ATTRIBUTES (fntype)); ++ if (ratree) ++ { ++ cum->num_of_regs = m68k_regparm ? m68k_regparm ++ : M68K_DEFAULT_REGPARM; ++ if (TREE_VALUE (ratree) ++ && TREE_CODE (TREE_VALUE (ratree)) == TREE_LIST) ++ { ++ tree num_of_regs = TREE_VALUE (TREE_VALUE (ratree)); ++ cum->num_of_regs = ++ num_of_regs ? TREE_INT_CST_LOW (num_of_regs) : ++ (m68k_regparm ? m68k_regparm : M68K_DEFAULT_REGPARM); ++ } ++ } ++ else ++ cum->num_of_regs = m68k_regparm; ++ } ++ } ++ else /* Libcall. */ ++ cum->num_of_regs = 0; ++ ++ if (cum->num_of_regs) ++ { ++ /* If this is a vararg call, put all arguments on stack. */ ++ tree param, next_param; ++ for (param = TYPE_ARG_TYPES (fntype); param; param = next_param) ++ { ++ next_param = TREE_CHAIN (param); ++ if (!next_param && TREE_VALUE (param) != void_type_node) ++ cum->num_of_regs = 0; ++ } ++ } ++ ++#if ! defined (PCC_STATIC_STRUCT_RETURN) && defined (STRUCT_VALUE_REGNUM) ++ /* If return value is a structure, and we pass the buffer address in a ++ register, we can't use this register for our own purposes. ++ FIXME: Something similar would be useful for static chain. */ ++ if (fntype && aggregate_value_p (TREE_TYPE (fntype), fntype)) ++ cum->regs_already_used |= (1 << STRUCT_VALUE_REGNUM); ++#endif ++} ++ ++/* Update the data in CUM to advance over an argument. */ ++ ++void ++m68k_function_arg_advance (CUMULATIVE_ARGS *cum) ++{ ++ if (cum->last_arg_reg != -1) ++ { ++ int count; ++ for (count = 0; count < cum->last_arg_len; count++) ++ cum->regs_already_used |= (1 << (cum->last_arg_reg + count)); ++ cum->last_arg_reg = -1; ++ } ++} ++ ++/* Define where to put the arguments to a function. ++ Value is zero to push the argument on the stack, ++ or a hard register in which to store the argument. ++ ++ MODE is the argument's machine mode. ++ TYPE is the data type of the argument (as a tree). ++ This is null for libcalls where that information may ++ not be available. ++ CUM is a variable of type CUMULATIVE_ARGS which gives info about ++ the preceding args and about the function being called. */ ++ ++struct rtx_def * ++m68k_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type) ++{ ++ if (cum->num_of_regs) ++ { ++ int regbegin = -1, altregbegin = -1, len; ++ ++ /* FIXME: The last condition below is a workaround for a bug. */ ++ if (TARGET_68881 && FLOAT_MODE_P (mode) && ++ GET_MODE_UNIT_SIZE (mode) <= 12 && ++ (GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT || mode == SCmode)) ++ { ++ regbegin = 16; /* FPx */ ++ len = GET_MODE_NUNITS (mode); ++ } ++ /* FIXME: Two last conditions below are workarounds for bugs. */ ++ else if (INTEGRAL_MODE_P (mode) && mode !=CQImode && mode != CHImode) ++ { ++ if (POINTER_TYPE_P (type)) ++ regbegin = 8; /* Ax */ ++ else ++ regbegin = 0; /* Dx */ ++ altregbegin = 8 - regbegin; ++ len = (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD; ++ } ++ ++ if (regbegin != -1) ++ { ++ int reg; ++ long mask; ++ ++look_for_reg: ++ mask = 1 << regbegin; ++ for (reg = 0; reg < cum->num_of_regs; reg++, mask <<= 1) ++ if (!(cum->regs_already_used & mask)) ++ { ++ int end; ++ for (end = reg; end < cum->num_of_regs && end < reg + len; ++ end++, mask <<= 1) ++ if (cum->regs_already_used & mask) ++ break; ++ if (end == reg + len) ++ { ++ cum->last_arg_reg = reg + regbegin; ++ cum->last_arg_len = len; ++ break; ++ } ++ } ++ ++ if (reg == cum->num_of_regs && altregbegin != -1) ++ { ++ regbegin = altregbegin; ++ altregbegin = -1; ++ goto look_for_reg; ++ } ++ } ++ ++ if (cum->last_arg_reg != -1) ++ return gen_rtx_REG (mode, cum->last_arg_reg); ++ } ++ return 0; ++} ++ + static void + m68k_compute_frame_layout (void) + { +@@ -428,10 +719,14 @@ + static bool + m68k_save_reg (unsigned int regno, bool interrupt_handler) + { +- if (flag_pic && current_function_uses_pic_offset_table ++ if (flag_pic && flag_pic < 3 && current_function_uses_pic_offset_table + && regno == PIC_OFFSET_TABLE_REGNUM) + return true; + ++#ifdef EXTRA_SAVE_REG ++ EXTRA_SAVE_REG(regno); ++#endif ++ + if (current_function_calls_eh_return) + { + unsigned int i; +@@ -480,6 +775,9 @@ + m68k_output_function_prologue (FILE *stream, HOST_WIDE_INT size ATTRIBUTE_UNUSED) + { + HOST_WIDE_INT fsize_with_regs; ++#if !defined (DWARF2_DEBUGGING_INFO) && !defined (DWARF2_UNWIND_INFO) ++#define dwarf2out_do_frame() 0 ++#endif + HOST_WIDE_INT cfa_offset = INCOMING_FRAME_SP_OFFSET; + + m68k_compute_frame_layout(); +@@ -496,8 +794,17 @@ + if (TARGET_COLDFIRE && current_frame.reg_no > 2) + fsize_with_regs += current_frame.reg_no * 4; + ++#ifdef PROLOGUE_BEGIN_HOOK ++ PROLOGUE_BEGIN_HOOK (stream, fsize_with_regs); ++#endif ++ + if (frame_pointer_needed) + { ++#ifdef HAVE_ALTERNATE_FRAME_SETUP_F ++ if (HAVE_ALTERNATE_FRAME_SETUP_F (fsize_with_regs)) ++ ALTERNATE_FRAME_SETUP_F (stream, fsize_with_regs); ++ else ++#endif + if (current_frame.size == 0 && TARGET_68040) + /* on the 68040, pea + move is faster than link.w 0 */ + fprintf (stream, MOTOROLA ? +@@ -528,6 +835,10 @@ + cfa_offset += current_frame.size; + } + } ++#ifdef HAVE_ALTERNATE_FRAME_SETUP ++ else if (HAVE_ALTERNATE_FRAME_SETUP (fsize_with_regs)) ++ ALTERNATE_FRAME_SETUP (stream, fsize_with_regs); ++#endif + else if (fsize_with_regs) /* !frame_pointer_needed */ + { + if (fsize_with_regs < 0x8000) +@@ -658,7 +969,12 @@ + dwarf2out_reg_save (l, regno, -cfa_offset + n_regs++ * 4); + } + } +- if (!TARGET_SEP_DATA && flag_pic && ++#ifdef HAVE_ALTERNATE_PIC_SETUP ++ if (HAVE_ALTERNATE_PIC_SETUP) ++ ALTERNATE_PIC_SETUP (stream); ++ else ++#endif ++ if (!TARGET_SEP_DATA && flag_pic && flag_pic < 3 && + (current_function_uses_pic_offset_table || + (!current_function_is_leaf && TARGET_ID_SHARED_LIBRARY))) + { +@@ -921,6 +1237,11 @@ + } + } + if (frame_pointer_needed) ++#ifdef HAVE_ALTERNATE_FRAME_DESTR_F ++ if (HAVE_ALTERNATE_FRAME_DESTR_F (fsize_with_regs)) ++ ALTERNATE_FRAME_DESTR_F (stream, fsize_with_regs); ++ else ++#endif + fprintf (stream, "\tunlk %s\n", + reg_names[FRAME_POINTER_REGNUM]); + else if (fsize_with_regs) +@@ -958,10 +1279,17 @@ + } + if (current_function_calls_eh_return) + asm_fprintf (stream, "\tadd" ASM_DOT"l %Ra0,%Rsp\n"); ++#ifdef EPILOGUE_END_HOOK ++ EPILOGUE_END_HOOK (stream); ++#endif + if (m68k_interrupt_function_p (current_function_decl)) + fprintf (stream, "\trte\n"); + else if (current_function_pops_args) + asm_fprintf (stream, "\trtd %I%d\n", current_function_pops_args); ++#ifdef HAVE_ALTERNATE_RETURN ++ else if (HAVE_ALTERNATE_RETURN) ++ ALTERNATE_RETURN (stream); ++#endif + else + fprintf (stream, "\trts\n"); + } +@@ -1454,12 +1782,20 @@ + /* First handle a simple SYMBOL_REF or LABEL_REF */ + if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF) + { ++#ifdef LEGITIMATE_BASEREL_OPERAND_P ++ if (LEGITIMATE_BASEREL_OPERAND_P (orig)) ++ return orig; ++#endif ++ + if (reg == 0) + abort (); + +- pic_ref = gen_rtx_MEM (Pmode, +- gen_rtx_PLUS (Pmode, +- pic_offset_table_rtx, orig)); ++ if (flag_pic < 3) ++ pic_ref = gen_rtx_MEM (Pmode, ++ gen_rtx_PLUS (Pmode, ++ pic_offset_table_rtx, orig)); ++ else ++ pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, orig); + current_function_uses_pic_offset_table = 1; + RTX_UNCHANGING_P (pic_ref) = 1; + emit_move_insn (reg, pic_ref); +@@ -3001,6 +3337,10 @@ + fprintf (file, ":w"); break; + case 2: + fprintf (file, ":l"); break; ++ case 3: ++ fprintf (file, ":W"); break; ++ case 4: ++ fprintf (file, ":L"); break; + default: + break; + } +@@ -3488,7 +3828,7 @@ + xops[0] = DECL_RTL (function); + + /* Logic taken from call patterns in m68k.md. */ +- if (flag_pic) ++ if (flag_pic && flag_pic < 3) + { + if (TARGET_PCREL) + fmt = "bra.l %o0"; +@@ -3544,7 +3884,8 @@ + + /* Value is true if hard register REGNO can hold a value of machine-mode MODE. + On the 68000, the cpu registers can hold any mode except bytes in address +- registers, but the 68881 registers can hold only SFmode or DFmode. */ ++ registers, but the 68881 registers can hold only SFmode or DFmode. ++ The 68881 registers can't hold anything if 68881 use is disabled. */ + bool + m68k_regno_mode_ok (int regno, enum machine_mode mode) + { +@@ -3569,6 +3910,7 @@ + smaller. */ + if ((GET_MODE_CLASS (mode) == MODE_FLOAT + || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT) ++ && TARGET_68881 + && GET_MODE_UNIT_SIZE (mode) <= 12) + return true; + } |