AmigaOS/m68k specific changes.
This commit is contained in:
parent
37aef96904
commit
2f3c76b3d7
|
@ -277,14 +277,14 @@ case $basic_machine in
|
|||
os=-sysv
|
||||
;;
|
||||
amiga | amiga-*)
|
||||
basic_machine=m68k-cbm
|
||||
basic_machine=m68k-unknown
|
||||
;;
|
||||
amigaos | amigados)
|
||||
basic_machine=m68k-cbm
|
||||
basic_machine=m68k-unknown
|
||||
os=-amigaos
|
||||
;;
|
||||
amigaunix | amix)
|
||||
basic_machine=m68k-cbm
|
||||
basic_machine=m68k-unknown
|
||||
os=-sysv4
|
||||
;;
|
||||
apollo68)
|
||||
|
|
|
@ -367,7 +367,7 @@ TARGET_LIBGCC2_CFLAGS =
|
|||
LIBGCC2_DEPS =
|
||||
|
||||
# libgcc1-test target (must also be overridable for a target)
|
||||
LIBGCC1_TEST = libgcc1-test
|
||||
LIBGCC1_TEST =
|
||||
|
||||
# List of extra executables that should be compiled for this target machine
|
||||
# that are used for compiling from source code to object code.
|
||||
|
@ -393,6 +393,21 @@ EXTRA_GCC_OBJS =@host_extra_gcc_objs@
|
|||
# Often this is edited directly by `configure'.
|
||||
EXTRA_HEADERS =@extra_headers_list@
|
||||
|
||||
### begin-GG-local
|
||||
# List of extra targets that should be executed by make when building
|
||||
# the `doc' target.
|
||||
EXTRA_DOC_TARGETS =
|
||||
### end-GG-local
|
||||
|
||||
### begin-GG-local
|
||||
# List of extra targets that should be executed by make when building
|
||||
# targets `stage1' to `stage4'.
|
||||
EXTRA_STAGE1_TARGETS =
|
||||
EXTRA_STAGE2_TARGETS =
|
||||
EXTRA_STAGE3_TARGETS =
|
||||
EXTRA_STAGE4_TARGETS =
|
||||
### end-GG-local
|
||||
|
||||
# Set this to `collect2' to enable use of collect2.
|
||||
USE_COLLECT2 = @will_use_collect2@
|
||||
# If we might be using collect2, then this variable will be set to
|
||||
|
@ -516,6 +531,11 @@ CRT0STUFF_T_CFLAGS =
|
|||
# "t" or nothing, for building multilibbed versions of, say, crtbegin.o.
|
||||
T =
|
||||
|
||||
# Even if ALLOCA is set, don't use it if compiling with GCC, unless
|
||||
# a configuration file overrides this default.
|
||||
USE_ALLOCA= ` case "${CC}" in "${OLDCC}") echo "${ALLOCA}" ;; esac `
|
||||
USE_HOST_ALLOCA= ` case "${HOST_CC}"@"${HOST_ALLOCA}" in "${OLDCC}"@?*) echo ${HOST_PREFIX}${HOST_ALLOCA} ;; esac `
|
||||
|
||||
# End of variables for you to override.
|
||||
|
||||
# Definition of `all' is here so that new rules inserted by sed
|
||||
|
@ -1359,7 +1379,7 @@ graph.o: graph.c $(CONFIG_H) system.h toplev.h flags.h output.h $(RTL_H) \
|
|||
hard-reg-set.h $(BASIC_BLOCK_H)
|
||||
sbitmap.o: sbitmap.c $(CONFIG_H) system.h $(RTL_H) flags.h $(BASIC_BLOCK_H)
|
||||
|
||||
COLLECT2_OBJS = collect2.o tlink.o hash.o intl.o underscore.o version.o
|
||||
COLLECT2_OBJS = collect2.o tlink.o hash.o intl.o underscore.o version.o $(EXTRA_COLLECT2_OBJS)
|
||||
collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS)
|
||||
# Don't try modifying collect2 (aka ld) in place--it might be linking this.
|
||||
-rm -f collect2$(exeext)
|
||||
|
@ -2265,7 +2285,7 @@ stmp-fixproto: fixhdr.ready fixproto stmp-headers
|
|||
#
|
||||
# Remake the info files.
|
||||
|
||||
doc: info
|
||||
doc: info $(EXTRA_DOC_TARGETS)
|
||||
info: cpp.info gcc.info lang.info
|
||||
|
||||
cpp.info: $(srcdir)/cpp.texi
|
||||
|
@ -3049,7 +3069,7 @@ stage1-start:
|
|||
cp stage1/$${f} . ; \
|
||||
else true; \
|
||||
fi; done
|
||||
stage1: force stage1-start lang.stage1
|
||||
stage1: force stage1-start lang.stage1 $(EXTRA_STAGE1_TARGETS)
|
||||
|
||||
stage2-start:
|
||||
-if [ -d stage2 ] ; then true ; else mkdir stage2 ; fi
|
||||
|
@ -3073,7 +3093,7 @@ stage2-start:
|
|||
cp stage2/$${f} . ; \
|
||||
else true; \
|
||||
fi; done
|
||||
stage2: force stage2-start lang.stage2
|
||||
stage2: force stage2-start lang.stage2 $(EXTRA_STAGE2_TARGETS)
|
||||
|
||||
stage3-start:
|
||||
-if [ -d stage3 ] ; then true ; else mkdir stage3 ; fi
|
||||
|
@ -3097,7 +3117,7 @@ stage3-start:
|
|||
cp stage3/$${f} . ; \
|
||||
else true; \
|
||||
fi; done
|
||||
stage3: force stage3-start lang.stage3
|
||||
stage3: force stage3-start lang.stage3 $(EXTRA_STAGE3_TARGETS)
|
||||
|
||||
stage4-start:
|
||||
-if [ -d stage4 ] ; then true ; else mkdir stage4 ; fi
|
||||
|
@ -3121,7 +3141,7 @@ stage4-start:
|
|||
cp stage4/$${f} . ; \
|
||||
else true; \
|
||||
fi; done
|
||||
stage4: force stage4-start lang.stage4
|
||||
stage4: force stage4-start lang.stage4 $(EXTRA_STAGE4_TARGETS)
|
||||
|
||||
# Copy just the executable files from a particular stage into a subdirectory,
|
||||
# and delete the object files. Use this if you're just verifying a version
|
||||
|
|
76
gcc/c-decl.c
76
gcc/c-decl.c
|
@ -4227,8 +4227,9 @@ maybe_build_cleanup (decl)
|
|||
record the given order of parms in `parm_order'. */
|
||||
|
||||
void
|
||||
push_parm_decl (parm)
|
||||
tree parm;
|
||||
/* Amiga: explicit register specification for parameters */
|
||||
push_parm_decl (parm, asmspec)
|
||||
tree parm, asmspec;
|
||||
{
|
||||
tree decl;
|
||||
int old_immediate_size_expand = immediate_size_expand;
|
||||
|
@ -4253,6 +4254,77 @@ push_parm_decl (parm)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Amiga: explicit register specification for parameters */
|
||||
if (asmspec)
|
||||
#ifdef TARGET_AMIGAOS
|
||||
{
|
||||
char *regname=TREE_STRING_POINTER(asmspec);
|
||||
int regnum;
|
||||
if ((regnum=decode_reg_name(regname))>=0)
|
||||
{
|
||||
tree type=TREE_TYPE(decl);
|
||||
if (HARD_REGNO_MODE_OK(regnum, TYPE_MODE(type)))
|
||||
{
|
||||
tree t, attrs;
|
||||
push_obstacks_nochange();
|
||||
end_temporary_allocation();
|
||||
/* Build tree for __attribute__ ((asm(regnum))). */
|
||||
#if 0
|
||||
/* This doesn't work well because of a bug in
|
||||
attribute_list_contained(), which passes list of arguments to
|
||||
simple_cst_equal() instead of passing every argument
|
||||
separately. */
|
||||
attrs=tree_cons(get_identifier("asm"), tree_cons(NULL_TREE,
|
||||
build_int_2_wide(regnum, 0), NULL_TREE), NULL_TREE);
|
||||
#else
|
||||
attrs=tree_cons(get_identifier("asm"),
|
||||
build_int_2_wide(regnum, 0), NULL_TREE);
|
||||
#endif
|
||||
#if 0
|
||||
/* build_type_attribute_variant() would seem to be more
|
||||
appropriate here. However, that function does not support
|
||||
attributes for parameters properly. It modifies
|
||||
TYPE_MAIN_VARIANT of a new type. As a result, comptypes()
|
||||
thinks that types of parameters in prototype and definition
|
||||
are different and issues error messages. See also comment
|
||||
below. */
|
||||
type=build_type_attribute_variant(type, attrs);
|
||||
#else
|
||||
/* First check whether such a type already exists - if yes, use
|
||||
that one. This is very important, since otherwise
|
||||
common_type() would think that it sees two different
|
||||
types and would try to merge them - this could result in
|
||||
warning messages. */
|
||||
for (t=TYPE_MAIN_VARIANT(type); t; t=TYPE_NEXT_VARIANT(t))
|
||||
if (comptypes(t, type)==1
|
||||
&& attribute_list_equal(TYPE_ATTRIBUTES(t), attrs))
|
||||
break;
|
||||
if (t)
|
||||
type=t;
|
||||
else
|
||||
{
|
||||
/* Create a new variant, with differing attributes.
|
||||
(Hack! Type with differing attributes should no longer be
|
||||
a variant of its main type. See comment above for
|
||||
explanation why this was necessary). */
|
||||
type=build_type_copy(type);
|
||||
TYPE_ATTRIBUTES(type)=attrs;
|
||||
}
|
||||
#endif
|
||||
TREE_TYPE(decl)=type;
|
||||
pop_obstacks();
|
||||
}
|
||||
else
|
||||
error_with_decl(decl,
|
||||
"register number for `%s' isn't suitable for the data type");
|
||||
}
|
||||
else
|
||||
error("invalid register name `%s'", regname);
|
||||
}
|
||||
#else /* !TARGET_AMIGAOS */
|
||||
error("explicit register specification for parameters is not supported for this target");
|
||||
#endif /* !TARGET_AMIGAOS */
|
||||
|
||||
decl = pushdecl (decl);
|
||||
|
||||
immediate_size_expand = old_immediate_size_expand;
|
||||
|
|
|
@ -2329,56 +2329,63 @@ parmlist_2: /* empty */
|
|||
|
||||
parms:
|
||||
parm
|
||||
{ push_parm_decl ($1); }
|
||||
/* begin-GG-local: explicit register specification for parameters */
|
||||
{ push_parm_decl (TREE_PURPOSE($1), TREE_VALUE($1)); }
|
||||
| parms ',' parm
|
||||
{ push_parm_decl ($3); }
|
||||
{ push_parm_decl (TREE_PURPOSE($3), TREE_VALUE($3)); }
|
||||
;
|
||||
|
||||
/* A single parameter declaration or parameter type name,
|
||||
as found in a parmlist. */
|
||||
parm:
|
||||
typed_declspecs setspecs parm_declarator maybe_attribute
|
||||
{ $$ = build_tree_list (build_tree_list (current_declspecs,
|
||||
typed_declspecs setspecs parm_declarator maybeasm maybe_attribute
|
||||
{ $$ = build_tree_list (
|
||||
build_tree_list (build_tree_list (current_declspecs,
|
||||
$3),
|
||||
build_tree_list (prefix_attributes,
|
||||
$4));
|
||||
$5)), $4);
|
||||
current_declspecs = TREE_VALUE (declspec_stack);
|
||||
prefix_attributes = TREE_PURPOSE (declspec_stack);
|
||||
declspec_stack = TREE_CHAIN (declspec_stack);
|
||||
resume_momentary ($2); }
|
||||
| typed_declspecs setspecs notype_declarator maybe_attribute
|
||||
{ $$ = build_tree_list (build_tree_list (current_declspecs,
|
||||
| typed_declspecs setspecs notype_declarator maybeasm maybe_attribute
|
||||
{ $$ = build_tree_list (
|
||||
build_tree_list (build_tree_list (current_declspecs,
|
||||
$3),
|
||||
build_tree_list (prefix_attributes,
|
||||
$4));
|
||||
$5)), $4);
|
||||
current_declspecs = TREE_VALUE (declspec_stack);
|
||||
prefix_attributes = TREE_PURPOSE (declspec_stack);
|
||||
declspec_stack = TREE_CHAIN (declspec_stack);
|
||||
resume_momentary ($2); }
|
||||
| typed_declspecs setspecs absdcl maybe_attribute
|
||||
{ $$ = build_tree_list (build_tree_list (current_declspecs,
|
||||
| typed_declspecs setspecs absdcl maybeasm maybe_attribute
|
||||
{ $$ = build_tree_list (
|
||||
build_tree_list (build_tree_list (current_declspecs,
|
||||
$3),
|
||||
build_tree_list (prefix_attributes,
|
||||
$4));
|
||||
$5)), $4);
|
||||
current_declspecs = TREE_VALUE (declspec_stack);
|
||||
prefix_attributes = TREE_PURPOSE (declspec_stack);
|
||||
declspec_stack = TREE_CHAIN (declspec_stack);
|
||||
resume_momentary ($2); }
|
||||
| declmods setspecs notype_declarator maybe_attribute
|
||||
{ $$ = build_tree_list (build_tree_list (current_declspecs,
|
||||
| declmods setspecs notype_declarator maybeasm maybe_attribute
|
||||
{ $$ = build_tree_list (
|
||||
build_tree_list (build_tree_list (current_declspecs,
|
||||
$3),
|
||||
build_tree_list (prefix_attributes,
|
||||
$4));
|
||||
$5)), $4);
|
||||
current_declspecs = TREE_VALUE (declspec_stack);
|
||||
prefix_attributes = TREE_PURPOSE (declspec_stack);
|
||||
declspec_stack = TREE_CHAIN (declspec_stack);
|
||||
resume_momentary ($2); }
|
||||
|
||||
| declmods setspecs absdcl maybe_attribute
|
||||
{ $$ = build_tree_list (build_tree_list (current_declspecs,
|
||||
| declmods setspecs absdcl maybeasm maybe_attribute
|
||||
{ $$ = build_tree_list (
|
||||
build_tree_list (build_tree_list (current_declspecs,
|
||||
$3),
|
||||
build_tree_list (prefix_attributes,
|
||||
$4));
|
||||
$5)), $4);
|
||||
/* end-GG-local */
|
||||
current_declspecs = TREE_VALUE (declspec_stack);
|
||||
prefix_attributes = TREE_PURPOSE (declspec_stack);
|
||||
declspec_stack = TREE_CHAIN (declspec_stack);
|
||||
|
@ -2871,30 +2878,35 @@ mydecl:
|
|||
|
||||
myparms:
|
||||
myparm
|
||||
{ push_parm_decl ($1); }
|
||||
/* begin-GG-local: explicit register specification for parameters */
|
||||
{ push_parm_decl (TREE_PURPOSE($1), TREE_VALUE($1)); }
|
||||
| myparms ',' myparm
|
||||
{ push_parm_decl ($3); }
|
||||
{ push_parm_decl (TREE_PURPOSE($3), TREE_VALUE($3)); }
|
||||
;
|
||||
|
||||
/* A single parameter declaration or parameter type name,
|
||||
as found in a parmlist. DOES NOT ALLOW AN INITIALIZER OR ASMSPEC */
|
||||
as found in a parmlist. DOES NOT ALLOW AN INITIALIZER */
|
||||
|
||||
myparm:
|
||||
parm_declarator maybe_attribute
|
||||
{ $$ = build_tree_list (build_tree_list (current_declspecs,
|
||||
parm_declarator maybeasm maybe_attribute
|
||||
{ $$ = build_tree_list (
|
||||
build_tree_list (build_tree_list (current_declspecs,
|
||||
$1),
|
||||
build_tree_list (prefix_attributes,
|
||||
$2)); }
|
||||
| notype_declarator maybe_attribute
|
||||
{ $$ = build_tree_list (build_tree_list (current_declspecs,
|
||||
$3)), $2); }
|
||||
| notype_declarator maybeasm maybe_attribute
|
||||
{ $$ = build_tree_list (
|
||||
build_tree_list (build_tree_list (current_declspecs,
|
||||
$1),
|
||||
build_tree_list (prefix_attributes,
|
||||
$2)); }
|
||||
| absdcl maybe_attribute
|
||||
{ $$ = build_tree_list (build_tree_list (current_declspecs,
|
||||
$3)), $2); }
|
||||
| absdcl maybeasm maybe_attribute
|
||||
{ $$ = build_tree_list (
|
||||
build_tree_list (build_tree_list (current_declspecs,
|
||||
$1),
|
||||
build_tree_list (prefix_attributes,
|
||||
$2)); }
|
||||
$3)), $2); }
|
||||
/* end-GG-local */
|
||||
;
|
||||
|
||||
optparmlist:
|
||||
|
|
|
@ -331,7 +331,8 @@ extern void print_lang_identifier PROTO((FILE *, tree, int));
|
|||
extern void print_lang_type PROTO((FILE *, tree, int));
|
||||
extern void push_c_function_context PROTO((void));
|
||||
extern void push_label_level PROTO((void));
|
||||
extern void push_parm_decl PROTO((tree));
|
||||
/* Amiga: explicit register specification for parameters */
|
||||
extern void push_parm_decl PROTO((tree, tree));
|
||||
extern tree pushdecl PROTO((tree));
|
||||
extern tree pushdecl_top_level PROTO((tree));
|
||||
extern void pushlevel PROTO((int));
|
||||
|
|
|
@ -2613,6 +2613,10 @@ emit_library_call VPROTO((rtx orgfun, int no_queue, enum machine_mode outmode,
|
|||
|
||||
fun = orgfun;
|
||||
|
||||
#ifdef LIBCALL_ENCODE_SECTION_INFO
|
||||
LIBCALL_ENCODE_SECTION_INFO (fun);
|
||||
#endif
|
||||
|
||||
/* Copy all the libcall-arguments out of the varargs data
|
||||
and into a vector ARGVEC.
|
||||
|
||||
|
@ -3113,6 +3117,10 @@ emit_library_call_value VPROTO((rtx orgfun, rtx value, int no_queue,
|
|||
is_const = no_queue;
|
||||
fun = orgfun;
|
||||
|
||||
#ifdef LIBCALL_ENCODE_SECTION_INFO
|
||||
LIBCALL_ENCODE_SECTION_INFO (fun);
|
||||
#endif
|
||||
|
||||
/* If this kind of value comes back in memory,
|
||||
decide where in memory it should come back. */
|
||||
if (aggregate_value_p (type_for_mode (outmode, 0)))
|
||||
|
|
|
@ -0,0 +1,421 @@
|
|||
/* Configuration for GNU C-compiler for m68k Amiga, running AmigaOS.
|
||||
Copyright (C) 1992, 93-96, 1997 Free Software Foundation, Inc.
|
||||
Contributed by Markus M. Wild (wild@amiga.physik.unizh.ch).
|
||||
Heavily modified by Kamil Iskra (iskra@student.uci.agh.edu.pl).
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "rtl.h"
|
||||
#include "output.h"
|
||||
#include "tree.h"
|
||||
#include "flags.h"
|
||||
#include "expr.h"
|
||||
|
||||
/* Baserel support. */
|
||||
|
||||
/* Does operand (which is a symbolic_operand) live in text space? If
|
||||
so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true.
|
||||
|
||||
This function is used in base relative code generation. */
|
||||
|
||||
int
|
||||
read_only_operand (operand)
|
||||
rtx operand;
|
||||
{
|
||||
if (GET_CODE (operand) == CONST)
|
||||
operand = XEXP (XEXP (operand, 0), 0);
|
||||
if (GET_CODE (operand) == SYMBOL_REF)
|
||||
return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This function is used while generating a base relative code.
|
||||
It returns 1 if a decl is not relocatable, i. e., if it can be put
|
||||
in the text section.
|
||||
Currently, it's very primitive: it just checks if the object size
|
||||
is less than 4 bytes (i. e., if it can hold a pointer). It also
|
||||
supports arrays and floating point types. */
|
||||
|
||||
int
|
||||
amigaos_put_in_text (decl)
|
||||
tree decl;
|
||||
{
|
||||
tree type = TREE_TYPE (decl);
|
||||
if (TREE_CODE (type) == ARRAY_TYPE)
|
||||
type = TREE_TYPE (type);
|
||||
return (TREE_INT_CST_HIGH (TYPE_SIZE (type)) == 0
|
||||
&& TREE_INT_CST_LOW (TYPE_SIZE (type)) < 32)
|
||||
|| FLOAT_TYPE_P (type);
|
||||
}
|
||||
|
||||
/* Common routine used to check if a4 should be preserved/restored. */
|
||||
|
||||
int
|
||||
amigaos_restore_a4 ()
|
||||
{
|
||||
return (flag_pic >= 3 &&
|
||||
(TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4
|
||||
|| lookup_attribute ("saveds",
|
||||
TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))));
|
||||
}
|
||||
|
||||
void
|
||||
amigaos_alternate_pic_setup (stream)
|
||||
FILE *stream;
|
||||
{
|
||||
if (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4)
|
||||
asm_fprintf (stream, "\tjbsr %U__restore_a4\n");
|
||||
else if (lookup_attribute ("saveds",
|
||||
TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
|
||||
asm_fprintf (stream, "\tlea %U__a4_init,%Ra4\n");
|
||||
}
|
||||
|
||||
/* Attributes support. */
|
||||
|
||||
#define AMIGA_CHIP_SECTION_NAME ".datachip"
|
||||
|
||||
/* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine
|
||||
specific attribute for DECL. The attributes in ATTRIBUTES have previously
|
||||
been assigned to DECL. */
|
||||
|
||||
int
|
||||
valid_amigaos_decl_attribute (decl, identifier)
|
||||
tree decl, identifier;
|
||||
{
|
||||
if (TREE_CODE (decl) == VAR_DECL)
|
||||
if (is_attribute_p ("chip", identifier))
|
||||
#ifdef ASM_OUTPUT_SECTION_NAME
|
||||
{
|
||||
if (! TREE_STATIC (decl) && ! DECL_EXTERNAL (decl))
|
||||
error ("`chip' attribute cannot be specified for local variables");
|
||||
else
|
||||
{
|
||||
/* The decl may have already been given a section attribute from
|
||||
a previous declaration. Ensure they match. */
|
||||
if (DECL_SECTION_NAME (decl) == NULL_TREE)
|
||||
DECL_SECTION_NAME (decl) =
|
||||
build_string (strlen (AMIGA_CHIP_SECTION_NAME) + 1,
|
||||
AMIGA_CHIP_SECTION_NAME);
|
||||
else if (strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
|
||||
AMIGA_CHIP_SECTION_NAME) != 0)
|
||||
{
|
||||
error_with_decl (decl,
|
||||
"`chip' for `%s' conflicts with previous declaration");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
error ("`chip' attribute is not supported for this target");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine
|
||||
specific attribute for TYPE. The attributes in ATTRIBUTES have previously
|
||||
been assigned to TYPE. */
|
||||
|
||||
int
|
||||
valid_amigaos_type_attribute (type, attributes, identifier, args)
|
||||
tree type, attributes, identifier, args;
|
||||
{
|
||||
if (valid_m68k_type_attribute (type, attributes, identifier, args))
|
||||
return 1;
|
||||
else if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
|
||||
{
|
||||
if (is_attribute_p ("stackext", identifier))
|
||||
{
|
||||
if (lookup_attribute ("interrupt", attributes) ||
|
||||
lookup_attribute ("interrupt_handler", attributes))
|
||||
{
|
||||
error ("`stackext' and `interrupt' are mutually exclusive");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (is_attribute_p ("interrupt", identifier) ||
|
||||
is_attribute_p ("interrupt_handler", identifier))
|
||||
{
|
||||
if (lookup_attribute ("stackext", attributes))
|
||||
{
|
||||
error ("`stackext' and `interrupt' are mutually exclusive");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (is_attribute_p ("saveds", identifier))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Stack checking and automatic extension support. */
|
||||
|
||||
void
|
||||
amigaos_prologue_begin_hook (stream, fsize)
|
||||
FILE *stream;
|
||||
int fsize;
|
||||
{
|
||||
if (TARGET_STACKCHECK)
|
||||
{
|
||||
if (fsize < 256)
|
||||
asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
|
||||
"\tjcc 0f\n"
|
||||
"\tjra %U__stkovf\n"
|
||||
"\t0:\n",
|
||||
(flag_pic == 3 ? "a4@(___stk_limit:W)" :
|
||||
(flag_pic == 4 ? "a4@(___stk_limit:L)" :
|
||||
"___stk_limit")));
|
||||
else if (fsize < 0x8000)
|
||||
asm_fprintf (stream, "\tmovel #%d:W,%Rd0\n\tjbsr %U__stkchk_d0\n",
|
||||
fsize);
|
||||
else
|
||||
asm_fprintf (stream, "\tmovel #%d,%Rd0\n\tjbsr %U__stkchk_d0\n",
|
||||
fsize);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
amigaos_alternate_frame_setup_f (stream, fsize)
|
||||
FILE *stream;
|
||||
int fsize;
|
||||
{
|
||||
if (fsize < 128)
|
||||
asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
|
||||
"\tjcc 0f\n"
|
||||
"\tmoveq #%d,%Rd0\n"
|
||||
"\tmoveq #0,%Rd1\n"
|
||||
"\tjbsr %U__stkext_f\n"
|
||||
"0:\tlink %Ra5,#%d:W\n",
|
||||
(flag_pic == 3 ? "a4@(___stk_limit:W)" :
|
||||
(flag_pic == 4 ? "a4@(___stk_limit:L)" :
|
||||
"___stk_limit")),
|
||||
fsize, -fsize);
|
||||
else if (fsize < 0x8000)
|
||||
asm_fprintf (stream, "\tmovel #%d:W,%Rd0\n\tjbsr %U__link_a5_d0_f\n",
|
||||
fsize);
|
||||
else
|
||||
asm_fprintf (stream, "\tmovel #%d,%Rd0\n\tjbsr %U__link_a5_d0_f\n",
|
||||
fsize);
|
||||
}
|
||||
|
||||
void
|
||||
amigaos_alternate_frame_setup (stream, fsize)
|
||||
FILE *stream;
|
||||
int fsize;
|
||||
{
|
||||
if (! fsize)
|
||||
asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
|
||||
"\tjcc 0f\n"
|
||||
"\tmoveq #0,%Rd0\n"
|
||||
"\tmoveq #0,%Rd1\n"
|
||||
"\tjbsr %U__stkext_f\n"
|
||||
"0:\n",
|
||||
(flag_pic == 3 ? "a4@(___stk_limit:W)" :
|
||||
(flag_pic == 4 ? "a4@(___stk_limit:L)" :
|
||||
"___stk_limit")));
|
||||
else if (fsize + 4 < 128)
|
||||
asm_fprintf (stream, "\tcmpl %s,%Rsp\n"
|
||||
"\tjcc 0f\n"
|
||||
"\tmoveq #%d,%Rd0\n"
|
||||
"\tmoveq #0,%Rd1\n"
|
||||
"\tjbsr %U__stkext_f\n"
|
||||
"0:\taddw #%d,%Rsp\n",
|
||||
(flag_pic == 3 ? "a4@(___stk_limit:W)" :
|
||||
(flag_pic == 4 ? "a4@(___stk_limit:L)" :
|
||||
"___stk_limit")),
|
||||
fsize + 4, -(fsize + 4));
|
||||
else if (fsize + 4 < 0x8000)
|
||||
asm_fprintf (stream, "\tmovel #%d:W,%Rd0\n\tjbsr %U__sub_d0_sp_f\n",
|
||||
fsize + 4);
|
||||
else
|
||||
asm_fprintf (stream, "\tmovel %0I%d,%Rd0\n\tjbsr %U__sub_d0_sp_f\n",
|
||||
fsize + 4);
|
||||
}
|
||||
|
||||
static rtx
|
||||
gen_stack_management_call (stack_pointer, arg, func)
|
||||
rtx stack_pointer;
|
||||
rtx arg;
|
||||
char *func;
|
||||
{
|
||||
rtx call_insn, call, seq, name;
|
||||
start_sequence ();
|
||||
|
||||
/* Move arg to d0. */
|
||||
emit_move_insn (gen_rtx (REG, SImode, 0), arg);
|
||||
|
||||
/* Generate the function reference. */
|
||||
name = gen_rtx (SYMBOL_REF, Pmode, func);
|
||||
SYMBOL_REF_FLAG (name) = 1;
|
||||
/* If optimizing, put it in a psedo so that several loads can be merged
|
||||
into one. */
|
||||
if (optimize && ! flag_no_function_cse)
|
||||
name = copy_to_reg (name);
|
||||
|
||||
/* Generate the function call. */
|
||||
call = gen_rtx (CALL, VOIDmode, gen_rtx (MEM, FUNCTION_MODE, name),
|
||||
const0_rtx);
|
||||
/* If we are doing stack extension, notify about the sp change. */
|
||||
if (stack_pointer)
|
||||
call = gen_rtx (SET, VOIDmode, stack_pointer, call);
|
||||
|
||||
/* Generate the call instruction. */
|
||||
call_insn = emit_call_insn (call);
|
||||
/* Stack extension does not change memory in an unpredictable way. */
|
||||
CONST_CALL_P (call_insn) = 1;
|
||||
/* We pass an argument in d0. */
|
||||
CALL_INSN_FUNCTION_USAGE (call_insn) = gen_rtx (EXPR_LIST, VOIDmode,
|
||||
gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, 0)), 0);
|
||||
|
||||
seq = gen_sequence ();
|
||||
end_sequence ();
|
||||
return seq;
|
||||
}
|
||||
|
||||
rtx
|
||||
gen_stack_cleanup_call (stack_pointer, sa)
|
||||
rtx stack_pointer;
|
||||
rtx sa;
|
||||
{
|
||||
return gen_stack_management_call (stack_pointer, sa, "__move_d0_sp");
|
||||
}
|
||||
|
||||
void
|
||||
amigaos_alternate_allocate_stack (operands)
|
||||
rtx *operands;
|
||||
{
|
||||
if (TARGET_STACKEXTEND)
|
||||
emit_insn ((rtx)gen_stack_management_call (stack_pointer_rtx, operands[1],
|
||||
"__sub_d0_sp"));
|
||||
else
|
||||
{
|
||||
if (TARGET_STACKCHECK)
|
||||
emit_insn ((rtx)gen_stack_management_call (0, operands[1],
|
||||
"__stkchk_d0"));
|
||||
anti_adjust_stack (operands[1]);
|
||||
}
|
||||
emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
|
||||
}
|
||||
|
||||
/* begin-GG-local: explicit register specification for parameters */
|
||||
|
||||
/* 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
|
||||
amigaos_init_cumulative_args(CUMULATIVE_ARGS *cum, tree fntype)
|
||||
{
|
||||
m68k_init_cumulative_args(cum, fntype);
|
||||
|
||||
if (fntype)
|
||||
cum->formal_type=TYPE_ARG_TYPES(fntype);
|
||||
else /* Call to compiler-support function. */
|
||||
cum->formal_type=0;
|
||||
}
|
||||
|
||||
/* Update the data in CUM to advance over an argument. */
|
||||
|
||||
void
|
||||
amigaos_function_arg_advance(CUMULATIVE_ARGS *cum)
|
||||
{
|
||||
m68k_function_arg_advance(cum);
|
||||
|
||||
if (cum->formal_type)
|
||||
cum->formal_type=TREE_CHAIN((tree)cum->formal_type);
|
||||
}
|
||||
|
||||
/* A C expression that controls whether a function argument is passed
|
||||
in a register, and which register. */
|
||||
|
||||
struct rtx_def *
|
||||
amigaos_function_arg(CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
||||
tree type)
|
||||
{
|
||||
tree asmtree;
|
||||
if (cum->formal_type && TREE_VALUE((tree)cum->formal_type)
|
||||
&& (asmtree=lookup_attribute("asm",
|
||||
TYPE_ATTRIBUTES(TREE_VALUE((tree)cum->formal_type)))))
|
||||
{
|
||||
int i;
|
||||
#if 0
|
||||
/* See c-decl.c/push_parm_decl for an explanation why this doesn't work.
|
||||
*/
|
||||
cum->last_arg_reg=TREE_INT_CST_LOW(TREE_VALUE(TREE_VALUE(asmtree)));
|
||||
#else
|
||||
cum->last_arg_reg=TREE_INT_CST_LOW(TREE_VALUE(asmtree));
|
||||
#endif
|
||||
cum->last_arg_len=HARD_REGNO_NREGS(cum->last_arg_reg, mode);
|
||||
|
||||
for (i=0; i<cum->last_arg_len; i++)
|
||||
if (cum->regs_already_used & (1 << cum->last_arg_reg+i))
|
||||
{
|
||||
error("two parameters allocated for one register");
|
||||
break;
|
||||
}
|
||||
return gen_rtx(REG, mode, cum->last_arg_reg);
|
||||
}
|
||||
else
|
||||
return (struct rtx_def *)m68k_function_arg(cum, mode, type);
|
||||
}
|
||||
|
||||
/* 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). */
|
||||
|
||||
int
|
||||
comp_amigaos_type_attributes(tree type1, tree type2)
|
||||
{
|
||||
int ret;
|
||||
if ((ret=comp_m68k_type_attributes(type1, type2))!=1)
|
||||
return ret;
|
||||
|
||||
/* 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;
|
||||
arg1=TYPE_ARG_TYPES(type1);
|
||||
arg2=TYPE_ARG_TYPES(type2);
|
||||
for (; arg1 && arg2; arg1=TREE_CHAIN(arg1), arg2=TREE_CHAIN(arg2))
|
||||
if (TREE_VALUE(arg1) && TREE_VALUE(arg2))
|
||||
{
|
||||
tree asm1, asm2;
|
||||
asm1=lookup_attribute("asm", TYPE_ATTRIBUTES(TREE_VALUE(arg1)));
|
||||
asm2=lookup_attribute("asm", TYPE_ATTRIBUTES(TREE_VALUE(arg2)));
|
||||
if (asm1 && asm2)
|
||||
{
|
||||
if (TREE_INT_CST_LOW(TREE_VALUE(asm1))!=
|
||||
TREE_INT_CST_LOW(TREE_VALUE(asm2)))
|
||||
return 0; /* Two different registers specified. */
|
||||
}
|
||||
else
|
||||
if (asm1 || asm2)
|
||||
return 0; /* "asm" used in only one type. */
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* end-GG-local */
|
|
@ -0,0 +1,637 @@
|
|||
/* Configuration for GNU C-compiler for m68k Amiga, running AmigaOS.
|
||||
Copyright (C) 1992, 93-97, 1998 Free Software Foundation, Inc.
|
||||
Contributed by Markus M. Wild (wild@amiga.physik.unizh.ch).
|
||||
Heavily modified by Kamil Iskra (iskra@student.uci.agh.edu.pl).
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "m68k/m68k.h"
|
||||
|
||||
/* begin-GG-local: explicit register specification for parameters */
|
||||
#define TARGET_AMIGAOS
|
||||
/* end-GG-local */
|
||||
|
||||
/* Specs, switches. */
|
||||
|
||||
/* See m68k.h for bits in TARGET_DEFAULT.
|
||||
0 means 68000, no hardware fpu (68881/68882/68040/68060). */
|
||||
|
||||
#define TARGET_DEFAULT 0
|
||||
|
||||
/* Define __HAVE_68881__ in preprocessor according to the -m flags.
|
||||
This will control the use of inline 68881 insns in certain macros.
|
||||
Also inform the program which CPU we compile for.
|
||||
When creating shared libraries, use different 'errno'. */
|
||||
|
||||
/* -msoft-float is the default, assume -mc68000 as well */
|
||||
#define CPP_SPEC \
|
||||
"%{m68881:-D__HAVE_68881__} " \
|
||||
"%{!ansi:" \
|
||||
"%{m68020:-Dmc68020} " \
|
||||
"%{mc68020:-Dmc68020} " \
|
||||
"%{m68020-40:-Dmc68020} " \
|
||||
"%{m68020-60:-Dmc68020} " \
|
||||
"%{m68030:-Dmc68030} " \
|
||||
"%{m68040:-Dmc68040} " \
|
||||
"%{m68060:-Dmc68060} " \
|
||||
"%{!noixemul:-Dixemul} " \
|
||||
"%{noixemul:-Dlibnix}} " \
|
||||
"%{m68020:-D__mc68020__ -D__mc68020} " \
|
||||
"%{mc68020:-D__mc68020__ -D__mc68020} " \
|
||||
"%{m68020-40:-D__mc68020__ -D__mc68020} " \
|
||||
"%{m68020-60:-D__mc68020__ -D__mc68020} " \
|
||||
"%{m68030:-D__mc68030__ -D__mc68030} " \
|
||||
"%{m68040:-D__mc68040__ -D__mc68040} " \
|
||||
"%{m68060:-D__mc68060__ -D__mc68060} " \
|
||||
"%{!noixemul:-D__ixemul__ -D__ixemul} " \
|
||||
"%{noixemul:-D__libnix__ -D__libnix} " \
|
||||
"%{malways-restore-a4:-Derrno=(*ixemul_errno)} " \
|
||||
"%{mrestore-a4:-Derrno=(*ixemul_errno)} "
|
||||
|
||||
/* Various -m flags require special flags to the assembler. */
|
||||
|
||||
#define ASM_SPEC "\
|
||||
%{m68000:-mc68010}\
|
||||
%{mc68000:-mc68010}\
|
||||
%{m68020:-mc68020}\
|
||||
%{mc68020:-mc68020}\
|
||||
%{m68030:-mc68030}\
|
||||
%{m68040:-mc68040}\
|
||||
%{m68060:-mc68060}\
|
||||
%{m68020-40:-mc68020}\
|
||||
%{m68020-60:-mc68020}\
|
||||
%{!mc68000:%{!m68000:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68060:%{!m68020-40:%{!m68020-60:-mc68010}}}}}}}}}\
|
||||
%{msmall-code:-sc}\
|
||||
"
|
||||
|
||||
/* amiga/amigaos are the new "standard" defines for the Amiga.
|
||||
* MCH_AMIGA, AMIGA, __chip etc. are used in other compilers and are
|
||||
* provided for compatibility reasons. */
|
||||
|
||||
#define CPP_PREDEFINES "\
|
||||
-Dmc68000\
|
||||
-Damiga\
|
||||
-Damigaos\
|
||||
-DMCH_AMIGA\
|
||||
-DAMIGA\
|
||||
-D__chip=__attribute__((__chip__))\
|
||||
-D__saveds=__attribute__((__saveds__))\
|
||||
-D__interrupt=__attribute__((__interrupt__))\
|
||||
-D__interrupt_handler=__attribute__((__interrupt_handler__))\
|
||||
-D__stackext=__attribute__((__stackext__))\
|
||||
-D__regargs=__attribute__((__regparm__))\
|
||||
-D__stdargs=__attribute__((__stkparm__))\
|
||||
-D__aligned=__attribute__((__aligned__(4)))\
|
||||
-Asystem(amigaos)\
|
||||
-Acpu(m68k)\
|
||||
-Amachine(m68k)\
|
||||
"
|
||||
|
||||
/* Choose the right startup file, depending on whether we use base relative
|
||||
code, base relative code with automatic relocation (-resident), their
|
||||
32-bit versions, libnix, profiling or plain crt0.o. */
|
||||
|
||||
#define STARTFILE_SPEC \
|
||||
"%{!noixemul:" \
|
||||
"%{fbaserel:%{!resident:bcrt0.o%s}}" \
|
||||
"%{resident:rcrt0.o%s}" \
|
||||
"%{fbaserel32:%{!resident32:lcrt0.o%s}}" \
|
||||
"%{resident32:scrt0.o%s}" \
|
||||
"%{!resident:%{!fbaserel:%{!resident32:%{!fbaserel32:" \
|
||||
"%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}}}}}" \
|
||||
"%{noixemul:" \
|
||||
"%{ramiga-*:" \
|
||||
"%{ramiga-lib:libnix/libinit.o%s}" \
|
||||
"%{ramiga-libr:libnix/libinitr.o%s}" \
|
||||
"%{ramiga-dev:libnix/devinit.o%s}}" \
|
||||
"%{!ramiga-*:" \
|
||||
"%{resident:libnix/nrcrt0.o%s}" \
|
||||
"%{!resident:" \
|
||||
"%{fbaserel:libnix/nbcrt0.o%s}" \
|
||||
"%{!fbaserel:libnix/ncrt0.o%s}}}}" \
|
||||
|
||||
#define ENDFILE_SPEC "%{noixemul:-lstubs}"
|
||||
|
||||
/* Automatically search libamiga.a for AmigaOS specific functions. Note
|
||||
that we first search the standard C library to resolve as much as
|
||||
possible from there, since it has names that are duplicated in libamiga.a
|
||||
which we *don't* want from there. Then search libamiga.a for any calls
|
||||
that were not generated inline, and finally search the standard C library
|
||||
again to resolve any references that libamiga.a might have generated.
|
||||
This may only be a temporary solution since it might be better to simply
|
||||
remove the things from libamiga.a that should be pulled in from libc.a
|
||||
instead, which would eliminate the first reference to libc.a. Note that
|
||||
if we don't search it automatically, it is very easy for the user to try
|
||||
to put in a -lamiga himself and get it in the wrong place, so that (for
|
||||
example) calls like sprintf come from -lamiga rather than -lc. */
|
||||
|
||||
#define LIB_SPEC \
|
||||
"%{!noixemul:" \
|
||||
"%{!p:%{!pg:-lc -lamiga -lc}}" \
|
||||
"%{p:-lc_p}%{pg:-lc_p}}" \
|
||||
"%{noixemul:-lnixmain -lnix -lamiga " \
|
||||
"%{mstackcheck:-lstack} " \
|
||||
"%{mstackextend:-lstack}}"
|
||||
|
||||
#define LIBGCC_SPEC \
|
||||
"-lgcc %{noixemul:-lnix}"
|
||||
|
||||
/* If debugging, tell the linker to output amiga-hunk symbols *and* a BSD
|
||||
compatible debug hunk.
|
||||
Also, pass appropriate linker flavours depending on user-supplied
|
||||
commandline options. */
|
||||
|
||||
#define LINK_SPEC \
|
||||
"%{noixemul:-fl libnix} " \
|
||||
"%{fbaserel:%{!resident:-m amiga_bss -fl libb}} " \
|
||||
"%{resident:-m amiga_bss -amiga-datadata-reloc -fl libb} " \
|
||||
"%{fbaserel32:%{!resident32:-m amiga_bss -fl libb32}} " \
|
||||
"%{resident32:-m amiga_bss -amiga-datadata-reloc -fl libb32} " \
|
||||
"%{g:-amiga-debug-hunk} " \
|
||||
"%{m68020:-fl libm020} " \
|
||||
"%{mc68020:-fl libm020} " \
|
||||
"%{m68030:-fl libm020} " \
|
||||
"%{m68040:-fl libm020} " \
|
||||
"%{m68060:-fl libm020} " \
|
||||
"%{m68020-40:-fl libm020} " \
|
||||
"%{m68020-60:-fl libm020} " \
|
||||
"%{m68881:-fl libm881} "
|
||||
|
||||
/* Translate '-resident' to '-fbaserel' (they differ in linking stage only).
|
||||
Don't put function addresses in registers for PC-relative code. */
|
||||
|
||||
#define CC1_SPEC \
|
||||
"%{resident:-fbaserel} " \
|
||||
"%{resident32:-fbaserel32} " \
|
||||
"%{msmall-code:-fno-function-cse} "
|
||||
|
||||
/* A modified copy of LINK_COMMAND_SPEC from gcc/gcc.c file. If -noixemul
|
||||
* option is enabled, don't prepend libgcc.a to link libraries and make sure
|
||||
* the options is at the end of command line. Otherwise linker chooses main()
|
||||
* function from libgcc.a instead from libnix.a. */
|
||||
|
||||
#define LINK_COMMAND_SPEC \
|
||||
"%{!fsyntax-only: " \
|
||||
"%{!c:%{!M:%{!MM:%{!E:%{!S:%(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} " \
|
||||
"%{r} %{s} %{t} %{u*} %{x} %{z} %{Z} " \
|
||||
"%{!A:%{!nostdlib:%{!nostartfiles:%S}}} " \
|
||||
"%{static:} %{L*} %D %o " \
|
||||
"%{!nostdlib:%{!nodefaultlibs:%{!noixemul:%G} %L}} " \
|
||||
"%{!A:%{!nostdlib:%{!nostartfiles:%E}}} " \
|
||||
"%{!nostdlib:%{!nodefaultlibs:%G}} " \
|
||||
"%{T*} }}}}}} "
|
||||
|
||||
/* Compile with stack extension. */
|
||||
|
||||
#define MASK_STACKEXTEND 0x40000000
|
||||
#define TARGET_STACKEXTEND (((target_flags & MASK_STACKEXTEND) \
|
||||
&& !lookup_attribute ("interrupt", \
|
||||
TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))) \
|
||||
&& !lookup_attribute ("interrupt_handler", \
|
||||
TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))) \
|
||||
|| lookup_attribute ("stackext", \
|
||||
TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
|
||||
|
||||
/* Compile with stack checking. */
|
||||
|
||||
#define MASK_STACKCHECK 0x20000000
|
||||
#define TARGET_STACKCHECK ((target_flags & MASK_STACKCHECK) \
|
||||
&& !(target_flags & MASK_STACKEXTEND) \
|
||||
&& !lookup_attribute ("interrupt", \
|
||||
TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))) \
|
||||
&& !lookup_attribute ("interrupt_handler", \
|
||||
TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))) \
|
||||
&& !lookup_attribute ("stackext", \
|
||||
TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
|
||||
|
||||
/* Compile with a4 restoring in public functions. */
|
||||
|
||||
#define MASK_RESTORE_A4 0x10000000
|
||||
#define TARGET_RESTORE_A4 \
|
||||
((target_flags & MASK_RESTORE_A4) && TREE_PUBLIC (current_function_decl))
|
||||
|
||||
/* Compile with a4 restoring in all functions. */
|
||||
|
||||
#define MASK_ALWAYS_RESTORE_A4 0x8000000
|
||||
#define TARGET_ALWAYS_RESTORE_A4 (target_flags & MASK_ALWAYS_RESTORE_A4)
|
||||
|
||||
/* Provide a dummy entry for the '-msmall-code' switch. This is used by
|
||||
the assembler and '*_SPEC'. */
|
||||
|
||||
#undef SUBTARGET_SWITCHES
|
||||
#define SUBTARGET_SWITCHES \
|
||||
{ "small-code", 0}, \
|
||||
{ "stackcheck", MASK_STACKCHECK}, \
|
||||
{ "no-stackcheck", - MASK_STACKCHECK}, \
|
||||
{ "stackextend", MASK_STACKEXTEND}, \
|
||||
{ "no-stackextend", - MASK_STACKEXTEND}, \
|
||||
{ "fixedstack", - (MASK_STACKCHECK|MASK_STACKEXTEND)}, \
|
||||
{ "restore-a4", MASK_RESTORE_A4}, \
|
||||
{ "no-restore-a4", - MASK_RESTORE_A4}, \
|
||||
{ "always-restore-a4", MASK_ALWAYS_RESTORE_A4}, \
|
||||
{ "no-always-restore-a4", - MASK_ALWAYS_RESTORE_A4},
|
||||
|
||||
#undef SUBTARGET_OVERRIDE_OPTIONS
|
||||
#define SUBTARGET_OVERRIDE_OPTIONS \
|
||||
do \
|
||||
{ \
|
||||
if (!TARGET_68020 && flag_pic==4) \
|
||||
error ("-fbaserel32 is not supported on the 68000 or 68010\n"); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Various ABI issues. */
|
||||
|
||||
/* This is (almost;-) BSD, so it wants DBX format. */
|
||||
|
||||
#define DBX_DEBUGGING_INFO
|
||||
|
||||
/* GDB goes mad if it sees the function end marker. */
|
||||
|
||||
#define NO_DBX_FUNCTION_END 1
|
||||
|
||||
/* Allow folding division by zero. */
|
||||
|
||||
#define REAL_INFINITY
|
||||
|
||||
/* Don't try using XFmode since we don't have appropriate runtime software
|
||||
support. */
|
||||
#undef LONG_DOUBLE_TYPE_SIZE
|
||||
#define LONG_DOUBLE_TYPE_SIZE 64
|
||||
|
||||
/* Use A5 as framepointer instead of A6, since the AmigaOS ABI requires A6
|
||||
to be used as a shared library base pointer in direct library calls. */
|
||||
|
||||
#undef FRAME_POINTER_REGNUM
|
||||
#define FRAME_POINTER_REGNUM 13
|
||||
#undef ARG_POINTER_REGNUM
|
||||
#define ARG_POINTER_REGNUM 13
|
||||
|
||||
/* We use A4 for the PIC pointer, not A5, which is the framepointer. */
|
||||
|
||||
#undef PIC_OFFSET_TABLE_REGNUM
|
||||
#define PIC_OFFSET_TABLE_REGNUM 12
|
||||
|
||||
/* The AmigaOS ABI does not define how structures should be returned, so,
|
||||
contrary to 'm68k.h', we prefer a multithread-safe solution. */
|
||||
|
||||
#undef PCC_STATIC_STRUCT_RETURN
|
||||
|
||||
/* Setup a default shell return value for those (gazillion..) programs that
|
||||
(inspite of ANSI-C) declare main() to be void (or even VOID...) and thus
|
||||
cause the shell to randomly caugh upon executing such programs (contrary
|
||||
to Unix, AmigaOS scripts are terminated with an error if a program returns
|
||||
with an error code above the `error' or even `failure' level
|
||||
(which is configurable with the FAILAT command)). */
|
||||
|
||||
#define DEFAULT_MAIN_RETURN c_expand_return (integer_zero_node)
|
||||
|
||||
#undef WCHAR_TYPE
|
||||
#define WCHAR_TYPE "unsigned int"
|
||||
|
||||
/* Support sections in chip memory, currently '.datachip' only. */
|
||||
#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \
|
||||
fprintf ((FILE), "\t%s\n", (NAME))
|
||||
|
||||
/* We define ASM_OUTPUT_SECTON_NAME, but we don't support arbitrary sections,
|
||||
including '.gcc_except_table', so we emulate the standard behaviour. */
|
||||
#define EXCEPTION_SECTION() \
|
||||
do \
|
||||
{ \
|
||||
if (flag_pic) \
|
||||
data_section (); \
|
||||
else \
|
||||
readonly_data_section (); \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
#define EH_FRAME_SECTION() readonly_data_section ()
|
||||
|
||||
/* Use sjlj exceptions until problems with DWARF2 unwind info on a.out
|
||||
targets using GNU ld are fixed. */
|
||||
#define DWARF2_UNWIND_INFO 0
|
||||
|
||||
/* GAS supports alignment up to 32768 bytes. */
|
||||
#undef ASM_OUTPUT_ALIGN
|
||||
#define ASM_OUTPUT_ALIGN(FILE, LOG) \
|
||||
do \
|
||||
{ \
|
||||
if ((LOG) == 1) \
|
||||
fprintf ((FILE), "\t.even\n"); \
|
||||
else \
|
||||
fprintf ((FILE), "\t.align %d\n", (LOG)); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define MAX_OFILE_ALIGNMENT ((1 << 15)*BITS_PER_UNIT)
|
||||
|
||||
/* It is not uncommon to use a custom startup code on AmigaOS. The OS
|
||||
starts an application by jumping to the first byte of the text section,
|
||||
so we prefer the constants to be put after the functions. */
|
||||
/* FIXME: Disabled for now, it's buggy. */
|
||||
|
||||
/* #define CONSTANT_AFTER_FUNCTION_P(EXP) 1 */ /**/
|
||||
|
||||
/* Call __flush_cache() after building the trampoline: it will call
|
||||
an appropriate OS cache-clearing routine. */
|
||||
|
||||
#undef FINALIZE_TRAMPOLINE
|
||||
#define FINALIZE_TRAMPOLINE(TRAMP) \
|
||||
emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__flush_cache"), \
|
||||
0, VOIDmode, 2, (TRAMP), Pmode, \
|
||||
GEN_INT (TRAMPOLINE_SIZE), SImode)
|
||||
|
||||
/* Baserel support. */
|
||||
|
||||
/* Given that symbolic_operand(X), return TRUE if no special
|
||||
base relative relocation is necessary */
|
||||
|
||||
#define LEGITIMATE_BASEREL_OPERAND_P(X) \
|
||||
(flag_pic >= 3 && read_only_operand (X))
|
||||
|
||||
#undef LEGITIMATE_PIC_OPERAND_P
|
||||
#define LEGITIMATE_PIC_OPERAND_P(X) \
|
||||
(! symbolic_operand (X, VOIDmode) || LEGITIMATE_BASEREL_OPERAND_P (X))
|
||||
|
||||
/* Define this macro if references to a symbol must be treated
|
||||
differently depending on something about the variable or
|
||||
function named by the symbol (such as what section it is in).
|
||||
|
||||
The macro definition, if any, is executed immediately after the
|
||||
rtl for DECL or other node is created.
|
||||
The value of the rtl will be a `mem' whose address is a
|
||||
`symbol_ref'.
|
||||
|
||||
The usual thing for this macro to do is to a flag in the
|
||||
`symbol_ref' (such as `SYMBOL_REF_FLAG') or to store a modified
|
||||
name string in the `symbol_ref' (if one bit is not enough
|
||||
information).
|
||||
|
||||
On the Amiga we use this to indicate if references to a symbol should be
|
||||
absolute or base relative. */
|
||||
|
||||
#define ENCODE_SECTION_INFO(DECL) \
|
||||
do \
|
||||
{ \
|
||||
if (TREE_CODE (DECL) == FUNCTION_DECL) \
|
||||
SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1; \
|
||||
else \
|
||||
{ \
|
||||
rtx rtl = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \
|
||||
? TREE_CST_RTL (DECL) : DECL_RTL (DECL)); \
|
||||
if ((RTX_UNCHANGING_P (rtl) && !MEM_VOLATILE_P (rtl) \
|
||||
&& (flag_pic<3 || (TREE_CODE (DECL) == STRING_CST \
|
||||
&& !flag_writable_strings) \
|
||||
|| amigaos_put_in_text (DECL))) \
|
||||
|| (TREE_CODE (DECL) == VAR_DECL \
|
||||
&& DECL_SECTION_NAME (DECL) != NULL_TREE)) \
|
||||
SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define LIBCALL_ENCODE_SECTION_INFO(FUN) \
|
||||
do \
|
||||
{ \
|
||||
if (flag_pic >= 3) \
|
||||
SYMBOL_REF_FLAG (FUN) = 1; \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* according to varasm.c, RELOC referrs *only* to whether constants (!)
|
||||
are addressed by address. */
|
||||
|
||||
#undef SELECT_SECTION
|
||||
#define SELECT_SECTION(DECL, RELOC) \
|
||||
{ \
|
||||
if (TREE_CODE (DECL) == STRING_CST) \
|
||||
{ \
|
||||
if (! flag_writable_strings) \
|
||||
readonly_data_section (); \
|
||||
else \
|
||||
data_section (); \
|
||||
} \
|
||||
else if (TREE_CODE (DECL) == VAR_DECL) \
|
||||
{ \
|
||||
if (TREE_READONLY (DECL) \
|
||||
&& ! TREE_THIS_VOLATILE (DECL) \
|
||||
&& DECL_INITIAL (DECL) \
|
||||
&& (DECL_INITIAL (DECL) == error_mark_node \
|
||||
|| TREE_CONSTANT (DECL_INITIAL (DECL))) \
|
||||
&& (!flag_pic || (flag_pic<3 && !RELOC) \
|
||||
|| SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)))) \
|
||||
readonly_data_section (); \
|
||||
else \
|
||||
data_section (); \
|
||||
} \
|
||||
else if ((!flag_pic || (flag_pic<3 && !RELOC)) \
|
||||
&& SYMBOL_REF_FLAG (XEXP ((TREE_CODE_CLASS (TREE_CODE (DECL))\
|
||||
!= 'd' ? TREE_CST_RTL (DECL) : DECL_RTL (DECL)), 0))) \
|
||||
readonly_data_section (); \
|
||||
else \
|
||||
data_section (); \
|
||||
}
|
||||
|
||||
/* Preserve the initial value of a4. */
|
||||
|
||||
#define PROLOGUE_EXTRA_SAVE(MASK, NUM_SAVED_REGS) \
|
||||
do \
|
||||
{ \
|
||||
if (amigaos_restore_a4 ()) \
|
||||
{ \
|
||||
(MASK) |= 1 << (15 - PIC_OFFSET_TABLE_REGNUM); \
|
||||
(NUM_SAVED_REGS)++; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Restore the initial value of a4. */
|
||||
|
||||
#define EPILOGUE_EXTRA_RESTORE(MASK, NREGS) \
|
||||
do \
|
||||
{ \
|
||||
if (amigaos_restore_a4 ()) \
|
||||
{ \
|
||||
(MASK) |= 1 << PIC_OFFSET_TABLE_REGNUM; \
|
||||
(NREGS)++; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define HAVE_ALTERNATE_PIC_SETUP (flag_pic >= 3)
|
||||
|
||||
/* Make a4 point at data hunk. */
|
||||
|
||||
void amigaos_alternate_pic_setup ();
|
||||
#define ALTERNATE_PIC_SETUP(STREAM) \
|
||||
(amigaos_alternate_pic_setup (STREAM))
|
||||
|
||||
/* If preserving a4, let the code generator know about it. */
|
||||
|
||||
#undef SUBTARGET_INITIAL_FP_OFFSET
|
||||
#define SUBTARGET_INITIAL_FP_OFFSET(OFFSET) \
|
||||
do \
|
||||
{ \
|
||||
if (amigaos_restore_a4 ()) \
|
||||
(OFFSET) += 4; \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Determine if the epilogue should be output as RTL.
|
||||
Don't do it if preserving a4. */
|
||||
|
||||
#undef USE_RETURN_INSN
|
||||
#define USE_RETURN_INSN (use_return_insn () && ! amigaos_restore_a4 ())
|
||||
|
||||
/* Attribute support. */
|
||||
|
||||
/* A C expression whose value is nonzero if IDENTIFIER with arguments
|
||||
ARGS is a valid machine specific attribute for DECL. The attributes
|
||||
in ATTRIBUTES have previously been assigned to DECL. */
|
||||
|
||||
#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \
|
||||
(valid_amigaos_decl_attribute ((DECL), (IDENTIFIER)))
|
||||
|
||||
/* A C expression whose value is nonzero if IDENTIFIER with arguments
|
||||
ARGS is a valid machine specific attribute for TYPE. The attributes
|
||||
in ATTRIBUTES have previously been assigned to TYPE. */
|
||||
|
||||
#undef VALID_MACHINE_TYPE_ATTRIBUTE
|
||||
#define VALID_MACHINE_TYPE_ATTRIBUTE(TYPE, ATTRIBUTES, IDENTIFIER, ARGS) \
|
||||
(valid_amigaos_type_attribute ((TYPE), (ATTRIBUTES), (IDENTIFIER), (ARGS)))
|
||||
|
||||
/* Generate the test of d0 before return to set cc register in 'interrupt'
|
||||
function. */
|
||||
|
||||
#define EPILOGUE_END_HOOK(STREAM) \
|
||||
do \
|
||||
{ \
|
||||
if (lookup_attribute ("interrupt", \
|
||||
TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))) \
|
||||
asm_fprintf ((STREAM), "\ttstl %Rd0\n"); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* begin-GG-local: explicit register specification for parameters */
|
||||
|
||||
/* Note: this is an extension of m68k_args */
|
||||
struct amigaos_args
|
||||
{
|
||||
int num_of_regs;
|
||||
long regs_already_used;
|
||||
int last_arg_reg;
|
||||
int last_arg_len;
|
||||
void *formal_type; /* New field: formal type of the current argument. */
|
||||
};
|
||||
|
||||
/* A C type for declaring a variable that is used as the first
|
||||
argument of `FUNCTION_ARG' and other related values. */
|
||||
|
||||
#undef CUMULATIVE_ARGS
|
||||
#define CUMULATIVE_ARGS struct amigaos_args
|
||||
|
||||
/* 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. */
|
||||
|
||||
#undef INIT_CUMULATIVE_ARGS
|
||||
#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \
|
||||
(amigaos_init_cumulative_args(&(CUM), (FNTYPE)))
|
||||
|
||||
/* Update the data in CUM to advance over an argument
|
||||
of mode MODE and data type TYPE.
|
||||
(TYPE is null for libcalls where that information may not be available.) */
|
||||
|
||||
#undef FUNCTION_ARG_ADVANCE
|
||||
#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
|
||||
(amigaos_function_arg_advance (&(CUM)))
|
||||
|
||||
/* A C expression that controls whether a function argument is passed
|
||||
in a register, and which register. */
|
||||
|
||||
#undef FUNCTION_ARG
|
||||
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
|
||||
((struct rtx_def *)amigaos_function_arg (&(CUM), (MODE), (TYPE)))
|
||||
|
||||
/* A C expression whose value is 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). */
|
||||
|
||||
#undef COMP_TYPE_ATTRIBUTES
|
||||
#define COMP_TYPE_ATTRIBUTES(TYPE1, TYPE2) \
|
||||
(comp_amigaos_type_attributes ((TYPE1), (TYPE2)))
|
||||
|
||||
/* end-GG-local */
|
||||
|
||||
/* Stack checking and automatic extension support. */
|
||||
|
||||
void amigaos_prologue_begin_hook ();
|
||||
#define PROLOGUE_BEGIN_HOOK(STREAM, FSIZE) \
|
||||
(amigaos_prologue_begin_hook ((STREAM), (FSIZE)))
|
||||
|
||||
#define HAVE_ALTERNATE_FRAME_SETUP_F(FSIZE) TARGET_STACKEXTEND
|
||||
|
||||
void amigaos_alternate_frame_setup_f ();
|
||||
#define ALTERNATE_FRAME_SETUP_F(STREAM, FSIZE) \
|
||||
(amigaos_alternate_frame_setup_f ((STREAM), (FSIZE)))
|
||||
|
||||
#define HAVE_ALTERNATE_FRAME_SETUP(FSIZE) TARGET_STACKEXTEND
|
||||
|
||||
void amigaos_alternate_frame_setup ();
|
||||
#define ALTERNATE_FRAME_SETUP(STREAM, FSIZE) \
|
||||
(amigaos_alternate_frame_setup ((STREAM), (FSIZE)))
|
||||
|
||||
#define HAVE_ALTERNATE_FRAME_DESTR_F(FSIZE) \
|
||||
(TARGET_STACKEXTEND && current_function_calls_alloca)
|
||||
|
||||
#define ALTERNATE_FRAME_DESTR_F(STREAM, FSIZE) \
|
||||
(asm_fprintf ((STREAM), "\tjra %U__unlk_a5_rts\n"))
|
||||
|
||||
#define HAVE_ALTERNATE_RETURN \
|
||||
((TARGET_STACKEXTEND && frame_pointer_needed && \
|
||||
current_function_calls_alloca) \
|
||||
|| current_function_is_interrupt)
|
||||
|
||||
#define ALTERNATE_RETURN(STREAM) \
|
||||
do \
|
||||
{ \
|
||||
if (current_function_is_interrupt) \
|
||||
asm_fprintf ((STREAM), "\trte\n"); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
struct rtx_def* gen_stack_cleanup_call ();
|
||||
#define HAVE_restore_stack_nonlocal TARGET_STACKEXTEND
|
||||
#define gen_restore_stack_nonlocal gen_stack_cleanup_call
|
||||
|
||||
#define HAVE_restore_stack_function TARGET_STACKEXTEND
|
||||
#define gen_restore_stack_function gen_stack_cleanup_call
|
||||
|
||||
#define HAVE_restore_stack_block TARGET_STACKEXTEND
|
||||
#define gen_restore_stack_block gen_stack_cleanup_call
|
||||
|
||||
#undef TARGET_ALTERNATE_ALLOCATE_STACK
|
||||
#define TARGET_ALTERNATE_ALLOCATE_STACK 1
|
||||
|
||||
#define ALTERNATE_ALLOCATE_STACK(OPERANDS) \
|
||||
do \
|
||||
{ \
|
||||
amigaos_alternate_allocate_stack (OPERANDS); \
|
||||
DONE; \
|
||||
} \
|
||||
while (0)
|
|
@ -63,6 +63,8 @@ const char *m68k_align_loops_string;
|
|||
const char *m68k_align_jumps_string;
|
||||
/* Specify power of two alignment used for functions. */
|
||||
const char *m68k_align_funcs_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;
|
||||
|
@ -70,6 +72,8 @@ int m68k_align_loops;
|
|||
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
|
||||
|
@ -124,6 +128,19 @@ override_options ()
|
|||
}
|
||||
else
|
||||
m68k_align_funcs = def_align;
|
||||
|
||||
/* Validate -mregparm and -mregparm= value. */
|
||||
if (m68k_regparm_string)
|
||||
{
|
||||
m68k_regparm = atoi (m68k_regparm_string);
|
||||
if (m68k_regparm < 1 || m68k_regparm > M68K_MAX_REGPARM)
|
||||
fatal ("-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;
|
||||
}
|
||||
|
||||
/* This function generates the assembly code for function entry.
|
||||
|
@ -151,9 +168,17 @@ output_function_prologue (stream, size)
|
|||
int fsize = (size + 3) & -4;
|
||||
int cfa_offset = INCOMING_FRAME_SP_OFFSET, cfa_store_offset = cfa_offset;
|
||||
|
||||
#ifdef PROLOGUE_BEGIN_HOOK
|
||||
PROLOGUE_BEGIN_HOOK (stream, fsize);
|
||||
#endif
|
||||
|
||||
if (frame_pointer_needed)
|
||||
{
|
||||
#ifdef HAVE_ALTERNATE_FRAME_SETUP_F
|
||||
if (HAVE_ALTERNATE_FRAME_SETUP_F (fsize))
|
||||
ALTERNATE_FRAME_SETUP_F (stream, fsize);
|
||||
else
|
||||
#endif
|
||||
if (fsize == 0 && TARGET_68040)
|
||||
{
|
||||
/* on the 68040, pea + move is faster than link.w 0 */
|
||||
|
@ -209,6 +234,10 @@ output_function_prologue (stream, size)
|
|||
cfa_store_offset += fsize;
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_ALTERNATE_FRAME_SETUP
|
||||
else if (HAVE_ALTERNATE_FRAME_SETUP (fsize))
|
||||
ALTERNATE_FRAME_SETUP (stream, fsize);
|
||||
#endif
|
||||
else if (fsize)
|
||||
{
|
||||
if (fsize + 4 < 0x8000)
|
||||
|
@ -313,7 +342,8 @@ output_function_prologue (stream, size)
|
|||
if (TARGET_68881)
|
||||
{
|
||||
for (regno = 16; regno < 24; regno++)
|
||||
if (regs_ever_live[regno] && ! call_used_regs[regno])
|
||||
if (regs_ever_live[regno] && (! call_used_regs[regno]
|
||||
|| current_function_is_interrupt))
|
||||
{
|
||||
mask |= 1 << (regno - 16);
|
||||
num_saved_regs++;
|
||||
|
@ -346,7 +376,8 @@ output_function_prologue (stream, size)
|
|||
num_saved_regs = 0;
|
||||
}
|
||||
for (regno = 0; regno < 16; regno++)
|
||||
if (regs_ever_live[regno] && ! call_used_regs[regno])
|
||||
if (regs_ever_live[regno] && (! call_used_regs[regno]
|
||||
|| current_function_is_interrupt))
|
||||
{
|
||||
mask |= 1 << (15 - regno);
|
||||
num_saved_regs++;
|
||||
|
@ -356,11 +387,14 @@ output_function_prologue (stream, size)
|
|||
mask &= ~ (1 << (15 - FRAME_POINTER_REGNUM));
|
||||
num_saved_regs--;
|
||||
}
|
||||
if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
|
||||
if (flag_pic && flag_pic < 3 && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
|
||||
{
|
||||
mask |= 1 << (15 - PIC_OFFSET_TABLE_REGNUM);
|
||||
num_saved_regs++;
|
||||
}
|
||||
#ifdef PROLOGUE_EXTRA_SAVE
|
||||
PROLOGUE_EXTRA_SAVE (mask, num_saved_regs);
|
||||
#endif
|
||||
|
||||
#if NEED_PROBE
|
||||
#ifdef MOTOROLA
|
||||
|
@ -462,6 +496,11 @@ output_function_prologue (stream, size)
|
|||
-cfa_store_offset + n_regs++ * 4);
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_ALTERNATE_PIC_SETUP
|
||||
if (HAVE_ALTERNATE_PIC_SETUP)
|
||||
ALTERNATE_PIC_SETUP (stream);
|
||||
else
|
||||
#endif
|
||||
if (flag_pic && current_function_uses_pic_offset_table)
|
||||
{
|
||||
#ifdef MOTOROLA
|
||||
|
@ -491,7 +530,8 @@ use_return_insn ()
|
|||
separate layout routine to perform the common work. */
|
||||
|
||||
for (regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno++)
|
||||
if (regs_ever_live[regno] && ! call_used_regs[regno])
|
||||
if (regs_ever_live[regno] && (! call_used_regs[regno]
|
||||
|| current_function_is_interrupt))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
@ -552,7 +592,8 @@ output_function_epilogue (stream, size)
|
|||
if (TARGET_68881)
|
||||
{
|
||||
for (regno = 16; regno < 24; regno++)
|
||||
if (regs_ever_live[regno] && ! call_used_regs[regno])
|
||||
if (regs_ever_live[regno] && (! call_used_regs[regno]
|
||||
|| current_function_is_interrupt))
|
||||
{
|
||||
nregs++;
|
||||
fmask |= 1 << (23 - regno);
|
||||
|
@ -563,16 +604,20 @@ output_function_epilogue (stream, size)
|
|||
if (frame_pointer_needed)
|
||||
regs_ever_live[FRAME_POINTER_REGNUM] = 0;
|
||||
for (regno = 0; regno < 16; regno++)
|
||||
if (regs_ever_live[regno] && ! call_used_regs[regno])
|
||||
if (regs_ever_live[regno] && (! call_used_regs[regno]
|
||||
|| current_function_is_interrupt))
|
||||
{
|
||||
nregs++;
|
||||
mask |= 1 << regno;
|
||||
}
|
||||
if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
|
||||
if (flag_pic && flag_pic < 3 && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
|
||||
{
|
||||
nregs++;
|
||||
mask |= 1 << PIC_OFFSET_TABLE_REGNUM;
|
||||
}
|
||||
#ifdef EPILOGUE_EXTRA_RESTORE
|
||||
EPILOGUE_EXTRA_RESTORE (mask, nregs);
|
||||
#endif
|
||||
offset = foffset + nregs * 4;
|
||||
/* FIXME : leaf_function_p below is too strong.
|
||||
What we really need to know there is if there could be pending
|
||||
|
@ -759,6 +804,11 @@ output_function_epilogue (stream, size)
|
|||
fpoffset -= 8;
|
||||
}
|
||||
if (frame_pointer_needed)
|
||||
#ifdef HAVE_ALTERNATE_FRAME_DESTR_F
|
||||
if (HAVE_ALTERNATE_FRAME_DESTR_F (fsize))
|
||||
ALTERNATE_FRAME_DESTR_F (stream, fsize);
|
||||
else
|
||||
#endif
|
||||
fprintf (stream, "\tunlk %s\n",
|
||||
reg_names[FRAME_POINTER_REGNUM]);
|
||||
else if (fsize)
|
||||
|
@ -828,9 +878,19 @@ output_function_epilogue (stream, size)
|
|||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef EPILOGUE_END_HOOK
|
||||
EPILOGUE_END_HOOK (stream);
|
||||
#endif
|
||||
|
||||
if (current_function_pops_args)
|
||||
asm_fprintf (stream, "\trtd %0I%d\n", current_function_pops_args);
|
||||
else
|
||||
#ifdef HAVE_ALTERNATE_RETURN
|
||||
if (HAVE_ALTERNATE_RETURN)
|
||||
ALTERNATE_RETURN (stream);
|
||||
else
|
||||
#endif
|
||||
fprintf (stream, "\trts\n");
|
||||
}
|
||||
|
||||
|
@ -1327,12 +1387,20 @@ legitimize_pic_address (orig, mode, reg)
|
|||
/* 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 ();
|
||||
|
||||
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;
|
||||
if (reload_in_progress)
|
||||
regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
|
||||
|
@ -3104,6 +3172,10 @@ print_operand_address (file, addr)
|
|||
fprintf (file, ":w");
|
||||
if ((flag_pic == 2) && (breg == pic_offset_table_rtx))
|
||||
fprintf (file, ":l");
|
||||
if ((flag_pic == 3) && (breg == pic_offset_table_rtx))
|
||||
fprintf (file, ":W");
|
||||
if ((flag_pic == 4) && (breg == pic_offset_table_rtx))
|
||||
fprintf (file, ":L");
|
||||
}
|
||||
if (addr != 0 && ireg != 0)
|
||||
{
|
||||
|
@ -3279,6 +3351,252 @@ const_sint32_operand (op, mode)
|
|||
return (GET_CODE (op) == CONST_INT
|
||||
&& (INTVAL (op) >= (-0x7fffffff - 1) && INTVAL (op) <= 0x7fffffff));
|
||||
}
|
||||
|
||||
/* 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 (cum, fntype)
|
||||
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)))
|
||||
cum->regs_already_used |= (1 << STRUCT_VALUE_REGNUM);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Update the data in CUM to advance over an argument. */
|
||||
|
||||
void
|
||||
m68k_function_arg_advance (cum)
|
||||
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 (cum, mode, type)
|
||||
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;
|
||||
}
|
||||
|
||||
/* Attributes support. */
|
||||
|
||||
/* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine
|
||||
specific attribute for TYPE. The attributes in ATTRIBUTES have previously
|
||||
been assigned to TYPE. */
|
||||
|
||||
int
|
||||
valid_m68k_type_attribute (type, attributes, identifier, args)
|
||||
tree type, attributes, identifier, args;
|
||||
{
|
||||
if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == 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", identifier))
|
||||
{
|
||||
if (lookup_attribute ("stkparm", attributes))
|
||||
{
|
||||
error ("`regparm' and `stkparm' are mutually exclusive");
|
||||
return 0;
|
||||
}
|
||||
if (args && TREE_CODE (args) == TREE_LIST)
|
||||
{
|
||||
tree numofregs = TREE_VALUE (args);
|
||||
if (numofregs)
|
||||
if (TREE_CODE (numofregs) != INTEGER_CST
|
||||
|| 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");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (is_attribute_p ("stkparm", identifier))
|
||||
{
|
||||
if (lookup_attribute ("regparm", attributes))
|
||||
{
|
||||
error ("`regparm' and `stkparm' are mutually exclusive");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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). */
|
||||
|
||||
int
|
||||
comp_m68k_type_attributes (type1, type2)
|
||||
tree type1, 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. */
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *
|
||||
output_andsi3 (operands)
|
||||
|
|
|
@ -68,10 +68,8 @@ extern int target_flags;
|
|||
#define MASK_RTD 8
|
||||
#define TARGET_RTD (target_flags & MASK_RTD)
|
||||
|
||||
/* Compile passing first two args in regs 0 and 1.
|
||||
This exists only to test compiler features that will
|
||||
be needed for RISC chips. It is not usable
|
||||
and is not intended to be usable on this cpu. */
|
||||
/* Compile using the first 'm68k_regparm' data, address and float
|
||||
registers for arguments passing. */
|
||||
#define MASK_REGPARM 16
|
||||
#define TARGET_REGPARM (target_flags & MASK_REGPARM)
|
||||
|
||||
|
@ -182,6 +180,8 @@ extern int target_flags;
|
|||
{ "cpu32", MASK_68020}, \
|
||||
{ "align-int", MASK_ALIGN_INT }, \
|
||||
{ "no-align-int", -MASK_ALIGN_INT }, \
|
||||
{ "regparm", MASK_REGPARM}, \
|
||||
{ "no-regparm", - MASK_REGPARM}, \
|
||||
SUBTARGET_SWITCHES \
|
||||
{ "", TARGET_DEFAULT}}
|
||||
/* TARGET_DEFAULT is defined in sun*.h and isi.h, etc. */
|
||||
|
@ -199,6 +199,7 @@ extern int target_flags;
|
|||
{ { "align-loops=", &m68k_align_loops_string }, \
|
||||
{ "align-jumps=", &m68k_align_jumps_string }, \
|
||||
{ "align-functions=", &m68k_align_funcs_string }, \
|
||||
{ "regparm=", &m68k_regparm_string }, \
|
||||
SUBTARGET_OPTIONS \
|
||||
}
|
||||
|
||||
|
@ -809,7 +810,7 @@ extern enum reg_class regno_reg_class[];
|
|||
#ifndef SUPPORT_SUN_FPA
|
||||
|
||||
#define CLASS_MAX_NREGS(CLASS, MODE) \
|
||||
((CLASS) == FP_REGS ? 1 \
|
||||
((CLASS) == FP_REGS ? GET_MODE_NUNITS (MODE) \
|
||||
: ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
|
||||
|
||||
/* Moves between fp regs and other regs are two insns. */
|
||||
|
@ -821,7 +822,8 @@ extern enum reg_class regno_reg_class[];
|
|||
#else /* defined SUPPORT_SUN_FPA */
|
||||
|
||||
#define CLASS_MAX_NREGS(CLASS, MODE) \
|
||||
((CLASS) == FP_REGS || (CLASS) == FPA_REGS || (CLASS) == LO_FPA_REGS ? 1 \
|
||||
((CLASS) == FP_REGS || (CLASS) == FPA_REGS || (CLASS) == LO_FPA_REGS ? \
|
||||
GET_MODE_NUNITS (MODE) \
|
||||
: ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
|
||||
|
||||
/* Moves between fp regs and other regs are two insns. */
|
||||
|
@ -925,10 +927,19 @@ extern enum reg_class regno_reg_class[];
|
|||
|
||||
#define PCC_STATIC_STRUCT_RETURN
|
||||
|
||||
/* 1 if N is a possible register number for function argument passing.
|
||||
On the 68000, no registers are used in this way. */
|
||||
/* 1 if N is a possible register number for function argument passing. */
|
||||
|
||||
#define FUNCTION_ARG_REGNO_P(N) 0
|
||||
#define FUNCTION_ARG_REGNO_P(N) \
|
||||
(((N) >= 0 && (N) < M68K_MAX_REGPARM) \
|
||||
|| ((N) >= 8 && (N) < 8 + M68K_MAX_REGPARM) \
|
||||
|| (TARGET_68881 && (N) >= 16 && (N) < 16 + M68K_MAX_REGPARM))
|
||||
|
||||
/* Nonzero if we need to generate special stack-allocating insns.
|
||||
On most systems they are not needed.
|
||||
When they are needed, also define ALTERNATE_ALLOCATE_STACK (see m68k.md)
|
||||
to perform the necessary actions. */
|
||||
|
||||
#define TARGET_ALTERNATE_ALLOCATE_STACK 0
|
||||
|
||||
/* Define a data type for recording info about an argument list
|
||||
during the scan of that argument list. This data type should
|
||||
|
@ -936,28 +947,52 @@ extern enum reg_class regno_reg_class[];
|
|||
and about the args processed so far, enough to enable macros
|
||||
such as FUNCTION_ARG to determine where the next arg should go.
|
||||
|
||||
On the m68k, this is a single integer, which is a number of bytes
|
||||
of arguments scanned so far. */
|
||||
On the m68k, this is a structure:
|
||||
num_of_regs: number of data, address and float registers to use for
|
||||
arguments passing (if it's 2, than pass arguments in d0, d1, a0, a1,
|
||||
fp0 and fp1). 0 - pass everything on stack. vararg calls are
|
||||
always passed entirely on stack.
|
||||
regs_already_used: bitmask of the already used registers.
|
||||
last_arg_reg - register number of the most recently passed argument.
|
||||
-1 if passed on stack.
|
||||
last_arg_len - number of registers used by the most recently passed
|
||||
argument.
|
||||
*/
|
||||
|
||||
#define CUMULATIVE_ARGS int
|
||||
struct m68k_args
|
||||
{
|
||||
int num_of_regs;
|
||||
long regs_already_used;
|
||||
int last_arg_reg;
|
||||
int last_arg_len;
|
||||
};
|
||||
|
||||
#define CUMULATIVE_ARGS struct m68k_args
|
||||
|
||||
/* Max. number of data, address and float registers to be used for passing
|
||||
integer, pointer and float arguments when TARGET_REGPARM.
|
||||
It's 4, so d0-d3, a0-a3 and fp0-fp3 can be used. */
|
||||
|
||||
#define M68K_MAX_REGPARM 4
|
||||
|
||||
/* The default number of data, address and float registers to use when
|
||||
user specified '-mregparm' switch, not '-mregparm=<value>' option. */
|
||||
|
||||
#define M68K_DEFAULT_REGPARM 2
|
||||
|
||||
/* 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.
|
||||
|
||||
On the m68k, the offset starts at 0. */
|
||||
For a library call, FNTYPE is 0. */
|
||||
|
||||
#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \
|
||||
((CUM) = 0)
|
||||
(m68k_init_cumulative_args (&(CUM), (FNTYPE)))
|
||||
|
||||
/* Update the data in CUM to advance over an argument
|
||||
of mode MODE and data type TYPE.
|
||||
(TYPE is null for libcalls where that information may not be available.) */
|
||||
|
||||
#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
|
||||
((CUM) += ((MODE) != BLKmode \
|
||||
? (GET_MODE_SIZE (MODE) + 3) & ~3 \
|
||||
: (int_size_in_bytes (TYPE) + 3) & ~3))
|
||||
(m68k_function_arg_advance (&(CUM)))
|
||||
|
||||
/* Define where to put the arguments to a function.
|
||||
Value is zero to push the argument on the stack,
|
||||
|
@ -972,24 +1007,21 @@ extern enum reg_class regno_reg_class[];
|
|||
NAMED is nonzero if this argument is a named parameter
|
||||
(otherwise it is an extra parameter matching an ellipsis). */
|
||||
|
||||
/* On the 68000 all args are pushed, except if -mregparm is specified
|
||||
then the first two words of arguments are passed in d0, d1.
|
||||
*NOTE* -mregparm does not work.
|
||||
It exists only to test register calling conventions. */
|
||||
/* On the 68000 all args are pushed, except if -mregparm is specified,
|
||||
then a number of arguments is passed in the first 'm68k_regparm' data,
|
||||
address and float registers.
|
||||
Note: by default, the static-chain is passed in a0. Targets that want
|
||||
to make full use of '-mregparm' are advised to pass the static-chain
|
||||
somewhere else. */
|
||||
|
||||
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
|
||||
((TARGET_REGPARM && (CUM) < 8) ? gen_rtx_REG ((MODE), (CUM) / 4) : 0)
|
||||
((struct rtx_def *)m68k_function_arg (&(CUM), (MODE), (TYPE)))
|
||||
|
||||
/* For an arg passed partly in registers and partly in memory,
|
||||
this is the number of registers used.
|
||||
For args passed entirely in registers or entirely in memory, zero. */
|
||||
|
||||
#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
|
||||
((TARGET_REGPARM && (CUM) < 8 \
|
||||
&& 8 < ((CUM) + ((MODE) == BLKmode \
|
||||
? int_size_in_bytes (TYPE) \
|
||||
: GET_MODE_SIZE (MODE)))) \
|
||||
? 2 - (CUM) / 4 : 0)
|
||||
#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) (0)
|
||||
|
||||
/* Generate the assembly code for function entry. */
|
||||
#define FUNCTION_PROLOGUE(FILE, SIZE) output_function_prologue(FILE, SIZE)
|
||||
|
@ -1190,6 +1222,8 @@ while(0)
|
|||
of a local variable as a function of frame_pointer_needed, which
|
||||
is hard. */
|
||||
|
||||
#define SUBTARGET_INITIAL_FP_OFFSET(OFFSET)
|
||||
|
||||
#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) \
|
||||
{ int regno; \
|
||||
int offset = -4; \
|
||||
|
@ -1199,8 +1233,9 @@ while(0)
|
|||
for (regno = 0; regno < 16; regno++) \
|
||||
if (regs_ever_live[regno] && ! call_used_regs[regno]) \
|
||||
offset += 4; \
|
||||
if (flag_pic && current_function_uses_pic_offset_table) \
|
||||
if (flag_pic && flag_pic <= 2 && current_function_uses_pic_offset_table) \
|
||||
offset += 4; \
|
||||
SUBTARGET_INITIAL_FP_OFFSET (offset); \
|
||||
(DEPTH) = (offset + ((get_frame_size () + 3) & -4) \
|
||||
+ (get_frame_size () == 0 ? 0 : 4)); \
|
||||
}
|
||||
|
@ -2083,6 +2118,23 @@ do { long l; \
|
|||
|
||||
#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)
|
||||
|
||||
|
||||
/* Attributes support. */
|
||||
|
||||
/* A C expression whose value is nonzero if IDENTIFIER with arguments
|
||||
ARGS is a valid machine specific attribute for TYPE. The attributes
|
||||
in ATTRIBUTES have previously been assigned to TYPE. */
|
||||
|
||||
#define VALID_MACHINE_TYPE_ATTRIBUTE(TYPE, ATTRIBUTES, IDENTIFIER, ARGS) \
|
||||
(valid_m68k_type_attribute ((TYPE), (ATTRIBUTES), (IDENTIFIER), (ARGS)))
|
||||
|
||||
/* A C expression whose value is 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). */
|
||||
|
||||
#define COMP_TYPE_ATTRIBUTES(TYPE1, TYPE2) \
|
||||
(comp_m68k_type_attributes ((TYPE1), (TYPE2)))
|
||||
|
||||
/* Define functions defined in aux-output.c and used in templates. */
|
||||
|
||||
extern char *output_move_const_into_data_reg ();
|
||||
|
@ -2115,9 +2167,11 @@ extern int strict_low_part_peephole_ok ();
|
|||
extern const char *m68k_align_loops_string;
|
||||
extern const char *m68k_align_jumps_string;
|
||||
extern const char *m68k_align_funcs_string;
|
||||
extern const char *m68k_regparm_string;
|
||||
extern int m68k_align_loops;
|
||||
extern int m68k_align_jumps;
|
||||
extern int m68k_align_funcs;
|
||||
extern int m68k_regparm;
|
||||
extern int m68k_last_compare_had_fp_operands;
|
||||
|
||||
/* Functions from m68k.c used in macros. */
|
||||
|
|
|
@ -3840,7 +3840,7 @@
|
|||
case -1 :
|
||||
/* FIXME : a scratch register would be welcome here if operand[0]
|
||||
is not a register */
|
||||
output_asm_insn (\"move%.l %#-1,%R0\", operands);
|
||||
output_asm_insn (\"move%.l %#-1,%0\", operands);
|
||||
break;
|
||||
default :
|
||||
{
|
||||
|
@ -6818,7 +6818,7 @@
|
|||
(match_operand:SI 1 "general_operand" "g"))]
|
||||
;; Operand 1 not really used on the m68000.
|
||||
|
||||
"! flag_pic"
|
||||
"(! flag_pic || flag_pic >= 3)"
|
||||
"*
|
||||
#if defined (MOTOROLA) && !defined (USE_GAS)
|
||||
#ifdef MOTOROLA_BSR
|
||||
|
@ -6838,7 +6838,7 @@
|
|||
(match_operand:SI 1 "general_operand" "g"))]
|
||||
;; Operand 1 not really used on the m68000.
|
||||
|
||||
"flag_pic"
|
||||
"(flag_pic && flag_pic < 3)"
|
||||
"*
|
||||
if (GET_CODE (operands[0]) == MEM
|
||||
&& GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
|
||||
|
@ -6881,7 +6881,7 @@
|
|||
(call (match_operand:QI 1 "memory_operand" "o")
|
||||
(match_operand:SI 2 "general_operand" "g")))]
|
||||
;; Operand 2 not really used on the m68000.
|
||||
"! flag_pic"
|
||||
"(! flag_pic || flag_pic >= 3)"
|
||||
"*
|
||||
#if defined (MOTOROLA) && !defined (USE_GAS)
|
||||
#ifdef MOTOROLA_BSR
|
||||
|
@ -6901,7 +6901,7 @@
|
|||
(call (match_operand:QI 1 "memory_operand" "o")
|
||||
(match_operand:SI 2 "general_operand" "g")))]
|
||||
;; Operand 2 not really used on the m68000.
|
||||
"flag_pic"
|
||||
"(flag_pic && flag_pic < 3)"
|
||||
"*
|
||||
if (GET_CODE (operands[1]) == MEM
|
||||
&& GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
|
||||
|
@ -6984,7 +6984,10 @@
|
|||
"*
|
||||
{
|
||||
if (current_function_pops_args == 0)
|
||||
if (current_function_is_interrupt == 0)
|
||||
return \"rts\";
|
||||
else
|
||||
return \"rte\";
|
||||
operands[0] = GEN_INT (current_function_pops_args);
|
||||
return \"rtd %0\";
|
||||
}")
|
||||
|
@ -7945,3 +7948,16 @@
|
|||
(unspec:XF [(match_operand:XF 1 "nonimmediate_operand" "fm")] 2))]
|
||||
"TARGET_68881 && flag_fast_math"
|
||||
"fcos%.x %1,%0")
|
||||
|
||||
; This is only needed for some subtargets.
|
||||
(define_expand "allocate_stack"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||
(minus:SI (reg:SI 15) (match_operand:SI 1 "general_operand" "")))
|
||||
(set (reg:SI 15) (minus:SI (reg:SI 15) (match_dup 1)))]
|
||||
"TARGET_ALTERNATE_ALLOCATE_STACK"
|
||||
"
|
||||
{
|
||||
#ifdef ALTERNATE_ALLOCATE_STACK
|
||||
ALTERNATE_ALLOCATE_STACK(operands);
|
||||
#endif
|
||||
}")
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
# Makefile fragment for AmigaOS target.
|
||||
|
||||
# Each compilation environment (Manx, Dice, GCC, SAS/C, etc) provides its
|
||||
# own equivalent of the UNIX /usr/include tree. For gcc, the standard headers
|
||||
# are in /gg/include and system specific headers are in /gg/os-include.
|
||||
# Use these paths for fixincludes.
|
||||
|
||||
SYSTEM_HEADER_DIR = /gg/include
|
||||
|
||||
# Extra object file linked to the cc1* executables.
|
||||
amigaos.o: $(srcdir)/config/m68k/amigaos.c $(CONFIG_H)
|
||||
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
|
||||
|
||||
# We don't need a libgcc1, it's all in ixemul.library and LibNIX
|
||||
|
||||
LIBGCC1 = libgcc1.null
|
||||
CROSS_LIBGCC1 = libgcc1.null
|
||||
|
||||
# Additional target dependent options for compiling libgcc.a. This just
|
||||
# ensures that we don't compile libgcc* with anything other than a
|
||||
# fixed stack.
|
||||
|
||||
TARGET_LIBGCC2_CFLAGS = -mfixedstack
|
||||
|
||||
# Support for building multiple version of libgcc.
|
||||
# Note: this is taken from the toplevel Makefile.in multilib support.
|
||||
LIBGCC = stmp-libgcc-multi
|
||||
INSTALL_LIBGCC = install-libgcc-multi
|
||||
|
||||
LIBGCC_MULTI = ".;" \
|
||||
"libb;@resident" \
|
||||
"libm020;@m68020" \
|
||||
"libb/libm020;@resident@m68020" \
|
||||
"libb32/libm020;@resident32@m68020"
|
||||
|
||||
# Build multiple copies of libgcc.a, one for each target switch.
|
||||
stmp-libgcc-multi: $(LIBGCC1) libgcc2.c libgcc2.ready $(CONFIG_H) \
|
||||
frame.h \
|
||||
$(LIB2ADD) machmode.h longlong.h gbl-ctors.h config.status
|
||||
# We need the following explicit mkdir, since the toplevel
|
||||
# Makefile.in attempts to create only the last directory
|
||||
# of a path.
|
||||
if [ -d libb32 ]; then true; else mkdir libb32; fi
|
||||
for i in $(LIBGCC_MULTI); do \
|
||||
dir=`echo $$i | sed -e 's/;.*$$//'`; \
|
||||
flags=`echo $$i | sed -e 's/^[^;]*;//' -e 's/@/ -/g'`; \
|
||||
$(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
|
||||
AR_FOR_TARGET="$(AR_FOR_TARGET)" \
|
||||
AR_FLAGS_FOR_TARGET="$(AR_FLAGS_FOR_TARGET)" \
|
||||
CC="$(CC)" CFLAGS="$(CFLAGS)" \
|
||||
RANLIB_FOR_TARGET="$(RANLIB_FOR_TARGET)" \
|
||||
RANLIB_TEST_FOR_TARGET="$(RANLIB_TEST_FOR_TARGET)" \
|
||||
LANGUAGES="$(LANGUAGES)" \
|
||||
HOST_PREFIX="$(HOST_PREFIX)" HOST_PREFIX_1="$(HOST_PREFIX_1)" \
|
||||
LIBGCC2_CFLAGS="$(LIBGCC2_CFLAGS) $${flags}" \
|
||||
MULTILIB_CFLAGS="$${flags}" \
|
||||
LIBGCC1="$(LIBGCC1)" LIBGCC2="$(LIBGCC2)" \
|
||||
dir="$${dir}" stmp-multilib-sub; \
|
||||
if [ $$? -eq 0 ] ; then true; else exit 1; fi; \
|
||||
done
|
||||
touch stmp-libgcc-multi
|
||||
|
||||
# Install multiple versions of libgcc.a.
|
||||
install-libgcc-multi: stmp-libgcc-multi installdirs
|
||||
# We need the following explicit mkdir, since below we attempt to
|
||||
# create only the last directory of a path.
|
||||
if [ -d $(libsubdir)/libb32 ]; then true; else mkdir $(libsubdir)/libb32; fi
|
||||
for i in $(LIBGCC_MULTI); do \
|
||||
dir=`echo $$i | sed -e 's/;.*$$//'`; \
|
||||
if [ -d $(libsubdir)/$${dir} ]; then true; else mkdir $(libsubdir)/$${dir}; fi; \
|
||||
for f in libgcc.a $(EXTRA_MULTILIB_PARTS); do \
|
||||
rm -f $(libsubdir)/$${dir}/$${f}; \
|
||||
$(INSTALL_DATA) $${dir}/$${f} $(libsubdir)/$${dir}/$${f}; \
|
||||
done; \
|
||||
if $(RANLIB_TEST_FOR_TARGET); then \
|
||||
(cd $(libsubdir)/$${dir}; $(RANLIB_FOR_TARGET) libgcc.a); \
|
||||
else true; fi; \
|
||||
chmod a-x $(libsubdir)/$${dir}/libgcc.a; \
|
||||
done
|
|
@ -0,0 +1,77 @@
|
|||
# Makefile fragment for AmigaOS host
|
||||
|
||||
# Uncomment the following macro to get a resident GCC. We don't do it
|
||||
# by default, since we want to support users with mc68000.
|
||||
# WARNING! If you uncomment this, you MUST add the same flags to the
|
||||
# libiberty's Makefile (libiberty is now linked into GCC executables).
|
||||
|
||||
#RESIDENT = -m68020 -resident32
|
||||
|
||||
# Additional host flags that are not used when compiling with GCC_FOR_TARGET,
|
||||
# such as when compiling the libgcc* runtime archives. GCC uses stack
|
||||
# a lot, and since AmigaOS provides processes with a small, fixed size
|
||||
# stack, we have to generate code that will extend it whenever necessary.
|
||||
|
||||
XCFLAGS = -mstackextend $(RESIDENT)
|
||||
|
||||
# AmigaOS supports "AmigaGuide(R)" hypertext files. For GCC, these are
|
||||
# build with a custom "makeinfo".
|
||||
|
||||
### begin-GG-local: gcc-amigaos
|
||||
EXTRA_DOC_TARGETS = guide gcc-amigaos-doc
|
||||
### end-GG-local
|
||||
|
||||
# Arrange for guides to be build with GCC, in the build directory.
|
||||
|
||||
ALL = all.internal doc
|
||||
|
||||
# Actually build guides
|
||||
|
||||
guide: cpp.guide gcc.guide
|
||||
|
||||
cpp.guide: cpp.texi
|
||||
$(MAKEINFO) -I$(srcdir) $(srcdir)/cpp.texi --output=$@ --amiga
|
||||
|
||||
gcc.guide: gcc.texi extend.texi install.texi invoke.texi \
|
||||
md.texi rtl.texi tm.texi
|
||||
$(MAKEINFO) -I$(srcdir) $(srcdir)/gcc.texi --output=$@ --amiga
|
||||
|
||||
# Arrange for guides to be installed with GCC.
|
||||
|
||||
### begin-GG-local: gcc-amigaos
|
||||
INSTALL_TARGET=install-normal install-guide install-gcc-amigaos-doc
|
||||
### end-GG-local
|
||||
|
||||
# Where the guide files go
|
||||
|
||||
guidedir = $(prefix)/guide
|
||||
|
||||
# Actually install guides.
|
||||
|
||||
install-guide: doc installdirs
|
||||
-if [ -d $(guidedir) ] ; then true ; else mkdir $(guidedir) ; chmod a+rx $(guidedir) ; fi
|
||||
-rm -f $(guidedir)/cpp.guide $(guidedir)/gcc.guide
|
||||
for f in cpp.guide gcc.guide; \
|
||||
do $(INSTALL_DATA) $$f $(guidedir)/$$f; done
|
||||
-chmod a-x $(guidedir)/cpp.guide $(guidedir)/gcc.guide
|
||||
|
||||
### begin-GG-local: gcc-amigaos
|
||||
# Build and install gcc-amigaos.guide - documentation specific to the
|
||||
# AmigaOS port of GCC.
|
||||
|
||||
gcc-amigaos-doc: gcc-amigaos.info gcc-amigaos.guide
|
||||
|
||||
gcc-amigaos.info: gcc-amigaos.texi
|
||||
$(MAKEINFO) -I$(srcdir) $(srcdir)/gcc-amigaos.texi --output=$@
|
||||
|
||||
gcc-amigaos.guide: gcc-amigaos.texi
|
||||
$(MAKEINFO) -I$(srcdir) $(srcdir)/gcc-amigaos.texi --output=$@ --amiga
|
||||
|
||||
install-gcc-amigaos-doc: doc installdirs
|
||||
-if [ -d $(guidedir) ] ; then true ; else mkdir $(guidedir) ; chmod a+rx $(guidedir) ; fi
|
||||
-rm -f $(infodir)/gcc-amigaos.info* $(guidedir)/gcc-amigaos.guide
|
||||
for f in gcc-amigaos.info*; \
|
||||
do $(INSTALL_DATA) $$f $(infodir)/$$f; done
|
||||
$(INSTALL_DATA) gcc-amigaos.guide $(guidedir)
|
||||
-chmod a-x $(infodir)/gcc-amigaos.info* $(guidedir)/gcc-amigaos.guide
|
||||
### end-GG-local
|
|
@ -4341,6 +4341,13 @@ for machine in $build $host $target; do
|
|||
thread_file='vxworks'
|
||||
float_format=m68k
|
||||
;;
|
||||
m68k-*-amigaos*)
|
||||
tm_file=m68k/amigaos.h
|
||||
tmake_file=m68k/t-amigaos
|
||||
xmake_file=m68k/x-amigaos
|
||||
extra_objs=amigaos.o
|
||||
gnu_ld=yes
|
||||
;;
|
||||
m68k-*-aout*)
|
||||
tmake_file=m68k/t-m68kbare
|
||||
tm_file="m68k/m68k-aout.h libgloss.h"
|
||||
|
|
|
@ -134,10 +134,11 @@ AC_ARG_WITH(elf,
|
|||
elf="$with_elf",
|
||||
elf=no)
|
||||
|
||||
### begin-GG-local: local prefix
|
||||
# Specify the local prefix
|
||||
local_prefix=
|
||||
AC_ARG_WITH(local-prefix,
|
||||
[ --with-local-prefix=DIR specifies directory to put local include.],
|
||||
[ --with-local-prefix=DIR specifies directory to put local include directory (not files).],
|
||||
[case "${withval}" in
|
||||
yes) AC_MSG_ERROR(bad value ${withval} given for local include directory prefix) ;;
|
||||
no) ;;
|
||||
|
@ -146,8 +147,9 @@ esac])
|
|||
|
||||
# Default local prefix if it is empty
|
||||
if test x$local_prefix = x; then
|
||||
local_prefix=/usr/local
|
||||
local_prefix='${prefix}'/local
|
||||
fi
|
||||
### end-GG-local
|
||||
|
||||
# Don't set gcc_gxx_include_dir to gxx_include_dir since that's only
|
||||
# passed in by the toplevel make and thus we'd get different behavior
|
||||
|
@ -2013,6 +2015,13 @@ changequote([,])dnl
|
|||
thread_file='vxworks'
|
||||
float_format=m68k
|
||||
;;
|
||||
m68k-*-amigaos*)
|
||||
tm_file=m68k/amigaos.h
|
||||
tmake_file=m68k/t-amigaos
|
||||
xmake_file=m68k/x-amigaos
|
||||
extra_objs=amigaos.o
|
||||
gnu_ld=yes
|
||||
;;
|
||||
m68k-*-aout*)
|
||||
tmake_file=m68k/t-m68kbare
|
||||
tm_file="m68k/m68k-aout.h libgloss.h"
|
||||
|
|
|
@ -140,6 +140,7 @@ include_defaults_array[]
|
|||
/* This is another place that the target system's headers might be. */
|
||||
{ TOOL_INCLUDE_DIR, "BINUTILS", 0, 1 },
|
||||
#endif
|
||||
{ LOCAL_INCLUDE_DIR, 0, 0, 1 },
|
||||
#else /* not CROSS_COMPILE */
|
||||
#ifdef LOCAL_INCLUDE_DIR
|
||||
/* This should be /usr/local/include and should come before
|
||||
|
|
|
@ -87,6 +87,7 @@ case $machine in
|
|||
i[34567]86-*-pe | i[34567]86-*-cygwin* | \
|
||||
i[34567]86-*-mingw32* | \
|
||||
mips-sgi-irix5cross64 | \
|
||||
m68k-*-amigaos* | \
|
||||
powerpc-*-eabiaix* | \
|
||||
powerpc-*-eabisim* | \
|
||||
powerpc-*-eabi* | \
|
||||
|
|
|
@ -3157,11 +3157,13 @@ regno_uninitialized (regno)
|
|||
if (n_basic_blocks == 0
|
||||
|| (regno < FIRST_PSEUDO_REGISTER
|
||||
&& (global_regs[regno]
|
||||
|| fixed_regs[regno]
|
||||
|| FUNCTION_ARG_REGNO_P (regno))))
|
||||
/* begin-GG-local: explicit register specification for parameters */
|
||||
|| fixed_regs[regno])))
|
||||
return 0;
|
||||
|
||||
return REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start, regno);
|
||||
return (REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start, regno)
|
||||
&& (regno >= FIRST_PSEUDO_REGISTER || ! function_arg_regno_p (regno)));
|
||||
/* end-GG-local */
|
||||
}
|
||||
|
||||
/* 1 if register REGNO was alive at a place where `setjmp' was called
|
||||
|
|
|
@ -165,6 +165,8 @@ int current_function_has_computed_jump;
|
|||
we should try to cut corners where we can. */
|
||||
int current_function_is_thunk;
|
||||
|
||||
int current_function_is_interrupt;
|
||||
|
||||
/* Nonzero if function being compiled can call alloca,
|
||||
either as a subroutine or builtin. */
|
||||
|
||||
|
@ -572,6 +574,7 @@ push_function_context_to (context)
|
|||
p->contains_functions = current_function_contains_functions;
|
||||
p->has_computed_jump = current_function_has_computed_jump;
|
||||
p->is_thunk = current_function_is_thunk;
|
||||
p->is_interrupt = current_function_is_interrupt;
|
||||
p->args_size = current_function_args_size;
|
||||
p->pretend_args_size = current_function_pretend_args_size;
|
||||
p->arg_offset_rtx = current_function_arg_offset_rtx;
|
||||
|
@ -658,6 +661,7 @@ pop_function_context_from (context)
|
|||
current_function_has_nonlocal_label = p->has_nonlocal_label;
|
||||
current_function_has_nonlocal_goto = p->has_nonlocal_goto;
|
||||
current_function_is_thunk = p->is_thunk;
|
||||
current_function_is_interrupt = p->is_interrupt;
|
||||
current_function_args_size = p->args_size;
|
||||
current_function_pretend_args_size = p->pretend_args_size;
|
||||
current_function_arg_offset_rtx = p->arg_offset_rtx;
|
||||
|
@ -5130,6 +5134,9 @@ assign_parms (fndecl, second_time)
|
|||
current_function_pops_args = RETURN_POPS_ARGS (fndecl, TREE_TYPE (fndecl),
|
||||
current_function_args_size);
|
||||
|
||||
current_function_is_interrupt = lookup_attribute ("interrupt_handler",
|
||||
TYPE_ATTRIBUTES (TREE_TYPE (fndecl)));
|
||||
|
||||
/* For stdarg.h function, save info about
|
||||
regs and stack space used by the named args. */
|
||||
|
||||
|
@ -5958,6 +5965,7 @@ init_function_start (subr, filename, line)
|
|||
current_function_uses_only_leaf_regs = 0;
|
||||
current_function_has_computed_jump = 0;
|
||||
current_function_is_thunk = 0;
|
||||
current_function_is_interrupt = 0;
|
||||
|
||||
current_function_returns_pcc_struct = 0;
|
||||
current_function_returns_struct = 0;
|
||||
|
@ -7027,3 +7035,29 @@ reposition_prologue_and_epilogue_notes (f)
|
|||
}
|
||||
#endif /* HAVE_prologue or HAVE_epilogue */
|
||||
}
|
||||
|
||||
/* begin-GG-local: explicit register specification for parameters */
|
||||
/* Return 1 if an argument for the current function was passed in
|
||||
register REGNO. */
|
||||
|
||||
int
|
||||
function_arg_regno_p (regno)
|
||||
int regno;
|
||||
{
|
||||
tree parm = DECL_ARGUMENTS (current_function_decl);
|
||||
for (; parm; parm = TREE_CHAIN (parm))
|
||||
{
|
||||
rtx incoming = DECL_INCOMING_RTL (parm);
|
||||
if (GET_CODE (incoming) == REG)
|
||||
{
|
||||
int incoming_reg;
|
||||
incoming_reg = REGNO (incoming);
|
||||
if (regno >= incoming_reg &&
|
||||
regno < incoming_reg + HARD_REGNO_NREGS (incoming_reg,
|
||||
GET_MODE (incoming)))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* end-GG-local */
|
||||
|
|
|
@ -82,6 +82,7 @@ struct function
|
|||
int contains_functions;
|
||||
int has_computed_jump;
|
||||
int is_thunk;
|
||||
int is_interrupt;
|
||||
rtx nonlocal_goto_handler_slots;
|
||||
rtx nonlocal_goto_handler_labels;
|
||||
rtx nonlocal_goto_stack_level;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -327,8 +327,8 @@ main (argc, argv)
|
|||
printf ("/* Generated automatically by the program `genconfig'\n\
|
||||
from the machine description file `md'. */\n\n");
|
||||
|
||||
/* Allow at least 10 operands for the sake of asm constructs. */
|
||||
max_recog_operands = 9; /* We will add 1 later. */
|
||||
/* Allow at least 15 operands for the sake of asm constructs. */
|
||||
max_recog_operands = 14; /* We will add 1 later. */
|
||||
max_dup_operands = 1;
|
||||
|
||||
/* Read the machine description. */
|
||||
|
|
|
@ -178,7 +178,7 @@ typedef __gnuc_va_list va_list;
|
|||
But on BSD NET2 we must not test or define or undef it.
|
||||
(Note that the comments in NET 2's ansi.h
|
||||
are incorrect for _VA_LIST_--see stdio.h!) */
|
||||
#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__) || defined(WINNT)
|
||||
#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__) || defined(WINNT) || defined(__amigaos__)
|
||||
/* The macro _VA_LIST_DEFINED is used in Windows NT 3.5 */
|
||||
#ifndef _VA_LIST_DEFINED
|
||||
/* The macro _VA_LIST is used in SCO Unix 3.2. */
|
||||
|
@ -189,7 +189,7 @@ typedef __gnuc_va_list va_list;
|
|||
#endif /* not _VA_LIST_T_H */
|
||||
#endif /* not _VA_LIST */
|
||||
#endif /* not _VA_LIST_DEFINED */
|
||||
#if !(defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__))
|
||||
#if !(defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__) || defined(__amigaos__))
|
||||
#define _VA_LIST_
|
||||
#endif
|
||||
#ifndef _VA_LIST
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
/* On 4.3bsd-net2, make sure ansi.h is included, so we have
|
||||
one less case to deal with in the following. */
|
||||
#if defined (__BSD_NET2__) || defined (____386BSD____) || defined (__FreeBSD__) || defined(__NetBSD__)
|
||||
#if defined (__BSD_NET2__) || defined (____386BSD____) || defined (__FreeBSD__) || defined(__NetBSD__) || defined (__ixemul__) || defined (__libnix__)
|
||||
#include <machine/ansi.h>
|
||||
#endif
|
||||
|
||||
|
|
|
@ -194,7 +194,7 @@ typedef __gnuc_va_list va_list;
|
|||
/* Michael Eriksson <mer@sics.se> at Thu Sep 30 11:00:57 1993:
|
||||
Sequent defines _VA_LIST_ in <machine/machtypes.h> to be the type to
|
||||
use for va_list (``typedef _VA_LIST_ va_list'') */
|
||||
#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__) || defined(WINNT)
|
||||
#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__) || defined(WINNT) || defined(__amigaos__)
|
||||
/* The macro _VA_LIST_DEFINED is used in Windows NT 3.5 */
|
||||
#ifndef _VA_LIST_DEFINED
|
||||
/* The macro _VA_LIST is used in SCO Unix 3.2. */
|
||||
|
@ -205,7 +205,7 @@ typedef __gnuc_va_list va_list;
|
|||
#endif /* not _VA_LIST_T_H */
|
||||
#endif /* not _VA_LIST */
|
||||
#endif /* not _VA_LIST_DEFINED */
|
||||
#if !(defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__))
|
||||
#if !(defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__) || defined(__amigaos__))
|
||||
#define _VA_LIST_
|
||||
#endif
|
||||
#ifndef _VA_LIST
|
||||
|
|
|
@ -347,6 +347,8 @@ extern rtx final_sequence;
|
|||
|
||||
extern int current_function_pops_args;
|
||||
|
||||
extern int current_function_is_interrupt;
|
||||
|
||||
/* Nonzero if function being compiled needs to be given an address
|
||||
where the value should be stored. */
|
||||
|
||||
|
|
|
@ -255,6 +255,7 @@ struct default_include { const char *fname;
|
|||
{ CROSS_INCLUDE_DIR, 0, 0, 0 },
|
||||
/* This is another place that the target system's headers might be. */
|
||||
{ TOOL_INCLUDE_DIR, "BINUTILS", 0, 0 },
|
||||
{ LOCAL_INCLUDE_DIR, 0, 0, 1 },
|
||||
#else /* not CROSS_COMPILE */
|
||||
/* This should be /use/local/include and should come before
|
||||
the fixincludes-fixed header files. */
|
||||
|
|
|
@ -924,6 +924,10 @@ lang_independent_options f_options[] =
|
|||
{"pic", &flag_pic, 1,
|
||||
"Generate position independent code, if possible"},
|
||||
{"PIC", &flag_pic, 2, ""},
|
||||
{"baserel", &flag_pic, 3,
|
||||
"Generate base relative code"},
|
||||
{"baserel32", &flag_pic, 4,
|
||||
"Generate base relative code with no data limits"},
|
||||
{"exceptions", &flag_exceptions, 1,
|
||||
"Enable exception handling" },
|
||||
{"new-exceptions", &flag_new_exceptions, 1,
|
||||
|
|
|
@ -16,6 +16,9 @@ extern "C" {
|
|||
|
||||
#include "ansidecl.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Build an argument vector from a string. Allocates memory using
|
||||
malloc. Use freeargv to free the vector. */
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@ Boston, MA 02111-1307, USA. */
|
|||
|
||||
#include "ansidecl.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* These routines allocate space for an object. The assumption is
|
||||
that the object will want to allocate space as it goes along, but
|
||||
will never want to free any particular block. There is a function
|
||||
|
|
|
@ -35,12 +35,13 @@ Boston, MA 02111-1307, USA. */
|
|||
#ifdef __STDC__
|
||||
|
||||
#include <stddef.h>
|
||||
#ifndef __APPLE__
|
||||
extern void *memcpy (void *s1, const void *s2, size_t n); /* 4.11.2.1 */
|
||||
extern size_t strlen (const char *s); /* 4.11.6.3 */
|
||||
extern void *malloc (size_t size); /* 4.10.3.3 */
|
||||
extern void *realloc (void *ptr, size_t size); /* 4.10.3.4 */
|
||||
extern void free (void *ptr); /* 4.10.3.2 */
|
||||
extern char *strdup (const char *s); /* Non-ANSI */
|
||||
#endif
|
||||
|
||||
#else /* !__STDC__ */
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#define HAVE_SYS_ERRLIST
|
||||
|
||||
#ifdef HAVE_SYS_ERRLIST
|
||||
/* Note that errno.h (not sure what OS) or stdio.h (BSD 4.4, at least)
|
||||
might declare sys_errlist in a way that the compiler might consider
|
||||
|
@ -27,8 +29,10 @@
|
|||
|
||||
#ifdef __STDC__
|
||||
#include <stddef.h>
|
||||
#ifndef __APPLE__
|
||||
extern void *malloc (size_t size); /* 4.10.3.3 */
|
||||
extern void *memset (void *s, int c, size_t n); /* 4.11.6.1 */
|
||||
#endif
|
||||
#else /* !__STDC__ */
|
||||
extern char *malloc (); /* Standard memory allocater */
|
||||
extern char *memset ();
|
||||
|
@ -462,8 +466,12 @@ static const char **sys_errlist;
|
|||
|
||||
#else
|
||||
|
||||
#ifdef __APPLE__
|
||||
extern const int sys_nerr;
|
||||
#else
|
||||
extern int sys_nerr;
|
||||
extern char *sys_errlist[];
|
||||
#endif
|
||||
extern const char *const sys_errlist[];
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -25,8 +25,10 @@
|
|||
|
||||
#ifdef __STDC__
|
||||
#include <stddef.h>
|
||||
#ifndef __APPLE__
|
||||
extern void *malloc (size_t size); /* 4.10.3.3 */
|
||||
extern void *memset (void *s, int c, size_t n); /* 4.11.6.1 */
|
||||
#endif
|
||||
#else /* !__STDC__ */
|
||||
extern char *malloc (); /* Standard memory allocater */
|
||||
extern char *memset ();
|
||||
|
@ -584,8 +586,8 @@ DESCRIPTION
|
|||
|
||||
void
|
||||
psignal (signo, message)
|
||||
unsigned signo;
|
||||
char *message;
|
||||
unsigned int signo;
|
||||
const char *message;
|
||||
{
|
||||
if (signal_names == NULL)
|
||||
{
|
||||
|
|
|
@ -419,7 +419,10 @@ _IO_file_sync (fp)
|
|||
return retval;
|
||||
}
|
||||
|
||||
_IO_pos_t
|
||||
// Changed 2001-04-05 Andreas Wolff <andreas.wolff@dusnet.de>
|
||||
// Avoid conflicting types with libioP.h
|
||||
// This may be obsolete for future versions of libio
|
||||
_IO_off_t
|
||||
_IO_file_seekoff (fp, offset, dir, mode)
|
||||
_IO_FILE *fp;
|
||||
_IO_off_t offset;
|
||||
|
@ -587,7 +590,10 @@ _IO_file_read (fp, buf, size)
|
|||
return read (fp->_fileno, buf, size);
|
||||
}
|
||||
|
||||
_IO_pos_t
|
||||
// Changed 2001-04-05 Andreas Wolff <andreas.wolff@dusnet.de>
|
||||
// Avoid conflicting types with libioP.h
|
||||
// This may be obsolete for future versions of libio
|
||||
_IO_off_t
|
||||
_IO_file_seek (fp, offset, dir)
|
||||
_IO_FILE *fp;
|
||||
_IO_off_t offset;
|
||||
|
|
|
@ -467,10 +467,13 @@ _IO_default_setbuf (fp, p, len)
|
|||
return fp;
|
||||
}
|
||||
|
||||
_IO_pos_t
|
||||
// Changed 2001-04-05 Andreas Wolff <andreas.wolff@dusnet.de>
|
||||
// Avoid conflicting types with libioP.h
|
||||
// This may be obsolete for future versions of libio
|
||||
_IO_off_t
|
||||
_IO_default_seekpos (fp, pos, mode)
|
||||
_IO_FILE *fp;
|
||||
_IO_pos_t pos;
|
||||
_IO_off_t pos;
|
||||
int mode;
|
||||
{
|
||||
return _IO_SEEKOFF (fp, _IO_pos_as_off (pos), 0, mode);
|
||||
|
@ -551,7 +554,10 @@ _IO_default_finish (fp, dummy)
|
|||
_IO_un_link (fp);
|
||||
}
|
||||
|
||||
_IO_pos_t
|
||||
// Changed 2001-04-05 Andreas Wolff <andreas.wolff@dusnet.de>
|
||||
// Avoid conflicting types with libioP.h
|
||||
// This may be obsolete for future versions of libio
|
||||
_IO_off_t
|
||||
_IO_default_seekoff (fp, offset, dir, mode)
|
||||
_IO_FILE *fp;
|
||||
_IO_off_t offset;
|
||||
|
@ -882,7 +888,10 @@ _IO_default_pbackfail (fp, c)
|
|||
return (unsigned char) *fp->_IO_read_ptr;
|
||||
}
|
||||
|
||||
_IO_pos_t
|
||||
// Changed 2001-04-05 Andreas Wolff <andreas.wolff@dusnet.de>
|
||||
// Avoid conflicting types with libioP.h
|
||||
// This may be obsolete for future versions of libio
|
||||
_IO_off_t
|
||||
_IO_default_seek (fp, offset, dir)
|
||||
_IO_FILE *fp;
|
||||
_IO_off_t offset;
|
||||
|
|
|
@ -25,7 +25,10 @@
|
|||
|
||||
#include <libioP.h>
|
||||
|
||||
_IO_pos_t
|
||||
// Changed 2001-04-05 Andreas Wolff <andreas.wolff@dusnet.de>
|
||||
// Avoid conflicting types with libioP.h
|
||||
// This may be obsolete for future versions of libio
|
||||
_IO_off_t
|
||||
_IO_seekoff (fp, offset, dir, mode)
|
||||
_IO_FILE *fp;
|
||||
_IO_off_t offset;
|
||||
|
|
|
@ -25,10 +25,13 @@
|
|||
|
||||
#include <libioP.h>
|
||||
|
||||
_IO_pos_t
|
||||
// Changed 2001-04-05 Andreas Wolff <andreas.wolff@dusnet.de>
|
||||
// Avoid conflicting types with libioP.h
|
||||
// This may be obsolete for future versions of libio
|
||||
_IO_off_t
|
||||
_IO_seekpos (fp, pos, mode)
|
||||
_IO_FILE *fp;
|
||||
_IO_pos_t pos;
|
||||
_IO_off_t pos;
|
||||
int mode;
|
||||
{
|
||||
_IO_pos_t retval;
|
||||
|
|
|
@ -205,7 +205,10 @@ _IO_str_count (fp)
|
|||
- fp->_IO_read_base);
|
||||
}
|
||||
|
||||
_IO_pos_t
|
||||
// Changed 2001-04-05 Andreas Wolff <andreas.wolff@dusnet.de>
|
||||
// Avoid conflicting types with libioP.h
|
||||
// This may be obsolete for future versions of libio
|
||||
_IO_off_t
|
||||
_IO_str_seekoff (fp, offset, dir, mode)
|
||||
_IO_FILE *fp;
|
||||
_IO_off_t offset;
|
||||
|
|
Loading…
Reference in New Issue