--- gcc/config/rs6000/rs6000.h 2018/04/24 18:10:26 1.1.1.1 +++ 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 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" +#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,63 +74,239 @@ 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. -#define LINK_SPEC "-T512 -H512 -btextro -bhalt:4 -bnodelcsect\ - %{static:-bnso -bI:/lib/syscalls.exp}" + -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} \ + %{!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 -/* Run-time compilation parameters selecting different hardware subsets. */ +/* Architecture type. */ + +extern int target_flags; + +/* Use POWER architecture instructions and MQ register. */ +#define MASK_POWER 0x01 + +/* Use POWER2 extensions to POWER architecture. */ +#define MASK_POWER2 0x02 + +/* Use PowerPC architecture instructions. */ +#define MASK_POWERPC 0x04 + +/* Use PowerPC General Purpose group optional instructions, e.g. fsqrt. */ +#define MASK_PPC_GPOPT 0x08 -/* Flag to allow putting fp constants in the TOC; can be turned off when +/* Use PowerPC Graphics group optional instructions, e.g. fsel. */ +#define MASK_PPC_GFXOPT 0x10 + +/* Use PowerPC-64 architecture instructions. */ +#define MASK_POWERPC64 0x20 + +/* Use revised mnemonic names defined for PowerPC architecture. */ +#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 0x80 + +/* Disable placing symbol+offset constants in the TOC; can be turned on when the TOC overflows. */ +#define MASK_NO_SUM_IN_TOC 0x100 -#define TARGET_FP_IN_TOC (target_flags & 1) +/* Output only one TOC entry per module. Normally linking fails if + there are more than 16K unique variables/constants in an executable. With + this option, linking fails only if there are more than 16K modules, or + if there are more than 16K unique variables/constant in a single module. + + 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 0x200 + +/* Nonzero for the 64bit model: ints, longs, and pointers are 64 bits. */ +#define MASK_64BIT 0x400 + +/* 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 -extern int target_flags; +/* 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 -/* Macro to define tables used to set the flags. +/* Run-time compilation parameters selecting different hardware subsets. + + Macro to define tables used to set the flags. This is a list in braces of pairs in braces, each pair being { "NAME", VALUE } 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 \ - {{"fp-in-toc", 1}, \ - {"no-fp-in-toc", -1}, \ - { "", TARGET_DEFAULT}} - -#define TARGET_DEFAULT 1 +/* This is meant to be redefined in the host dependent files */ +#ifndef SUBTARGET_SWITCHES +#define SUBTARGET_SWITCHES +#endif -/* On the RS/6000, we turn on various flags if optimization is selected. */ +#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 | MASK_MULTIPLE | MASK_STRING) + +/* Processor type. */ +enum processor_type + {PROCESSOR_RIOS1, + PROCESSOR_RIOS2, + PROCESSOR_PPC403, + PROCESSOR_PPC601, + PROCESSOR_PPC603, + PROCESSOR_PPC604, + PROCESSOR_PPC620}; + +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 + +/* Specify the dialect of assembler to use. New mnemonics is dialect one + and the old mnemonics are dialect zero. */ +#define ASSEMBLER_DIALECT TARGET_NEW_MNEMONICS ? 1 : 0 + +/* This macro is similar to `TARGET_SWITCHES' but defines names of + command options that have values. Its definition is an + initializer with a subgrouping for each command option. + + Each subgrouping contains a string constant, that defines the + fixed part of the option name, and the address of a variable. + The variable, type `char *', is set to the variable part of the + given option if the fixed part matches. The actual option name + is made by appending `-m' to the specified name. + + Here is an example which defines `-mshort-data-NUMBER'. If the + given option is `-mshort-data-512', the variable `m88k_short_data' + will be set to the string `"512"'. + + extern char *m88k_short_data; + #define TARGET_OPTIONS { { "short-data-", &m88k_short_data } } */ + +#define TARGET_OPTIONS \ +{ {"cpu=", &rs6000_cpu_string}} + +extern char *rs6000_cpu_string; + +/* Sometimes certain combinations of command options do not make sense + on a particular target machine. You can define a macro + `OVERRIDE_OPTIONS' to take account of this. This macro, if + defined, is executed once just after all the command options have + been parsed. -#define OPTIMIZATION_OPTIONS(LEVEL) \ -{ \ - if ((LEVEL) > 0) \ - { \ - flag_force_mem = 1; \ - flag_omit_frame_pointer = 1; \ - } \ -} + On the RS/6000 this is used to define the target cpu type. */ -/* Define this to modify the options specified by the user. */ +#define OVERRIDE_OPTIONS rs6000_override_options () -#define OVERRIDE_OPTIONS \ -{ \ - profile_block_flag = 0; \ -} +/* 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 @@ -139,10 +341,13 @@ extern int target_flags; 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" @@ -153,12 +358,56 @@ extern int target_flags; /* 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 @@ -167,7 +416,7 @@ extern int target_flags; #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 @@ -217,10 +466,16 @@ extern int target_flags; 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, \ @@ -234,7 +489,7 @@ extern int target_flags; 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, \ @@ -296,19 +551,23 @@ extern int target_flags; #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 \ + : ! 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 @@ -336,6 +595,12 @@ extern int target_flags; ((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 @@ -343,7 +608,11 @@ extern int target_flags; 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. @@ -361,8 +630,21 @@ extern int target_flags; 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, RSC, and PPC601) so that it will not be allocated. + Conditionally disable FPRs. */ + +#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. */ @@ -525,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 @@ -547,6 +830,12 @@ enum reg_class { NO_REGS, BASE_REGS, GEN #define SECONDARY_RELOAD_CLASS(CLASS,MODE,IN) \ secondary_reload_class (CLASS, MODE, IN) +/* If we are copying between FP registers and anything else, we need a memory + location. */ + +#define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE) \ + ((CLASS1) != (CLASS2) && ((CLASS1) == FLOAT_REGS || (CLASS2) == FLOAT_REGS)) + /* Return the maximum number of consecutive registers needed to represent mode MODE in a register of class CLASS. @@ -554,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 @@ -572,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 @@ -581,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. @@ -591,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. */ @@ -605,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 @@ -614,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). @@ -626,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. @@ -646,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 @@ -668,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. */ @@ -686,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, @@ -743,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. @@ -782,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); \ - 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. @@ -879,12 +1237,47 @@ 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 frame pointer register can often be eliminated in favor of the stack pointer register. Secondly, the argument pointer register can always be - eliminated; it is replaced with either the stack or frame pointer. */ + eliminated; it is replaced with either the stack or frame pointer. + + In addition, we use the elimination mechanism to see if r30 is needed + Initially we assume that it isn't. If it is, we spill it. This is done + by making it an eliminable register. We replace it with itself so that + if it isn't needed, then existing uses won't be modified. */ /* This is an array of structures. Each structure initializes one pair of eliminable registers. The "from" register number is given first, @@ -893,44 +1286,38 @@ struct rs6000_args {int words, fregno, n #define ELIMINABLE_REGS \ {{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ - { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM} } + { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ + { 30, 30} } /* Given FROM and TO register numbers, say whether this elimination is allowed. Frame pointer elimination is automatically handled. For the RS/6000, if frame pointer elimination is being done, we would like - to convert ap into fp, not sp. */ + to convert ap into fp, not sp. + + 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 || 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 \ abort (); \ } @@ -1032,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)))) @@ -1065,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; \ @@ -1079,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 @@ -1106,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) @@ -1151,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) */ @@ -1183,16 +1598,23 @@ 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 is undesirable. */ #define SLOW_BYTE_ACCESS 1 -/* Define if normal loads of shorter-than-word items from memory clears - the rest of the bigs in the register. */ -#define BYTE_LOADS_ZERO_EXTEND +/* Define if operations between registers always perform the operation + on the full register even if a narrower mode is specified. */ +#define WORD_REGISTER_OPERATIONS + +/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD + will either zero-extend or sign-extend. The value of this macro should + be the code that says which one of the two operations is implicitly + done, NIL if none. */ +#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND /* Define if loading short immediate values into registers sign extends. */ #define SHORT_IMMEDIATES_SIGN_EXTEND @@ -1216,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. */ @@ -1224,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. @@ -1237,9 +1661,13 @@ struct rs6000_args {int words, fregno, n but a CALL with constant address is cheap. */ #define NO_FUNCTION_CSE -/* Define this if shift instructions ignore all but the low-order - few bits. */ -#define SHIFT_COUNT_TRUNCATED +/* Define this to be nonzero if shift instructions ignore all but the low-order + few bits. + + 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) /* Use atexit for static constructors/destructors, instead of defining our own exit function. */ @@ -1250,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 @@ -1266,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 \ @@ -1278,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; @@ -1337,13 +1796,39 @@ 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. + Specify filename to assembler. + We want to go into the TOC section so at least one .toc will be emitted. Also, in order to output proper .bs/.es pairs, we need at least one static [RW] section emitted. @@ -1355,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, \ @@ -1362,6 +1848,7 @@ extern int rs6000_trunc_used; rs6000_gen_section_name (&xcoff_read_only_section_name, \ main_input_filename, ".ro_"); \ \ + output_file_directive (FILE, main_input_filename); \ toc_section (); \ if (write_symbols != NO_DEBUG) \ private_data_section (); \ @@ -1410,6 +1897,16 @@ extern int rs6000_trunc_used; #define READONLY_DATA_SECTION read_only_data_section +/* If we are referencing a function that is static or is known to be + in this file, make the SYMBOL_REF special. We can use this to indicate + that we can branch to this function without emitting a no-op after the + call. */ + +#define ENCODE_SECTION_INFO(DECL) \ + if (TREE_CODE (DECL) == FUNCTION_DECL \ + && (TREE_ASM_WRITTEN (DECL) || ! TREE_PUBLIC (DECL))) \ + SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1; + /* Indicate that jump tables go in the text section. */ #define JUMP_TABLES_IN_TEXT_SECTION @@ -1455,9 +1952,28 @@ read_only_private_data_section () \ void \ toc_section () \ { \ - if (in_section != toc) \ - fprintf (asm_out_file, ".toc\n"); \ + if (TARGET_MINIMAL_TOC) \ + { \ + static int toc_initialized = 0; \ + \ + /* toc_section is always called at least once from ASM_FILE_START, \ + so this is guaranteed to always be defined once and only once \ + in each file. */ \ + if (! toc_initialized) \ + { \ + fprintf (asm_out_file, ".toc\nLCTOC..0:\n"); \ + fprintf (asm_out_file, "\t.tc toc_table[TC],toc_table[RW]\n"); \ + toc_initialized = 1; \ + } \ \ + if (in_section != toc) \ + fprintf (asm_out_file, ".csect toc_table[RW]\n"); \ + } \ + else \ + { \ + if (in_section != toc) \ + fprintf (asm_out_file, ".toc\n"); \ + } \ in_section = toc; \ } @@ -1478,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); \ @@ -1492,7 +2008,7 @@ toc_section () \ fprintf (FILE, "\t.long ."); \ RS6000_OUTPUT_BASENAME (FILE, NAME); \ fprintf (FILE, ", TOC[tc0], 0\n"); \ - fprintf (FILE, ".csect [PR]\n."); \ + fprintf (FILE, ".csect .text[PR]\n."); \ RS6000_OUTPUT_BASENAME (FILE, NAME); \ fprintf (FILE, ":\n"); \ if (write_symbols == XCOFF_DEBUG) \ @@ -1507,14 +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_FP_IN_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. @@ -1549,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 (); \ @@ -1572,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. @@ -1631,7 +2173,7 @@ toc_section () \ /* Output before instructions. */ -#define TEXT_SECTION_ASM_OP ".csect [PR]" +#define TEXT_SECTION_ASM_OP ".csect .text[PR]" /* Output before writable data. */ @@ -1680,6 +2222,10 @@ toc_section () \ #define DBX_REGISTER_NUMBER(REGNO) (REGNO) +/* Text to write out after a CALL that may be replaced by glue code by + the loader. This depends on the AIX version. */ +#define RS6000_CALL_GLUE "cror 31,31,31" + /* This is how to output the definition of a user-level label named NAME, such as the label on a static function or variable NAME. */ @@ -1705,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. */ @@ -1722,13 +2274,44 @@ toc_section () \ /* This is how to output an assembler line defining a `double' constant. */ -#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ - fprintf (FILE, "\t.double 0d%.20e\n", (VALUE)) +#define ASM_OUTPUT_DOUBLE(FILE, VALUE) \ + { \ + if (REAL_VALUE_ISINF (VALUE) \ + || REAL_VALUE_ISNAN (VALUE) \ + || REAL_VALUE_MINUS_ZERO (VALUE)) \ + { \ + long t[2]; \ + REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t); \ + fprintf (FILE, "\t.long 0x%lx\n\t.long 0x%lx\n", \ + t[0] & 0xffffffff, t[1] & 0xffffffff); \ + } \ + else \ + { \ + char str[30]; \ + REAL_VALUE_TO_DECIMAL (VALUE, "%.20e", str); \ + fprintf (FILE, "\t.double 0d%s\n", str); \ + } \ + } /* This is how to output an assembler line defining a `float' constant. */ -#define ASM_OUTPUT_FLOAT(FILE,VALUE) \ - fprintf (FILE, "\t.float 0d%.20e\n", (VALUE)) +#define ASM_OUTPUT_FLOAT(FILE, VALUE) \ + { \ + if (REAL_VALUE_ISINF (VALUE) \ + || REAL_VALUE_ISNAN (VALUE) \ + || REAL_VALUE_MINUS_ZERO (VALUE)) \ + { \ + long t; \ + REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \ + fprintf (FILE, "\t.long 0x%lx\n", t & 0xffffffff); \ + } \ + else \ + { \ + char str[30]; \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \ + fprintf (FILE, "\t.float 0d%s\n", str); \ + } \ + } /* This is how to output an assembler line defining an `int' constant. */ @@ -1762,26 +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) \ - fprintf (FILE, "\tstu %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) \ - fprintf (FILE, "\tl %s,0(r1)\n\tai 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 @@ -1842,7 +2447,7 @@ toc_section () \ /* Define which CODE values are valid. */ -#define PRINT_OPERAND_PUNCT_VALID_P(CODE) 0 +#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '.' || (CODE) == '*') /* Print a memory address as an operand to reference that memory location. */ @@ -1862,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}}, \ @@ -1872,8 +2479,79 @@ toc_section () \ {"non_logical_cint_operand", {CONST_INT}}, \ {"mask_operand", {CONST_INT}}, \ {"call_operand", {SYMBOL_REF, REG}}, \ - {"input_operand", {SUBREG, MEM, REG, CONST_INT}}, \ - {"branch_comparison_operation", {EQ, NE, LE, LT, GE, \ - LT, LEU, LTU, GEU, GTU}}, \ - {"scc_comparison_operation", {EQ, NE, LE, LT, GE, \ - LT, LEU, LTU, GEU, GTU}}, + {"current_file_function_operand", {SYMBOL_REF}}, \ + {"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 ();