--- gcc/config/alpha/alpha.h 2018/04/24 18:16:16 1.1.1.2 +++ gcc/config/alpha/alpha.h 2018/04/24 18:30:12 1.1.1.4 @@ -1,6 +1,6 @@ /* Definitions of target machine for GNU compiler, for DEC Alpha. - Copyright (C) 1992, 1993 Free Software Foundation, Inc. - Contributed by Richard Kenner (kenner@nyu.edu) + Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) This file is part of GNU CC. @@ -16,7 +16,8 @@ GNU General Public License for more deta You should have received a copy of the GNU General Public License along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ /* Names to predefine in the preprocessor for this target machine. */ @@ -41,21 +42,36 @@ the Free Software Foundation, 675 Mass A #define SIGNED_CHAR_SPEC "%{funsigned-char:-D__CHAR_UNSIGNED__}" -/* No point in running CPP on our assembler output. */ -#define ASM_SPEC "-nocpp" - -/* Right now Alpha OSF/1 doesn't seem to have debugging libraries. */ +/* Under OSF/1, -p and -pg require -lprof1. */ -#define LIB_SPEC "%{p:-lprof1} -lc" +#define LIB_SPEC "%{p:-lprof1} %{pg:-lprof1} %{a:-lprof2} -lc" -/* Pass "-G 8" to ld because Alpha's CC does. Pass -O3 if we are optimizing, - -O1 if we are not. Pass -non_shared or -call_shared as appropriate. */ +/* Pass "-G 8" to ld because Alpha's CC does. Pass -O3 if we are + optimizing, -O1 if we are not. Pass -shared, -non_shared or + -call_shared as appropriate. Also pass -pg. */ #define LINK_SPEC \ - "-G 8 %{O*:-O3} %{!O*:-O1} %{static:-non_shared} %{!static:-call_shared}" + "-G 8 %{O*:-O3} %{!O*:-O1} %{static:-non_shared} \ + %{!static:%{shared:-shared} %{!shared:-call_shared}} %{pg} %{taso} \ + %{rpath*}" + +#define WORD_SWITCH_TAKES_ARG(STR) \ + (!strcmp (STR, "rpath") || !strcmp (STR, "include") \ + || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \ + || !strcmp (STR, "idirafter") || !strcmp (STR, "iprefix") \ + || !strcmp (STR, "iwithprefix") || !strcmp (STR, "iwithprefixbefore") \ + || !strcmp (STR, "isystem")) + +#define STARTFILE_SPEC \ + "%{!shared:%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}" /* Print subsidiary information on the compiler version in use. */ #define TARGET_VERSION +/* Default this to not be compiling for Windows/NT. */ +#ifndef WINDOWS_NT +#define WINDOWS_NT 0 +#endif + /* Define the location for the startup file on OSF/1 for Alpha. */ #define MD_STARTFILE_PREFIX "/usr/lib/cmplrs/cc/" @@ -93,10 +109,14 @@ extern int target_flags; {"no-fp-regs", -3}, \ {"alpha-as", -MASK_GAS}, \ {"gas", MASK_GAS}, \ - {"", TARGET_DEFAULT} } + {"", TARGET_DEFAULT | TARGET_CPU_DEFAULT} } #define TARGET_DEFAULT 3 +#ifndef TARGET_CPU_DEFAULT +#define TARGET_CPU_DEFAULT 0 +#endif + /* Define this macro to change register usage conditional on target flags. On the Alpha, we use this to disable the floating-point registers when @@ -104,20 +124,11 @@ extern int target_flags; #define CONDITIONAL_REGISTER_USAGE \ if (! TARGET_FPREGS) \ - for (i = 32; i < 64; i++) \ + for (i = 32; i < 63; i++) \ fixed_regs[i] = call_used_regs[i] = 1; -/* Define this to change the optimizations performed by default. */ - -#define OPTIMIZATION_OPTIONS(LEVEL) \ -{ \ - if ((LEVEL) > 0) \ - { \ - flag_force_addr = 1; \ - 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 */ @@ -281,7 +292,11 @@ extern int target_flags; Since $31 is always zero, we will use register number 31 as the argument pointer. It will never appear in the generated code because we will always be eliminating it in favor of the stack - poointer or frame pointer. */ + pointer or hardware frame pointer. + + Likewise, we use $f31 for the frame pointer, which will always + be eliminated in favor of the hardware frame pointer or the + stack pointer. */ #define FIRST_PSEUDO_REGISTER 64 @@ -321,12 +336,12 @@ extern int target_flags; $28 (likewise) $0 (likewise, but return value) $21-$16 (likewise, but input args) - $27 (procedure value) + $27 (procedure value in OSF, nonsaved in NT) $9-$14 (saved integer registers) $26 (return PC) $15 (frame pointer) $29 (global pointer) - $30, $31, $f31 (stack pointer and always zero/ap) */ + $30, $31, $f31 (stack pointer and always zero/ap & fp) */ #define REG_ALLOC_ORDER \ {33, \ @@ -381,7 +396,7 @@ extern int target_flags; #define STACK_POINTER_REGNUM 30 /* Base register for access to local variables of the function. */ -#define FRAME_POINTER_REGNUM 15 +#define HARD_FRAME_POINTER_REGNUM 15 /* Value should be nonzero if functions must have frame pointers. Zero means the frame pointer need not be set up (and parms @@ -392,6 +407,9 @@ extern int target_flags; /* Base register for access to arguments of the function. */ #define ARG_POINTER_REGNUM 31 +/* Base register for access to local variables of function. */ +#define FRAME_POINTER_REGNUM 63 + /* Register in which static-chain is passed to a function. For the Alpha, this is based on an example; the calling sequence @@ -438,14 +456,15 @@ enum reg_class { NO_REGS, GENERAL_REGS, of length N_REG_CLASSES. */ #define REG_CLASS_CONTENTS \ - { {0, 0}, {~0, 0}, {0, ~0}, {~0, ~0} } + { {0, 0}, {~0, 0x80000000}, {0, 0x7fffffff}, {~0, ~0} } /* The same information, inverted: Return the class number of the smallest class containing reg number REGNO. This could be a conditional expression or could index an array. */ -#define REGNO_REG_CLASS(REGNO) ((REGNO) >= 32 ? FLOAT_REGS : GENERAL_REGS) +#define REGNO_REG_CLASS(REGNO) \ + ((REGNO) >= 32 && (REGNO) <= 62 ? FLOAT_REGS : GENERAL_REGS) /* The class value for index registers, and the one for base regs. */ #define INDEX_REG_CLASS NO_REGS @@ -480,7 +499,9 @@ enum reg_class { NO_REGS, GENERAL_REGS, : (C) == 'J' ? (VALUE) == 0 \ : (C) == 'K' ? (unsigned HOST_WIDE_INT) ((VALUE) + 0x8000) < 0x10000 \ : (C) == 'L' ? (((VALUE) & 0xffff) == 0 \ - && (((VALUE)) >> 31 == -1 || (VALUE) >> 31 == 0)) \ + && (((VALUE)) >> 31 == -1 || (VALUE) >> 31 == 0) \ + && ((HOST_BITS_PER_WIDE_INT == 64 \ + || (unsigned) (VALUE) != 0x80000000U))) \ : (C) == 'M' ? zap_mask (VALUE) \ : (C) == 'N' ? (unsigned HOST_WIDE_INT) (~ (VALUE)) < 0x100 \ : (C) == 'O' ? (unsigned HOST_WIDE_INT) (- (VALUE)) < 0x100 \ @@ -504,10 +525,13 @@ enum reg_class { NO_REGS, GENERAL_REGS, /* Optional extra constraints for this machine. For the Alpha, `Q' means that this is a memory operand but not a - reference to an unaligned location. */ + reference to an unaligned location. + `R' is a SYMBOL_REF that has SYMBOL_REF_FLAG set or is the current + function. */ #define EXTRA_CONSTRAINT(OP, C) \ ((C) == 'Q' ? GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) != AND \ + : (C) == 'R' ? current_file_function_operand (OP, Pmode) \ : 0) /* Given an rtx X being reloaded into a reg required to be @@ -526,7 +550,8 @@ enum reg_class { NO_REGS, GENERAL_REGS, /* Loading and storing HImode or QImode values to and from memory usually requires a scratch register. The exceptions are loading QImode and HImode from an aligned address to a general register. - We also cannot load an unaligned address into an FP register. */ + We also cannot load an unaligned address or a paradoxical SUBREG into an + FP register. */ #define SECONDARY_INPUT_RELOAD_CLASS(CLASS,MODE,IN) \ (((GET_CODE (IN) == MEM \ @@ -542,6 +567,9 @@ enum reg_class { NO_REGS, GENERAL_REGS, ? GENERAL_REGS \ : ((CLASS) == FLOAT_REGS && GET_CODE (IN) == MEM \ && GET_CODE (XEXP (IN, 0)) == AND) ? GENERAL_REGS \ + : ((CLASS) == FLOAT_REGS && GET_CODE (IN) == SUBREG \ + && (GET_MODE_SIZE (GET_MODE (IN)) \ + > GET_MODE_SIZE (GET_MODE (SUBREG_REG (IN))))) ? GENERAL_REGS \ : NO_REGS) #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS,MODE,OUT) \ @@ -556,19 +584,37 @@ enum reg_class { NO_REGS, GENERAL_REGS, ? GENERAL_REGS \ : ((CLASS) == FLOAT_REGS && GET_CODE (OUT) == MEM \ && GET_CODE (XEXP (OUT, 0)) == AND) ? GENERAL_REGS \ - : NO_REGS) + : ((CLASS) == FLOAT_REGS && GET_CODE (OUT) == SUBREG \ + && (GET_MODE_SIZE (GET_MODE (OUT)) \ + > GET_MODE_SIZE (GET_MODE (SUBREG_REG (OUT))))) ? GENERAL_REGS \ + : NO_REGS) /* If we are copying between general and FP registers, we need a memory location. */ #define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE) ((CLASS1) != (CLASS2)) +/* Specify the mode to be used for memory when a secondary memory + location is needed. If MODE is floating-point, use it. Otherwise, + widen to a word like the default. This is needed because we always + store integers in FP registers in quadword format. This whole + area is very tricky! */ +#define SECONDARY_MEMORY_NEEDED_MODE(MODE) \ + (GET_MODE_CLASS (MODE) == MODE_FLOAT ? (MODE) \ + : GET_MODE_SIZE (MODE) >= 4 ? (MODE) \ + : mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (MODE), 0)) + /* Return the maximum number of consecutive registers needed to represent mode MODE in a register of class CLASS. */ #define CLASS_MAX_NREGS(CLASS, MODE) \ ((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 + /* Define the cost of moving between registers of various classes. Moving between FLOAT_REGS and anything else except float regs is expensive. In fact, we make it quite expensive because we really don't want to @@ -611,7 +657,7 @@ enum reg_class { NO_REGS, GENERAL_REGS, first local allocated. Otherwise, it is the offset to the BEGINNING of the first local allocated. */ -#define STARTING_FRAME_OFFSET current_function_outgoing_args_size +#define STARTING_FRAME_OFFSET 0 /* If we generate an insn to push BYTES bytes, this says how many the stack pointer really advances by. @@ -639,10 +685,11 @@ enum reg_class { NO_REGS, GENERAL_REGS, followed by "to". Eliminations of the same "from" register are listed in order of preference. */ -#define ELIMINABLE_REGS \ -{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ - { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ - { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}} +#define ELIMINABLE_REGS \ +{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ + { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \ + { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ + { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}} /* Given FROM and TO register numbers, say whether this elimination is allowed. Frame pointer elimination is automatically handled. @@ -652,20 +699,21 @@ enum reg_class { NO_REGS, GENERAL_REGS, #define CAN_ELIMINATE(FROM, TO) 1 +/* Round up to a multiple of 16 bytes. */ +#define ALPHA_ROUND(X) (((X) + 15) & ~ 15) + /* 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) \ -{ if ((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ - (OFFSET) = 0; \ - else \ - { \ - (OFFSET) = ((get_frame_size () + current_function_outgoing_args_size \ - + current_function_pretend_args_size \ - + alpha_sa_size () + 15) \ - & ~ 15); \ - if ((FROM) == ARG_POINTER_REGNUM) \ - (OFFSET) -= current_function_pretend_args_size; \ - } \ +{ if ((FROM) == FRAME_POINTER_REGNUM) \ + (OFFSET) = (ALPHA_ROUND (current_function_outgoing_args_size) \ + + alpha_sa_size ()); \ + else if ((FROM) == ARG_POINTER_REGNUM) \ + (OFFSET) = (ALPHA_ROUND (current_function_outgoing_args_size) \ + + alpha_sa_size () \ + + (ALPHA_ROUND (get_frame_size () \ + + current_function_pretend_args_size) \ + - current_function_pretend_args_size)); \ } /* Define this if stack space is still allocated for a parameter passed @@ -674,11 +722,12 @@ enum reg_class { NO_REGS, GENERAL_REGS, /* 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). @@ -690,12 +739,7 @@ enum reg_class { NO_REGS, GENERAL_REGS, #define FUNCTION_VALUE(VALTYPE, FUNC) \ gen_rtx (REG, \ - ((TREE_CODE (VALTYPE) == INTEGER_TYPE \ - || TREE_CODE (VALTYPE) == ENUMERAL_TYPE \ - || TREE_CODE (VALTYPE) == BOOLEAN_TYPE \ - || TREE_CODE (VALTYPE) == CHAR_TYPE \ - || TREE_CODE (VALTYPE) == POINTER_TYPE \ - || TREE_CODE (VALTYPE) == OFFSET_TYPE) \ + (INTEGRAL_MODE_P (TYPE_MODE (VALTYPE)) \ && TYPE_PRECISION (VALTYPE) < BITS_PER_WORD) \ ? word_mode : TYPE_MODE (VALTYPE), \ TARGET_FPREGS && TREE_CODE (VALTYPE) == REAL_TYPE ? 32 : 0) @@ -783,8 +827,11 @@ enum reg_class { NO_REGS, GENERAL_REGS, #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ ((CUM) < 6 && ! MUST_PASS_IN_STACK (MODE, TYPE) \ ? gen_rtx(REG, (MODE), \ - (CUM) + 16 + (TARGET_FPREGS \ - && GET_MODE_CLASS (MODE) == MODE_FLOAT) * 32) : 0) + (CUM) + 16 + ((TARGET_FPREGS \ + && (GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT \ + || GET_MODE_CLASS (MODE) == MODE_FLOAT)) \ + * 32)) \ + : 0) /* Specify the padding direction of arguments. @@ -852,6 +899,13 @@ enum reg_class { NO_REGS, GENERAL_REGS, } \ } +/* Try to output insns to set TARGET equal to the constant C if it can be + done in less than N insns. Do all computations in MODE. Returns the place + where the output has been placed if it can be done and the insns have been + emitted. If it would take more than N insns, zero is returned and no + insns and emitted. */ +extern struct rtx_def *alpha_emit_set_const (); + /* Generate necessary RTL for __builtin_saveregs(). ARGLIST is the argument list; see expr.c. */ extern struct rtx_def *alpha_builtin_saveregs (); @@ -885,10 +939,47 @@ extern char *alpha_function_name; #define FUNCTION_PROLOGUE(FILE, SIZE) output_prolog (FILE, SIZE) /* Output assembler code to FILE to increment profiler label # LABELNO - for profiling a function entry. */ + for profiling a function entry. Under OSF/1, profiling is enabled + by simply passing -pg to the assembler and linker. */ #define FUNCTION_PROFILER(FILE, LABELNO) +/* Output assembler code to FILE to initialize this source file's + basic block profiling info, if that has not already been done. + This assumes that __bb_init_func doesn't garble a1-a5. */ + +#define FUNCTION_BLOCK_PROFILER(FILE, LABELNO) \ + do { \ + ASM_OUTPUT_REG_PUSH (FILE, 16); \ + fputs ("\tlda $16,$PBX32\n", (FILE)); \ + fputs ("\tldq $26,0($16)\n", (FILE)); \ + fputs ("\tbne $26,1f\n", (FILE)); \ + fputs ("\tlda $27,__bb_init_func\n", (FILE)); \ + fputs ("\tjsr $26,($27),__bb_init_func\n", (FILE)); \ + fputs ("\tldgp $29,0($26)\n", (FILE)); \ + fputs ("1:\n", (FILE)); \ + ASM_OUTPUT_REG_POP (FILE, 16); \ + } while (0); + +/* Output assembler code to FILE to increment the entry-count for + the BLOCKNO'th basic block in this source file. */ + +#define BLOCK_PROFILER(FILE, BLOCKNO) \ + do { \ + int blockn = (BLOCKNO); \ + fputs ("\tsubq $30,16,$30\n", (FILE)); \ + fputs ("\tstq $26,0($30)\n", (FILE)); \ + fputs ("\tstq $27,8($30)\n", (FILE)); \ + fputs ("\tlda $26,$PBX34\n", (FILE)); \ + fprintf ((FILE), "\tldq $27,%d($26)\n", 8*blockn); \ + fputs ("\taddq $27,1,$27\n", (FILE)); \ + fprintf ((FILE), "\tstq $27,%d($26)\n", 8*blockn); \ + fputs ("\tldq $26,0($30)\n", (FILE)); \ + fputs ("\tldq $27,8($30)\n", (FILE)); \ + fputs ("\taddq $30,16,$30\n", (FILE)); \ + } while (0) + + /* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, the stack pointer does not matter. The value is tested only in functions that have frame pointers. @@ -994,6 +1085,20 @@ __enable_execute_stack (addr) \ if (mprotect (page, end - page, 7) < 0) \ perror ("mprotect of trampoline code"); \ } + +/* A C expression whose value is RTL representing the value of the return + address for the frame COUNT steps up from the current frame. + FRAMEADDR is the frame pointer of the COUNT frame, or the frame pointer of + the COUNT-1 frame if RETURN_ADDR_IN_PREVIOUS_FRAME} is defined. + + This definition for Alpha is broken, but is put in at the request of + Mike Stump. */ + +#define RETURN_ADDR_RTX(COUNT, FRAME) \ +((COUNT == 0 && alpha_sa_size () == 0 && 0 /* not right. */) \ + ? gen_rtx (REG, Pmode, 26) \ + : gen_rtx (MEM, Pmode, \ + memory_address (Pmode, FRAME))) /* Addressing modes, and classification of registers for them. */ @@ -1013,7 +1118,8 @@ __enable_execute_stack (addr) \ #define REGNO_OK_FOR_INDEX_P(REGNO) 0 #define REGNO_OK_FOR_BASE_P(REGNO) \ -(((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32)) +((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32 \ + || (REGNO) == 63 || reg_renumber[REGNO] == 63) /* Maximum number of registers that can appear in a valid memory address. */ #define MAX_REGS_PER_ADDRESS 1 @@ -1054,7 +1160,7 @@ __enable_execute_stack (addr) \ /* Nonzero if X is a hard reg that can be used as a base reg or if it is a pseudo reg. */ #define REG_OK_FOR_BASE_P(X) \ - (REGNO (X) < 32 || REGNO (X) >= FIRST_PSEUDO_REGISTER) + (REGNO (X) < 32 || REGNO (X) == 63 || REGNO (X) >= FIRST_PSEUDO_REGISTER) #else @@ -1075,10 +1181,6 @@ __enable_execute_stack (addr) \ forms can be surrounded with an AND that clear the low-order three bits; this is an "unaligned" access. - We also allow a SYMBOL_REF that is the name of the current function as - valid address. This is for CALL_INSNs. It cannot be used in any other - context. - First define the basic valid address. */ #define GO_IF_LEGITIMATE_SIMPLE_ADDRESS(MODE, X, ADDR) \ @@ -1096,8 +1198,6 @@ __enable_execute_stack (addr) \ /* Now accept the simple address, or, for DImode only, an AND of a simple address that turns off the low three bits. */ -extern char *current_function_name; - #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ { GO_IF_LEGITIMATE_SIMPLE_ADDRESS (MODE, X, ADDR); \ if ((MODE) == DImode \ @@ -1105,9 +1205,6 @@ extern char *current_function_name; && GET_CODE (XEXP (X, 1)) == CONST_INT \ && INTVAL (XEXP (X, 1)) == -8) \ GO_IF_LEGITIMATE_SIMPLE_ADDRESS (MODE, XEXP (X, 0), ADDR); \ - if ((MODE) == Pmode && GET_CODE (X) == SYMBOL_REF \ - && ! strcmp (XSTR (X, 0), current_function_name)) \ - goto ADDR; \ } /* Try machine-dependent ways of modifying an illegitimate address @@ -1211,8 +1308,11 @@ extern char *current_function_name; /* Define this if the tablejump instruction expects the table to contain offsets from the address of the table. - Do not define this if the table should contain absolute addresses. */ -/* #define CASE_VECTOR_PC_RELATIVE */ + Do not define this if the table should contain absolute addresses. + On the Alpha, the table is really GP-relative, not relative to the PC + of the table, but we pretend that it is PC-relative; this should be OK, + but we should try to find some better way sometime. */ +#define CASE_VECTOR_PC_RELATIVE /* Specify the tree operation to be used to convert reals to integers. */ #define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR @@ -1275,6 +1375,26 @@ extern char *current_function_name; #define FLOAT_STORE_FLAG_VALUE 0.5 +/* Canonicalize a comparison from one we don't have to one we do have. */ + +#define CANONICALIZE_COMPARISON(CODE,OP0,OP1) \ + do { \ + if (((CODE) == GE || (CODE) == GT || (CODE) == GEU || (CODE) == GTU) \ + && (GET_CODE (OP1) == REG || (OP1) == const0_rtx)) \ + { \ + rtx tem = (OP0); \ + (OP0) = (OP1); \ + (OP1) = tem; \ + (CODE) = swap_condition (CODE); \ + } \ + if (((CODE) == LT || (CODE) == LTU) \ + && GET_CODE (OP1) == CONST_INT && INTVAL (OP1) == 256) \ + { \ + (CODE) = (CODE) == LT ? LE : LEU; \ + (OP1) = GEN_INT (255); \ + } \ + } while (0) + /* 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. */ @@ -1309,25 +1429,35 @@ extern char *current_function_name; of a switch statement. If the code is computed here, return it with a return statement. Otherwise, break from the switch. - We only care about the cost if it is valid in an insn, so all constants - are cheap. */ + If this is an 8-bit constant, return zero since it can be used + nearly anywhere with no cost. If it is a valid operand for an + ADD or AND, likewise return 0 if we know it will be used in that + context. Otherwise, return 2 since it might be used there later. + All other constants take at least two insns. */ #define CONST_COSTS(RTX,CODE,OUTER_CODE) \ case CONST_INT: \ + if (INTVAL (RTX) >= 0 && INTVAL (RTX) < 256) \ + return 0; \ case CONST_DOUBLE: \ - return 0; \ + if (((OUTER_CODE) == PLUS && add_operand (RTX, VOIDmode)) \ + || ((OUTER_CODE) == AND && and_operand (RTX, VOIDmode))) \ + return 0; \ + else if (add_operand (RTX, VOIDmode) || and_operand (RTX, VOIDmode)) \ + return 2; \ + else \ + return COSTS_N_INSNS (2); \ case CONST: \ case SYMBOL_REF: \ case LABEL_REF: \ - return 6; \ + return COSTS_N_INSNS (3); /* Provide the costs of a rtl expression. This is in the body of a switch on CODE. */ #define RTX_COSTS(X,CODE,OUTER_CODE) \ - case PLUS: \ - case MINUS: \ - if (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) \ + case PLUS: case MINUS: \ + if (FLOAT_MODE_P (GET_MODE (X))) \ return COSTS_N_INSNS (6); \ else if (GET_CODE (XEXP (X, 0)) == MULT \ && const48_operand (XEXP (XEXP (X, 0), 1), VOIDmode)) \ @@ -1335,14 +1465,9 @@ extern char *current_function_name; + rtx_cost (XEXP (X, 1), OUTER_CODE)); \ break; \ case MULT: \ - if (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) \ + if (FLOAT_MODE_P (GET_MODE (X))) \ return COSTS_N_INSNS (6); \ - else if (GET_CODE (XEXP (X, 1)) != CONST_INT \ - || exact_log2 (INTVAL (XEXP (X, 1))) < 0) \ - return COSTS_N_INSNS (21); \ - else if (const48_operand (XEXP (X, 1), VOIDmode)) \ - break; \ - return COSTS_N_INSNS (2); \ + return COSTS_N_INSNS (23); \ case ASHIFT: \ if (GET_CODE (XEXP (X, 1)) == CONST_INT \ && INTVAL (XEXP (X, 1)) <= 3) \ @@ -1350,10 +1475,7 @@ extern char *current_function_name; /* ... fall through ... */ \ case ASHIFTRT: case LSHIFTRT: case IF_THEN_ELSE: \ return COSTS_N_INSNS (2); \ - case DIV: \ - case UDIV: \ - case MOD: \ - case UMOD: \ + case DIV: case UDIV: case MOD: case UMOD: \ if (GET_MODE (X) == SFmode) \ return COSTS_N_INSNS (34); \ else if (GET_MODE (X) == DFmode) \ @@ -1361,7 +1483,14 @@ extern char *current_function_name; else \ return COSTS_N_INSNS (70); \ case MEM: \ - return COSTS_N_INSNS (3); + return COSTS_N_INSNS (3); \ + case FLOAT: case UNSIGNED_FLOAT: case FIX: case UNSIGNED_FIX: \ + case FLOAT_EXTEND: case FLOAT_TRUNCATE: \ + return COSTS_N_INSNS (6); \ + case NEG: case ABS: \ + if (FLOAT_MODE_P (GET_MODE (X))) \ + return COSTS_N_INSNS (6); \ + break; /* Control the assembler format that we output. */ @@ -1371,6 +1500,7 @@ extern char *current_function_name; { \ alpha_write_verstamp (FILE); \ fprintf (FILE, "\t.set noreorder\n"); \ + fprintf (FILE, "\t.set volatile\n"); \ fprintf (FILE, "\t.set noat\n"); \ ASM_OUTPUT_SOURCE_FILENAME (FILE, main_input_filename); \ } @@ -1396,7 +1526,11 @@ extern char *current_function_name; #define DATA_SECTION_ASM_OP ".data" /* Define an extra section for read-only data, a routine to enter it, and - indicate that it is for read-only data. */ + indicate that it is for read-only data. + + The first time we enter the readonly data section for a file, we write + eight bytes of zero. This works around a bug in DEC's assembler in + some versions of OSF/1 V3.x. */ #define EXTRA_SECTIONS readonly_data @@ -1406,21 +1540,27 @@ literal_section () \ { \ if (in_section != readonly_data) \ { \ + static int firsttime = 1; \ + \ fprintf (asm_out_file, "%s\n", READONLY_DATA_SECTION_ASM_OP); \ + if (firsttime) \ + { \ + firsttime = 0; \ + ASM_OUTPUT_DOUBLE_INT (asm_out_file, const0_rtx); \ + } \ + \ in_section = readonly_data; \ } \ } \ #define READONLY_DATA_SECTION literal_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 see - indicate that we can branch to this function without setting PV or - restoring GP. */ +/* If we are referencing a function that is static, make the SYMBOL_REF + special. We use this to see indicate we can branch to this function + without setting PV or restoring GP. */ #define ENCODE_SECTION_INFO(DECL) \ - if (TREE_CODE (DECL) == FUNCTION_DECL \ - && (TREE_ASM_WRITTEN (DECL) || ! TREE_PUBLIC (DECL))) \ + if (TREE_CODE (DECL) == FUNCTION_DECL && ! TREE_PUBLIC (DECL)) \ SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1; /* How to refer to registers in assembler output. @@ -1434,7 +1574,7 @@ literal_section () \ "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", \ "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", \ "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",\ - "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31"} + "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "FP"} /* How to renumber registers for dbx and gdb. */ @@ -1529,9 +1669,9 @@ literal_section () \ /* This is how to output an assembler line defining an `int' constant. */ #define ASM_OUTPUT_INT(FILE,VALUE) \ - fprintf (FILE, "\t.long %d\n", \ - (GET_CODE (VALUE) == CONST_INT \ - ? INTVAL (VALUE) & 0xffffffff : (abort (), 0))) +( fprintf (FILE, "\t.long "), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) /* This is how to output an assembler line defining a `long' constant. */ @@ -1589,13 +1729,14 @@ literal_section () \ can get it to parse the data properly. */ \ if (i < thissize - 1 \ && p[i + 1] >= '0' && p[i + 1] <= '9') \ - fprintf (asm_out_file, "\"\n\t.ascii \""); \ + _size_so_far = 0, fprintf (asm_out_file, "\"\n\t.ascii \""); \ } \ } \ fprintf (asm_out_file, "\"\n"); \ } \ } \ while (0) + /* This is how to output an insn to push a register on the stack. It need not be very fast code. */ @@ -1617,15 +1758,20 @@ literal_section () \ #define ASM_OUTPUT_BYTE(FILE,VALUE) \ fprintf (FILE, "\t.byte 0x%x\n", (VALUE) & 0xff) -/* This is how to output an element of a case-vector that is absolute. */ +/* This is how to output an element of a case-vector that is absolute. + (Alpha does not use such vectors, but we must define this macro anyway.) */ -#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ - fprintf (FILE, "\t.gprel32 $%d\n", (VALUE) + 32) +#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) abort () -/* This is how to output an element of a case-vector that is relative. - (Alpha does not use such vectors, but we must define this macro anyway.) */ +/* This is how to output an element of a case-vector that is relative. */ -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) abort () +#if WINDOWS_NT +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ + fprintf (FILE, "\t.long $%d\n", (VALUE) + 32) +#else +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ + fprintf (FILE, "\t.gprel32 $%d\n", (VALUE) + 32) +#endif /* This is how to output an assembler line that says to advance the location counter @@ -1719,11 +1865,13 @@ literal_section () \ {"reg_or_0_operand", {SUBREG, REG, CONST_INT}}, \ {"reg_or_6bit_operand", {SUBREG, REG, CONST_INT}}, \ {"reg_or_8bit_operand", {SUBREG, REG, CONST_INT}}, \ + {"cint8_operand", {CONST_INT}}, \ {"reg_or_cint_operand", {SUBREG, REG, CONST_INT}}, \ {"add_operand", {SUBREG, REG, CONST_INT}}, \ {"sext_add_operand", {SUBREG, REG, CONST_INT}}, \ {"const48_operand", {CONST_INT}}, \ {"and_operand", {SUBREG, REG, CONST_INT}}, \ + {"or_operand", {SUBREG, REG, CONST_INT}}, \ {"mode_mask_operand", {CONST_INT}}, \ {"mul8_operand", {CONST_INT}}, \ {"mode_width_operand", {CONST_INT}}, \ @@ -1733,12 +1881,22 @@ literal_section () \ {"divmod_operator", {DIV, MOD, UDIV, UMOD}}, \ {"fp0_operand", {CONST_DOUBLE}}, \ {"current_file_function_operand", {SYMBOL_REF}}, \ + {"call_operand", {REG, SYMBOL_REF}}, \ {"input_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \ SYMBOL_REF, CONST, LABEL_REF}}, \ + {"some_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \ + SYMBOL_REF, CONST, LABEL_REF}}, \ {"aligned_memory_operand", {MEM}}, \ {"unaligned_memory_operand", {MEM}}, \ {"any_memory_operand", {MEM}}, +/* Tell collect that the object format is ECOFF. */ +#define OBJECT_FORMAT_COFF +#define EXTENDED_COFF + +/* If we use NM, pass -g to it so it only lists globals. */ +#define NM_FLAGS "-pg" + /* Definitions for debugging. */ #define SDB_DEBUGGING_INFO /* generate info for mips-tfile */ @@ -1746,7 +1904,8 @@ literal_section () \ #define MIPS_DEBUGGING_INFO /* MIPS specific debugging info */ #ifndef PREFERRED_DEBUGGING_TYPE /* assume SDB_DEBUGGING_INFO */ -#define PREFERRED_DEBUGGING_TYPE ((len > 1 && !strncmp (str, "ggdb", len)) ? DBX_DEBUG : SDB_DEBUG) +#define PREFERRED_DEBUGGING_TYPE \ + ((len > 1 && !strncmp (str, "ggdb", len)) ? DBX_DEBUG : SDB_DEBUG) #endif @@ -1763,8 +1922,8 @@ literal_section () \ from the virtual frame pointer and adjust the debugger arg/auto offsets accordingly. These debugger offsets are set up in output_prolog. */ -long alpha_arg_offset; -long alpha_auto_offset; +extern long alpha_arg_offset; +extern long alpha_auto_offset; #define DEBUGGER_AUTO_OFFSET(X) \ ((GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0) + alpha_auto_offset) #define DEBUGGER_ARG_OFFSET(OFFSET, X) (OFFSET + alpha_arg_offset) @@ -1854,12 +2013,26 @@ do { \ #define PUT_SDB_EPILOGUE_END(NAME) +/* No point in running CPP on our assembler output. */ +#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & MASK_GAS) != 0 +/* Don't pass -g to GNU as, because some versions don't accept this option. */ +#define ASM_SPEC "%{malpha-as:-g} -nocpp %{pg}" +#else +/* In OSF/1 v3.2c, the assembler by default does not output file names which + causes mips-tfile to fail. Passing -g to the assembler fixes this problem. + ??? Stricly speaking, we only need -g if the user specifies -g. Passing + it always means that we get slightly larger than necessary object files + if the user does not specify -g. If we don't pass -g, then mips-tfile + will need to be fixed to work in this case. */ +#define ASM_SPEC "%{!mgas:-g} -nocpp %{pg}" +#endif + /* Specify to run a post-processor, mips-tfile after the assembler has run to stuff the ecoff debug information into the object file. This is needed because the Alpha assembler provides no way of specifying such information in the assembly file. */ -#if (TARGET_DEFAULT & MASK_GAS) != 0 +#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & MASK_GAS) != 0 #define ASM_FINAL_SPEC "\ %{malpha-as: %{!mno-mips-tfile: \ @@ -1895,3 +2068,18 @@ do { \ #define SHASH_SIZE 511 #define THASH_SIZE 55 + +/* Align ecoff symbol tables to avoid OSF1/1.3 nm complaints. */ + +#define ALIGN_SYMTABLE_OFFSET(OFFSET) (((OFFSET) + 7) & ~7) + +/* The system headers under OSF/1 are C++-aware. */ +#define NO_IMPLICIT_EXTERN_C + +/* The linker will stick __main into the .init section. */ +#define HAS_INIT_SECTION +#define LD_INIT_SWITCH "-init" +#define LD_FINI_SWITCH "-fini" + +/* We do want to link in libgcc when building shared libraries under OSF/1. */ +#define LIBGCC_SPEC "-lgcc"