--- gcc/config/rs6000/rs6000.h 2018/04/24 18:16:36 1.1.1.2 +++ 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, 1993 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 -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 +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. @@ -76,18 +105,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,15 +132,17 @@ 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 #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_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) /* Run-time compilation parameters selecting different hardware subsets. @@ -121,17 +159,22 @@ extern int target_flags; {"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}, \ + {"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}, \ - {"normal-toc", - (MASK_NO_FP_IN_TOC | MASK_MINIMAL_TOC)}, \ + {"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}} @@ -151,6 +194,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,14 +238,8 @@ 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 */ @@ -396,16 +438,19 @@ extern char *rs6000_cpu_string; : ((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 \ - && 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 +478,10 @@ 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) \ + && ((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 @@ -440,7 +489,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,13 +511,11 @@ 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. */ #define CONDITIONAL_REGISTER_USAGE \ if (!TARGET_POWER) \ @@ -631,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 @@ -668,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. */ @@ -1278,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) */ @@ -1400,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 \ @@ -1412,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; @@ -1471,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. */ @@ -1644,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); \ @@ -1716,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 (); \ @@ -1739,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 @@ -1876,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. */ @@ -1978,13 +2076,26 @@ toc_section () \ (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 +2156,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. */ @@ -2076,7 +2187,7 @@ 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, \