parent
b3ae05da16
commit
4697a36cef
|
@ -47,6 +47,29 @@ Boston, MA 02111-1307, USA. */
|
|||
%{mcpu=603: -mppc} \
|
||||
%{mcpu=604: -mppc}"
|
||||
|
||||
/* Define the options for the binder: Start text at 512, align all segments
|
||||
to 512 bytes, and warn if there is text relocation.
|
||||
|
||||
The -bhalt:4 option supposedly changes the level at which ld will abort,
|
||||
but it also suppresses warnings about multiply defined symbols and is
|
||||
used by the AIX cc command. So we use it here.
|
||||
|
||||
-bnodelcsect undoes a poor choice of default relating to multiply-defined
|
||||
csects. See AIX documentation for more information about this.
|
||||
|
||||
-bM:SRE tells the linker that the output file is Shared REusable. Note
|
||||
that to actually build a shared library you will also need to specify an
|
||||
export list with the -Wl,-bE option.
|
||||
|
||||
If -mcpu=common, export the architecture dependent multiply/divide routines
|
||||
as per README.RS6000. */
|
||||
|
||||
#undef LINK_SPEC
|
||||
#define LINK_SPEC "-T512 -H512 %{!r:-btextro} -bhalt:4 -bnodelcsect\
|
||||
%{static:-bnso -bI:/lib/syscalls.exp} \
|
||||
%{mcpu=common: milli.exp%s} \
|
||||
%{!shared:%{g*:-bexport:/usr/lib/libg.exp}} %{shared:-bM:SRE}"
|
||||
|
||||
/* These are not necessary when we pass -u to the assembler, and undefining
|
||||
them saves a great deal of space in object files. */
|
||||
|
||||
|
|
|
@ -27,6 +27,12 @@
|
|||
.Lgot2e = .-.LCTOC1
|
||||
.long _GOT2_END_ # -mrelocatable GOT pointers end
|
||||
|
||||
.Lfixups = .-.LCTOC1
|
||||
.long _FIXUP_START_ # start of .fixup section
|
||||
|
||||
.Lfixupe = .-.LCTOC1
|
||||
.long _FIXUP_END_ # end of .fixup section
|
||||
|
||||
.text
|
||||
.Lptr:
|
||||
.long .LCTOC1-.Laddr # PC relative pointer to .got2
|
||||
|
@ -64,16 +70,36 @@ __eabi: mflr 0
|
|||
add 4,12,4
|
||||
|
||||
cmpw 1,3,4 # any pointers to adjust
|
||||
bc 12,6,.Ldone
|
||||
bc 12,6,.Lfix
|
||||
|
||||
.Lloop:
|
||||
lwz 11,0(3) # next pointer
|
||||
add 11,11,12 # adjust
|
||||
stw 11,0(3)
|
||||
lwz 5,0(3) # next pointer
|
||||
add 5,5,12 # adjust
|
||||
stw 5,0(3)
|
||||
addi 3,3,4 # bump to next word
|
||||
cmpw 1,3,4 # more pointers to adjust?
|
||||
bc 4,6,.Lloop
|
||||
|
||||
# Fixup any user initialized pointers now (the compiler drops pointers to
|
||||
# each of the relocs that it does in the .fixup section). Note, the pointers
|
||||
# themselves have already been fixed up by the previous loop.
|
||||
|
||||
.Lfix:
|
||||
lwz 3,.Lfixups(11) # fixup pointers start
|
||||
lwz 4,.Lfixupe(11) # fixup pointers end
|
||||
|
||||
cmpw 1,3,4 # any user pointers to adjust
|
||||
bc 12,6,.Ldone
|
||||
|
||||
.Lfloop:
|
||||
lwz 5,0(3) # next pointer
|
||||
lwz 6,0(5) # get the pointer it points to
|
||||
add 6,6,12 # adjust
|
||||
stw 6,0(5)
|
||||
addi 3,3,4 # bump to next word
|
||||
cmpw 1,3,4 # more pointers to adjust?
|
||||
bc 4,6,.Lfloop
|
||||
|
||||
# Done adjusting pointers, return
|
||||
|
||||
.Ldone:
|
||||
|
|
|
@ -50,6 +50,11 @@ Boston, MA 02111-1307, USA. */
|
|||
#define MINIMAL_TOC_SECTION_ASM_OP \
|
||||
((TARGET_RELOCATABLE) ? "\t.section\t\".got2\",\"aw\"" : "\t.section\t\".got1\",\"aw\"")
|
||||
|
||||
/* Put relocatable data in .data, not .rodata so initialized pointers can be updated */
|
||||
#undef CONST_SECTION_ASM_OP
|
||||
#define CONST_SECTION_ASM_OP \
|
||||
((TARGET_RELOCATABLE) ? "\t.section\t\".data\"\t# .rodata" : "\t.section\t\".rodata\"")
|
||||
|
||||
/* Invoke an initializer function to set up the GOT */
|
||||
#define NAME__MAIN "__eabi"
|
||||
#define INVOKE__main 1
|
||||
|
@ -74,3 +79,43 @@ Boston, MA 02111-1307, USA. */
|
|||
#undef ENDFILE_SPEC
|
||||
#define ENDFILE_SPEC ""
|
||||
|
||||
/* This is how to output an assembler line defining an `int' constant.
|
||||
For -mrelocatable, we mark all addresses that need to be fixed up
|
||||
in the .fixup section. */
|
||||
#undef ASM_OUTPUT_INT
|
||||
#define ASM_OUTPUT_INT(FILE,VALUE) \
|
||||
do { \
|
||||
static int recurse = 0; \
|
||||
if (TARGET_RELOCATABLE \
|
||||
&& in_section != in_toc \
|
||||
&& in_section != in_text \
|
||||
&& in_section != in_ctors \
|
||||
&& in_section != in_dtors \
|
||||
&& !recurse \
|
||||
&& GET_CODE (VALUE) != CONST_INT \
|
||||
&& GET_CODE (VALUE) != CONST_DOUBLE) \
|
||||
{ \
|
||||
static int labelno = 0; \
|
||||
char buf[256], *p; \
|
||||
\
|
||||
recurse = 1; \
|
||||
ASM_GENERATE_INTERNAL_LABEL (buf, "LCP", labelno++); \
|
||||
STRIP_NAME_ENCODING (p, buf); \
|
||||
fprintf (FILE, "%s:\n", p); \
|
||||
fprintf (FILE, "\t.long ("); \
|
||||
output_addr_const (FILE, (VALUE)); \
|
||||
fprintf (FILE, ")@fixup\n"); \
|
||||
fprintf (FILE, "\t.section\t\".fixup\",\"aw\"\n"); \
|
||||
ASM_OUTPUT_ALIGN (FILE, 2); \
|
||||
fprintf (FILE, "\t.long\t%s\n", p); \
|
||||
fprintf (FILE, "\t.previous\n"); \
|
||||
recurse = 0; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
fprintf (FILE, "\t.long "); \
|
||||
output_addr_const (FILE, (VALUE)); \
|
||||
fprintf (FILE, "\n"); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/* Embedded ELF system support, using old AIX based calling sequence.
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support.
|
||||
|
||||
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 "rs6000/eabi.h"
|
||||
|
||||
#undef TARGET_DEFAULT
|
||||
#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_AIX_CALLS)
|
||||
|
||||
#undef CPP_SPEC
|
||||
#define CPP_SPEC "\
|
||||
%{posix: -D_POSIX_SOURCE} \
|
||||
%{mrelocatable: -D_RELOCATABLE} \
|
||||
%{mcall-sysv: -D_CALL_SYSV} %{mcall-aix: -D_CALL_AIX} %{!mcall-sysv: %{!mcall-aix: -D_CALL_AIX}} \
|
||||
%{msoft-float: -D_SOFT_FLOAT} %{mcpu=403: -D_SOFT_FLOAT} \
|
||||
%{mlittle: -D_LITTLE_ENDIAN -Amachine(littleendian)} \
|
||||
%{mlittle-endian: -D_LITTLE_ENDIAN -Amachine(littleendian)} \
|
||||
%{!mlittle: %{!mlittle-endian: -D_BIG_ENDIAN -Amachine(bigendian)}} \
|
||||
%{!mcpu*: \
|
||||
%{mpower: %{!mpower2: -D_ARCH_PWR}} \
|
||||
%{mpower2: -D_ARCH_PWR2} \
|
||||
%{mpowerpc*: -D_ARCH_PPC} \
|
||||
%{mno-powerpc: %{!mpower: %{!mpower2: -D_ARCH_COM}}} \
|
||||
%{!mno-powerpc: -D_ARCH_PPC}} \
|
||||
%{mcpu=common: -D_ARCH_COM} \
|
||||
%{mcpu=power: -D_ARCH_PWR} \
|
||||
%{mcpu=powerpc: -D_ARCH_PPC} \
|
||||
%{mcpu=rios: -D_ARCH_PWR} \
|
||||
%{mcpu=rios1: -D_ARCH_PWR} \
|
||||
%{mcpu=rios2: -D_ARCH_PWR2} \
|
||||
%{mcpu=rsc: -D_ARCH_PWR} \
|
||||
%{mcpu=rsc1: -D_ARCH_PWR} \
|
||||
%{mcpu=403: -D_ARCH_PPC} \
|
||||
%{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \
|
||||
%{mcpu=603: -D_ARCH_PPC} \
|
||||
%{mcpu=604: -D_ARCH_PPC}"
|
|
@ -29,6 +29,8 @@ Boston, MA 02111-1307, USA. */
|
|||
#define CPP_SPEC "\
|
||||
%{posix: -D_POSIX_SOURCE} \
|
||||
%{mrelocatable: -D_RELOCATABLE} \
|
||||
%{mcall-sysv: -D_CALL_SYSV} %{mcall-aix: -D_CALL_AIX} %{!mcall-sysv: %{!mcall-aix: -D_CALL_SYSV}} \
|
||||
%{msoft-float: -D_SOFT_FLOAT} %{mcpu=403: -D_SOFT_FLOAT} \
|
||||
%{mbig: -D_BIG_ENDIAN -Amachine(bigendian)} \
|
||||
%{mbig-endian: -D_BIG_ENDIAN -Amachine(bigendian)} \
|
||||
%{!mbig: %{!mbig-endian: -D_LITTLE_ENDIAN -Amachine(littleendian)}} \
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
#!
|
||||
__mulh 0x3100
|
||||
__mull 0x3180
|
||||
__divss 0x3200
|
||||
__divus 0x3280
|
||||
__quoss 0x3300
|
||||
__quous 0x3380
|
File diff suppressed because it is too large
Load Diff
|
@ -150,6 +150,10 @@ extern int target_flags;
|
|||
#define MASK_STRING 0x4000
|
||||
#define MASK_STRING_SET 0x8000
|
||||
|
||||
/* Temporary debug switches */
|
||||
#define MASK_DEBUG_STACK 0x10000
|
||||
#define MASK_DEBUG_ARG 0x20000
|
||||
|
||||
#define TARGET_POWER (target_flags & MASK_POWER)
|
||||
#define TARGET_POWER2 (target_flags & MASK_POWER2)
|
||||
#define TARGET_POWERPC (target_flags & MASK_POWERPC)
|
||||
|
@ -166,9 +170,23 @@ extern int target_flags;
|
|||
#define TARGET_MULTIPLE_SET (target_flags & MASK_MULTIPLE_SET)
|
||||
#define TARGET_STRING (target_flags & MASK_STRING)
|
||||
#define TARGET_STRING_SET (target_flags & MASK_STRING_SET)
|
||||
#define TARGET_DEBUG_STACK (target_flags & MASK_DEBUG_STACK)
|
||||
#define TARGET_DEBUG_ARG (target_flags & MASK_DEBUG_ARG)
|
||||
|
||||
#define TARGET_HARD_FLOAT (! TARGET_SOFT_FLOAT)
|
||||
|
||||
/* Pseudo target to indicate whether the object format is ELF
|
||||
(to get around not having conditional compilation in the md file) */
|
||||
#ifndef TARGET_ELF
|
||||
#define TARGET_ELF 0
|
||||
#endif
|
||||
|
||||
/* If this isn't V.4, don't support -mno-toc. */
|
||||
#ifndef TARGET_NO_TOC
|
||||
#define TARGET_NO_TOC 0
|
||||
#define TARGET_TOC 1
|
||||
#endif
|
||||
|
||||
/* Run-time compilation parameters selecting different hardware subsets.
|
||||
|
||||
Macro to define tables used to set the flags.
|
||||
|
@ -215,6 +233,8 @@ extern int target_flags;
|
|||
{"string", MASK_STRING | MASK_STRING_SET}, \
|
||||
{"no-string", - MASK_STRING}, \
|
||||
{"no-string", MASK_STRING_SET}, \
|
||||
{"debug-stack", MASK_DEBUG_STACK}, \
|
||||
{"debug-arg", MASK_DEBUG_ARG}, \
|
||||
SUBTARGET_SWITCHES \
|
||||
{"", TARGET_DEFAULT}}
|
||||
|
||||
|
@ -833,6 +853,32 @@ enum reg_class { NO_REGS, BASE_REGS, GENERAL_REGS, FLOAT_REGS,
|
|||
|
||||
/* Stack layout; function entry, exit and calling. */
|
||||
|
||||
/* Structure used to define the rs6000 stack */
|
||||
typedef struct rs6000_stack {
|
||||
int first_gp_reg_save; /* first callee saved GP register used */
|
||||
int first_fp_reg_save; /* first callee saved FP register used */
|
||||
int lr_save_p; /* true if the link reg needs to be saved */
|
||||
int cr_save_p; /* true if the CR reg needs to be saved */
|
||||
int push_p; /* true if we need to allocate stack space */
|
||||
int calls_p; /* true if the function makes any calls */
|
||||
int v4_call_p; /* true if V.4 calling sequence used */
|
||||
int gp_save_offset; /* offset to save GP regs from inital SP */
|
||||
int fp_save_offset; /* offset to save FP regs from inital SP */
|
||||
int lr_save_offset; /* offset to save LR from initial SP */
|
||||
int cr_save_offset; /* offset to save CR from initial SP */
|
||||
int varargs_save_offset; /* offset to save the varargs registers */
|
||||
int reg_size; /* register size (4 or 8) */
|
||||
int varargs_size; /* size to hold V.4 args passed in regs */
|
||||
int vars_size; /* variable save area size */
|
||||
int parm_size; /* outgoing parameter size */
|
||||
int save_size; /* save area size */
|
||||
int fixed_size; /* fixed size of stack frame */
|
||||
int gp_size; /* size of saved GP registers */
|
||||
int fp_size; /* size of saved FP registers */
|
||||
int cr_size; /* size to hold CR if not in save_size */
|
||||
int total_size; /* total bytes allocated for stack */
|
||||
} rs6000_stack_t;
|
||||
|
||||
/* Define this if pushing a word on the stack
|
||||
makes the stack pointer a smaller address. */
|
||||
#define STACK_GROWS_DOWNWARD
|
||||
|
@ -846,6 +892,29 @@ enum reg_class { NO_REGS, BASE_REGS, GENERAL_REGS, FLOAT_REGS,
|
|||
arguments. */
|
||||
/* #define FRAME_GROWS_DOWNWARD */
|
||||
|
||||
/* Size of the outgoing register save area */
|
||||
#define RS6000_REG_SAVE (TARGET_64BIT ? 64 : 32)
|
||||
|
||||
/* Size of the fixed area on the stack */
|
||||
#define RS6000_SAVE_AREA (TARGET_64BIT ? 48 : 24)
|
||||
|
||||
/* Size of the V.4 varargs area if needed */
|
||||
#define RS6000_VARARGS_AREA 0
|
||||
|
||||
/* Whether a V.4 varargs area is needed */
|
||||
extern int rs6000_sysv_varargs_p;
|
||||
|
||||
/* Align an address */
|
||||
#define ALIGN(n,a) (((n) + (a) - 1) & ~((a) - 1))
|
||||
|
||||
/* Size of V.4 varargs area in bytes */
|
||||
#define RS6000_VARARGS_SIZE \
|
||||
((GP_ARG_NUM_REG * (TARGET_64BIT ? 8 : 4)) + (FP_ARG_NUM_REG * 8) + 8)
|
||||
|
||||
/* Offset of V.4 varargs area */
|
||||
#define RS6000_VARARGS_OFFSET \
|
||||
(ALIGN (current_function_outgoing_args_size, 8) + RS6000_SAVE_AREA)
|
||||
|
||||
/* Offset within stack frame to start allocating local variables at.
|
||||
If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
|
||||
first local allocated. Otherwise, it is the offset to the BEGINNING
|
||||
|
@ -855,8 +924,9 @@ enum reg_class { NO_REGS, BASE_REGS, GENERAL_REGS, FLOAT_REGS,
|
|||
except for dynamic allocations. So we start after the fixed area and
|
||||
outgoing parameter area. */
|
||||
|
||||
#define STARTING_FRAME_OFFSET (current_function_outgoing_args_size \
|
||||
+ (TARGET_64BIT ? 48 : 24))
|
||||
#define STARTING_FRAME_OFFSET (ALIGN (current_function_outgoing_args_size, 8) \
|
||||
+ RS6000_VARARGS_AREA \
|
||||
+ RS6000_SAVE_AREA)
|
||||
|
||||
/* If we generate an insn to push BYTES bytes,
|
||||
this says how many the stack pointer really advances by.
|
||||
|
@ -866,12 +936,12 @@ enum reg_class { NO_REGS, BASE_REGS, GENERAL_REGS, FLOAT_REGS,
|
|||
/* Offset of first parameter from the argument pointer register value.
|
||||
On the RS/6000, we define the argument pointer to the start of the fixed
|
||||
area. */
|
||||
#define FIRST_PARM_OFFSET(FNDECL) (TARGET_64BIT ? 48 : 24)
|
||||
#define FIRST_PARM_OFFSET(FNDECL) RS6000_SAVE_AREA
|
||||
|
||||
/* Define this if stack space is still allocated for a parameter passed
|
||||
in a register. The value is the number of bytes allocated to this
|
||||
area. */
|
||||
#define REG_PARM_STACK_SPACE(FNDECL) (TARGET_64BIT ? 64 : 32)
|
||||
#define REG_PARM_STACK_SPACE(FNDECL) RS6000_REG_SAVE
|
||||
|
||||
/* Define this if the above stack space is to be considered part of the
|
||||
space allocated by the caller. */
|
||||
|
@ -880,7 +950,7 @@ enum reg_class { NO_REGS, BASE_REGS, GENERAL_REGS, FLOAT_REGS,
|
|||
/* This is the difference between the logical top of stack and the actual sp.
|
||||
|
||||
For the RS/6000, sp points past the fixed area. */
|
||||
#define STACK_POINTER_OFFSET (TARGET_64BIT ? 48 : 24)
|
||||
#define STACK_POINTER_OFFSET RS6000_SAVE_AREA
|
||||
|
||||
/* Define this if the maximum size of all the outgoing args is to be
|
||||
accumulated and pushed during the prologue. The amount can be
|
||||
|
@ -922,18 +992,35 @@ enum reg_class { NO_REGS, BASE_REGS, GENERAL_REGS, FLOAT_REGS,
|
|||
#define RETURN_IN_MEMORY(TYPE) \
|
||||
(TYPE_MODE (TYPE) == BLKmode)
|
||||
|
||||
/* Minimum and maximum general purpose registers used to hold arguments. */
|
||||
#define GP_ARG_MIN_REG 3
|
||||
#define GP_ARG_MAX_REG 10
|
||||
#define GP_ARG_NUM_REG (GP_ARG_MAX_REG - GP_ARG_MIN_REG + 1)
|
||||
|
||||
/* Minimum and maximum floating point registers used to hold arguments. */
|
||||
#define FP_ARG_MIN_REG 33
|
||||
#define FP_ARG_MAX_REG 45
|
||||
#define FP_ARG_NUM_REG (FP_ARG_MAX_REG - FP_ARG_MIN_REG + 1)
|
||||
|
||||
/* Return registers */
|
||||
#define GP_ARG_RETURN GP_ARG_MIN_REG
|
||||
#define FP_ARG_RETURN FP_ARG_MIN_REG
|
||||
|
||||
/* Define cutoff for using external functions to save floating point */
|
||||
#define FP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) == 62 || (FIRST_REG) == 63)
|
||||
|
||||
/* 1 if N is a possible register number for a function value
|
||||
as seen by the caller.
|
||||
|
||||
On RS/6000, this is r3 and fp1. */
|
||||
|
||||
#define FUNCTION_VALUE_REGNO_P(N) ((N) == 3 || ((N) == 33))
|
||||
#define FUNCTION_VALUE_REGNO_P(N) ((N) == GP_ARG_RETURN || ((N) == FP_ARG_RETURN))
|
||||
|
||||
/* 1 if N is a possible register number for function argument passing.
|
||||
On RS/6000, these are r3-r10 and fp1-fp13. */
|
||||
#define FUNCTION_ARG_REGNO_P(N) \
|
||||
(((unsigned)((N) - GP_ARG_MIN_REG) < (unsigned)(GP_ARG_NUM_REG)) \
|
||||
|| ((unsigned)((N) - FP_ARG_MIN_REG) < (unsigned)(FP_ARG_NUM_REG)))
|
||||
|
||||
#define FUNCTION_ARG_REGNO_P(N) \
|
||||
(((N) <= 10 && (N) >= 3) || ((N) >= 33 && (N) <= 45))
|
||||
|
||||
/* Define a data type for recording info about an argument list
|
||||
during the scan of that argument list. This data type should
|
||||
|
@ -944,10 +1031,21 @@ enum reg_class { NO_REGS, BASE_REGS, GENERAL_REGS, FLOAT_REGS,
|
|||
On the RS/6000, this is a structure. The first element is the number of
|
||||
total argument words, the second is used to store the next
|
||||
floating-point register number, and the third says how many more args we
|
||||
have prototype types for. */
|
||||
have prototype types for.
|
||||
|
||||
struct rs6000_args {int words, fregno, nargs_prototype; };
|
||||
#define CUMULATIVE_ARGS struct rs6000_args
|
||||
The System V.4 varargs/stdarg support requires that this structure's size
|
||||
be a multiple of sizeof(int), and that WORDS, FREGNO, NARGS_PROTOTYPE,
|
||||
ORIG_NARGS, and VARARGS_OFFSET be the first five ints. */
|
||||
|
||||
typedef struct rs6000_args
|
||||
{
|
||||
int words; /* # words uses for passing GP registers */
|
||||
int fregno; /* next available FP register */
|
||||
int nargs_prototype; /* # args left in the current prototype */
|
||||
int orig_nargs; /* Original value of nargs_prototype */
|
||||
int varargs_offset; /* offset of the varargs save area */
|
||||
int prototype; /* Whether a prototype was defined */
|
||||
} CUMULATIVE_ARGS;
|
||||
|
||||
/* Define intermediate macro to compute the size (in registers) of an argument
|
||||
for the RS/6000. */
|
||||
|
@ -962,40 +1060,27 @@ struct rs6000_args {int words, fregno, nargs_prototype; };
|
|||
for a call to a function whose data type is FNTYPE.
|
||||
For a library call, FNTYPE is 0. */
|
||||
|
||||
#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) \
|
||||
(CUM).words = 0, \
|
||||
(CUM).fregno = 33, \
|
||||
(CUM).nargs_prototype = (FNTYPE && TYPE_ARG_TYPES (FNTYPE) \
|
||||
? (list_length (TYPE_ARG_TYPES (FNTYPE)) - 1 \
|
||||
+ (TYPE_MODE (TREE_TYPE (FNTYPE)) == BLKmode \
|
||||
|| RETURN_IN_MEMORY (TREE_TYPE (FNTYPE)))) \
|
||||
: 0)
|
||||
#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) \
|
||||
init_cumulative_args (&CUM, FNTYPE, LIBNAME, FALSE)
|
||||
|
||||
/* Similar, but when scanning the definition of a procedure. We always
|
||||
set NARGS_PROTOTYPE large so we never return an EXPR_LIST. */
|
||||
|
||||
#define INIT_CUMULATIVE_INCOMING_ARGS(CUM,FNTYPE,IGNORE) \
|
||||
(CUM).words = 0, \
|
||||
(CUM).fregno = 33, \
|
||||
(CUM).nargs_prototype = 1000
|
||||
#define INIT_CUMULATIVE_INCOMING_ARGS(CUM,FNTYPE,LIBNAME) \
|
||||
init_cumulative_args (&CUM, FNTYPE, LIBNAME, TRUE)
|
||||
|
||||
/* 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).nargs_prototype--; \
|
||||
if (NAMED) \
|
||||
{ \
|
||||
(CUM).words += RS6000_ARG_SIZE (MODE, TYPE, NAMED); \
|
||||
if (GET_MODE_CLASS (MODE) == MODE_FLOAT) \
|
||||
(CUM).fregno++; \
|
||||
} \
|
||||
}
|
||||
function_arg_advance (&CUM, MODE, TYPE, NAMED)
|
||||
|
||||
/* Non-zero if we can use a floating-point register to pass this arg. */
|
||||
#define USE_FP_FOR_ARG_P(CUM,MODE,TYPE) \
|
||||
(GET_MODE_CLASS (MODE) == MODE_FLOAT && (CUM).fregno < 46 && TARGET_HARD_FLOAT)
|
||||
#define USE_FP_FOR_ARG_P(CUM,MODE,TYPE) \
|
||||
(GET_MODE_CLASS (MODE) == MODE_FLOAT \
|
||||
&& (CUM).fregno <= FP_ARG_MAX_REG \
|
||||
&& TARGET_HARD_FLOAT)
|
||||
|
||||
/* Determine where to put an argument to a function.
|
||||
Value is zero to push the argument on the stack,
|
||||
|
@ -1019,30 +1104,24 @@ struct rs6000_args {int words, fregno, nargs_prototype; };
|
|||
so we can pass the FP value just in one register. emit_library_function
|
||||
doesn't support EXPR_LIST anyway. */
|
||||
|
||||
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
|
||||
(! (NAMED) ? 0 \
|
||||
: ((TYPE) != 0 && TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST) ? 0 \
|
||||
: USE_FP_FOR_ARG_P (CUM, MODE, TYPE) \
|
||||
? ((CUM).nargs_prototype > 0 || (TYPE) == 0 \
|
||||
? gen_rtx (REG, MODE, (CUM).fregno) \
|
||||
: ((CUM).words < 8 \
|
||||
? gen_rtx (EXPR_LIST, VOIDmode, \
|
||||
gen_rtx (REG, (MODE), 3 + (CUM).words), \
|
||||
gen_rtx (REG, (MODE), (CUM).fregno)) \
|
||||
: gen_rtx (EXPR_LIST, VOIDmode, 0, \
|
||||
gen_rtx (REG, (MODE), (CUM).fregno)))) \
|
||||
: (CUM).words < 8 ? gen_rtx(REG, (MODE), 3 + (CUM).words) : 0)
|
||||
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
|
||||
function_arg (&CUM, MODE, TYPE, NAMED)
|
||||
|
||||
/* 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) \
|
||||
(! (NAMED) ? 0 \
|
||||
: USE_FP_FOR_ARG_P (CUM, MODE, TYPE) && (CUM).nargs_prototype >= 0 ? 0 \
|
||||
: (((CUM).words < 8 \
|
||||
&& 8 < ((CUM).words + RS6000_ARG_SIZE (MODE, TYPE, NAMED))) \
|
||||
? 8 - (CUM).words : 0))
|
||||
#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
|
||||
function_arg_partial_nregs (&CUM, MODE, TYPE, NAMED)
|
||||
|
||||
/* A C expression that indicates when an argument must be passed by
|
||||
reference. If nonzero for an argument, a copy of that argument is
|
||||
made in memory and a pointer to the argument is passed instead of
|
||||
the argument itself. The pointer is passed in whatever way is
|
||||
appropriate for passing a pointer to that type. */
|
||||
|
||||
#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
|
||||
function_arg_pass_by_reference(&CUM, MODE, TYPE, NAMED)
|
||||
|
||||
/* Perform any needed actions needed for a function that is receiving a
|
||||
variable number of arguments.
|
||||
|
@ -1058,27 +1137,23 @@ struct rs6000_args {int words, fregno, nargs_prototype; };
|
|||
Normally, this macro will push all remaining incoming registers on the
|
||||
stack and set PRETEND_SIZE to the length of the registers pushed. */
|
||||
|
||||
#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \
|
||||
{ if ((CUM).words < 8) \
|
||||
{ \
|
||||
int first_reg_offset = (CUM).words; \
|
||||
\
|
||||
if (MUST_PASS_IN_STACK (MODE, TYPE)) \
|
||||
first_reg_offset += RS6000_ARG_SIZE (TYPE_MODE (TYPE), TYPE, 1); \
|
||||
\
|
||||
if (first_reg_offset > 8) \
|
||||
first_reg_offset = 8; \
|
||||
\
|
||||
if (! (NO_RTL) && first_reg_offset != 8) \
|
||||
move_block_from_reg \
|
||||
(3 + first_reg_offset, \
|
||||
gen_rtx (MEM, BLKmode, \
|
||||
plus_constant (virtual_incoming_args_rtx, \
|
||||
first_reg_offset * 4)), \
|
||||
8 - first_reg_offset, (8 - first_reg_offset) * UNITS_PER_WORD); \
|
||||
PRETEND_SIZE = (8 - first_reg_offset) * UNITS_PER_WORD; \
|
||||
} \
|
||||
}
|
||||
#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \
|
||||
setup_incoming_varargs (&CUM, MODE, TYPE, &PRETEND_SIZE, NO_RTL)
|
||||
|
||||
/* If defined, is a C expression that produces the machine-specific
|
||||
code for a call to `__builtin_saveregs'. This code will be moved
|
||||
to the very beginning of the function, before any parameter access
|
||||
are made. The return value of this function should be an RTX that
|
||||
contains the value to use as the return of `__builtin_saveregs'.
|
||||
|
||||
The argument ARGS is a `tree_list' containing the arguments that
|
||||
were passed to `__builtin_saveregs'.
|
||||
|
||||
If this macro is not defined, the compiler will output an ordinary
|
||||
call to the library function `__builtin_saveregs'. */
|
||||
|
||||
#define EXPAND_BUILTIN_SAVEREGS(ARGS) \
|
||||
expand_builtin_saveregs (ARGS)
|
||||
|
||||
/* This macro generates the assembly code for function entry.
|
||||
FILE is a stdio stream to output the code to.
|
||||
|
@ -1210,34 +1285,21 @@ struct rs6000_args {int words, fregno, nargs_prototype; };
|
|||
#define CAN_ELIMINATE(FROM, TO) \
|
||||
((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM \
|
||||
? ! frame_pointer_needed \
|
||||
: (FROM) == 30 ? ! TARGET_MINIMAL_TOC || get_pool_size () == 0 \
|
||||
: (FROM) == 30 ? ! TARGET_MINIMAL_TOC || TARGET_NO_TOC || get_pool_size () == 0 \
|
||||
: 1)
|
||||
|
||||
/* Define the offset between two registers, one to be eliminated, and the other
|
||||
its replacement, at the start of a routine. */
|
||||
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
|
||||
{ \
|
||||
int total_stack_size = (rs6000_sa_size () + get_frame_size () \
|
||||
+ current_function_outgoing_args_size); \
|
||||
\
|
||||
total_stack_size = (total_stack_size + 7) & ~7; \
|
||||
rs6000_stack_t *info = rs6000_stack_info (); \
|
||||
\
|
||||
if ((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \
|
||||
{ \
|
||||
if (rs6000_pushes_stack ()) \
|
||||
(OFFSET) = 0; \
|
||||
else \
|
||||
(OFFSET) = - total_stack_size; \
|
||||
} \
|
||||
else if ((FROM) == ARG_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM) \
|
||||
(OFFSET) = total_stack_size; \
|
||||
else if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \
|
||||
{ \
|
||||
if (rs6000_pushes_stack ()) \
|
||||
(OFFSET) = total_stack_size; \
|
||||
else \
|
||||
(OFFSET) = 0; \
|
||||
} \
|
||||
(OFFSET) = (info->push_p) ? 0 : - info->total_size; \
|
||||
else if ((FROM) == ARG_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM) \
|
||||
(OFFSET) = info->total_size; \
|
||||
else if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \
|
||||
(OFFSET) = (info->push_p) ? info->total_size : 0; \
|
||||
else if ((FROM) == 30) \
|
||||
(OFFSET) = 0; \
|
||||
else \
|
||||
|
@ -1341,12 +1403,14 @@ struct rs6000_args {int words, fregno, nargs_prototype; };
|
|||
we must ensure that both words are addressable. */
|
||||
|
||||
#define LEGITIMATE_CONSTANT_POOL_BASE_P(X) \
|
||||
(GET_CODE (X) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (X) \
|
||||
(TARGET_TOC && GET_CODE (X) == SYMBOL_REF \
|
||||
&& CONSTANT_POOL_ADDRESS_P (X) \
|
||||
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (X)))
|
||||
|
||||
#define LEGITIMATE_CONSTANT_POOL_ADDRESS_P(X) \
|
||||
(LEGITIMATE_CONSTANT_POOL_BASE_P (X) \
|
||||
|| (GET_CODE (X) == CONST && GET_CODE (XEXP (X, 0)) == PLUS \
|
||||
|| (TARGET_TOC \
|
||||
&& GET_CODE (X) == CONST && GET_CODE (XEXP (X, 0)) == PLUS \
|
||||
&& GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
|
||||
&& LEGITIMATE_CONSTANT_POOL_BASE_P (XEXP (XEXP (X, 0), 0))))
|
||||
|
||||
|
@ -1374,6 +1438,16 @@ struct rs6000_args {int words, fregno, nargs_prototype; };
|
|||
#define LEGITIMATE_INDIRECT_ADDRESS_P(X) \
|
||||
(GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X))
|
||||
|
||||
#define LEGITIMATE_LO_SUM_ADDRESS_P(MODE, X) \
|
||||
(TARGET_ELF \
|
||||
&& (MODE) != DImode \
|
||||
&& (MODE) != TImode \
|
||||
&& (TARGET_HARD_FLOAT || (MODE) != DFmode) \
|
||||
&& GET_CODE (X) == LO_SUM \
|
||||
&& GET_CODE (XEXP (X, 0)) == REG \
|
||||
&& REG_OK_FOR_BASE_P (XEXP (X, 0)) \
|
||||
&& CONSTANT_P (XEXP (X, 1)))
|
||||
|
||||
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
|
||||
{ if (LEGITIMATE_INDIRECT_ADDRESS_P (X)) \
|
||||
goto ADDR; \
|
||||
|
@ -1391,6 +1465,8 @@ struct rs6000_args {int words, fregno, nargs_prototype; };
|
|||
&& (TARGET_HARD_FLOAT || (MODE) != DFmode) \
|
||||
&& LEGITIMATE_INDEXED_ADDRESS_P (X)) \
|
||||
goto ADDR; \
|
||||
if (LEGITIMATE_LO_SUM_ADDRESS_P (MODE, X)) \
|
||||
goto ADDR; \
|
||||
}
|
||||
|
||||
/* Try machine-dependent ways of modifying an illegitimate address
|
||||
|
@ -1416,32 +1492,42 @@ struct rs6000_args {int words, fregno, nargs_prototype; };
|
|||
Then check for the sum of a register and something not constant, try to
|
||||
load the other things into a register and return the sum. */
|
||||
|
||||
#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
|
||||
{ if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == REG \
|
||||
&& GET_CODE (XEXP (X, 1)) == CONST_INT \
|
||||
&& (unsigned) (INTVAL (XEXP (X, 1)) + 0x8000) >= 0x10000) \
|
||||
{ int high_int, low_int; \
|
||||
high_int = INTVAL (XEXP (X, 1)) >> 16; \
|
||||
low_int = INTVAL (XEXP (X, 1)) & 0xffff; \
|
||||
if (low_int & 0x8000) \
|
||||
high_int += 1, low_int |= 0xffff0000; \
|
||||
(X) = gen_rtx (PLUS, SImode, \
|
||||
force_operand \
|
||||
(gen_rtx (PLUS, SImode, XEXP (X, 0), \
|
||||
gen_rtx (CONST_INT, VOIDmode, \
|
||||
high_int << 16)), 0),\
|
||||
gen_rtx (CONST_INT, VOIDmode, low_int)); \
|
||||
goto WIN; \
|
||||
} \
|
||||
else if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == REG \
|
||||
&& GET_CODE (XEXP (X, 1)) != CONST_INT \
|
||||
&& (TARGET_HARD_FLOAT || (MODE) != DFmode) \
|
||||
&& (MODE) != DImode && (MODE) != TImode) \
|
||||
{ \
|
||||
(X) = gen_rtx (PLUS, SImode, XEXP (X, 0), \
|
||||
#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
|
||||
{ if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == REG \
|
||||
&& GET_CODE (XEXP (X, 1)) == CONST_INT \
|
||||
&& (unsigned) (INTVAL (XEXP (X, 1)) + 0x8000) >= 0x10000) \
|
||||
{ int high_int, low_int; \
|
||||
high_int = INTVAL (XEXP (X, 1)) >> 16; \
|
||||
low_int = INTVAL (XEXP (X, 1)) & 0xffff; \
|
||||
if (low_int & 0x8000) \
|
||||
high_int += 1, low_int |= 0xffff0000; \
|
||||
(X) = gen_rtx (PLUS, SImode, \
|
||||
force_operand \
|
||||
(gen_rtx (PLUS, SImode, XEXP (X, 0), \
|
||||
gen_rtx (CONST_INT, VOIDmode, \
|
||||
high_int << 16)), 0), \
|
||||
gen_rtx (CONST_INT, VOIDmode, low_int)); \
|
||||
goto WIN; \
|
||||
} \
|
||||
else if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == REG \
|
||||
&& GET_CODE (XEXP (X, 1)) != CONST_INT \
|
||||
&& (TARGET_HARD_FLOAT || (MODE) != DFmode) \
|
||||
&& (MODE) != DImode && (MODE) != TImode) \
|
||||
{ \
|
||||
(X) = gen_rtx (PLUS, SImode, XEXP (X, 0), \
|
||||
force_reg (SImode, force_operand (XEXP (X, 1), 0))); \
|
||||
goto WIN; \
|
||||
} \
|
||||
goto WIN; \
|
||||
} \
|
||||
else if (TARGET_ELF && !TARGET_64BIT && TARGET_NO_TOC \
|
||||
&& GET_CODE (X) != CONST_INT \
|
||||
&& GET_CODE (X) != CONST_DOUBLE && CONSTANT_P (X) \
|
||||
&& (TARGET_HARD_FLOAT || (MODE) != DFmode) \
|
||||
&& (MODE) != DImode && (MODE) != TImode) \
|
||||
{ \
|
||||
rtx reg = gen_reg_rtx (Pmode); \
|
||||
emit_insn (gen_elf_high (reg, (X))); \
|
||||
(X) = gen_rtx (LO_SUM, Pmode, reg, (X)); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Go to LABEL if ADDR (a legitimate address expression)
|
||||
|
@ -1462,6 +1548,8 @@ struct rs6000_args {int words, fregno, nargs_prototype; };
|
|||
goto LABEL; \
|
||||
if (GET_CODE (ADDR) == PRE_DEC) \
|
||||
goto LABEL; \
|
||||
if (GET_CODE (ADDR) == LO_SUM) \
|
||||
goto LABEL; \
|
||||
}
|
||||
|
||||
/* Define this if some processing needs to be done immediately before
|
||||
|
@ -1561,7 +1649,7 @@ struct rs6000_args {int words, fregno, nargs_prototype; };
|
|||
The sle and sre instructions which allow SHIFT_COUNT_TRUNCATED
|
||||
have been dropped from the PowerPC architecture. */
|
||||
|
||||
#define SHIFT_COUNT_TRUNCATED TARGET_POWER ? 1 : 0
|
||||
#define SHIFT_COUNT_TRUNCATED (TARGET_POWER ? 1 : 0)
|
||||
|
||||
/* Use atexit for static constructors/destructors, instead of defining
|
||||
our own exit function. */
|
||||
|
@ -1575,12 +1663,13 @@ struct rs6000_args {int words, fregno, nargs_prototype; };
|
|||
On the RS/6000, if it is valid in the insn, it is free. So this
|
||||
always returns 0. */
|
||||
|
||||
#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
|
||||
#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
case CONST: \
|
||||
case LABEL_REF: \
|
||||
case SYMBOL_REF: \
|
||||
case CONST_DOUBLE: \
|
||||
case HIGH: \
|
||||
return 0;
|
||||
|
||||
/* Provide the costs of a rtl expression. This is in the body of a
|
||||
|
@ -1894,7 +1983,7 @@ toc_section () \
|
|||
fprintf (FILE, "\t.long ."); \
|
||||
RS6000_OUTPUT_BASENAME (FILE, NAME); \
|
||||
fprintf (FILE, ", TOC[tc0], 0\n"); \
|
||||
fprintf (FILE, ".csect .text[PR]\n."); \
|
||||
fprintf (FILE, ".csect .text[PR]\n."); \
|
||||
RS6000_OUTPUT_BASENAME (FILE, NAME); \
|
||||
fprintf (FILE, ":\n"); \
|
||||
if (write_symbols == XCOFF_DEBUG) \
|
||||
|
@ -1909,15 +1998,16 @@ toc_section () \
|
|||
we can't check that since not every file that uses
|
||||
GO_IF_LEGITIMATE_ADDRESS_P includes real.h. */
|
||||
|
||||
#define ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X) \
|
||||
(GET_CODE (X) == SYMBOL_REF \
|
||||
|| (GET_CODE (X) == CONST && GET_CODE (XEXP (X, 0)) == PLUS \
|
||||
&& GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF) \
|
||||
|| GET_CODE (X) == LABEL_REF \
|
||||
|| (! (TARGET_NO_FP_IN_TOC && ! TARGET_MINIMAL_TOC) \
|
||||
&& GET_CODE (X) == CONST_DOUBLE \
|
||||
&& GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
|
||||
&& BITS_PER_WORD == HOST_BITS_PER_INT))
|
||||
#define ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X) \
|
||||
(TARGET_TOC \
|
||||
&& (GET_CODE (X) == SYMBOL_REF \
|
||||
|| (GET_CODE (X) == CONST && GET_CODE (XEXP (X, 0)) == PLUS \
|
||||
&& GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF) \
|
||||
|| GET_CODE (X) == LABEL_REF \
|
||||
|| (! (TARGET_NO_FP_IN_TOC && ! TARGET_MINIMAL_TOC) \
|
||||
&& GET_CODE (X) == CONST_DOUBLE \
|
||||
&& GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
|
||||
&& BITS_PER_WORD == HOST_BITS_PER_INT)))
|
||||
|
||||
/* Select section for constant in constant pool.
|
||||
|
||||
|
@ -2230,15 +2320,23 @@ toc_section () \
|
|||
/* This is how to output code to push a register on the stack.
|
||||
It need not be very fast code. */
|
||||
|
||||
#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
|
||||
asm_fprintf (FILE, "\{tstu|stwu} %s,-4(r1)\n", reg_names[REGNO]);
|
||||
#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
|
||||
do { \
|
||||
extern char *reg_names[]; \
|
||||
asm_fprintf (FILE, "\{tstu|stwu} %s,-4(%s)\n", reg_names[REGNO], \
|
||||
reg_names[1]); \
|
||||
} while (0)
|
||||
|
||||
/* This is how to output an insn to pop a register from the stack.
|
||||
It need not be very fast code. */
|
||||
|
||||
#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
|
||||
asm_fprintf (FILE, "\t{l|lwz} %s,0(r1)\n\t{ai|addic} r1,r1,4\n", \
|
||||
reg_names[REGNO])
|
||||
#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
|
||||
do { \
|
||||
extern char *reg_names[]; \
|
||||
asm_fprintf (FILE, "\t{l|lwz} %s,0(%s)\n\t{ai|addic} %s,%s,4\n", \
|
||||
reg_names[REGNO], reg_names[1], reg_names[1], \
|
||||
reg_names[1]); \
|
||||
} while (0)
|
||||
|
||||
/* This is how to output an element of a case-vector that is absolute.
|
||||
(RS/6000 does not use such vectors, but we must define this macro
|
||||
|
@ -2396,6 +2494,13 @@ extern int lwa_operand ();
|
|||
extern int call_operand ();
|
||||
extern int current_file_function_operand ();
|
||||
extern int input_operand ();
|
||||
extern void init_cumulative_args ();
|
||||
extern void function_arg_advance ();
|
||||
extern struct rtx_def *function_arg ();
|
||||
extern int function_arg_partial_nregs ();
|
||||
extern int function_arg_pass_by_reference ();
|
||||
extern void setup_incoming_varargs ();
|
||||
extern struct rtx_def *expand_builtin_saveregs ();
|
||||
extern int expand_block_move ();
|
||||
extern int load_multiple_operation ();
|
||||
extern int store_multiple_operation ();
|
||||
|
@ -2411,10 +2516,8 @@ extern void print_operand ();
|
|||
extern void print_operand_address ();
|
||||
extern int first_reg_to_save ();
|
||||
extern int first_fp_reg_to_save ();
|
||||
extern int must_save_cr ();
|
||||
extern int rs6000_sa_size ();
|
||||
extern int rs6000_makes_calls ();
|
||||
extern int rs6000_pushes_stack ();
|
||||
extern rs6000_stack_t *rs6000_stack_info ();
|
||||
extern void svr4_traceback ();
|
||||
extern void output_prolog ();
|
||||
extern void output_epilog ();
|
||||
|
|
|
@ -3487,6 +3487,7 @@
|
|||
(use (reg:DF 33))
|
||||
(parallel [(set (reg:SI 3)
|
||||
(call (mem:SI (match_operand 2 "" "")) (const_int 0)))
|
||||
(use (const_int 0))
|
||||
(clobber (scratch:SI))])
|
||||
(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||||
(reg:SI 3))]
|
||||
|
@ -3832,7 +3833,24 @@
|
|||
[(set_attr "type" "delayed_compare")])
|
||||
|
||||
;; Now define ways of moving data around.
|
||||
;;
|
||||
|
||||
;; Elf specific ways of loading addresses for non-PIC code.
|
||||
;; The output of this could be r0, but we limit it to base
|
||||
;; registers, since almost all uses of this will need it
|
||||
;; in a base register shortly.
|
||||
(define_insn "elf_high"
|
||||
[(set (match_operand:SI 0 "register_operand" "=b")
|
||||
(high:SI (match_operand 1 "" "")))]
|
||||
"TARGET_ELF && !TARGET_64BIT"
|
||||
"{cau|addis} %0,0,%1@ha")
|
||||
|
||||
(define_insn "elf_low"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||
(lo_sum:SI (match_operand:SI 1 "register_operand" "b")
|
||||
(match_operand 2 "" "")))]
|
||||
"TARGET_ELF && !TARGET_64BIT"
|
||||
"{cal %0,%a2@l(%1)|addi %0,%1,%2@l}")
|
||||
|
||||
;; For SI, we special-case integers that can't be loaded in one insn. We
|
||||
;; do the load 16-bits at a time. We could do this by loading from memory,
|
||||
;; and this is even supposed to be faster, but it is simpler not to get
|
||||
|
@ -3850,7 +3868,22 @@
|
|||
if (GET_CODE (operands[1]) == CONST_DOUBLE)
|
||||
operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
|
||||
|
||||
if (CONSTANT_P (operands[1]) && GET_CODE (operands[1]) != CONST_INT
|
||||
if (TARGET_ELF && TARGET_NO_TOC && !TARGET_64BIT
|
||||
&& CONSTANT_P (operands[1])
|
||||
&& GET_CODE (operands[1]) != HIGH
|
||||
&& GET_CODE (operands[1]) != CONST_INT)
|
||||
{
|
||||
rtx target = (reload_completed || reload_in_progress)
|
||||
? operands[0] : gen_reg_rtx (SImode);
|
||||
|
||||
emit_insn (gen_elf_high (target, operands[1]));
|
||||
emit_insn (gen_elf_low (operands[0], target, operands[1]));
|
||||
DONE;
|
||||
}
|
||||
|
||||
if (CONSTANT_P (operands[1])
|
||||
&& GET_CODE (operands[1]) != CONST_INT
|
||||
&& GET_CODE (operands[1]) != HIGH
|
||||
&& ! LEGITIMATE_CONSTANT_POOL_ADDRESS_P (operands[1]))
|
||||
{
|
||||
/* If we are to limit the number of things we put in the TOC and
|
||||
|
@ -5014,7 +5047,7 @@
|
|||
"lwaux %3,%0,%2"
|
||||
[(set_attr "type" "load")])
|
||||
|
||||
(define_insn ""
|
||||
(define_insn "movdi_update"
|
||||
[(set (mem:DI (plus:DI (match_operand:DI 1 "gpc_reg_operand" "0,0")
|
||||
(match_operand:DI 2 "reg_or_short_operand" "r,I")))
|
||||
(match_operand:DI 3 "gpc_reg_operand" "r,r"))
|
||||
|
@ -5037,7 +5070,7 @@
|
|||
{lu|lwzu} %3,%2(%0)"
|
||||
[(set_attr "type" "load")])
|
||||
|
||||
(define_insn ""
|
||||
(define_insn "movsi_update"
|
||||
[(set (mem:SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
|
||||
(match_operand:SI 2 "reg_or_short_operand" "r,I")))
|
||||
(match_operand:SI 3 "gpc_reg_operand" "r,r"))
|
||||
|
@ -5215,12 +5248,48 @@
|
|||
(minus:SI (reg:SI 1) (match_operand:SI 0 "reg_or_short_operand" "")))]
|
||||
""
|
||||
"
|
||||
{ rtx chain = gen_reg_rtx (SImode);
|
||||
{ rtx chain = gen_reg_rtx (Pmode);
|
||||
rtx stack_bot = gen_rtx (MEM, Pmode, stack_pointer_rtx);
|
||||
rtx neg_op0;
|
||||
rtx lr_addr = NULL_RTX;
|
||||
rtx lr = NULL_RTX;
|
||||
|
||||
emit_move_insn (chain, stack_bot);
|
||||
emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, operands[0]));
|
||||
emit_move_insn (stack_bot, chain);
|
||||
|
||||
#ifdef TARGET_V4_CALLS
|
||||
if (TARGET_V4_CALLS)
|
||||
{
|
||||
lr = gen_reg_rtx (Pmode);
|
||||
lr_addr = gen_rtx (MEM, Pmode, gen_rtx (PLUS, Pmode,
|
||||
stack_pointer_rtx,
|
||||
GEN_INT (4)));
|
||||
emit_move_insn (lr, lr_addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (GET_CODE (operands[0]) != CONST_INT
|
||||
|| INTVAL (operands[0]) < -32767
|
||||
|| INTVAL (operands[0]) > 32768)
|
||||
{
|
||||
neg_op0 = gen_reg_rtx (Pmode);
|
||||
if (TARGET_POWERPC64)
|
||||
emit_insn (gen_negdi2 (neg_op0, operands[0]));
|
||||
else
|
||||
emit_insn (gen_negsi2 (neg_op0, operands[0]));
|
||||
}
|
||||
else
|
||||
neg_op0 = GEN_INT (- INTVAL (operands[0]));
|
||||
|
||||
if (TARGET_POWERPC64)
|
||||
emit_insn (gen_movdi_update (stack_pointer_rtx, stack_pointer_rtx, neg_op0, chain));
|
||||
else
|
||||
emit_insn (gen_movsi_update (stack_pointer_rtx, stack_pointer_rtx, neg_op0, chain));
|
||||
|
||||
#ifdef TARGET_V4_CALLS
|
||||
if (TARGET_V4_CALLS)
|
||||
emit_move_insn (lr_addr, lr);
|
||||
#endif
|
||||
|
||||
DONE;
|
||||
}")
|
||||
|
||||
|
@ -5310,6 +5379,7 @@
|
|||
(define_expand "call"
|
||||
[(parallel [(call (mem:SI (match_operand:SI 0 "address_operand" ""))
|
||||
(match_operand 1 "" ""))
|
||||
(use (match_operand 2 "" ""))
|
||||
(clobber (scratch:SI))])]
|
||||
""
|
||||
"
|
||||
|
@ -5334,6 +5404,7 @@
|
|||
[(parallel [(set (match_operand 0 "" "")
|
||||
(call (mem:SI (match_operand:SI 1 "address_operand" ""))
|
||||
(match_operand 2 "" "")))
|
||||
(use (match_operand 3 "" ""))
|
||||
(clobber (scratch:SI))])]
|
||||
""
|
||||
"
|
||||
|
@ -5355,24 +5426,50 @@
|
|||
}")
|
||||
|
||||
;; Call to function in current module. No TOC pointer reload needed.
|
||||
;; Operand2 is non-zero if we are using the V.4 calling sequence and
|
||||
;; either the function was not prototyped, or it was prototyped as a
|
||||
;; variable argument function. It is > 0 if FP registers were passed
|
||||
;; and < 0 if they were not.
|
||||
|
||||
(define_insn ""
|
||||
[(call (mem:SI (match_operand:SI 0 "current_file_function_operand" "s"))
|
||||
(match_operand 1 "" "g"))
|
||||
(clobber (match_scratch:SI 2 "=l"))]
|
||||
""
|
||||
"bl %z0")
|
||||
|
||||
;; Call to function which may be in another module. Restore the TOC
|
||||
;; pointer (r2) after the call unless this is System V.
|
||||
|
||||
(define_insn ""
|
||||
[(call (mem:SI (match_operand:SI 0 "call_operand" "l,s"))
|
||||
(match_operand 1 "" "fg,fg"))
|
||||
(clobber (match_scratch:SI 2 "=l,l"))]
|
||||
[(call (mem:SI (match_operand:SI 0 "current_file_function_operand" "s,s"))
|
||||
(match_operand 1 "" "g,g"))
|
||||
(use (match_operand:SI 2 "immediate_operand" "O,n"))
|
||||
(clobber (match_scratch:SI 3 "=l,l"))]
|
||||
""
|
||||
"*
|
||||
{
|
||||
if (INTVAL (operands[2]) > 0)
|
||||
return \"creqv 6,6,6\;bl %z0\";
|
||||
|
||||
else if (INTVAL (operands[2]) < 0)
|
||||
return \"crxor 6,6,6\;bl %z0\";
|
||||
|
||||
return \"bl %z0\";
|
||||
}"
|
||||
[(set_attr "length" "4,8")])
|
||||
|
||||
;; Call to function which may be in another module. Restore the TOC
|
||||
;; pointer (r2) after the call unless this is System V.
|
||||
;; Operand2 is non-zero if we are using the V.4 calling sequence and
|
||||
;; either the function was not prototyped, or it was prototyped as a
|
||||
;; variable argument function. It is > 0 if FP registers were passed
|
||||
;; and < 0 if they were not.
|
||||
|
||||
(define_insn ""
|
||||
[(call (mem:SI (match_operand:SI 0 "call_operand" "l,s,l,s"))
|
||||
(match_operand 1 "" "fg,fg,fg,fg"))
|
||||
(use (match_operand:SI 2 "immediate_operand" "O,O,n,n"))
|
||||
(clobber (match_scratch:SI 3 "=l,l,l,l"))]
|
||||
""
|
||||
"*
|
||||
{
|
||||
if (INTVAL (operands[2]) > 0)
|
||||
output_asm_insn (\"creqv 6,6,6\", operands);
|
||||
|
||||
else if (INTVAL (operands[2]) < 0)
|
||||
output_asm_insn (\"crxor 6,6,6\", operands);
|
||||
|
||||
#ifndef USING_SVR4_H
|
||||
if (GET_CODE (operands[0]) == REG)
|
||||
return \"{brl|blrl}\;{l|lwz} 2,20(1)\";
|
||||
|
@ -5386,24 +5483,42 @@
|
|||
return \"bl %z0\";
|
||||
#endif
|
||||
}"
|
||||
[(set_attr "length" "8")])
|
||||
|
||||
(define_insn ""
|
||||
[(set (match_operand 0 "" "=fg")
|
||||
(call (mem:SI (match_operand:SI 1 "current_file_function_operand" "s"))
|
||||
(match_operand 2 "" "g")))
|
||||
(clobber (match_scratch:SI 3 "=l"))]
|
||||
""
|
||||
"bl %z1")
|
||||
[(set_attr "length" "8,8,12,12")])
|
||||
|
||||
(define_insn ""
|
||||
[(set (match_operand 0 "" "=fg,fg")
|
||||
(call (mem:SI (match_operand:SI 1 "call_operand" "l,s"))
|
||||
(match_operand 2 "" "fg,fg")))
|
||||
(clobber (match_scratch:SI 3 "=l,l"))]
|
||||
(call (mem:SI (match_operand:SI 1 "current_file_function_operand" "s,s"))
|
||||
(match_operand 2 "" "g,g")))
|
||||
(use (match_operand:SI 3 "immediate_operand" "O,n"))
|
||||
(clobber (match_scratch:SI 4 "=l,l"))]
|
||||
""
|
||||
"*
|
||||
{
|
||||
if (INTVAL (operands[3]) > 0)
|
||||
return \"creqv 6,6,6\;bl %z1\";
|
||||
|
||||
else if (INTVAL (operands[3]) < 0)
|
||||
return \"crxor 6,6,6\;bl %z1\";
|
||||
|
||||
return \"bl %z1\";
|
||||
}"
|
||||
[(set_attr "length" "4,8")])
|
||||
|
||||
(define_insn ""
|
||||
[(set (match_operand 0 "" "=fg,fg,fg,fg")
|
||||
(call (mem:SI (match_operand:SI 1 "call_operand" "l,s,l,s"))
|
||||
(match_operand 2 "" "fg,fg,fg,fg")))
|
||||
(use (match_operand:SI 3 "immediate_operand" "O,O,n,n"))
|
||||
(clobber (match_scratch:SI 4 "=l,l,l,l"))]
|
||||
""
|
||||
"*
|
||||
{
|
||||
if (INTVAL (operands[3]) > 0)
|
||||
output_asm_insn (\"creqv 6,6,6\", operands);
|
||||
|
||||
else if (INTVAL (operands[3]) < 0)
|
||||
output_asm_insn (\"crxor 6,6,6\", operands);
|
||||
|
||||
#ifndef USING_SVR4_H
|
||||
if (GET_CODE (operands[1]) == REG)
|
||||
return \"{brl|blrl}\;{l|lwz} 2,20(1)\";
|
||||
|
@ -5417,7 +5532,7 @@
|
|||
return \"bl %z1\";
|
||||
#endif
|
||||
}"
|
||||
[(set_attr "length" "8")])
|
||||
[(set_attr "length" "8,8,12,12")])
|
||||
|
||||
;; Call subroutine returning any type.
|
||||
|
||||
|
@ -5431,7 +5546,7 @@
|
|||
{
|
||||
int i;
|
||||
|
||||
emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
|
||||
emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx, const0_rtx));
|
||||
|
||||
for (i = 0; i < XVECLEN (operands[2], 0); i++)
|
||||
{
|
||||
|
@ -5455,6 +5570,13 @@
|
|||
[(unspec_volatile [(const_int 0)] 0)]
|
||||
""
|
||||
"")
|
||||
|
||||
;; Sync instruction used for V.4 trampolines
|
||||
(define_insn "sync"
|
||||
[(unspec [(match_operand 0 "" "")] 1)]
|
||||
""
|
||||
"sync")
|
||||
|
||||
|
||||
;; Compare insns are next. Note that the RS/6000 has two types of compares,
|
||||
;; signed & unsigned, and one type of branch.
|
||||
|
|
|
@ -27,20 +27,35 @@ Boston, MA 02111-1307, USA. */
|
|||
#define MASK_RELOCATABLE 0x10000000 /* GOT pointers are PC relative */
|
||||
#define MASK_NO_TRACEBACK 0x08000000 /* eliminate traceback words */
|
||||
#define MASK_LITTLE_ENDIAN 0x04000000 /* target is little endian */
|
||||
#define MASK_NO_TOC 0x02000000 /* do not use TOC for loading addresses */
|
||||
#define MASK_AIX_CALLS 0x02000000 /* Use AIX calling sequence */
|
||||
#define MASK_PROTOTYPE 0x01000000 /* Only prototyped fcns pass variable args */
|
||||
|
||||
#define TARGET_NO_BITFIELD_TYPE (target_flags & MASK_NO_BITFIELD_TYPE)
|
||||
#define TARGET_STRICT_ALIGN (target_flags & MASK_STRICT_ALIGN)
|
||||
#define TARGET_RELOCATABLE (target_flags & MASK_RELOCATABLE)
|
||||
#define TARGET_NO_TRACEBACK (target_flags & MASK_NO_TRACEBACK)
|
||||
#define TARGET_LITTLE_ENDIAN (target_flags & MASK_LITTLE_ENDIAN)
|
||||
#define TARGET_NO_TOC (target_flags & MASK_NO_TOC)
|
||||
#define TARGET_AIX_CALLS (target_flags & MASK_AIX_CALLS)
|
||||
#define TARGET_PROTOTYPE (target_flags & MASK_PROTOTYPE)
|
||||
#define TARGET_TOC (target_flags & (MASK_64BIT \
|
||||
| MASK_RELOCATABLE \
|
||||
| MASK_MINIMAL_TOC))
|
||||
|
||||
#define TARGET_BITFIELD_TYPE (! TARGET_NO_BITFIELD_TYPE)
|
||||
#define TARGET_TRACEBACK (! TARGET_NO_TRACEBACK)
|
||||
#define TARGET_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN)
|
||||
#define TARGET_TOC (! TARGET_NO_TOC)
|
||||
#define TARGET_NO_AIX_CALLS (! TARGET_AIX_CALLS)
|
||||
#define TARGET_NO_PROTOTYPE (! TARGET_PROTOTYPE)
|
||||
#define TARGET_NO_TOC (! TARGET_TOC)
|
||||
|
||||
#define TARGET_V4_CALLS TARGET_NO_AIX_CALLS
|
||||
|
||||
/* Pseudo target to indicate whether the object format is ELF
|
||||
(to get around not having conditional compilation in the md file) */
|
||||
#define TARGET_ELF 1
|
||||
|
||||
/* Note, V.4 no longer uses a normal TOC, so make -mfull-toc, be just
|
||||
the same as -mminimal-toc. */
|
||||
#undef SUBTARGET_SWITCHES
|
||||
#define SUBTARGET_SWITCHES \
|
||||
{ "bit-align", -MASK_NO_BITFIELD_TYPE }, \
|
||||
|
@ -55,8 +70,13 @@ Boston, MA 02111-1307, USA. */
|
|||
{ "little", MASK_LITTLE_ENDIAN }, \
|
||||
{ "big-endian", -MASK_LITTLE_ENDIAN }, \
|
||||
{ "big", -MASK_LITTLE_ENDIAN }, \
|
||||
{ "no-toc", MASK_NO_TOC | MASK_MINIMAL_TOC }, \
|
||||
{ "toc", -MASK_NO_TOC },
|
||||
{ "no-toc", 0 }, \
|
||||
{ "toc", MASK_MINIMAL_TOC }, \
|
||||
{ "full-toc", MASK_MINIMAL_TOC }, \
|
||||
{ "call-aix", MASK_AIX_CALLS }, \
|
||||
{ "call-sysv", -MASK_AIX_CALLS }, \
|
||||
{ "prototype", MASK_PROTOTYPE }, \
|
||||
{ "no-prototype", -MASK_PROTOTYPE },
|
||||
|
||||
/* Sometimes certain combinations of command options do not make sense
|
||||
on a particular target machine. You can define a macro
|
||||
|
@ -69,22 +89,10 @@ Boston, MA 02111-1307, USA. */
|
|||
|
||||
#define SUBTARGET_OVERRIDE_OPTIONS \
|
||||
do { \
|
||||
if (TARGET_RELOCATABLE && TARGET_NO_TOC) \
|
||||
{ \
|
||||
target_flags &= ~ MASK_NO_TOC; \
|
||||
error ("-mrelocatable and -mno-toc are incompatible."); \
|
||||
} \
|
||||
\
|
||||
if (TARGET_RELOCATABLE && !TARGET_MINIMAL_TOC) \
|
||||
{ \
|
||||
target_flags |= MASK_MINIMAL_TOC; \
|
||||
error ("-mrelocatable and -mno-minimal-toc are incompatible."); \
|
||||
} \
|
||||
\
|
||||
if (TARGET_NO_TOC && !TARGET_MINIMAL_TOC) \
|
||||
{ \
|
||||
target_flags |= MASK_MINIMAL_TOC; \
|
||||
error ("-mno-toc and -mno-minimal-toc are incompatible."); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
@ -96,12 +104,38 @@ do { \
|
|||
#undef FIXED_R13
|
||||
#define FIXED_R13 1
|
||||
|
||||
/* System V.4 passes the first 8 floating arguments in registers,
|
||||
instead of the first 13 like AIX does. */
|
||||
#undef FP_ARG_MAX_REG
|
||||
#define FP_ARG_AIX_MAX_REG 45
|
||||
#define FP_ARG_V4_MAX_REG 40
|
||||
#define FP_ARG_MAX_REG ((TARGET_AIX_CALLS) ? FP_ARG_AIX_MAX_REG : FP_ARG_V4_MAX_REG)
|
||||
|
||||
/* Size of the V.4 varargs area if needed */
|
||||
#undef RS6000_VARARGS_AREA
|
||||
#define RS6000_VARARGS_AREA ((rs6000_sysv_varargs_p) ? RS6000_VARARGS_SIZE : 0)
|
||||
|
||||
/* Override default big endianism */
|
||||
#undef BYTES_BIG_ENDIAN
|
||||
#undef WORDS_BIG_ENDIAN
|
||||
#define BYTES_BIG_ENDIAN (TARGET_BIG_ENDIAN)
|
||||
#define WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN)
|
||||
|
||||
/* Size of the outgoing register save area */
|
||||
#undef RS6000_REG_SAVE
|
||||
#define RS6000_REG_SAVE (TARGET_AIX_CALLS ? (TARGET_64BIT ? 64 : 32) : 0)
|
||||
|
||||
/* Size of the fixed area on the stack. For AIX, use the standard 6 word
|
||||
area, otherwise use 2 words to store back chain & LR. */
|
||||
#undef RS6000_SAVE_AREA
|
||||
#define RS6000_SAVE_AREA \
|
||||
((TARGET_AIX_CALLS ? 24 : 8) << (TARGET_64BIT ? 1 : 0))
|
||||
|
||||
/* Define cutoff for using external functions to save floating point.
|
||||
Currently on V.4, always use inline stores */
|
||||
#undef FP_SAVE_INLINE
|
||||
#define FP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) < 64)
|
||||
|
||||
/* Don't generate XCOFF debugging information. */
|
||||
|
||||
#undef XCOFF_DEBUGGING_INFO
|
||||
|
@ -192,37 +226,14 @@ toc_section () \
|
|||
\
|
||||
if (in_section != in_toc) \
|
||||
{ \
|
||||
in_section = in_toc; \
|
||||
fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP); \
|
||||
if (! toc_initialized) \
|
||||
{ \
|
||||
if (!TARGET_RELOCATABLE && !TARGET_NO_TOC) \
|
||||
fprintf (asm_out_file, "%s\n", TOC_SECTION_ASM_OP); \
|
||||
\
|
||||
if (TARGET_MINIMAL_TOC) \
|
||||
{ \
|
||||
if (!TARGET_RELOCATABLE && !TARGET_NO_TOC) \
|
||||
{ \
|
||||
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LCTOC", 0); \
|
||||
fprintf (asm_out_file, "\t.tc "); \
|
||||
ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1[TC],"); \
|
||||
ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1"); \
|
||||
fprintf (asm_out_file, "\n"); \
|
||||
} \
|
||||
\
|
||||
fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP); \
|
||||
ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1"); \
|
||||
fprintf (asm_out_file, " = .+32768\n"); \
|
||||
} \
|
||||
\
|
||||
ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1"); \
|
||||
fprintf (asm_out_file, " = .+32768\n"); \
|
||||
toc_initialized = 1; \
|
||||
} \
|
||||
\
|
||||
else \
|
||||
fprintf (asm_out_file, "%s\n", \
|
||||
(TARGET_MINIMAL_TOC \
|
||||
? MINIMAL_TOC_SECTION_ASM_OP \
|
||||
: TOC_SECTION_ASM_OP)); \
|
||||
\
|
||||
in_section = in_toc; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
@ -342,7 +353,78 @@ while (0)
|
|||
|
||||
#undef TARGET_VERSION
|
||||
#define TARGET_VERSION fprintf (stderr, " (PowerPC System V.4)");
|
||||
|
||||
|
||||
/* Output assembler code for a block containing the constant parts
|
||||
of a trampoline, leaving space for the variable parts.
|
||||
|
||||
The trampoline should set the static chain pointer to value placed
|
||||
into the trampoline and should branch to the specified routine.
|
||||
|
||||
Unlike AIX, this needs real code. */
|
||||
|
||||
#undef TRAMPOLINE_TEMPLATE
|
||||
#define TRAMPOLINE_TEMPLATE(FILE) \
|
||||
do { \
|
||||
char *sc = reg_names[STATIC_CHAIN_REGNUM]; \
|
||||
char *r0 = reg_names[0]; \
|
||||
\
|
||||
if (STATIC_CHAIN_REGNUM == 0 || !TARGET_NEW_MNEMONICS) \
|
||||
abort (); \
|
||||
\
|
||||
if (TARGET_64BIT) \
|
||||
{ \
|
||||
fprintf (FILE, "\tmflr %s\n", r0); /* offset 0 */ \
|
||||
fprintf (FILE, "\tbl .LTRAMP1\n"); /* offset 4 */ \
|
||||
fprintf (FILE, "\t.long 0,0,0,0\n"); /* offset 8 */ \
|
||||
fprintf (FILE, ".LTRAMP1:\n"); \
|
||||
fprintf (FILE, "\tmflr %s\n", sc); /* offset 28 */ \
|
||||
fprintf (FILE, "\tmtlr %s\n", r0); /* offset 32 */ \
|
||||
fprintf (FILE, "\tld %s,0(%s)\n", r0, sc); /* offset 36 */ \
|
||||
fprintf (FILE, "\tld %s,8(%s)\n", sc, sc); /* offset 40 */ \
|
||||
fprintf (FILE, "\tmtctr %s\n", r0); /* offset 44 */ \
|
||||
fprintf (FILE, "\tbctr\n"); /* offset 48 */ \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
fprintf (FILE, "\tmflr %s\n", r0); /* offset 0 */ \
|
||||
fprintf (FILE, "\tbl .LTRAMP1\n"); /* offset 4 */ \
|
||||
fprintf (FILE, "\t.long 0,0\n"); /* offset 8 */ \
|
||||
fprintf (FILE, ".LTRAMP1:\n"); \
|
||||
fprintf (FILE, "\tmflr %s\n", sc); /* offset 20 */ \
|
||||
fprintf (FILE, "\tmtlr %s\n", r0); /* offset 24 */ \
|
||||
fprintf (FILE, "\tlwz %s,0(%s)\n", r0, sc); /* offset 28 */ \
|
||||
fprintf (FILE, "\tlwz %s,4(%s)\n", sc, sc); /* offset 32 */ \
|
||||
fprintf (FILE, "\tmtctr %s\n", r0); /* offset 36 */ \
|
||||
fprintf (FILE, "\tbctr\n"); /* offset 40 */ \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Length in units of the trampoline for entering a nested function. */
|
||||
|
||||
#undef TRAMPOLINE_SIZE
|
||||
#define TRAMPOLINE_SIZE (TARGET_64BIT ? 52 : 44)
|
||||
|
||||
/* Emit RTL insns to initialize the variable parts of a trampoline.
|
||||
FNADDR is an RTX for the address of the function's pure code.
|
||||
CXT is an RTX for the static chain value for the function. */
|
||||
|
||||
#undef INITIALIZE_TRAMPOLINE
|
||||
#define INITIALIZE_TRAMPOLINE(ADDR, FNADDR, CXT) \
|
||||
{ \
|
||||
rtx reg = gen_reg_rtx (Pmode); \
|
||||
\
|
||||
emit_move_insn (reg, FNADDR); \
|
||||
emit_move_insn (gen_rtx (MEM, Pmode, \
|
||||
plus_constant (ADDR, 8)), \
|
||||
reg); \
|
||||
emit_move_insn (gen_rtx (MEM, Pmode, \
|
||||
plus_constant (ADDR, (TARGET_64BIT ? 16 : 12))), \
|
||||
CXT); \
|
||||
emit_insn (gen_sync (gen_rtx (MEM, BLKmode, ADDR))); \
|
||||
}
|
||||
|
||||
|
||||
#undef CPP_PREDEFINES
|
||||
#define CPP_PREDEFINES \
|
||||
"-DPPC -Dunix -D__svr4__ -Asystem(unix) -Asystem(svr4) -Acpu(powerpc) -Amachine(powerpc)"
|
||||
|
@ -382,6 +464,8 @@ while (0)
|
|||
#define CPP_SPEC "\
|
||||
%{posix: -D_POSIX_SOURCE} \
|
||||
%{mrelocatable: -D_RELOCATABLE} \
|
||||
%{mcall-sysv: -D_CALL_SYSV} %{mcall-aix: -D_CALL_AIX} %{!mcall-sysv: %{!mcall-aix: -D_CALL_SYSV}} \
|
||||
%{msoft-float: -D_SOFT_FLOAT} %{mcpu=403: -D_SOFT_FLOAT} \
|
||||
%{mlittle: -D_LITTLE_ENDIAN -Amachine(littleendian)} \
|
||||
%{mlittle-endian: -D_LITTLE_ENDIAN -Amachine(littleendian)} \
|
||||
%{!mlittle: %{!mlittle-endian: -D_BIG_ENDIAN -Amachine(bigendian)}} \
|
||||
|
|
|
@ -29,6 +29,8 @@ Boston, MA 02111-1307, USA. */
|
|||
#define CPP_SPEC "\
|
||||
%{posix: -D_POSIX_SOURCE} \
|
||||
%{mrelocatable: -D_RELOCATABLE} \
|
||||
%{mcall-sysv: -D_CALL_SYSV} %{mcall-aix: -D_CALL_AIX} %{!mcall-sysv: %{!mcall-aix: -D_CALL_SYSV}} \
|
||||
%{msoft-float: -D_SOFT_FLOAT} %{mcpu=403: -D_SOFT_FLOAT} \
|
||||
%{mbig: -D_BIG_ENDIAN -Amachine(bigendian)} \
|
||||
%{mbig-endian: -D_BIG_ENDIAN -Amachine(bigendian)} \
|
||||
%{!mbig: %{!mbig-endian: -D_LITTLE_ENDIAN -Amachine(littleendian)}} \
|
||||
|
|
|
@ -16,15 +16,12 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
|
|||
# Build libgcc.a with different options.
|
||||
|
||||
MULTILIB_OPTIONS = msoft-float \
|
||||
mno-toc \
|
||||
mlittle/mbig
|
||||
mlittle
|
||||
|
||||
MULTILIB_DIRNAMES = soft-float \
|
||||
no-toc \
|
||||
little-endian big-endian
|
||||
little-endian
|
||||
|
||||
MULTILIB_MATCHES = mlittle=mlittle-endian \
|
||||
mbig=mbig-endian \
|
||||
msoft-float=mcpu?403 \
|
||||
msoft-float=mcpu?mpc403 \
|
||||
msoft-float=mcpu?ppc403
|
||||
|
|
|
@ -15,8 +15,8 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
|
|||
|
||||
# Build the libraries for both hard and soft floating point
|
||||
|
||||
MULTILIB_OPTIONS = msoft-float
|
||||
MULTILIB_DIRNAMES = soft-float
|
||||
MULTILIB_OPTIONS = msoft-float mcpu=common
|
||||
MULTILIB_DIRNAMES = soft-float common
|
||||
|
||||
LIBGCC = stmp-multilib
|
||||
INSTALL_LIBGCC = install-multilib
|
||||
|
|
Loading…
Reference in New Issue