--- gcc/config/rs6000/rs6000.h 2018/04/24 18:16:36 1.1.1.2 +++ gcc/config/rs6000/rs6000.h 2018/04/24 18:30:32 1.1.1.4 @@ -1,6 +1,6 @@ /* Definitions of target machine for GNU compiler, for IBM RS/6000. - Copyright (C) 1992, 1993 Free Software Foundation, Inc. - Contributed by Richard Kenner (kenner@nyu.edu) + Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) This file is part of GNU CC. @@ -16,7 +16,8 @@ GNU General Public License for more deta 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ /* Note that some other tm.h files include this one and then override @@ -25,7 +26,8 @@ the Free Software Foundation, 675 Mass A /* Names to predefine in the preprocessor for this target machine. */ -#define CPP_PREDEFINES "-D_IBMR2 -D_AIX -D_AIX32 -Asystem(unix) -Asystem(aix) -Acpu(rs6000) -Amachine(rs6000)" +#define CPP_PREDEFINES "-D_IBMR2 -D_POWER -D_AIX -D_AIX32 \ +-Asystem(unix) -Asystem(aix) -Acpu(rs6000) -Amachine(rs6000)" /* Print subsidiary information on the compiler version in use. */ #define TARGET_VERSION ; @@ -40,6 +42,30 @@ the Free Software Foundation, 675 Mass A /* #define ASM_SPEC "-u" */ +/* Define appropriate architecture macros for preprocessor depending on + target switches. */ + +#define CPP_SPEC "\ +%{posix: -D_POSIX_SOURCE} \ +%{!mcpu*: \ + %{mpower: %{!mpower2: -D_ARCH_PWR}} \ + %{mpower2: -D_ARCH_PWR2} \ + %{mpowerpc*: -D_ARCH_PPC} \ + %{mno-power: %{!mpowerpc*: -D_ARCH_COM}} \ + %{!mno-power: %{!mpower2: -D_ARCH_PWR}}} \ +%{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}" + /* Define the options for the binder: Start text at 512, align all segments to 512 bytes, and warn if there is text relocation. @@ -48,17 +74,22 @@ the Free Software Foundation, 675 Mass A 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. */ + 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. */ #define LINK_SPEC "-T512 -H512 %{!r:-btextro} -bhalt:4 -bnodelcsect\ - %{static:-bnso -bI:/lib/syscalls.exp} %{g*:-bexport:/usr/lib/libg.exp}" + %{static:-bnso -bI:/lib/syscalls.exp} \ + %{!shared:%{g*:-bexport:/usr/lib/libg.exp}} %{shared:-bM:SRE}" /* Profiled library versions are used by linking with special directories. */ #define LIB_SPEC "%{pg:-L/lib/profiled -L/usr/lib/profiled}\ - %{p:-L/lib/profiled -L/usr/lib/profiled} %{g*:-lg} -lc" + %{p:-L/lib/profiled -L/usr/lib/profiled} %{!shared:%{g*:-lg}} -lc" /* gcc must do the search itself to find libgcc.a, not use -l. */ -#define LINK_LIBGCC_SPECIAL_1 +#define LIBGCC_SPEC "libgcc.a%s" /* Don't turn -B into -L if the argument specifies a relative file name. */ #define RELATIVE_PREFIX_NOT_LINKDIR @@ -76,18 +107,25 @@ extern int target_flags; /* Use PowerPC architecture instructions. */ #define MASK_POWERPC 0x04 -/* Use PowerPC square root instructions. */ -#define MASK_POWERPCSQR 0x08 +/* Use PowerPC General Purpose group optional instructions, e.g. fsqrt. */ +#define MASK_PPC_GPOPT 0x08 + +/* Use PowerPC Graphics group optional instructions, e.g. fsel. */ +#define MASK_PPC_GFXOPT 0x10 /* Use PowerPC-64 architecture instructions. */ -#define MASK_POWERPC64 0x10 +#define MASK_POWERPC64 0x20 /* Use revised mnemonic names defined for PowerPC architecture. */ -#define MASK_NEW_MNEMONICS 0x20 +#define MASK_NEW_MNEMONICS 0x40 /* Disable placing fp constants in the TOC; can be turned on when the TOC overflows. */ -#define MASK_NO_FP_IN_TOC 0x40 +#define MASK_NO_FP_IN_TOC 0x80 + +/* Disable placing symbol+offset constants in the TOC; can be turned on when + the TOC overflows. */ +#define MASK_NO_SUM_IN_TOC 0x100 /* Output only one TOC entry per module. Normally linking fails if there are more than 16K unique variables/constants in an executable. With @@ -96,16 +134,58 @@ extern int target_flags; This is at the cost of having 2 extra loads and one extra store per function, and one less allocatable register. */ -#define MASK_MINIMAL_TOC 0x80 +#define MASK_MINIMAL_TOC 0x200 + +/* Nonzero for the 64bit model: ints, longs, and pointers are 64 bits. */ +#define MASK_64BIT 0x400 -#define TARGET_POWER (target_flags & MASK_POWER) -#define TARGET_POWER2 (target_flags & MASK_POWER2) -#define TARGET_POWERPC (target_flags & MASK_POWERPC) -#define TARGET_POWERPCSQR (target_flags & MASK_POWERPCSQR) -#define TARGET_POWERPC64 (target_flags & MASK_POWERPC64) -#define TARGET_NEW_MNEMONICS (target_flags & MASK_NEW_MNEMONICS) -#define TARGET_NO_FP_IN_TOC (target_flags & MASK_NO_FP_IN_TOC) -#define TARGET_MINIMAL_TOC (target_flags & MASK_MINIMAL_TOC) +/* Disable use of FPRs. */ +#define MASK_SOFT_FLOAT 0x800 + +/* Enable load/store multiple, even on powerpc */ +#define MASK_MULTIPLE 0x1000 +#define MASK_MULTIPLE_SET 0x2000 + +/* Use string instructions for block moves */ +#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) +#define TARGET_PPC_GPOPT (target_flags & MASK_PPC_GPOPT) +#define TARGET_PPC_GFXOPT (target_flags & MASK_PPC_GFXOPT) +#define TARGET_POWERPC64 (target_flags & MASK_POWERPC64) +#define TARGET_NEW_MNEMONICS (target_flags & MASK_NEW_MNEMONICS) +#define TARGET_NO_FP_IN_TOC (target_flags & MASK_NO_FP_IN_TOC) +#define TARGET_NO_SUM_IN_TOC (target_flags & MASK_NO_SUM_IN_TOC) +#define TARGET_MINIMAL_TOC (target_flags & MASK_MINIMAL_TOC) +#define TARGET_64BIT (target_flags & MASK_64BIT) +#define TARGET_SOFT_FLOAT (target_flags & MASK_SOFT_FLOAT) +#define TARGET_MULTIPLE (target_flags & MASK_MULTIPLE) +#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. @@ -115,32 +195,56 @@ extern int target_flags; where VALUE is the bits to set or minus the bits to clear. An empty string NAME is used to identify the default VALUE. */ -#define TARGET_SWITCHES \ - {{"power", MASK_POWER}, \ - {"power2", MASK_POWER | MASK_POWER2}, \ - {"no-power2", - MASK_POWER2}, \ - {"no-power", - (MASK_POWER | MASK_POWER2)}, \ - {"powerpc", MASK_POWERPC}, \ - {"no-powerpc", - (MASK_POWERPC | MASK_POWERPCSQR | MASK_POWERPC64)}, \ - {"powerpc-sqr", MASK_POWERPC | MASK_POWERPCSQR}, \ - {"no-powerpc-sqr", - MASK_POWERPCSQR}, \ - {"powerpc64", MASK_POWERPC | MASK_POWERPC64}, \ - {"no-powerpc64", -MASK_POWERPC64}, \ - {"new-mnemonics", MASK_NEW_MNEMONICS}, \ - {"old-mnemonics", -MASK_NEW_MNEMONICS}, \ - {"normal-toc", - (MASK_NO_FP_IN_TOC | MASK_MINIMAL_TOC)}, \ - {"fp-in-toc", - MASK_NO_FP_IN_TOC}, \ - {"no-fp-in-toc", MASK_NO_FP_IN_TOC}, \ - {"minimal-toc", MASK_MINIMAL_TOC}, \ - {"no-minimal-toc", - MASK_MINIMAL_TOC}, \ +/* This is meant to be redefined in the host dependent files */ +#ifndef SUBTARGET_SWITCHES +#define SUBTARGET_SWITCHES +#endif + +#define TARGET_SWITCHES \ + {{"power", MASK_POWER | MASK_MULTIPLE | MASK_STRING}, \ + {"power2", (MASK_POWER | MASK_MULTIPLE | MASK_STRING \ + | MASK_POWER2)}, \ + {"no-power2", - MASK_POWER2}, \ + {"no-power", - (MASK_POWER | MASK_POWER2 | MASK_MULTIPLE \ + | MASK_STRING)}, \ + {"powerpc", MASK_POWERPC}, \ + {"no-powerpc", - (MASK_POWERPC | MASK_PPC_GPOPT \ + | MASK_PPC_GFXOPT | MASK_POWERPC64)}, \ + {"powerpc-gpopt", MASK_POWERPC | MASK_PPC_GPOPT}, \ + {"no-powerpc-gpopt", - MASK_PPC_GPOPT}, \ + {"powerpc-gfxopt", MASK_POWERPC | MASK_PPC_GFXOPT}, \ + {"no-powerpc-gfxopt", - MASK_PPC_GFXOPT}, \ + {"new-mnemonics", MASK_NEW_MNEMONICS}, \ + {"old-mnemonics", -MASK_NEW_MNEMONICS}, \ + {"full-toc", - (MASK_NO_FP_IN_TOC | MASK_NO_SUM_IN_TOC \ + | MASK_MINIMAL_TOC)}, \ + {"fp-in-toc", - MASK_NO_FP_IN_TOC}, \ + {"no-fp-in-toc", MASK_NO_FP_IN_TOC}, \ + {"sum-in-toc", - MASK_NO_SUM_IN_TOC}, \ + {"no-sum-in-toc", MASK_NO_SUM_IN_TOC}, \ + {"minimal-toc", MASK_MINIMAL_TOC}, \ + {"minimal-toc", - (MASK_NO_FP_IN_TOC | MASK_NO_SUM_IN_TOC)}, \ + {"no-minimal-toc", - MASK_MINIMAL_TOC}, \ + {"hard-float", - MASK_SOFT_FLOAT}, \ + {"soft-float", MASK_SOFT_FLOAT}, \ + {"multiple", MASK_MULTIPLE | MASK_MULTIPLE_SET}, \ + {"no-multiple", - MASK_MULTIPLE}, \ + {"no-multiple", MASK_MULTIPLE_SET}, \ + {"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}} -#define TARGET_DEFAULT MASK_POWER +#define TARGET_DEFAULT (MASK_POWER | MASK_MULTIPLE | MASK_STRING) /* Processor type. */ enum processor_type {PROCESSOR_RIOS1, PROCESSOR_RIOS2, + PROCESSOR_PPC403, PROCESSOR_PPC601, PROCESSOR_PPC603, PROCESSOR_PPC604, @@ -151,6 +255,11 @@ extern enum processor_type rs6000_cpu; /* Recast the processor type to the cpu attribute. */ #define rs6000_cpu_attr ((enum attr_cpu)rs6000_cpu) +/* Define generic processor types based upon current deployment. */ +#define PROCESSOR_COMMON PROCESSOR_PPC601 +#define PROCESSOR_POWER PROCESSOR_RIOS1 +#define PROCESSOR_POWERPC PROCESSOR_PPC601 + /* Define the default processor. This is overridden by other tm.h files. */ #define PROCESSOR_DEFAULT PROCESSOR_RIOS1 @@ -190,17 +299,14 @@ extern char *rs6000_cpu_string; #define OVERRIDE_OPTIONS rs6000_override_options () -#define OPTIMIZATION_OPTIONS(LEVEL) \ -{ \ - if ((LEVEL) > 0) \ - { \ - flag_force_mem = 1; \ - flag_omit_frame_pointer = 1; \ - } \ -} +/* Show we can debug even without a frame pointer. */ +#define CAN_DEBUG_WITHOUT_FP /* target machine storage layout */ +/* Define to support cross compilation to an RS6000 target. */ +#define REAL_ARITHMETIC + /* Define this macro if it is advisable to hold scalars in registers in a wider mode than that declared by the program. In such cases, the value is constrained to be within the bounds of the declared @@ -235,10 +341,13 @@ extern char *rs6000_cpu_string; Note that this is not necessarily the width of data type `int'; if using 16-bit ints on a 68000, this would still be 32. But on a machine with 16-bit registers, this would be 16. */ -#define BITS_PER_WORD 32 +#define BITS_PER_WORD (TARGET_POWERPC64 ? 64 : 32) +#define MAX_BITS_PER_WORD 64 /* Width of a word, in units (bytes). */ -#define UNITS_PER_WORD 4 +#define UNITS_PER_WORD (TARGET_POWERPC64 ? 8 : 4) +#define MIN_UNITS_PER_WORD 4 +#define UNITS_PER_FP_WORD 8 /* Type used for ptrdiff_t, as a string used in a declaration. */ #define PTRDIFF_TYPE "int" @@ -249,12 +358,56 @@ extern char *rs6000_cpu_string; /* Width of wchar_t in bits. */ #define WCHAR_TYPE_SIZE 16 +/* A C expression for the size in bits of the type `short' on the + target machine. If you don't define this, the default is half a + word. (If this would be less than one storage unit, it is + rounded up to one unit.) */ +#define SHORT_TYPE_SIZE 16 + +/* A C expression for the size in bits of the type `int' on the + target machine. If you don't define this, the default is one + word. */ +#define INT_TYPE_SIZE (TARGET_64BIT ? 64 : 32) +#define MAX_INT_TYPE_SIZE 64 + +/* A C expression for the size in bits of the type `long' on the + target machine. If you don't define this, the default is one + word. */ +#define LONG_TYPE_SIZE (TARGET_64BIT ? 64 : 32) +#define MAX_LONG_TYPE_SIZE 64 + +/* A C expression for the size in bits of the type `long long' on the + target machine. If you don't define this, the default is two + words. */ +#define LONG_LONG_TYPE_SIZE 64 + +/* A C expression for the size in bits of the type `char' on the + target machine. If you don't define this, the default is one + quarter of a word. (If this would be less than one storage unit, + it is rounded up to one unit.) */ +#define CHAR_TYPE_SIZE BITS_PER_UNIT + +/* A C expression for the size in bits of the type `float' on the + target machine. If you don't define this, the default is one + word. */ +#define FLOAT_TYPE_SIZE 32 + +/* A C expression for the size in bits of the type `double' on the + target machine. If you don't define this, the default is two + words. */ +#define DOUBLE_TYPE_SIZE 64 + +/* A C expression for the size in bits of the type `long double' on + the target machine. If you don't define this, the default is two + words. */ +#define LONG_DOUBLE_TYPE_SIZE 64 + /* Width in bits of a pointer. See also the macro `Pmode' defined below. */ -#define POINTER_SIZE 32 +#define POINTER_SIZE (TARGET_64BIT ? 64 : 32) /* Allocation boundary (in *bits*) for storing arguments in argument list. */ -#define PARM_BOUNDARY 32 +#define PARM_BOUNDARY (TARGET_64BIT ? 64 : 32) /* Boundary (in *bits*) on which stack pointer should be aligned. */ #define STACK_BOUNDARY 64 @@ -263,7 +416,7 @@ extern char *rs6000_cpu_string; #define FUNCTION_BOUNDARY 32 /* No data type wants to be aligned rounder than this. */ -#define BIGGEST_ALIGNMENT 32 +#define BIGGEST_ALIGNMENT (TARGET_64BIT ? 64 : 32) /* Alignment of field after `int : 0' in a structure. */ #define EMPTY_FIELD_BOUNDARY 32 @@ -313,10 +466,16 @@ extern char *rs6000_cpu_string; On RS/6000, r1 is used for the stack and r2 is used as the TOC pointer. - cr5 is not supposed to be used. */ + cr5 is not supposed to be used. + + On System V implementations, r13 is fixed and not available for use. */ + +#ifndef FIXED_R13 +#define FIXED_R13 0 +#endif #define FIXED_REGISTERS \ - {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FIXED_R13, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ @@ -330,7 +489,7 @@ extern char *rs6000_cpu_string; Aside from that, you can include as many other registers as you like. */ #define CALL_USED_REGISTERS \ - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, \ + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, FIXED_R13, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ @@ -392,20 +551,23 @@ extern char *rs6000_cpu_string; #define HARD_REGNO_NREGS(REGNO, MODE) \ (FP_REGNO_P (REGNO) \ - ? ((GET_MODE_SIZE (MODE) + 2 * UNITS_PER_WORD - 1) / (2 * UNITS_PER_WORD)) \ + ? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \ : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. - On RS/6000, the cpu registers can hold any mode but the float registers - can hold only floating modes and CR register can only hold CC modes. We - cannot put DImode or TImode anywhere except general register and they - must be able to fit within the register set. */ + For POWER and PowerPC, the GPRs can hold any mode, but the float + registers only can hold floating modes and DImode, and CR register only + can hold CC modes. We cannot put TImode anywhere except general + register and it must be able to fit within the register set. */ #define HARD_REGNO_MODE_OK(REGNO, MODE) \ - (FP_REGNO_P (REGNO) ? GET_MODE_CLASS (MODE) == MODE_FLOAT \ + (FP_REGNO_P (REGNO) ? \ + (GET_MODE_CLASS (MODE) == MODE_FLOAT \ + || (GET_MODE_CLASS (MODE) == MODE_INT \ + && GET_MODE_SIZE (MODE) == UNITS_PER_FP_WORD)) \ : CR_REGNO_P (REGNO) ? GET_MODE_CLASS (MODE) == MODE_CC \ - : ! INT_REGNO_P (REGNO) ? (GET_MODE_CLASS (MODE) == MODE_INT \ - && GET_MODE_SIZE (MODE) <= UNITS_PER_WORD) \ + : ! INT_REGNO_P (REGNO) ? (GET_MODE_CLASS (MODE) == MODE_INT \ + && GET_MODE_SIZE (MODE) <= UNITS_PER_WORD) \ : 1) /* Value is 1 if it is a good idea to tie two pseudo registers @@ -433,6 +595,12 @@ extern char *rs6000_cpu_string; ((CLASS1) == FLOAT_REGS && (CLASS2) == FLOAT_REGS ? 2 \ : (CLASS1) == FLOAT_REGS && (CLASS2) != FLOAT_REGS ? 10 \ : (CLASS1) != FLOAT_REGS && (CLASS2) == FLOAT_REGS ? 10 \ + : (((CLASS1) == SPECIAL_REGS || (CLASS1) == MQ_REGS \ + || (CLASS1) == LINK_REGS || (CLASS1) == CTR_REGS \ + || (CLASS1) == LINK_OR_CTR_REGS) \ + && ((CLASS2) == SPECIAL_REGS || (CLASS2) == MQ_REGS \ + || (CLASS2) == LINK_REGS || (CLASS2) == CTR_REGS \ + || (CLASS2) == LINK_OR_CTR_REGS)) ? 10 \ : 2) /* A C expressions returning the cost of moving data of MODE from a register to @@ -440,7 +608,11 @@ extern char *rs6000_cpu_string; On the RS/6000, bump this up a bit. */ -#define MEMORY_MOVE_COST(MODE) 6 +#define MEMORY_MOVE_COST(MODE) \ + ((GET_MODE_CLASS (MODE) == MODE_FLOAT \ + && (rs6000_cpu == PROCESSOR_RIOS1 || rs6000_cpu == PROCESSOR_PPC601) \ + ? 3 : 2) \ + + 4) /* Specify the cost of a branch insn; roughly the number of extra insns that should be added to avoid a branch. @@ -458,17 +630,21 @@ extern char *rs6000_cpu_string; a cost, but it is probably not worthwhile to track it. */ #define ADJUST_COST(INSN,LINK,DEP_INSN,COST) \ - if (REG_NOTE_KIND (LINK) != 0) \ - (COST) = 0; /* Anti or output dependence. */ + (COST) = rs6000_adjust_cost (INSN,LINK,DEP_INSN,COST) /* Define this macro to change register usage conditional on target flags. Set MQ register fixed (already call_used) if not POWER architecture - (RIOS1, RIOS2, and PPC601) so that it will not be allocated. - Provide alternate register names for ppcas assembler */ + (RIOS1, RIOS2, RSC, and PPC601) so that it will not be allocated. + Conditionally disable FPRs. */ -#define CONDITIONAL_REGISTER_USAGE \ - if (!TARGET_POWER) \ - fixed_regs[64] = 1; +#define CONDITIONAL_REGISTER_USAGE \ +{ \ + if (! TARGET_POWER) \ + fixed_regs[64] = 1; \ + if (TARGET_SOFT_FLOAT) \ + for (i = 32; i < 64; i++) \ + fixed_regs[i] = call_used_regs[i] = 1; \ +} /* Specify the registers used for certain standard purposes. The values of these macros are register numbers. */ @@ -631,6 +807,7 @@ enum reg_class { NO_REGS, BASE_REGS, GEN #define EXTRA_CONSTRAINT(OP, C) \ ((C) == 'Q' ? GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG \ + : (C) == 'R' ? LEGITIMATE_CONSTANT_POOL_ADDRESS_P (OP) \ : 0) /* Given an rtx X being reloaded into a reg required to be @@ -666,11 +843,49 @@ enum reg_class { NO_REGS, BASE_REGS, GEN except in the FP regs, where a single reg is enough for two words. */ #define CLASS_MAX_NREGS(CLASS, MODE) \ ((CLASS) == FLOAT_REGS \ - ? ((GET_MODE_SIZE (MODE) + 2 * UNITS_PER_WORD - 1) / (2 * UNITS_PER_WORD)) \ + ? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \ : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) + +/* If defined, gives a class of registers that cannot be used as the + operand of a SUBREG that changes the size of the object. */ + +#define CLASS_CANNOT_CHANGE_SIZE FLOAT_REGS /* Stack layout; function entry, exit and calling. */ +/* Enumeration to give which calling sequence to use. */ +enum rs6000_abi { + ABI_NONE, + ABI_AIX, /* IBM's AIX */ + ABI_V4 /* System V.4/eabi */ +}; + +/* 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 */ + enum rs6000_abi abi; /* which ABI to use */ + int gp_save_offset; /* offset to save GP regs from initial SP */ + int fp_save_offset; /* offset to save FP regs from initial 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 @@ -684,6 +899,29 @@ enum reg_class { NO_REGS, BASE_REGS, GEN 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 @@ -693,7 +931,9 @@ enum reg_class { NO_REGS, BASE_REGS, GEN except for dynamic allocations. So we start after the fixed area and outgoing parameter area. */ -#define STARTING_FRAME_OFFSET (current_function_outgoing_args_size + 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. @@ -703,12 +943,12 @@ enum reg_class { NO_REGS, BASE_REGS, GEN /* 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) 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) 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. */ @@ -717,7 +957,7 @@ enum reg_class { NO_REGS, BASE_REGS, GEN /* 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 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 @@ -726,11 +966,12 @@ enum reg_class { NO_REGS, BASE_REGS, GEN /* Value is the number of bytes of arguments automatically popped when returning from a subroutine call. + FUNDECL is the declaration node of the function (as a tree), FUNTYPE is the data type of the function (as a tree), or for a library call it is an identifier node for the subroutine name. SIZE is the number of bytes of arguments passed on the stack. */ -#define RETURN_POPS_ARGS(FUNTYPE,SIZE) 0 +#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 /* Define how to find the value returned by a function. VALTYPE is the data type of the value (as a tree). @@ -738,17 +979,17 @@ enum reg_class { NO_REGS, BASE_REGS, GEN otherwise, FUNC is 0. On RS/6000 an integer value is in r3 and a floating-point value is in - fp1. */ + fp1, unless -msoft-float. */ #define FUNCTION_VALUE(VALTYPE, FUNC) \ gen_rtx (REG, TYPE_MODE (VALTYPE), \ - TREE_CODE (VALTYPE) == REAL_TYPE ? 33 : 3) + TREE_CODE (VALTYPE) == REAL_TYPE && TARGET_HARD_FLOAT ? 33 : 3) /* Define how to find the value returned by a library function assuming the value has mode MODE. */ #define LIBCALL_VALUE(MODE) \ - gen_rtx (REG, MODE, GET_MODE_CLASS (MODE) == MODE_FLOAT ? 33 : 3) + gen_rtx (REG, MODE, GET_MODE_CLASS (MODE) == MODE_FLOAT && TARGET_HARD_FLOAT ? 33 : 3) /* The definition of this macro implies that there are cases where a scalar value cannot be returned in registers. @@ -758,18 +999,35 @@ enum reg_class { NO_REGS, BASE_REGS, GEN #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 @@ -780,10 +1038,21 @@ enum reg_class { NO_REGS, BASE_REGS, GEN 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. */ @@ -798,40 +1067,27 @@ struct rs6000_args {int words, fregno, n 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) +#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, @@ -855,30 +1111,24 @@ struct rs6000_args {int words, fregno, n 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. @@ -894,27 +1144,23 @@ struct rs6000_args {int words, fregno, n 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. @@ -991,6 +1237,36 @@ struct rs6000_args {int words, fregno, n force_reg (SImode, (CXT))); \ } +/* Definitions for __builtin_return_address and __builtin_frame_address. + __builtin_return_address (0) should give link register (65), enable + this. */ +/* This should be uncommented, so that the link register is used, but + currently this would result in unmatched insns and spilling fixed + registers so we'll leave it for another day. When these problems are + taken care of one additional fetch will be necessary in RETURN_ADDR_RTX. + (mrs) */ +/* #define RETURN_ADDR_IN_PREVIOUS_FRAME */ + +/* Number of bytes into the frame return addresses can be found. */ +#ifndef TARGET_V4_CALLS +#define RETURN_ADDRESS_OFFSET 8 +#else +#define RETURN_ADDRESS_OFFSET \ + ((TARGET_V4_CALLS) ? (TARGET_64BIT ? 8 : 4) : 8) +#endif + +/* The current return address is in link register (65). The return address + of anything farther back is accessed normally at an offset of 8 from the + frame pointer. */ +#define RETURN_ADDR_RTX(count, frame) \ + ((count == -1) \ + ? gen_rtx (REG, Pmode, 65) \ + : gen_rtx (MEM, Pmode, \ + memory_address (Pmode, \ + plus_constant (copy_to_reg (gen_rtx (MEM, Pmode, \ + memory_address (Pmode, frame))), \ + RETURN_ADDRESS_OFFSET)))) + /* Definitions for register eliminations. We have two registers that can be eliminated on the RS/6000. First, the @@ -1019,40 +1295,27 @@ struct rs6000_args {int words, fregno, n For the RS/6000, if frame pointer elimination is being done, we would like to convert ap into fp, not sp. - We need r30 if -mmininal-toc was specified, and there are constant pool + We need r30 if -mminimal-toc was specified, and there are constant pool references. */ #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 \ @@ -1156,12 +1419,14 @@ struct rs6000_args {int words, fregno, n 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)))) @@ -1189,6 +1454,16 @@ struct rs6000_args {int words, fregno, n #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; \ @@ -1203,8 +1478,11 @@ struct rs6000_args {int words, fregno, n if (LEGITIMATE_OFFSET_ADDRESS_P (MODE, X)) \ goto ADDR; \ if ((MODE) != DImode && (MODE) != TImode \ + && (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 @@ -1230,31 +1508,42 @@ struct rs6000_args {int words, fregno, n 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 \ - && (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) @@ -1275,10 +1564,12 @@ struct rs6000_args {int words, fregno, n 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 - emitting code for an insn. */ + emitting code for an insn. */ /* #define FINAL_PRESCAN_INSN(INSN,OPERANDS,NOPERANDS) */ @@ -1307,7 +1598,8 @@ struct rs6000_args {int words, fregno, n /* Max number of bytes we can move from memory to memory in one reasonably fast instruction. */ -#define MOVE_MAX 16 +#define MOVE_MAX (TARGET_POWERPC64 ? 8 : 4) +#define MAX_MOVE_MAX 8 /* Nonzero if access to memory by bytes is no faster than for words. Also non-zero if doing byte operations (specifically shifts) in registers @@ -1346,6 +1638,8 @@ struct rs6000_args {int words, fregno, n .stabs in cc1plus. */ #define FASCIST_ASSEMBLER +#define ASM_OUTPUT_CONSTRUCTOR(file, name) +#define ASM_OUTPUT_DESTRUCTOR(file, name) /* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits is done just by pretending it is already truncated. */ @@ -1354,12 +1648,12 @@ struct rs6000_args {int words, fregno, n /* Specify the machine mode that pointers have. After generation of rtl, the compiler makes no further distinction between pointers and any other objects of this machine mode. */ -#define Pmode SImode +#define Pmode (TARGET_64BIT ? DImode : SImode) /* Mode of a function address in a call instruction (for indexing purposes). Doesn't matter on RS/6000. */ -#define FUNCTION_MODE SImode +#define FUNCTION_MODE (TARGET_64BIT ? DImode : SImode) /* Define this if addresses of constant functions shouldn't be put through pseudo regs where they can be cse'd. @@ -1373,7 +1667,7 @@ struct rs6000_args {int words, fregno, n 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. */ @@ -1384,15 +1678,16 @@ struct rs6000_args {int words, fregno, n of a switch statement. If the code is computed here, return it with a return statement. Otherwise, break from the switch. - On the RS/6000, if it is legal in the insn, it is free. So this + 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 @@ -1400,10 +1695,23 @@ struct rs6000_args {int words, fregno, n #define RTX_COSTS(X,CODE,OUTER_CODE) \ case MULT: \ - return (GET_CODE (XEXP (X, 1)) != CONST_INT \ - ? COSTS_N_INSNS (5) \ - : INTVAL (XEXP (X, 1)) >= -256 && INTVAL (XEXP (X, 1)) <= 255 \ - ? COSTS_N_INSNS (3) : COSTS_N_INSNS (4)); \ + switch (rs6000_cpu) \ + { \ + case PROCESSOR_RIOS1: \ + return (GET_CODE (XEXP (X, 1)) != CONST_INT \ + ? COSTS_N_INSNS (5) \ + : INTVAL (XEXP (X, 1)) >= -256 && INTVAL (XEXP (X, 1)) <= 255 \ + ? COSTS_N_INSNS (3) : COSTS_N_INSNS (4)); \ + case PROCESSOR_RIOS2: \ + return COSTS_N_INSNS (2); \ + case PROCESSOR_PPC601: \ + case PROCESSOR_PPC603: \ + return COSTS_N_INSNS (5); \ + case PROCESSOR_PPC403: \ + case PROCESSOR_PPC604: \ + case PROCESSOR_PPC620: \ + return COSTS_N_INSNS (4); \ + } \ case DIV: \ case MOD: \ if (GET_CODE (XEXP (X, 1)) == CONST_INT \ @@ -1412,7 +1720,24 @@ struct rs6000_args {int words, fregno, n /* otherwise fall through to normal divide. */ \ case UDIV: \ case UMOD: \ - return COSTS_N_INSNS (19); \ + switch (rs6000_cpu) \ + { \ + case PROCESSOR_RIOS1: \ + return COSTS_N_INSNS (19); \ + case PROCESSOR_RIOS2: \ + return COSTS_N_INSNS (13); \ + case PROCESSOR_PPC403: \ + return COSTS_N_INSNS (33); \ + case PROCESSOR_PPC601: \ + return COSTS_N_INSNS (36); \ + case PROCESSOR_PPC603: \ + return COSTS_N_INSNS (37); \ + case PROCESSOR_PPC604: \ + case PROCESSOR_PPC620: \ + return COSTS_N_INSNS (20); \ + } \ + case FFS: \ + return COSTS_N_INSNS (4); \ case MEM: \ /* MEM should be slightly more expensive than (plus (reg) (const)) */ \ return 5; @@ -1471,9 +1796,33 @@ extern int rs6000_compare_fp_p; uitrunc must be defined. */ extern int rs6000_trunc_used; + +/* Function names to call to do floating point truncation. */ + +#define RS6000_ITRUNC "itrunc" +#define RS6000_UITRUNC "uitrunc" + +/* Prefix and suffix to use to saving floating point */ +#ifndef SAVE_FP_PREFIX +#define SAVE_FP_PREFIX "._savef" +#define SAVE_FP_SUFFIX "" +#endif + +/* Prefix and suffix to use to restoring floating point */ +#ifndef RESTORE_FP_PREFIX +#define RESTORE_FP_PREFIX "._restf" +#define RESTORE_FP_SUFFIX "" +#endif + /* Control the assembler format that we output. */ +/* Common macro to output the options used to the asm file. */ +#define ASM_OUTPUT_OPTIONS(FILE) \ + output_options (FILE, \ + f_options, sizeof (f_options) / sizeof (f_options[0]), \ + W_options, sizeof (W_options) / sizeof (W_options[0])) \ + /* Output at beginning of assembler file. Initialize the section names for the RS/6000 at this point. @@ -1491,6 +1840,7 @@ extern int rs6000_trunc_used; #define ASM_FILE_START(FILE) \ { \ + ASM_OUTPUT_OPTIONS (FILE); \ rs6000_gen_section_name (&xcoff_bss_section_name, \ main_input_filename, ".bss_"); \ rs6000_gen_section_name (&xcoff_private_data_section_name, \ @@ -1644,7 +1994,7 @@ toc_section () \ RS6000_OUTPUT_BASENAME (FILE, NAME); \ fprintf (FILE, "\n"); \ } \ - else if (write_symbols == XCOFF_DEBUG) \ + else \ { \ fprintf (FILE, "\t.lglobl ."); \ RS6000_OUTPUT_BASENAME (FILE, NAME); \ @@ -1658,7 +2008,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) \ @@ -1673,15 +2023,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. @@ -1716,11 +2067,14 @@ toc_section () \ #define SELECT_SECTION(EXP,RELOC) \ { \ - if ((TREE_READONLY (EXP) \ - || (TREE_CODE (EXP) == STRING_CST \ - && !flag_writable_strings)) \ - && ! TREE_THIS_VOLATILE (EXP) \ - && ! (RELOC)) \ + if ((TREE_CODE (EXP) == STRING_CST \ + && !flag_writable_strings) \ + || (TREE_CODE_CLASS (TREE_CODE (EXP)) == 'd' \ + && TREE_READONLY (EXP) && ! TREE_THIS_VOLATILE (EXP) \ + && DECL_INITIAL (EXP) \ + && (DECL_INITIAL (EXP) == error_mark_node \ + || TREE_CONSTANT (DECL_INITIAL (EXP))) \ + && ! (RELOC))) \ { \ if (TREE_PUBLIC (EXP)) \ read_only_data_section (); \ @@ -1739,14 +2093,35 @@ toc_section () \ /* This outputs NAME to FILE up to the first null or '['. */ #define RS6000_OUTPUT_BASENAME(FILE, NAME) \ - if ((NAME)[0] == '*') \ - assemble_name (FILE, NAME); \ - else \ - { \ - char *_p; \ - for (_p = (NAME); *_p && *_p != '['; _p++) \ - fputc (*_p, FILE); \ - } + { \ + char *_p; \ + \ + STRIP_NAME_ENCODING (_p, (NAME)); \ + assemble_name ((FILE), _p); \ + } + +/* Remove any trailing [DS] or the like from the symbol name. */ + +#define STRIP_NAME_ENCODING(VAR,NAME) \ + do \ + { \ + char *_name = (NAME); \ + if (_name[0] == '*') \ + (VAR) = _name+1; \ + else \ + { \ + int _len = strlen (_name); \ + if (_name[_len - 1] != ']') \ + (VAR) = _name; \ + else \ + { \ + (VAR) = (char *) alloca (_len + 1); \ + strcpy ((VAR), _name); \ + (VAR)[_len - 4] = '\0'; \ + } \ + } \ + } \ + while (0) /* Output something to declare an external symbol to the assembler. Most assemblers don't need this. @@ -1876,6 +2251,12 @@ toc_section () \ #define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ fprintf (FILE, "%s..%d:\n", PREFIX, NUM) +/* This is how to output an internal label prefix. rs6000.c uses this + when generating traceback tables. */ + +#define ASM_OUTPUT_INTERNAL_LABEL_PREFIX(FILE,PREFIX) \ + fprintf (FILE, "%s..", PREFIX) + /* This is how to output a label for a jump table. Arguments are the same as for ASM_OUTPUT_INTERNAL_LABEL, except the insn for the jump table is passed. */ @@ -1964,27 +2345,48 @@ 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 anyway.) */ -#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ - fprintf (FILE, "\t.long L..%d\n", VALUE) +#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ + do { char buf[100]; \ + fprintf (FILE, "\t.long "); \ + ASM_GENERATE_INTERNAL_LABEL (buf, "L", VALUE); \ + assemble_name (FILE, buf); \ + fprintf (FILE, "\n"); \ + } while (0) /* This is how to output an element of a case-vector that is relative. */ #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ - fprintf (FILE, "\t.long L..%d-L..%d\n", VALUE, REL) + do { char buf[100]; \ + fprintf (FILE, "\t.long "); \ + ASM_GENERATE_INTERNAL_LABEL (buf, "L", VALUE); \ + assemble_name (FILE, buf); \ + fprintf (FILE, "-"); \ + ASM_GENERATE_INTERNAL_LABEL (buf, "L", REL); \ + assemble_name (FILE, buf); \ + fprintf (FILE, "\n"); \ + } while (0) /* This is how to output an assembler line that says to advance the location counter @@ -2045,7 +2447,7 @@ toc_section () \ /* Define which CODE values are valid. */ -#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '.') +#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '.' || (CODE) == '*') /* Print a memory address as an operand to reference that memory location. */ @@ -2065,6 +2467,8 @@ toc_section () \ {"reg_or_cint_operand", {SUBREG, REG, CONST_INT}}, \ {"easy_fp_constant", {CONST_DOUBLE}}, \ {"reg_or_mem_operand", {SUBREG, MEM, REG}}, \ + {"lwa_operand", {SUBREG, MEM, REG}}, \ + {"offsettable_addr_operand", {REG, SUBREG, PLUS}}, \ {"fp_reg_or_mem_operand", {SUBREG, MEM, REG}}, \ {"mem_or_easy_const_operand", {SUBREG, MEM, CONST_DOUBLE}}, \ {"add_operand", {SUBREG, REG, CONST_INT}}, \ @@ -2076,10 +2480,78 @@ toc_section () \ {"mask_operand", {CONST_INT}}, \ {"call_operand", {SYMBOL_REF, REG}}, \ {"current_file_function_operand", {SYMBOL_REF}}, \ - {"input_operand", {SUBREG, MEM, REG, CONST_INT}}, \ + {"input_operand", {SUBREG, MEM, REG, CONST_INT, SYMBOL_REF}}, \ {"load_multiple_operation", {PARALLEL}}, \ {"store_multiple_operation", {PARALLEL}}, \ {"branch_comparison_operator", {EQ, NE, LE, LT, GE, \ GT, LEU, LTU, GEU, GTU}}, \ {"scc_comparison_operator", {EQ, NE, LE, LT, GE, \ GT, LEU, LTU, GEU, GTU}}, + +/* Declare functions in rs6000.c */ +extern void output_options (); +extern void rs6000_override_options (); +extern struct rtx_def *rs6000_float_const (); +extern struct rtx_def *rs6000_immed_double_const (); +extern int direct_return (); +extern int any_operand (); +extern int short_cint_operand (); +extern int u_short_cint_operand (); +extern int non_short_cint_operand (); +extern int gpc_reg_operand (); +extern int cc_reg_operand (); +extern int reg_or_short_operand (); +extern int reg_or_neg_short_operand (); +extern int reg_or_u_short_operand (); +extern int reg_or_cint_operand (); +extern int easy_fp_constant (); +extern int volatile_mem_operand (); +extern int offsettable_addr_operand (); +extern int fp_reg_or_mem_operand (); +extern int mem_or_easy_const_operand (); +extern int add_operand (); +extern int non_add_cint_operand (); +extern int logical_operand (); +extern int non_logical_operand (); +extern int mask_constant (); +extern int mask_operand (); +extern int and_operand (); +extern int non_and_cint_operand (); +extern int reg_or_mem_operand (); +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 struct rtx_def *rs6000_stack_temp (); +extern int expand_block_move (); +extern int load_multiple_operation (); +extern int store_multiple_operation (); +extern int branch_comparison_operator (); +extern int scc_comparison_operator (); +extern int includes_lshift_p (); +extern int includes_rshift_p (); +extern int registers_ok_for_quad_peep (); +extern int addrs_ok_for_quad_peep (); +extern enum reg_class secondary_reload_class (); +extern int ccr_bit (); +extern void print_operand (); +extern void print_operand_address (); +extern int first_reg_to_save (); +extern int first_fp_reg_to_save (); +extern int rs6000_makes_calls (); +extern rs6000_stack_t *rs6000_stack_info (); +extern void svr4_traceback (); +extern void output_prolog (); +extern void output_epilog (); +extern void output_toc (); +extern void output_ascii (); +extern void rs6000_gen_section_name (); +extern void output_function_profiler (); +extern int rs6000_adjust_cost ();