From: Richard Kenner Date: Wed, 10 Feb 1993 21:12:20 +0000 (-0500) Subject: (ASM_OUTPUT_LOOP_ALIGN): Enable, now that assembler fixed. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=130d2d725d8c26a325c46d413e041d9ffb70ba73;p=gcc.git (ASM_OUTPUT_LOOP_ALIGN): Enable, now that assembler fixed. (SLOW_UNALIGNED_ACCESS): Define as 1. (ARG_POINTER_REGNUM): Use register number 31 as an arg pointer. (FRAME_GROWS_DOWNWARD): Do not define. (STARTING_FRAME_OFFSET): Now is outgoing args size. (FIRST_PARM_OFFSET): Now 0. (ELIMINABLE_REGS, etc.): Cannot eliminate gp, but do eliminate AP in favor of either SP or FP. (RETURN_IN_MEMORY): All structs or integers larger than 64 bits get returned via memory. (SETUP_INCOMING_VARARGS): Use homed arglist mechanism. (ASM_DECLARE_FUNCTION_NAME): Use proper second arg to .ent. (ASM_FILE_START): Call alpha_write_verstamp. (ENCODE_SECTION_INFO): Record when a decl is for a function in the current file. From-SVN: r3457 --- diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h index 3a371846290..8de0adc37ec 100644 --- a/gcc/config/alpha/alpha.h +++ b/gcc/config/alpha/alpha.h @@ -206,16 +206,15 @@ 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. */ - Don't do this until they fix the assembler. */ - -/* #define ASM_OUTPUT_LOOP_ALIGN(FILE) \ - ASM_OUTPUT_ALIGN (FILE, 5) */ +#define ASM_OUTPUT_LOOP_ALIGN(FILE) \ + 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) @@ -243,7 +242,8 @@ extern int target_flags; /* Set this non-zero if unaligned move instructions are extremely slow. On the Alpha, they trap. */ -/* #define SLOW_UNALIGNED_ACCESS 1 */ + +#define SLOW_UNALIGNED_ACCESS 1 /* Standard register usage. */ @@ -256,7 +256,12 @@ extern int target_flags; We define all 32 integer registers, even though $31 is always zero, and all 32 floating-point registers, even though $f31 is also always zero. We do not bother defining the FP status register and - there are no other registers. */ + there are no other registers. + + 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. */ #define FIRST_PSEUDO_REGISTER 64 @@ -301,7 +306,7 @@ extern int target_flags; $26 (return PC) $15 (frame pointer) $29 (global pointer) - $30, $31, $f31 (stack pointer and always zero) */ + $30, $31, $f31 (stack pointer and always zero/ap) */ #define REG_ALLOC_ORDER \ {33, \ @@ -365,7 +370,7 @@ extern int target_flags; #define FRAME_POINTER_REQUIRED 0 /* Base register for access to arguments of the function. */ -#define ARG_POINTER_REGNUM 15 +#define ARG_POINTER_REGNUM 31 /* Register in which static-chain is passed to a function. @@ -563,14 +568,14 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS, is at the high-address end of the local variables; that is, each additional local variable allocated goes at a more negative offset in the frame. */ -#define FRAME_GROWS_DOWNWARD +/* #define FRAME_GROWS_DOWNWARD */ /* Offset within stack frame to start allocating local variables at. If FRAME_GROWS_DOWNWARD, this is the offset to the END of the first local allocated. Otherwise, it is the offset to the BEGINNING of the first local allocated. */ -#define STARTING_FRAME_OFFSET (- current_function_pretend_args_size) +#define STARTING_FRAME_OFFSET current_function_outgoing_args_size /* If we generate an insn to push BYTES bytes, this says how many the stack pointer really advances by. @@ -584,18 +589,14 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS, /* Offset of first parameter from the argument pointer register value. */ -#define FIRST_PARM_OFFSET(FNDECL) (- current_function_pretend_args_size) +#define FIRST_PARM_OFFSET(FNDECL) 0 /* Definitions for register eliminations. - We have one register that can be eliminated on the Alpha. The + We have two registers that can be eliminated on the i386. First, the frame pointer register can often be eliminated in favor of the stack - pointer register. - - In addition, we use the elimination mechanism to see if gp (r29) is needed. - Initially we assume that it isn't. If it is, we spill it. This is done - by making it an eliminable register. It doesn't matter what we replace - it with, since it will never occur in the rtl at this point. */ + pointer register. Secondly, the argument pointer register can always be + eliminated; it is replaced with either the stack or frame pointer. */ /* This is an array of structures. Each structure initializes one pair of eliminable registers. The "from" register number is given first, @@ -603,24 +604,24 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS, in order of preference. */ #define ELIMINABLE_REGS \ -{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ - { 29, 0}} +{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ + { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ + { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}} /* Given FROM and TO register numbers, say whether this elimination is allowed. Frame pointer elimination is automatically handled. - We need gp (r29) if we have calls or load symbols - (tested in alpha_need_gp). - - All other eliminations are valid since the cases where FP can't be + All eliminations are valid since the cases where FP can't be eliminated are already handled. */ -#define CAN_ELIMINATE(FROM, TO) ((FROM) == 29 ? ! alpha_need_gp () : 1) +#define CAN_ELIMINATE(FROM, TO) 1 /* Define the offset between two registers, one to be eliminated, and the other its replacement, at the start of a routine. */ #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ { 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; \ @@ -665,6 +666,16 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS, gen_rtx (REG, MODE, \ TARGET_FPREGS && GET_MODE_CLASS (MODE) == MODE_FLOAT ? 32 : 0) +/* The definition of this macro implies that there are cases where + a scalar value cannot be returned in registers. + + For the Alpha, any structure or union type is returned in memory, as + are integers whose size is larger than 64 bits. */ + +#define RETURN_IN_MEMORY(TYPE) \ + (TREE_CODE (TYPE) == RECORD_TYPE || TREE_CODE (TYPE) == UNION_TYPE \ + || (TREE_CODE (TYPE) == INTEGER_TYPE && TYPE_PRECISION (TYPE) > 64)) + /* 1 if N is a possible register number for a function value as seen by the caller. */ @@ -749,6 +760,50 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS, ((CUM) < 6 && 6 < (CUM) + ALPHA_ARG_SIZE (MODE, TYPE, NAMED) \ ? 6 - (CUM) : 0) +/* Perform any needed actions needed for a function that is receiving a + variable number of arguments. + + CUM is as above. + + MODE and TYPE are the mode and type of the current parameter. + + PRETEND_SIZE is a variable that should be set to the amount of stack + that must be pushed by the prolog to pretend that our caller pushed + it. + + Normally, this macro will push all remaining incoming registers on the + stack and set PRETEND_SIZE to the length of the registers pushed. + + On the Alpha, we allocate space for all 12 arg registers, but only + push those that are remaining. + + 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. */ + +#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \ +{ if ((CUM) < 6) \ + { \ + if (! (NO_RTL)) \ + { \ + move_block_from_reg \ + (16 + CUM, \ + gen_rtx (MEM, BLKmode, \ + plus_constant (virtual_incoming_args_rtx, \ + ((CUM) - 6) * UNITS_PER_WORD)), \ + 6 - (CUM)); \ + move_block_from_reg \ + (16 + 32 + CUM, \ + gen_rtx (MEM, BLKmode, \ + plus_constant (virtual_incoming_args_rtx, \ + ((CUM) - 12) * UNITS_PER_WORD)), \ + 6 - (CUM)); \ + } \ + PRETEND_SIZE = 12 * UNITS_PER_WORD; \ + } \ +} + /* Generate necessary RTL for __builtin_saveregs(). ARGLIST is the argument list; see expr.c. */ extern struct rtx_def *alpha_builtin_saveregs (); @@ -762,12 +817,17 @@ extern struct rtx_def *alpha_compare_op0, *alpha_compare_op1; extern int alpha_compare_fp_p; /* This macro produces the initial definition of a function name. On the - 29k, we need to save the function name for the epilogue. */ + Alpha, we need to save the function name for the epilogue. */ extern char *alpha_function_name; #define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL) \ - { fprintf (FILE, "\t.ent %s 2\n", NAME); \ + { 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; \ } @@ -1253,13 +1313,10 @@ extern char *current_function_name; /* Output at beginning of assembler file. */ #define ASM_FILE_START(FILE) \ -{ extern char *version_string; \ - char *p, *after_dir = main_input_filename; \ +{ char *p, *after_dir = main_input_filename; \ \ - fprintf (FILE, "\t.verstamp 10 0 "); \ - for (p = version_string; *p != ' ' && *p != 0; p++) \ - fprintf (FILE, "%c", *p == '.' ? ' ' : *p); \ - fprintf (FILE, "\n\t.set noreorder\n"); \ + alpha_write_verstamp (FILE); \ + fprintf (FILE, "\t.set noreorder\n"); \ fprintf (FILE, "\t.set noat\n"); \ for (p = main_input_filename; *p; p++) \ if (*p == '/') \ @@ -1305,6 +1362,16 @@ literal_section () \ #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. */ + +#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; + /* How to refer to registers in assembler output. This sequence is indexed by compiler's hard-register-number (see above). */ @@ -1312,7 +1379,7 @@ literal_section () \ {"$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", \ "$9", "$10", "$11", "$12", "$13", "$14", "$15", \ "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", \ - "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31", \ + "$24", "$25", "$26", "$27", "$28", "$29", "$30", "AP", \ "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", \ "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", \ "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",\