summaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authormeissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4>1996-05-28 19:58:24 +0000
committermeissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4>1996-05-28 19:58:24 +0000
commit359e408d73f1088b80709eebf420fa854449b7c8 (patch)
tree627990e3a3942dae74f4cecab49c150bac528480 /gcc/config
parent57ed72532034e6376b2094ce11d974f9af2a0db6 (diff)
downloadgcc-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.c179
-rw-r--r--gcc/config/rs6000/rs6000.h154
-rw-r--r--gcc/config/rs6000/rs6000.md272
-rw-r--r--gcc/config/rs6000/sol2.h7
-rw-r--r--gcc/config/rs6000/sysv4.h42
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 }}}"