diff options
author | meissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4> | 1996-05-28 19:58:24 +0000 |
---|---|---|
committer | meissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4> | 1996-05-28 19:58:24 +0000 |
commit | 359e408d73f1088b80709eebf420fa854449b7c8 (patch) | |
tree | 627990e3a3942dae74f4cecab49c150bac528480 /gcc/config | |
parent | 57ed72532034e6376b2094ce11d974f9af2a0db6 (diff) | |
download | gcc-359e408d73f1088b80709eebf420fa854449b7c8.tar.gz |
Fix problems in float/int conversion in inline functions
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@12122 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 179 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.h | 154 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 272 | ||||
-rw-r--r-- | gcc/config/rs6000/sol2.h | 7 | ||||
-rw-r--r-- | gcc/config/rs6000/sysv4.h | 42 |
5 files changed, 478 insertions, 176 deletions
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 9fcb1017b52..276008b4b51 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -99,35 +99,42 @@ int rs6000_save_toc_p; /* ABI enumeration available for subtarget to use. */ enum rs6000_abi rs6000_current_abi; +/* Offset & size for fpmem stack locations used for converting between + float and integral types. */ +int rs6000_fpmem_offset; +int rs6000_fpmem_size; + /* Default register names. */ char rs6000_reg_names[][8] = { - "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", - "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", - "mq", "lr", "ctr","ap", - "0", "1", "2", "3", "4", "5", "6", "7" + "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", + "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", + "mq", "lr", "ctr","ap", + "0", "1", "2", "3", "4", "5", "6", "7", + "fpmem" }; #ifdef TARGET_REGNAMES static char alt_reg_names[][8] = { - "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7", - "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", - "%r16", "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%r23", - "%r24", "%r25", "%r26", "%r27", "%r28", "%r29", "%r30", "%r31", - "%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", - "mq", "lr", "ctr", "ap", - "%cr0", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5", "%cr6", "%cr7" + "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7", + "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", + "%r16", "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%r23", + "%r24", "%r25", "%r26", "%r27", "%r28", "%r29", "%r30", "%r31", + "%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", + "mq", "lr", "ctr", "ap", + "%cr0", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5", "%cr6", "%cr7", + "fpmem" }; #endif @@ -363,6 +370,26 @@ int count_register_operand(op, mode) return 0; } +/* Returns 1 if op is memory location for float/int conversions that masquerades + as a register. */ +int fpmem_operand(op, mode) + register rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) != REG) + return 0; + + if (FPMEM_REGNO_P (REGNO (op))) + return 1; + +#if 0 + if (REGNO (op) > FIRST_PSEUDO_REGISTER) + return 1; +#endif + + return 0; +} + /* Return 1 if OP is a constant that can fit in a D field. */ int @@ -404,7 +431,9 @@ gpc_reg_operand (op, mode) enum machine_mode mode; { return (register_operand (op, mode) - && (GET_CODE (op) != REG || REGNO (op) >= 67 || REGNO (op) < 64)); + && (GET_CODE (op) != REG + || (REGNO (op) >= 67 && !FPMEM_REGNO_P (REGNO (op))) + || REGNO (op) < 64)); } /* Returns 1 if OP is either a pseudo-register or a register denoting a @@ -1785,7 +1814,7 @@ includes_rshift_p (shiftop, andop) register rtx shiftop; register rtx andop; { - unsigned shift_mask = ~0; + unsigned shift_mask = ~(unsigned)0; shift_mask >>= INTVAL (shiftop); @@ -2319,13 +2348,29 @@ print_operand (file, x, code) return; case 'u': - /* High-order 16 bits of constant. */ + /* High-order 16 bits of constant for use in unsigned operand. */ if (! INT_P (x)) output_operand_lossage ("invalid %%u value"); fprintf (file, "0x%x", (INT_LOWPART (x) >> 16) & 0xffff); return; + case 'v': + /* High-order 16 bits of constant for use in signed operand. */ + if (! INT_P (x)) + output_operand_lossage ("invalid %%v value"); + + { + int value = (INT_LOWPART (x) >> 16) & 0xffff; + + /* Solaris assembler doesn't like lis 0,0x80000 */ + if (DEFAULT_ABI == ABI_SOLARIS && (value & 0x8000) != 0) + fprintf (file, "%d", value | (~0 << 16)); + else + fprintf (file, "0x%x", value); + return; + } + case 'U': /* Print `u' if this has an auto-increment or auto-decrement. */ if (GET_CODE (x) == MEM @@ -2575,13 +2620,15 @@ rs6000_makes_calls () +---------------------------------------+ | Parameter save area (P) | 24 +---------------------------------------+ - | Alloca space (A) | 24+P + | Float/int conversion temporary (X) | 24+P + +---------------------------------------+ + | Alloca space (A) | 24+P+X +---------------------------------------+ - | Local variable space (L) | 24+P+A + | Local variable space (L) | 24+P+X+A +---------------------------------------+ - | Save area for GP registers (G) | 24+P+A+L + | Save area for GP registers (G) | 24+P+X+A+L +---------------------------------------+ - | Save area for FP registers (F) | 24+P+A+L+G + | Save area for FP registers (F) | 24+P+X+A+L+G +---------------------------------------+ old SP->| back chain to caller's caller | +---------------------------------------+ @@ -2595,17 +2642,19 @@ rs6000_makes_calls () +---------------------------------------+ | Parameter save area (P) | 8 +---------------------------------------+ - | Alloca space (A) | 8+P + | Float/int conversion temporary (X) | 8+P +---------------------------------------+ - | Varargs save area (V) | 8+P+A + | Alloca space (A) | 8+P+X +---------------------------------------+ - | Local variable space (L) | 8+P+A+V + | Varargs save area (V) | 8+P+X+A +---------------------------------------+ - | saved CR (C) | 8+P+A+V+L + | Local variable space (L) | 8+P+X+A+V +---------------------------------------+ - | Save area for GP registers (G) | 8+P+A+V+L+C + | saved CR (C) | 8+P+X+A+V+L +---------------------------------------+ - | Save area for FP registers (F) | 8+P+A+V+L+C+G + | Save area for GP registers (G) | 8+P+X+A+V+L+C + +---------------------------------------+ + | Save area for FP registers (F) | 8+P+X+A+V+L+C+G +---------------------------------------+ old SP->| back chain to caller's caller | +---------------------------------------+ @@ -2628,21 +2677,23 @@ rs6000_makes_calls () +---------------------------------------+ | Parameter save area (P) | 24 +---------------------------------------+ - | Alloca space (A) | 24+P + | Float/int conversion temporary (X) | 24+P + +---------------------------------------+ + | Alloca space (A) | 24+P+X +---------------------------------------+ - | Local variable space (L) | 24+P+A + | Local variable space (L) | 24+P+X+A +---------------------------------------+ - | Save area for FP registers (F) | 24+P+A+L + | Save area for FP registers (F) | 24+P+X+A+L +---------------------------------------+ - | Possible alignment area (X) | 24+P+A+L+F + | Possible alignment area (X) | 24+P+X+A+L+F +---------------------------------------+ - | Save area for GP registers (G) | 24+P+A+L+F+X + | Save area for GP registers (G) | 24+P+X+A+L+F+X +---------------------------------------+ - | Save area for CR (C) | 24+P+A+L+F+X+G + | Save area for CR (C) | 24+P+X+A+L+F+X+G +---------------------------------------+ - | Save area for TOC (T) | 24+P+A+L+F+X+G+C + | Save area for TOC (T) | 24+P+X+A+L+F+X+G+C +---------------------------------------+ - | Save area for LR (R) | 24+P+A+L+F+X+G+C+T + | Save area for LR (R) | 24+P+X+A+L+F+X+G+C+T +---------------------------------------+ old SP->| back chain to caller's caller | +---------------------------------------+ @@ -2685,6 +2736,9 @@ rs6000_stack_info () info_ptr->toc_size = reg_size; } + /* Does this machine need the float/int conversion area? */ + info_ptr->fpmem_p = regs_ever_live[FPMEM_REGNUM]; + /* If this is main and we need to call a function to set things up, save main's arguments around the call. */ #ifdef TARGET_EABI @@ -2749,6 +2803,7 @@ rs6000_stack_info () info_ptr->varargs_size = RS6000_VARARGS_AREA; info_ptr->vars_size = ALIGN (get_frame_size (), 8); info_ptr->parm_size = ALIGN (current_function_outgoing_args_size, 8); + info_ptr->fpmem_size = (info_ptr->fpmem_p) ? 8 : 0; info_ptr->save_size = ALIGN (info_ptr->fp_size + info_ptr->gp_size + info_ptr->cr_size @@ -2758,6 +2813,7 @@ rs6000_stack_info () total_raw_size = (info_ptr->vars_size + info_ptr->parm_size + + info_ptr->fpmem_size + info_ptr->save_size + info_ptr->varargs_size + info_ptr->fixed_size); @@ -2785,6 +2841,7 @@ rs6000_stack_info () || info_ptr->total_size > 220); /* Calculate the offsets */ + info_ptr->fpmem_offset = info_ptr->total_size - info_ptr->parm_size; switch (abi) { case ABI_NONE: @@ -2842,6 +2899,16 @@ rs6000_stack_info () if (!info_ptr->main_save_p) info_ptr->main_save_offset = 0; + if (!info_ptr->fpmem_p) + info_ptr->fpmem_offset = 0; + else + { + rs6000_fpmem_size = info_ptr->fpmem_size; + rs6000_fpmem_offset = STACK_DYNAMIC_OFFSET (current_function_decl) - info_ptr->fpmem_size; + if (rs6000_fpmem_offset > 32767) + abort (); + } + return info_ptr; } @@ -2899,6 +2966,9 @@ debug_stack_info (info) if (info->main_save_p) fprintf (stderr, "\tmain_save_p = %5d\n", info->main_save_p); + if (info->fpmem_p) + fprintf (stderr, "\tfpmem_p = %5d\n", info->fpmem_p); + if (info->gp_save_offset) fprintf (stderr, "\tgp_save_offset = %5d\n", info->gp_save_offset); @@ -2920,6 +2990,9 @@ debug_stack_info (info) if (info->main_save_offset) fprintf (stderr, "\tmain_save_offset = %5d\n", info->main_save_offset); + if (info->fpmem_offset) + fprintf (stderr, "\tfpmem_offset = %5d\n", info->fpmem_offset); + if (info->total_size) fprintf (stderr, "\ttotal_size = %5d\n", info->total_size); @@ -2932,6 +3005,9 @@ debug_stack_info (info) if (info->parm_size) fprintf (stderr, "\tparm_size = %5d\n", info->parm_size); + if (info->fpmem_size) + fprintf (stderr, "\tfpmem_size = %5d\n", info->fpmem_size); + if (info->fixed_size) fprintf (stderr, "\tfixed_size = %5d\n", info->fixed_size); @@ -3619,6 +3695,8 @@ output_epilog (file, size) /* Reset varargs and save TOC indicator */ rs6000_sysv_varargs_p = 0; rs6000_save_toc_p = 0; + rs6000_fpmem_size = 0; + rs6000_fpmem_offset = 0; pic_offset_table_rtx = (rtx)0; if (DEFAULT_ABI == ABI_NT) @@ -4601,7 +4679,6 @@ handle_mac_pragma (finput, t) pname = IDENTIFIER_POINTER (t); if (strcmp (pname, "segment") == 0) { - retval = 1; /* (should collect pbuf + 8 into a segment name) */ } else if (strcmp (pname, "options") == 0) @@ -4613,7 +4690,10 @@ handle_mac_pragma (finput, t) /* Return without doing anything if no content. */ if (c == '\n' || c == EOF) - return 0; + { + ungetc (c, finput); + return 0; + } /* Collect the rest of the line. */ while (psize < sizeof (pbuf) - 1 && c != '\n') @@ -4624,14 +4704,21 @@ handle_mac_pragma (finput, t) if (strncmp (pbuf, "align=mac68k", 12) == 0) { - mac68k_aligned = retval = 1; + mac68k_aligned = 1; + retval = 1; + } + else if (strncmp (pbuf, "align=power", 11) == 0) + { + mac68k_aligned = 0; + retval = 1; } else if (strncmp (pbuf, "align=reset", 11) == 0) { - mac68k_aligned = 0, retval = 1; + mac68k_aligned = 0; + retval = 1; } } - return c; + return retval; } /* END CYGNUS LOCAL mac */ diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index e4857c6d1b4..5f0d7b922e4 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -618,9 +618,14 @@ extern struct rs6000_cpu_select rs6000_select[]; In addition, the difference between the frame and argument pointers is a function of the number of registers saved, so we need to have a register for AP that will later be eliminated in favor of SP or FP. - This is a normal register, but it is fixed. */ + This is a normal register, but it is fixed. -#define FIRST_PSEUDO_REGISTER 76 + We also create a pseudo register for float/int conversions, that will + really represent the memory location used. It is represented here as + a register, in order to work around problems in allocating stack storage + in inline functions. */ + +#define FIRST_PSEUDO_REGISTER 77 /* 1 for registers that have pervasive standard uses and are not available for the register allocator. @@ -640,7 +645,7 @@ extern struct rs6000_cpu_select rs6000_select[]; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0} + 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1} /* 1 for registers not available across function calls. These must include the FIXED_REGISTERS and also any @@ -654,7 +659,7 @@ extern struct rs6000_cpu_select rs6000_select[]; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ - 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1} + 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1} /* List the order in which to allocate registers. Each register must be listed once, even those in FIXED_REGISTERS. @@ -691,7 +696,7 @@ extern struct rs6000_cpu_select rs6000_select[]; 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, \ 18, 17, 16, 15, 14, 13, 12, \ 64, 66, 65, \ - 73, 1, 2, 67} + 73, 1, 2, 67, 76} /* True if register is floating-point. */ #define FP_REGNO_P(N) ((N) >= 32 && (N) <= 63) @@ -702,6 +707,10 @@ extern struct rs6000_cpu_select rs6000_select[]; /* True if register is an integer register. */ #define INT_REGNO_P(N) ((N) <= 31 || (N) == 67) +/* True if register is the temporary memory location used for int/float + conversion. */ +#define FPMEM_REGNO_P(N) ((N) == FPMEM_REGNUM) + /* Return number of consecutive hard regs needed starting at reg REGNO to hold something of mode MODE. This is ordinarily the length in words of a value of mode MODE @@ -710,8 +719,8 @@ extern struct rs6000_cpu_select rs6000_select[]; On RS/6000, ordinary registers hold 32 bits worth; a single floating point register holds 64 bits worth. */ -#define HARD_REGNO_NREGS(REGNO, MODE) \ - (FP_REGNO_P (REGNO) \ +#define HARD_REGNO_NREGS(REGNO, MODE) \ + (FP_REGNO_P (REGNO) || FPMEM_REGNO_P (REGNO) \ ? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \ : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) @@ -721,13 +730,14 @@ extern struct rs6000_cpu_select rs6000_select[]; 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 \ - || (GET_MODE_CLASS (MODE) == MODE_INT \ - && GET_MODE_SIZE (MODE) == UNITS_PER_FP_WORD)) \ - : CR_REGNO_P (REGNO) ? GET_MODE_CLASS (MODE) == MODE_CC \ - : ! INT_REGNO_P (REGNO) ? (GET_MODE_CLASS (MODE) == MODE_INT \ +#define HARD_REGNO_MODE_OK(REGNO, MODE) \ + (FP_REGNO_P (REGNO) ? \ + (GET_MODE_CLASS (MODE) == MODE_FLOAT \ + || (GET_MODE_CLASS (MODE) == MODE_INT \ + && GET_MODE_SIZE (MODE) == UNITS_PER_FP_WORD)) \ + : CR_REGNO_P (REGNO) ? GET_MODE_CLASS (MODE) == MODE_CC \ + : FPMEM_REGNO_P (REGNO) ? ((MODE) == DImode || (MODE) == DFmode) \ + : ! INT_REGNO_P (REGNO) ? (GET_MODE_CLASS (MODE) == MODE_INT \ && GET_MODE_SIZE (MODE) <= UNITS_PER_WORD) \ : 1) @@ -761,7 +771,7 @@ extern struct rs6000_cpu_select rs6000_select[]; || (CLASS1) == LINK_OR_CTR_REGS) \ && ((CLASS2) == SPECIAL_REGS || (CLASS2) == MQ_REGS \ || (CLASS2) == LINK_REGS || (CLASS2) == CTR_REGS \ - || (CLASS2) == LINK_OR_CTR_REGS)) ? 10 \ + || (CLASS2) == LINK_OR_CTR_REGS)) ? 10 \ : 2) /* A C expressions returning the cost of moving data of MODE from a register to @@ -834,6 +844,9 @@ extern struct rs6000_cpu_select rs6000_select[]; /* count register number for special purposes */ #define COUNT_REGISTER_REGNUM 66 +/* Special register that represents memory, used for float/int conversions. */ +#define FPMEM_REGNUM 76 + /* Place that structure value return address is placed. On the RS/6000, it is passed as an extra parameter. */ @@ -867,7 +880,14 @@ extern struct rs6000_cpu_select rs6000_select[]; So make a class for registers valid as base registers. Also, cr0 is the only condition code register that can be used in - arithmetic insns, so make a separate class for it. */ + arithmetic insns, so make a separate class for it. + + There is a special 'registrer' (76), which is not a register, but a + placeholder for memory allocated to convert between floating point and + integral types. This works around a problem where if we allocate memory + with allocate_stack_{local,temp} and the function is an inline function, the + memory allocated will clobber memory in the caller. So we use a special + register, and if that is used, we allocate stack space for it. */ enum reg_class { @@ -885,6 +905,8 @@ enum reg_class CR0_REGS, CR_REGS, NON_FLOAT_REGS, + FPMEM_REGS, + FLOAT_OR_FPMEM_REGS, ALL_REGS, LIM_REG_CLASSES }; @@ -909,6 +931,8 @@ enum reg_class "CR0_REGS", \ "CR_REGS", \ "NON_FLOAT_REGS", \ + "FPMEM_REGS", \ + "FLOAT_OR_FPMEM_REGS", \ "ALL_REGS" \ } @@ -932,7 +956,9 @@ enum reg_class { 0x00000000, 0x00000000, 0x00000010 }, /* CR0_REGS */ \ { 0x00000000, 0x00000000, 0x00000ff0 }, /* CR_REGS */ \ { 0xffffffff, 0x00000000, 0x0000ffff }, /* NON_FLOAT_REGS */ \ - { 0xffffffff, 0xffffffff, 0x0000ffff } /* ALL_REGS */ \ + { 0x00000000, 0x00000000, 0x00010000 }, /* FPMEM_REGS */ \ + { 0x00000000, 0xffffffff, 0x00010000 }, /* FLOAT_OR_FPMEM_REGS */ \ + { 0xffffffff, 0xffffffff, 0x0001ffff } /* ALL_REGS */ \ } /* The same information, inverted: @@ -940,16 +966,17 @@ enum reg_class reg number REGNO. This could be a conditional expression or could index an array. */ -#define REGNO_REG_CLASS(REGNO) \ - ((REGNO) == 0 ? GENERAL_REGS \ - : (REGNO) < 32 ? BASE_REGS \ - : FP_REGNO_P (REGNO) ? FLOAT_REGS \ - : (REGNO) == 68 ? CR0_REGS \ - : CR_REGNO_P (REGNO) ? CR_REGS \ - : (REGNO) == 64 ? MQ_REGS \ - : (REGNO) == 65 ? LINK_REGS \ - : (REGNO) == 66 ? CTR_REGS \ - : (REGNO) == 67 ? BASE_REGS \ +#define REGNO_REG_CLASS(REGNO) \ + ((REGNO) == 0 ? GENERAL_REGS \ + : (REGNO) < 32 ? BASE_REGS \ + : FP_REGNO_P (REGNO) ? FLOAT_REGS \ + : (REGNO) == 68 ? CR0_REGS \ + : CR_REGNO_P (REGNO) ? CR_REGS \ + : (REGNO) == 64 ? MQ_REGS \ + : (REGNO) == 65 ? LINK_REGS \ + : (REGNO) == 66 ? CTR_REGS \ + : (REGNO) == 67 ? BASE_REGS \ + : (REGNO) == 76 ? FPMEM_REGS \ : NO_REGS) /* The class value for index registers, and the one for base regs. */ @@ -967,6 +994,7 @@ enum reg_class : (C) == 'l' ? LINK_REGS \ : (C) == 'x' ? CR0_REGS \ : (C) == 'y' ? CR_REGS \ + : (C) == 'z' ? FPMEM_REGS \ : NO_REGS) /* The letters I, J, K, L, M, N, and P in a register constraint string @@ -1033,7 +1061,7 @@ enum reg_class On the RS/6000, we have to return NO_REGS when we want to reload a floating-point CONST_DOUBLE to force it to be copied to memory. */ -#define PREFERRED_RELOAD_CLASS(X,CLASS) \ +#define PREFERRED_RELOAD_CLASS(X,CLASS) \ ((GET_CODE (X) == CONST_DOUBLE \ && GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) \ ? NO_REGS : (CLASS)) @@ -1056,15 +1084,16 @@ enum reg_class On RS/6000, this is the size of MODE in words, except in the FP regs, where a single reg is enough for two words. */ -#define CLASS_MAX_NREGS(CLASS, MODE) \ - ((CLASS) == FLOAT_REGS \ +#define CLASS_MAX_NREGS(CLASS, MODE) \ + (((CLASS) == FLOAT_REGS || (CLASS) == FPMEM_REGS \ + || (CLASS) == FLOAT_OR_FPMEM_REGS) \ ? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_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 +#define CLASS_CANNOT_CHANGE_SIZE FLOAT_OR_FPMEM_REGS /* Stack layout; function entry, exit and calling. */ @@ -1096,6 +1125,7 @@ typedef struct rs6000_stack { int calls_p; /* true if the function makes any calls */ int main_p; /* true if this is main */ int main_save_p; /* true if this is main and we need to save args */ + int fpmem_p; /* true if float/int conversion temp needed */ enum rs6000_abi abi; /* which ABI to use */ int gp_save_offset; /* offset to save GP regs from initial SP */ int fp_save_offset; /* offset to save FP regs from initial SP */ @@ -1104,6 +1134,7 @@ typedef struct rs6000_stack { int toc_save_offset; /* offset to save the TOC pointer */ int varargs_save_offset; /* offset to save the varargs registers */ int main_save_offset; /* offset to save main's args */ + int fpmem_offset; /* offset for float/int conversion temp */ int reg_size; /* register size (4 or 8) */ int varargs_size; /* size to hold V.4 args passed in regs */ int vars_size; /* variable save area size */ @@ -1115,6 +1146,7 @@ typedef struct rs6000_stack { int fp_size; /* size of saved FP registers */ int cr_size; /* size to hold CR if not in save_size */ int lr_size; /* size to hold LR if not in save_size */ + int fpmem_size; /* size to hold float/int conversion */ int toc_size; /* size to hold TOC if not in save_size */ int total_size; /* total bytes allocated for stack */ } rs6000_stack_t; @@ -1144,6 +1176,11 @@ typedef struct rs6000_stack { /* Whether a separate TOC save area is needed */ extern int rs6000_save_toc_p; +/* Offset & size for fpmem stack locations used for converting between + float and integral types. */ +extern int rs6000_fpmem_offset; +extern int rs6000_fpmem_size; + /* Size of the V.4 varargs area if needed */ #define RS6000_VARARGS_AREA 0 @@ -1158,8 +1195,10 @@ extern int rs6000_sysv_varargs_p; ((GP_ARG_NUM_REG * (TARGET_32BIT ? 4 : 8)) + (FP_ARG_NUM_REG * 8) + 8) /* Offset of V.4 varargs area */ -#define RS6000_VARARGS_OFFSET \ - (ALIGN (current_function_outgoing_args_size, 8) + RS6000_SAVE_AREA) +#define RS6000_VARARGS_OFFSET \ + (ALIGN (current_function_outgoing_args_size, 8) \ + + ALIGN (rs6000_fpmem_size, 8) \ + + RS6000_SAVE_AREA) /* Offset within stack frame to start allocating local variables at. If FRAME_GROWS_DOWNWARD, this is the offset to the END of the @@ -1170,9 +1209,22 @@ extern int rs6000_sysv_varargs_p; except for dynamic allocations. So we start after the fixed area and outgoing parameter area. */ -#define STARTING_FRAME_OFFSET (ALIGN (current_function_outgoing_args_size, 8) \ - + RS6000_VARARGS_AREA \ - + RS6000_SAVE_AREA) +#define STARTING_FRAME_OFFSET \ + (ALIGN (current_function_outgoing_args_size, 8) \ + + ALIGN (rs6000_fpmem_size, 8) \ + + RS6000_VARARGS_AREA \ + + RS6000_SAVE_AREA) + +/* Offset from the stack pointer register to an item dynamically + allocated on the stack, e.g., by `alloca'. + + The default value for this macro is `STACK_POINTER_OFFSET' plus the + length of the outgoing arguments. The default is correct for most + machines. See `function.c' for details. */ +#define STACK_DYNAMIC_OFFSET(FUNDECL) \ + (ALIGN (current_function_outgoing_args_size, 8) \ + + ALIGN (rs6000_fpmem_size, 8) \ + + (STACK_POINTER_OFFSET)) /* If we generate an insn to push BYTES bytes, this says how many the stack pointer really advances by. @@ -2516,7 +2568,7 @@ toc_section () \ /* How to refer to registers in assembler output. This sequence is indexed by compiler's hard-register-number (see above). */ -extern char rs6000_reg_names[][8]; /* register names (a0 vs. $4). */ +extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */ #define REGISTER_NAMES \ { \ @@ -2599,6 +2651,8 @@ extern char rs6000_reg_names[][8]; /* register names (a0 vs. $4). */ &rs6000_reg_names[73][0], /* cr5 */ \ &rs6000_reg_names[74][0], /* cr6 */ \ &rs6000_reg_names[75][0], /* cr7 */ \ + \ + &rs6000_reg_names[76][0], /* fpmem */ \ } /* print-rtl can't handle the above REGISTER_NAMES, so define the @@ -2607,16 +2661,17 @@ extern char rs6000_reg_names[][8]; /* register names (a0 vs. $4). */ #define DEBUG_REGISTER_NAMES \ { \ - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \ - "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \ - "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", \ - "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", \ - "mq", "lr", "ctr", "ap", \ - "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7" \ + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \ + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \ + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", \ + "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", \ + "mq", "lr", "ctr", "ap", \ + "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ + "fpmem" \ } /* Table of additional register names to use in user input. */ @@ -2902,7 +2957,7 @@ do { \ /* Define the codes that are matched by predicates in rs6000.c. */ -#define PREDICATE_CODES \ +#define PREDICATE_CODES \ {"short_cint_operand", {CONST_INT}}, \ {"u_short_cint_operand", {CONST_INT}}, \ {"non_short_cint_operand", {CONST_INT}}, \ @@ -2928,6 +2983,7 @@ do { \ {"non_logical_cint_operand", {CONST_INT}}, \ {"mask_operand", {CONST_INT}}, \ {"count_register_operand", {REG}}, \ + {"fpmem_operand", {REG}}, \ {"call_operand", {SYMBOL_REF, REG}}, \ {"current_file_function_operand", {SYMBOL_REF}}, \ {"input_operand", {SUBREG, MEM, REG, CONST_INT, SYMBOL_REF}}, \ @@ -2983,6 +3039,8 @@ extern int non_logical_operand (); extern int mask_constant (); extern int mask_operand (); extern int and_operand (); +extern int count_register_operand (); +extern int fpmem_operand (); extern int non_and_cint_operand (); extern int reg_or_mem_operand (); extern int lwa_operand (); diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index cc843941b33..0dc5f4cb572 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -867,7 +867,7 @@ {cax|add} %0,%1,%2 {cal %0,%2(%1)|addi %0,%1,%2} {ai|addic} %0,%1,%2 - {cau|addis} %0,%1,%u2") + {cau|addis} %0,%1,%v2") (define_insn "" [(set (match_operand:CC 0 "cc_reg_operand" "=x,x") @@ -3543,100 +3543,238 @@ [(set_attr "type" "fp")]) ;; Conversions to and from floating-point. + (define_expand "floatsidf2" - [(set (match_operand:DF 0 "gpc_reg_operand" "") - (float:DF (match_operand:SI 1 "gpc_reg_operand" "")))] + [(parallel [(set (match_operand:DF 0 "gpc_reg_operand" "") + (float:DF (match_operand:SI 1 "gpc_reg_operand" ""))) + (use (match_dup 2)) + (use (match_dup 3)) + (clobber (reg:DF 76))])] "! TARGET_POWERPC64 && TARGET_HARD_FLOAT" " { - if (operands[0]) - { /* prevent unused warning messages */ - rtx high = force_reg (SImode, GEN_INT (0x43300000)); - rtx low = gen_reg_rtx (SImode); - rtx df = gen_reg_rtx (DFmode); - rtx adjust = force_reg (DFmode, rs6000_float_const (\"4503601774854144\", DFmode)); - - emit_insn (gen_xorsi3 (low, operands[1], GEN_INT (0x80000000))); - emit_insn (gen_move_to_float (df, low, high)); - emit_insn (gen_subdf3 (operands[0], df, adjust)); - DONE; - } + rtx low = gen_reg_rtx (SImode); + operands[2] = force_reg (SImode, GEN_INT (0x43300000)); + operands[3] = force_reg (DFmode, rs6000_float_const (\"4503601774854144\", DFmode)); + + emit_insn (gen_xorsi3 (low, operands[1], GEN_INT (0x80000000))); + operands[1] = low; }") -(define_expand "floatunssidf2" +(define_insn "*floatsidf2_internal" + [(set (match_operand:DF 0 "gpc_reg_operand" "=&f") + (float:DF (match_operand:SI 1 "gpc_reg_operand" "r"))) + (use (match_operand:SI 2 "gpc_reg_operand" "r")) + (use (match_operand:DF 3 "gpc_reg_operand" "f")) + (clobber (reg:DF 76))] + "! TARGET_POWERPC64 && TARGET_HARD_FLOAT" + "#" + [(set_attr "length" "16")]) + +(define_split [(set (match_operand:DF 0 "gpc_reg_operand" "") - (unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "")))] + (float:DF (match_operand:SI 1 "gpc_reg_operand" ""))) + (use (match_operand:SI 2 "gpc_reg_operand" "")) + (use (match_operand:DF 3 "gpc_reg_operand" "")) + (clobber (reg:DF 76))] + "! TARGET_POWERPC64 && TARGET_HARD_FLOAT" + [(set (match_dup 4) + (unspec [(match_dup 1) ;; low word + (reg:SI 1)] 11)) + (set (match_dup 4) + (unspec [(match_dup 2) ;; high word + (reg:SI 1) + (match_dup 4)] 12)) + (set (match_dup 0) + (unspec [(match_dup 4) + (reg:SI 1)] 13)) + (set (match_dup 0) + (minus:DF (match_dup 0) + (match_dup 3)))] + "operands[4] = gen_rtx (REG, DFmode, FPMEM_REGNUM);") + +(define_expand "floatunssidf2" + [(parallel [(set (match_operand:DF 0 "gpc_reg_operand" "") + (unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" ""))) + (use (match_dup 2)) + (use (match_dup 3)) + (clobber (reg:DF 76))])] "! TARGET_POWERPC64 && TARGET_HARD_FLOAT" " { - if (operands[0]) - { /* prevent unused warning messages */ - rtx high = force_reg (SImode, GEN_INT (0x43300000)); - rtx df = gen_reg_rtx (DFmode); - rtx adjust = force_reg (DFmode, rs6000_float_const (\"4503599627370496\", DFmode)); - - emit_insn (gen_move_to_float (df, operands[1], high)); - emit_insn (gen_subdf3 (operands[0], df, adjust)); - DONE; - } + operands[2] = force_reg (SImode, GEN_INT (0x43300000)); + operands[3] = force_reg (DFmode, rs6000_float_const (\"4503599627370496\", DFmode)); }") -(define_expand "move_to_float" - [(set (match_dup 4) ;; low word - (match_operand:SI 1 "register_operand" "")) - (set (match_dup 5) ;; high word - (match_operand:SI 2 "register_operand" "")) - (set (match_operand:SI 0 "register_operand" "") ;; float value - (match_dup 3))] +(define_insn "*floatunssidf2_internal" + [(set (match_operand:DF 0 "gpc_reg_operand" "=&f") + (unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "r"))) + (use (match_operand:SI 2 "gpc_reg_operand" "r")) + (use (match_operand:DF 3 "gpc_reg_operand" "f")) + (clobber (reg:DF 76))] "! TARGET_POWERPC64 && TARGET_HARD_FLOAT" - " + "#" + [(set_attr "length" "16")]) + +(define_split + [(set (match_operand:DF 0 "gpc_reg_operand" "") + (unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" ""))) + (use (match_operand:SI 2 "gpc_reg_operand" "")) + (use (match_operand:DF 3 "gpc_reg_operand" "")) + (clobber (reg:DF 76))] + "! TARGET_POWERPC64 && TARGET_HARD_FLOAT" + [(set (match_dup 4) + (unspec [(match_dup 1) ;; low word + (reg:SI 1)] 11)) + (set (match_dup 4) + (unspec [(match_dup 2) ;; high word + (reg:SI 1) + (reg:DF 76)] 12)) + (set (match_dup 0) + (unspec [(match_dup 4) + (reg:SI 1)] 13)) + (set (match_dup 0) + (minus:DF (match_dup 0) + (match_dup 3)))] + "operands[4] = gen_rtx (REG, DFmode, FPMEM_REGNUM);") + +;; Note, we list r1 in the unspec, so that the optimizer is not tempted to optimize +;; around an alloca call (the memory address is constructed directly from r1). + +(define_insn "*floatsidf2_store1" + [(set (reg:DF 76) + (unspec [(match_operand:SI 0 "gpc_reg_operand" "r") + (reg:SI 1)] 11))] + "! TARGET_POWERPC64 && TARGET_HARD_FLOAT" + "* { - operands[3] = gen_reg_rtx (DFmode); + operands[1] = gen_rtx (MEM, SImode, + gen_rtx (PLUS, Pmode, + stack_pointer_rtx, + GEN_INT (rs6000_fpmem_offset + + ((WORDS_BIG_ENDIAN != 0) * 4)))); - if (WORDS_BIG_ENDIAN) - { - operands[4] = gen_rtx (SUBREG, SImode, operands[3], 1); - operands[5] = gen_rtx (SUBREG, SImode, operands[3], 0); - } - else - { - operands[4] = gen_rtx (SUBREG, SImode, operands[3], 0); - operands[5] = gen_rtx (SUBREG, SImode, operands[3], 1); - } -}") + return \"{st|stw} %0,%1\"; +}" + [(set_attr "type" "store")]) + +(define_insn "*floatsidf2_store2" + [(set (reg:DF 76) + (unspec [(match_operand:SI 0 "gpc_reg_operand" "r") + (reg:SI 1) + (reg:DF 76)] 12))] + "! TARGET_POWERPC64 && TARGET_HARD_FLOAT" + "* +{ + operands[1] = gen_rtx (MEM, SImode, + gen_rtx (PLUS, Pmode, + stack_pointer_rtx, + GEN_INT (rs6000_fpmem_offset + + ((WORDS_BIG_ENDIAN == 0) * 4)))); + + return \"{st|stw} %0,%1\"; +}" + [(set_attr "type" "store")]) + +(define_insn "*floatsidf2_load" + [(set (match_operand:DF 0 "gpc_reg_operand" "=f") + (unspec [(reg:DF 76) + (reg:SI 1)] 13))] + "! TARGET_POWERPC64 && TARGET_HARD_FLOAT" + "* +{ + operands[1] = gen_rtx (MEM, SImode, + gen_rtx (PLUS, Pmode, + stack_pointer_rtx, + GEN_INT (rs6000_fpmem_offset))); + + return \"lfd %0,%1\"; +}" + [(set_attr "type" "fpload")]) (define_expand "fix_truncdfsi2" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))] + [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "") + (fix:SI (match_operand:DF 1 "gpc_reg_operand" ""))) + (clobber (match_dup 2)) + (clobber (match_dup 3))])] "TARGET_HARD_FLOAT" " { - if (TARGET_POWER2 || TARGET_POWERPC) - { - rtx temp1 = gen_reg_rtx (DImode); - rtx temp2 = gen_reg_rtx (SImode); - - emit_insn (gen_fpcvtsi (temp1, operands[1])); - emit_move_insn (temp2, gen_rtx (SUBREG, SImode, temp1, WORDS_BIG_ENDIAN)); - emit_move_insn (operands[0], temp2); - DONE; - } - else + if (!TARGET_POWER2 && !TARGET_POWERPC) { emit_insn (gen_trunc_call (operands[0], operands[1], gen_rtx (SYMBOL_REF, Pmode, RS6000_ITRUNC))); DONE; } + + operands[2] = gen_reg_rtx (DImode); + operands[3] = gen_rtx (REG, DImode, FPMEM_REGNUM); }") -(define_insn "fpcvtsi" +(define_insn "*fix_truncdfsi2_internal" + [(set (match_operand:SI 0 "gpc_reg_operand" "=r") + (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))) + (clobber (match_operand:DI 2 "gpc_reg_operand" "=f")) + (clobber (reg:DI 76))] + "TARGET_HARD_FLOAT" + "#" + [(set_attr "length" "12")]) + +(define_split + [(set (match_operand:SI 0 "gpc_reg_operand" "") + (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))) + (clobber (match_operand:DI 2 "gpc_reg_operand" "")) + (clobber (reg:DI 76))] + "TARGET_HARD_FLOAT" + [(set (match_dup 2) + (sign_extend:DI (fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))) + (set (match_dup 3) + (unspec [(match_dup 2) + (reg:SI 1)] 14)) + (set (match_operand:SI 0 "gpc_reg_operand" "") + (unspec [(match_dup 3) + (reg:SI 1)] 15))] + "operands[3] = gen_rtx (REG, DImode, FPMEM_REGNUM);") + +(define_insn "*fctiwz" [(set (match_operand:DI 0 "gpc_reg_operand" "=f") - (sign_extend:DI - (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))))] + (sign_extend:DI (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))))] "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT" "{fcirz|fctiwz} %0,%1" [(set_attr "type" "fp")]) +(define_insn "*fix_truncdfsi2_store" + [(set (reg:DI 76) + (unspec [(match_operand:DI 0 "gpc_reg_operand" "f") + (reg:SI 1)] 14))] + "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT" + "* +{ + operands[1] = gen_rtx (MEM, DFmode, + gen_rtx (PLUS, Pmode, + stack_pointer_rtx, + GEN_INT (rs6000_fpmem_offset))); + + return \"stfd %0,%1\"; +}" + [(set_attr "type" "fpstore")]) + +(define_insn "*fix_truncdfsi2_load" + [(set (match_operand:SI 0 "gpc_reg_operand" "=r") + (unspec [(reg:DI 76) + (reg:SI 1)] 15))] + "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT" + "* +{ + operands[1] = gen_rtx (MEM, DFmode, + gen_rtx (PLUS, Pmode, + stack_pointer_rtx, + GEN_INT (rs6000_fpmem_offset + ((WORDS_BIG_ENDIAN) ? 4 : 0)))); + + return \"{l|lwz} %0,%1\"; +}" + [(set_attr "type" "load")]) + (define_expand "fixuns_truncdfsi2" [(set (match_operand:SI 0 "gpc_reg_operand" "") (unsigned_fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))] @@ -3988,7 +4126,7 @@ add %0,%1,%2 addi %0,%1,%2 addic %0,%1,%2 - addis %0,%1,%u2") + addis %0,%1,%v2") (define_insn "" [(set (match_operand:CC 0 "cc_reg_operand" "=x,x") @@ -5011,7 +5149,7 @@ {l%U1%X1|lwz%U1%X1} %0,%1 {st%U0%X0|stw%U0%X0} %1,%0 {lil|li} %0,%1 - {liu|lis} %0,%u1 + {liu|lis} %0,%v1 # {cal|la} %0,%1(%*) mf%1 %0 @@ -5288,7 +5426,7 @@ {l%U1%X1|lwz%U1%X1} %0,%1 {st%U0%X0|stw%U0%X0} %1,%0 {lil|li} %0,%1 - {liu|lis} %0,%u1 + {liu|lis} %0,%v1 {cal|la} %0,%1(%*)" [(set_attr "type" "*,load,store,*,*,*")]) @@ -5691,7 +5829,7 @@ ld%U1%X1 %0,%1 std%U0%X0 %1,%0 li %0,%1 - lis %0,%u1 + lis %0,%v1 # {cal|la} %0,%1(%*) fmr %0,%1 diff --git a/gcc/config/rs6000/sol2.h b/gcc/config/rs6000/sol2.h index 9ed7ac23c64..357e21cbc33 100644 --- a/gcc/config/rs6000/sol2.h +++ b/gcc/config/rs6000/sol2.h @@ -21,6 +21,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "rs6000/sysv4le.h" +/* Default ABI to use */ +#undef RS6000_ABI_NAME +#define RS6000_ABI_NAME "solaris" + #undef CPP_PREDEFINES #define CPP_PREDEFINES \ "-Dsun=1 -Dunix -D__svr4__ -DSVR4 -DPPC \ @@ -82,6 +86,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define PREFERRED_DEBUGGING_TYPE DBX_DEBUG +#if 0 #undef ASM_OUTPUT_ALIGNED_LOCAL #define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ do { \ @@ -89,7 +94,7 @@ do { \ assemble_name ((FILE), (NAME)); \ fprintf ((FILE), ",%u,%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \ } while (0) - +#endif /* Like block addresses, stabs line numbers are relative to the current function. */ diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h index eb352ad836f..aa556b67b08 100644 --- a/gcc/config/rs6000/sysv4.h +++ b/gcc/config/rs6000/sysv4.h @@ -795,17 +795,22 @@ do { \ fputs (_name, FILE); \ } while (0) -#if 0 -/* The Solaris 2.51 linker has a bug in that it doesn't properly - resolve references from the .init and .fini sections. So fall - back to the old way of handling constructors and destructors. */ #undef ASM_OUTPUT_CONSTRUCTOR #define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ do { \ - init_section (); \ - fputs ("\tbl ", FILE); \ - assemble_name (FILE, NAME); \ - fputs ((flag_pic) ? "@plt\n" : "\n", FILE); \ + if (DEFAULT_ABI != ABI_SOLARIS) \ + { \ + ctors_section (); \ + fprintf (FILE, "\t%s\t ", INT_ASM_OP); \ + assemble_name (FILE, NAME); \ + } \ + else \ + { \ + init_section (); \ + fputs ("\tbl ", FILE); \ + assemble_name (FILE, NAME); \ + } \ + fputs ("\n", FILE); \ } while (0) /* A C statement (sans semicolon) to output an element in the table of @@ -813,12 +818,20 @@ do { \ #undef ASM_OUTPUT_DESTRUCTOR #define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ do { \ - fini_section (); \ - fputs ("\tbl ", FILE); \ - assemble_name (FILE, NAME); \ - fputs ((flag_pic) ? "@plt\n" : "\n", FILE); \ + if (DEFAULT_ABI != ABI_SOLARIS) \ + { \ + dtors_section (); \ + fprintf (FILE, "\t%s\t ", INT_ASM_OP); \ + assemble_name (FILE, NAME); \ + } \ + else \ + { \ + fini_section (); \ + fputs ("\tbl ", FILE); \ + assemble_name (FILE, NAME); \ + } \ + fputs ("\n", FILE); \ } while (0) -#endif /* But, to make this work, we have to output the stabs for the function name *first*... */ @@ -836,7 +849,7 @@ do { \ /* Pass various options to the assembler */ #undef ASM_SPEC -#define ASM_SPEC "-u %(asm_cpu) %{mregnames} \ +#define ASM_SPEC "%(asm_cpu) %{mregnames} \ %{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \ %{mrelocatable} %{mrelocatable-lib} \ %{memb} %{!memb: %{msdata: -memb} %{msdata=eabi: -memb}} \ @@ -856,6 +869,7 @@ do { \ %{mno-sdata: -msdata=none } \ %{meabi: %{!mcall-*: -mcall-sysv }} \ %{!meabi: %{!mno-eabi: \ + %{mrelocatable: -meabi } \ %{mcall-solaris: -mno-eabi } \ %{mcall-linux: -mno-eabi }}}" |