--- gcc/config/rs6000/rs6000.h 2018/04/24 18:10:26 1.1 +++ gcc/config/rs6000/rs6000.h 2018/04/24 18:22:48 1.1.1.3 @@ -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 Free Software Foundation, Inc. + Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) This file is part of GNU CC. @@ -25,7 +25,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 +41,34 @@ the Free Software Foundation, 675 Mass A /* #define ASM_SPEC "-u" */ +/* Define appropriate architecture macros for preprocessor depending on + target switches. */ + +#define CPP_SPEC "\ +%{!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=601: -D_ARCH_PPC -D_ARCH_PWR} \ +%{mcpu=mpc601: -D_ARCH_PPC -D_ARCH_PWR} \ +%{mcpu=ppc601: -D_ARCH_PPC -D_ARCH_PWR} \ +%{mcpu=603: -D_ARCH_PPC} \ +%{mcpu=mpc603: -D_ARCH_PPC} \ +%{mcpu=ppc603: -D_ARCH_PPC} \ +%{mcpu=604: -D_ARCH_PPC} \ +%{mcpu=mpc604: -D_ARCH_PPC} \ +%{mcpu=ppc604: -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. @@ -50,8 +79,8 @@ the Free Software Foundation, 675 Mass A -bnodelcsect undoes a poor choice of default relating to multiply-defined csects. See AIX documentation for more information about this. */ -#define LINK_SPEC "-T512 -H512 -btextro -bhalt:4 -bnodelcsect\ - %{static:-bnso -bI:/lib/syscalls.exp}" +#define LINK_SPEC "-T512 -H512 %{!r:-btextro} -bhalt:4 -bnodelcsect\ + %{static:-bnso -bI:/lib/syscalls.exp} %{g*:-bexport:/usr/lib/libg.exp}" /* Profiled library versions are used by linking with special directories. */ #define LIB_SPEC "%{pg:-L/lib/profiled -L/usr/lib/profiled}\ @@ -63,45 +92,154 @@ the Free Software Foundation, 675 Mass A /* 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 + +/* 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 -/* Flag to allow putting fp constants in the TOC; can be turned off when +/* 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 + +#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) -extern int target_flags; +/* Run-time compilation parameters selecting different hardware subsets. -/* Macro to define tables used to set the flags. + 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 - -/* On the RS/6000, we turn on various flags if optimization is selected. */ - -#define OPTIMIZATION_OPTIONS(LEVEL) \ -{ \ - if ((LEVEL) > 0) \ - { \ - flag_force_mem = 1; \ - flag_omit_frame_pointer = 1; \ - } \ -} +#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_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}, \ + {"", TARGET_DEFAULT}} + +#define TARGET_DEFAULT MASK_POWER + +/* Processor type. */ +enum processor_type + {PROCESSOR_RIOS1, + PROCESSOR_RIOS2, + 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 this to modify the options specified by the user. */ + On the RS/6000 this is used to define the target cpu type. */ -#define OVERRIDE_OPTIONS \ -{ \ - profile_block_flag = 0; \ -} +#define OVERRIDE_OPTIONS rs6000_override_options () + +/* Show we can debug even without a frame pointer. */ +#define CAN_DEBUG_WITHOUT_FP /* target machine storage layout */ @@ -300,15 +438,19 @@ extern int target_flags; : ((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) == 2 * UNITS_PER_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 +478,10 @@ 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) \ + && ((CLASS2) == SPECIAL_REGS || (CLASS2) == MQ_REGS \ + || (CLASS2) == LINK_REGS || (CLASS2) == CTR_REGS)) ? 10 \ : 2) /* A C expressions returning the cost of moving data of MODE from a register to @@ -343,7 +489,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 +511,15 @@ 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. */ + +#define CONDITIONAL_REGISTER_USAGE \ + if (!TARGET_POWER) \ + fixed_regs[64] = 1; /* Specify the registers used for certain standard purposes. The values of these macros are register numbers. */ @@ -525,6 +682,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' ? GET_CODE (OP) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (OP)\ : 0) /* Given an rtx X being reloaded into a reg required to be @@ -547,6 +705,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. @@ -556,6 +720,11 @@ enum reg_class { NO_REGS, BASE_REGS, GEN ((CLASS) == FLOAT_REGS \ ? ((GET_MODE_SIZE (MODE) + 2 * UNITS_PER_WORD - 1) / (2 * UNITS_PER_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. */ @@ -799,7 +968,7 @@ struct rs6000_args {int words, fregno, n gen_rtx (MEM, BLKmode, \ plus_constant (virtual_incoming_args_rtx, \ first_reg_offset * 4)), \ - 8 - first_reg_offset); \ + 8 - first_reg_offset, (8 - first_reg_offset) * UNITS_PER_WORD); \ PRETEND_SIZE = (8 - first_reg_offset) * UNITS_PER_WORD; \ } \ } @@ -884,7 +1053,12 @@ struct rs6000_args {int words, fregno, n 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,17 +1067,22 @@ 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 -mmininal-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 \ : 1) /* Define the offset between two registers, one to be eliminated, and the other @@ -931,6 +1110,8 @@ struct rs6000_args {int words, fregno, n else \ (OFFSET) = 0; \ } \ + else if ((FROM) == 30) \ + (OFFSET) = 0; \ else \ abort (); \ } @@ -1154,7 +1335,7 @@ struct rs6000_args {int words, fregno, n } /* 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) */ @@ -1190,9 +1371,15 @@ struct rs6000_args {int words, fregno, n 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 @@ -1237,9 +1424,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. */ @@ -1266,10 +1457,22 @@ 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_PPC604: \ + case PROCESSOR_PPC620: \ + return COSTS_N_INSNS (4); \ + } \ case DIV: \ case MOD: \ if (GET_CODE (XEXP (X, 1)) == CONST_INT \ @@ -1278,7 +1481,20 @@ 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_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 MEM: \ /* MEM should be slightly more expensive than (plus (reg) (const)) */ \ return 5; @@ -1337,6 +1553,11 @@ 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" /* Control the assembler format that we output. */ @@ -1344,6 +1565,8 @@ extern int rs6000_trunc_used; 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. @@ -1362,6 +1585,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 +1634,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 +1689,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 +1731,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 +1745,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) \ @@ -1512,7 +1765,8 @@ toc_section () \ || (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 \ + || (! (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)) @@ -1549,11 +1803,13 @@ 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_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,13 +1828,16 @@ toc_section () \ /* This outputs NAME to FILE up to the first null or '['. */ #define RS6000_OUTPUT_BASENAME(FILE, NAME) \ - if ((NAME)[0] == '*') \ + if ((NAME)[0] == '*' || (NAME)[strlen (NAME) - 1] != ']') \ assemble_name (FILE, NAME); \ else \ { \ - char *_p; \ - for (_p = (NAME); *_p && *_p != '['; _p++) \ - fputc (*_p, FILE); \ + int _len = strlen (NAME); \ + char *_p = alloca (_len + 1); \ + \ + strcpy (_p, NAME); \ + _p[_len - 4] = '\0'; \ + assemble_name (FILE, _p); \ } /* Output something to declare an external symbol to the assembler. Most @@ -1631,7 +1890,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 +1939,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 +1968,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 +1991,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. */ @@ -1763,25 +2063,39 @@ toc_section () \ It need not be very fast code. */ #define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ - fprintf (FILE, "\tstu %s,-4(r1)\n", reg_names[REGNO]); + asm_fprintf (FILE, "\{tstu|stwu} %s,-4(r1)\n", reg_names[REGNO]); /* 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]) + asm_fprintf (FILE, "\t{l|lwz} %s,0(r1)\n\t{ai|addic} r1,r1,4\n", \ + reg_names[REGNO]) /* 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 +2156,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. */ @@ -1872,8 +2186,11 @@ 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}},