--- gcc/config/alpha/alpha.h 2018/04/24 18:10:26 1.1.1.1 +++ 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,23 +16,24 @@ 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. */ #define CPP_PREDEFINES "\ -Dunix -D__osf__ -D__alpha -D__alpha__ -D_LONGLONG -DSYSTYPE_BSD \ --D_SYSTYPE_BSD" +-D_SYSTYPE_BSD -Asystem(unix) -Asystem(xpg4) -Acpu(alpha) -Amachine(alpha)" -/* Write out the correct language type definition for the header files. */ +/* Write out the correct language type definition for the header files. + Unless we have assembler language, write out the symbols for C. */ #define CPP_SPEC "\ -%{.c: -D__LANGUAGE_C__ -D__LANGUAGE_C %{!ansi:-DLANGUAGE_C}} \ -%{.h: -D__LANGUAGE_C__ -D__LANGUAGE_C %{!ansi:-DLANGUAGE_C}} \ +%{!.S: -D__LANGUAGE_C__ -D__LANGUAGE_C %{!ansi:-DLANGUAGE_C}} \ %{.S: -D__LANGUAGE_ASSEMBLY__ -D__LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \ -%{.cc: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS} \ -%{.cxx: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS} \ -%{.C: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS} \ +%{.cc: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__cplusplus} \ +%{.cxx: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__cplusplus} \ +%{.C: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__cplusplus} \ %{.m: -D__LANGUAGE_OBJECTIVE_C__ -D__LANGUAGE_OBJECTIVE_C}" /* Set the spec to use for signed char. The default tests the above macro @@ -41,23 +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 or profiled - libraries. */ +/* Under OSF/1, -p and -pg require -lprof1. */ -#define LIB_SPEC "-lc" +#define LIB_SPEC "%{p:-lprof1} %{pg:-lprof1} %{a:-lprof2} -lc" -/* Pass "-G 8" to ld because Alpha's CC does. Pass -O2 if we are optimizing, - -O1 if we are not. Pass -non_shared or -call_shared as appropriate. */ -/* Disable -O2 to ld; it seems to have problems. */ +/* 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*:-O1} %{!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/" @@ -75,7 +89,12 @@ extern int target_flags; that Alpha implementations without FP operations are required to provide the FP registers. */ -#define TARGET_FPREGS (target_flags & 2) +#define TARGET_FPREGS (target_flags & 2) + +/* This means that gas is used to process the assembler file. */ + +#define MASK_GAS 4 +#define TARGET_GAS (target_flags & MASK_GAS) /* Macro to define tables used to set the flags. This is a list in braces of pairs in braces, @@ -88,10 +107,16 @@ extern int target_flags; {"soft-float", -1}, \ {"fp-regs", 2}, \ {"no-fp-regs", -3}, \ - {"", TARGET_DEFAULT} } + {"alpha-as", -MASK_GAS}, \ + {"gas", MASK_GAS}, \ + {"", 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 @@ -99,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 */ @@ -215,17 +231,23 @@ extern int target_flags; /* A bitfield declared as `int' forces `int' alignment for the struct. */ #define PCC_BITFIELD_TYPE_MATTERS 1 -/* Align loop starts for optimal branching. */ +/* Align loop starts for optimal branching. + + ??? Kludge this and the next macro for the moment by not doing anything if + we don't optimize and also if we are writing ECOFF symbols to work around + a bug in DEC's assembler. */ #define ASM_OUTPUT_LOOP_ALIGN(FILE) \ - ASM_OUTPUT_ALIGN (FILE, 5) + if (optimize > 0 && write_symbols != SDB_DEBUG) \ + ASM_OUTPUT_ALIGN (FILE, 5) /* This is how to align an instruction for optimal branching. On Alpha we'll get better performance by aligning on a quadword boundary. */ #define ASM_OUTPUT_ALIGN_CODE(FILE) \ - ASM_OUTPUT_ALIGN ((FILE), 4) + if (optimize > 0 && write_symbols != SDB_DEBUG) \ + ASM_OUTPUT_ALIGN ((FILE), 4) /* No data type wants to be aligned rounder than this. */ #define BIGGEST_ALIGNMENT 64 @@ -270,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 @@ -310,16 +336,16 @@ 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, \ - 42, 43, 44, 45, \ + 42, 43, 44, 45, 46, 47, \ 54, 55, 56, 57, 58, 59, 60, 61, 62, \ 53, 52, 51, 50, 49, 48, \ 32, \ @@ -370,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 @@ -381,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 @@ -427,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 @@ -469,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 \ @@ -490,6 +522,18 @@ enum reg_class { NO_REGS, GENERAL_REGS, && zap_mask (CONST_DOUBLE_HIGH (VALUE))) \ : 0) +/* 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. + `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 in class CLASS, return the class of reg to actually use. In general this is just CLASS; but on some machines @@ -505,7 +549,9 @@ 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. */ + QImode and HImode from an aligned address to a general 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 \ @@ -518,7 +564,13 @@ enum reg_class { NO_REGS, GENERAL_REGS, && ((MODE) == SImode || (MODE) == HImode || (MODE) == QImode)) \ || (((MODE) == QImode || (MODE) == HImode) \ && unaligned_memory_operand (IN, MODE)))) \ - ? GENERAL_REGS : NO_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) \ (((GET_CODE (OUT) == MEM \ @@ -529,19 +581,40 @@ enum reg_class { NO_REGS, GENERAL_REGS, && REGNO (SUBREG_REG (OUT)) >= FIRST_PSEUDO_REGISTER)))) \ && (((MODE) == HImode || (MODE) == QImode \ || ((MODE) == SImode && (CLASS) == FLOAT_REGS)))) \ - ? GENERAL_REGS : NO_REGS) + ? GENERAL_REGS \ + : ((CLASS) == FLOAT_REGS && GET_CODE (OUT) == MEM \ + && GET_CODE (XEXP (OUT, 0)) == AND) ? GENERAL_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 @@ -584,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. @@ -612,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. @@ -625,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 @@ -647,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). @@ -663,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) @@ -756,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. @@ -794,7 +868,14 @@ enum reg_class { NO_REGS, GENERAL_REGS, However, if NO registers need to be saved, don't allocate any space. This is not only because we won't need the space, but because AP includes the current_pretend_args_size and we don't want to mess up any - ap-relative addresses already made. */ + ap-relative addresses already made. + + If we are not to use the floating-point registers, save the integer + registers where we would put the floating-point registers. This is + not the most efficient way to implement varargs with just one register + class, but it isn't worth doing anything more efficient in this rare + case. */ + #define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \ { if ((CUM) < 6) \ @@ -806,18 +887,25 @@ enum reg_class { NO_REGS, GENERAL_REGS, gen_rtx (MEM, BLKmode, \ plus_constant (virtual_incoming_args_rtx, \ ((CUM) + 6)* UNITS_PER_WORD)), \ - 6 - (CUM)); \ + 6 - (CUM), (6 - (CUM)) * UNITS_PER_WORD); \ move_block_from_reg \ - (16 + 32 + CUM, \ + (16 + (TARGET_FPREGS ? 32 : 0) + CUM, \ gen_rtx (MEM, BLKmode, \ plus_constant (virtual_incoming_args_rtx, \ (CUM) * UNITS_PER_WORD)), \ - 6 - (CUM)); \ + 6 - (CUM), (6 - (CUM)) * UNITS_PER_WORD); \ } \ PRETEND_SIZE = 12 * UNITS_PER_WORD; \ } \ } +/* 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 (); @@ -831,18 +919,12 @@ extern struct rtx_def *alpha_compare_op0 extern int alpha_compare_fp_p; /* This macro produces the initial definition of a function name. On the - Alpha, we need to save the function name for the epilogue. */ + Alpha, we need to save the function name for the prologue and epilogue. */ extern char *alpha_function_name; #define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL) \ - { int _level; \ - tree _context; \ - for (_level = -1, _context = (DECL); _context; \ - _context = DECL_CONTEXT (_context), _level++) \ - ; \ - fprintf (FILE, "\t.ent %s %d\n", NAME, _level); \ - ASM_OUTPUT_LABEL (FILE, NAME); \ +{ \ alpha_function_name = NAME; \ } @@ -857,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. @@ -966,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. */ @@ -985,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 @@ -1026,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 @@ -1047,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) \ @@ -1068,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 \ @@ -1077,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 @@ -1183,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 @@ -1221,28 +1349,19 @@ extern char *current_function_name; #define SLOW_BYTE_ACCESS 1 -/* Define if normal loads of shorter-than-word items from memory clears - the rest of the bits in the register. */ -/* #define BYTE_LOADS_ZERO_EXTEND */ - -/* Define if normal loads of shorter-than-word items from memory sign-extends - the rest of the bits in the register. */ -#define BYTE_LOADS_SIGN_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) SIGN_EXTEND /* Define if loading short immediate values into registers sign extends. */ #define SHORT_IMMEDIATES_SIGN_EXTEND -/* We aren't doing ANYTHING about debugging for now. */ -/* #define SDB_DEBUGGING_INFO */ - -/* Do not break .stabs pseudos into continuations. */ -#define DBX_CONTIN_LENGTH 0 - -/* Don't try to use the `x' type-cross-reference character in DBX data. - Also has the consequence of putting each struct, union or enum - into a separate .stabs, containing only cross-refs to the others. */ -#define DBX_NO_XREFS - /* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits is done just by pretending it is already truncated. */ #define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 @@ -1256,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. */ @@ -1277,48 +1416,58 @@ extern char *current_function_name; #define NO_FUNCTION_CSE -/* Define this if shift instructions ignore all but the low-order +/* Define this to be nonzero if shift instructions ignore all but the low-order few bits. */ -#define SHIFT_COUNT_TRUNCATED +#define SHIFT_COUNT_TRUNCATED 1 + +/* Use atexit for static constructors/destructors, instead of defining + our own exit function. */ +#define HAVE_ATEXIT /* Compute the cost of computing a constant rtl expression RTX whose rtx-code is CODE. The body of this macro is a portion 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)) \ - return 2 + rtx_cost (XEXP (XEXP (X, 0), 0)) + rtx_cost (XEXP (X, 1)); \ + return (2 + rtx_cost (XEXP (XEXP (X, 0), 0), OUTER_CODE) \ + + 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) \ @@ -1326,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) \ @@ -1337,22 +1483,26 @@ 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. */ /* Output at beginning of assembler file. */ #define ASM_FILE_START(FILE) \ -{ char *p, *after_dir = main_input_filename; \ - \ +{ \ alpha_write_verstamp (FILE); \ fprintf (FILE, "\t.set noreorder\n"); \ + fprintf (FILE, "\t.set volatile\n"); \ fprintf (FILE, "\t.set noat\n"); \ - for (p = main_input_filename; *p; p++) \ - if (*p == '/') \ - after_dir = p + 1; \ - fprintf (FILE, "\n\t.file 2 \"%s\"\n", after_dir); \ + ASM_OUTPUT_SOURCE_FILENAME (FILE, main_input_filename); \ } /* Output to assembler file text saying following lines @@ -1376,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 @@ -1386,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. @@ -1414,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. */ @@ -1509,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. */ @@ -1569,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. */ @@ -1597,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 @@ -1697,21 +1863,223 @@ literal_section () \ #define PREDICATE_CODES \ {"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}}, \ {"reg_or_fp0_operand", {SUBREG, REG, CONST_DOUBLE}}, \ {"alpha_comparison_operator", {EQ, LE, LT, LEU, LTU}}, \ {"signed_comparison_operator", {EQ, NE, LE, LT, GE, GT}}, \ + {"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 */ +#define DBX_DEBUGGING_INFO /* generate embedded stabs */ +#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) +#endif + + +/* Correct the offset of automatic variables and arguments. Note that + the Alpha debug format wants all automatic variables and arguments + to be in terms of two different offsets from the virtual frame pointer, + which is the stack pointer before any adjustment in the function. + The offset for the argument pointer is fixed for the native compiler, + it is either zero (for the no arguments case) or large enough to hold + all argument registers. + The offset for the auto pointer is the fourth argument to the .frame + directive (local_offset). + To stay compatible with the native tools we use the same offsets + from the virtual frame pointer and adjust the debugger arg/auto offsets + accordingly. These debugger offsets are set up in output_prolog. */ + +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) + + +#define ASM_OUTPUT_SOURCE_LINE(STREAM, LINE) \ + alpha_output_lineno (STREAM, LINE) +extern void alpha_output_lineno (); + +#define ASM_OUTPUT_SOURCE_FILENAME(STREAM, NAME) \ + alpha_output_filename (STREAM, NAME) +extern void alpha_output_filename (); + + +/* mips-tfile.c limits us to strings of one page. */ +#define DBX_CONTIN_LENGTH 4000 + +/* By default, turn on GDB extensions. */ +#define DEFAULT_GDB_EXTENSIONS 1 + +/* If we are smuggling stabs through the ALPHA ECOFF object + format, put a comment in front of the .stab operation so + that the ALPHA assembler does not choke. The mips-tfile program + will correctly put the stab into the object file. */ + +#define ASM_STABS_OP ((TARGET_GAS) ? ".stabs" : " #.stabs") +#define ASM_STABN_OP ((TARGET_GAS) ? ".stabn" : " #.stabn") +#define ASM_STABD_OP ((TARGET_GAS) ? ".stabd" : " #.stabd") + +/* Forward references to tags are allowed. */ +#define SDB_ALLOW_FORWARD_REFERENCES + +/* Unknown tags are also allowed. */ +#define SDB_ALLOW_UNKNOWN_REFERENCES + +#define PUT_SDB_DEF(a) \ +do { \ + fprintf (asm_out_file, "\t%s.def\t", \ + (TARGET_GAS) ? "" : "#"); \ + ASM_OUTPUT_LABELREF (asm_out_file, a); \ + fputc (';', asm_out_file); \ +} while (0) + +#define PUT_SDB_PLAIN_DEF(a) \ +do { \ + fprintf (asm_out_file, "\t%s.def\t.%s;", \ + (TARGET_GAS) ? "" : "#", (a)); \ +} while (0) + +#define PUT_SDB_TYPE(a) \ +do { \ + fprintf (asm_out_file, "\t.type\t0x%x;", (a)); \ +} while (0) + +/* For block start and end, we create labels, so that + later we can figure out where the correct offset is. + The normal .ent/.end serve well enough for functions, + so those are just commented out. */ + +extern int sdb_label_count; /* block start/end next label # */ + +#define PUT_SDB_BLOCK_START(LINE) \ +do { \ + fprintf (asm_out_file, \ + "$Lb%d:\n\t%s.begin\t$Lb%d\t%d\n", \ + sdb_label_count, \ + (TARGET_GAS) ? "" : "#", \ + sdb_label_count, \ + (LINE)); \ + sdb_label_count++; \ +} while (0) + +#define PUT_SDB_BLOCK_END(LINE) \ +do { \ + fprintf (asm_out_file, \ + "$Le%d:\n\t%s.bend\t$Le%d\t%d\n", \ + sdb_label_count, \ + (TARGET_GAS) ? "" : "#", \ + sdb_label_count, \ + (LINE)); \ + sdb_label_count++; \ +} while (0) + +#define PUT_SDB_FUNCTION_START(LINE) + +#define PUT_SDB_FUNCTION_END(LINE) + +#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 | TARGET_CPU_DEFAULT) & MASK_GAS) != 0 + +#define ASM_FINAL_SPEC "\ +%{malpha-as: %{!mno-mips-tfile: \ + \n mips-tfile %{v*: -v} \ + %{K: -I %b.o~} \ + %{!K: %{save-temps: -I %b.o~}} \ + %{c:%W{o*}%{!o*:-o %b.o}}%{!c:-o %U.o} \ + %{.s:%i} %{!.s:%g.s}}}" + +#else +#define ASM_FINAL_SPEC "\ +%{!mgas: %{!mno-mips-tfile: \ + \n mips-tfile %{v*: -v} \ + %{K: -I %b.o~} \ + %{!K: %{save-temps: -I %b.o~}} \ + %{c:%W{o*}%{!o*:-o %b.o}}%{!c:-o %U.o} \ + %{.s:%i} %{!.s:%g.s}}}" + +#endif + +/* Macros for mips-tfile.c to encapsulate stabs in ECOFF, and for + mips-tdump.c to print them out. + + These must match the corresponding definitions in gdb/mipsread.c. + Unfortunately, gcc and gdb do not currently share any directories. */ + +#define CODE_MASK 0x8F300 +#define MIPS_IS_STAB(sym) (((sym)->index & 0xFFF00) == CODE_MASK) +#define MIPS_MARK_STAB(code) ((code)+CODE_MASK) +#define MIPS_UNMARK_STAB(code) ((code)-CODE_MASK) + +/* Override some mips-tfile definitions. */ + +#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"