summaryrefslogtreecommitdiff
path: root/m68k-unknown-amigaos/recipes/patches/gcc/gcc.config.m68k.m68k.c.p
diff options
context:
space:
mode:
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.p513
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;
+ }