AmigaOS/m68k specific changes.

This commit is contained in:
Krystian Bacławski 2016-04-17 15:04:47 +02:00
parent 37aef96904
commit 2f3c76b3d7
38 changed files with 3080 additions and 130 deletions

6
config.sub vendored
View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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,
$3),
build_tree_list (prefix_attributes,
$4));
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,
$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,
$3),
build_tree_list (prefix_attributes,
$4));
| 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,
$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,
$3),
build_tree_list (prefix_attributes,
$4));
| typed_declspecs setspecs absdcl maybeasm maybe_attribute
{ $$ = build_tree_list (
build_tree_list (build_tree_list (current_declspecs,
$3),
build_tree_list (prefix_attributes,
$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,
$3),
build_tree_list (prefix_attributes,
$4));
| declmods setspecs notype_declarator maybeasm maybe_attribute
{ $$ = build_tree_list (
build_tree_list (build_tree_list (current_declspecs,
$3),
build_tree_list (prefix_attributes,
$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,
$3),
build_tree_list (prefix_attributes,
$4));
| declmods setspecs absdcl maybeasm maybe_attribute
{ $$ = build_tree_list (
build_tree_list (build_tree_list (current_declspecs,
$3),
build_tree_list (prefix_attributes,
$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,
$1),
build_tree_list (prefix_attributes,
$2)); }
| absdcl maybe_attribute
{ $$ = build_tree_list (build_tree_list (current_declspecs,
$1),
build_tree_list (prefix_attributes,
$2)); }
build_tree_list (prefix_attributes,
$3)), $2); }
| notype_declarator maybeasm maybe_attribute
{ $$ = build_tree_list (
build_tree_list (build_tree_list (current_declspecs,
$1),
build_tree_list (prefix_attributes,
$3)), $2); }
| absdcl maybeasm maybe_attribute
{ $$ = build_tree_list (
build_tree_list (build_tree_list (current_declspecs,
$1),
build_tree_list (prefix_attributes,
$3)), $2); }
/* end-GG-local */
;
optparmlist:

View File

@ -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));

View File

@ -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)))

421
gcc/config/m68k/amigaos.c Normal file
View File

@ -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 */

637
gcc/config/m68k/amigaos.h Normal file
View File

@ -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)

View File

@ -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 ();
pic_ref = gen_rtx_MEM (Pmode,
gen_rtx_PLUS (Pmode,
pic_offset_table_rtx, orig));
if (flag_pic < 3)
pic_ref = gen_rtx_MEM (Pmode,
gen_rtx_PLUS (Pmode,
pic_offset_table_rtx, orig));
else
pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, orig);
current_function_uses_pic_offset_table = 1;
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)

View File

@ -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. */

View File

@ -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)
return \"rts\";
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
}")

79
gcc/config/m68k/t-amigaos Normal file
View File

@ -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

77
gcc/config/m68k/x-amigaos Normal file
View File

@ -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

7
gcc/configure vendored
View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -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* | \

View File

@ -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

View File

@ -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 */

View File

@ -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;

1133
gcc/gcc-amigaos.texi Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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. */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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. */

View File

@ -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. */

View File

@ -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,

View File

@ -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. */

View File

@ -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

View File

@ -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__ */

View File

@ -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

View File

@ -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)
{

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;