Commit 802a0058 by Michael Meissner

Fix problems in float/int conversion in inline functions

From-SVN: r12122
parent 18496203
...@@ -99,35 +99,42 @@ int rs6000_save_toc_p; ...@@ -99,35 +99,42 @@ int rs6000_save_toc_p;
/* ABI enumeration available for subtarget to use. */ /* ABI enumeration available for subtarget to use. */
enum rs6000_abi rs6000_current_abi; 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. */ /* Default register names. */
char rs6000_reg_names[][8] = char rs6000_reg_names[][8] =
{ {
"0", "1", "2", "3", "4", "5", "6", "7", "0", "1", "2", "3", "4", "5", "6", "7",
"8", "9", "10", "11", "12", "13", "14", "15", "8", "9", "10", "11", "12", "13", "14", "15",
"16", "17", "18", "19", "20", "21", "22", "23", "16", "17", "18", "19", "20", "21", "22", "23",
"24", "25", "26", "27", "28", "29", "30", "31", "24", "25", "26", "27", "28", "29", "30", "31",
"0", "1", "2", "3", "4", "5", "6", "7", "0", "1", "2", "3", "4", "5", "6", "7",
"8", "9", "10", "11", "12", "13", "14", "15", "8", "9", "10", "11", "12", "13", "14", "15",
"16", "17", "18", "19", "20", "21", "22", "23", "16", "17", "18", "19", "20", "21", "22", "23",
"24", "25", "26", "27", "28", "29", "30", "31", "24", "25", "26", "27", "28", "29", "30", "31",
"mq", "lr", "ctr","ap", "mq", "lr", "ctr","ap",
"0", "1", "2", "3", "4", "5", "6", "7" "0", "1", "2", "3", "4", "5", "6", "7",
"fpmem"
}; };
#ifdef TARGET_REGNAMES #ifdef TARGET_REGNAMES
static char alt_reg_names[][8] = static char alt_reg_names[][8] =
{ {
"%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7", "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
"%r16", "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%r23", "%r16", "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%r23",
"%r24", "%r25", "%r26", "%r27", "%r28", "%r29", "%r30", "%r31", "%r24", "%r25", "%r26", "%r27", "%r28", "%r29", "%r30", "%r31",
"%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7", "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
"%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15", "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15",
"%f16", "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23", "%f16", "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23",
"%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31", "%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31",
"mq", "lr", "ctr", "ap", "mq", "lr", "ctr", "ap",
"%cr0", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5", "%cr6", "%cr7" "%cr0", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5", "%cr6", "%cr7",
"fpmem"
}; };
#endif #endif
...@@ -363,6 +370,26 @@ int count_register_operand(op, mode) ...@@ -363,6 +370,26 @@ int count_register_operand(op, mode)
return 0; 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. */ /* Return 1 if OP is a constant that can fit in a D field. */
int int
...@@ -404,7 +431,9 @@ gpc_reg_operand (op, mode) ...@@ -404,7 +431,9 @@ gpc_reg_operand (op, mode)
enum machine_mode mode; enum machine_mode mode;
{ {
return (register_operand (op, 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 /* Returns 1 if OP is either a pseudo-register or a register denoting a
...@@ -1785,7 +1814,7 @@ includes_rshift_p (shiftop, andop) ...@@ -1785,7 +1814,7 @@ includes_rshift_p (shiftop, andop)
register rtx shiftop; register rtx shiftop;
register rtx andop; register rtx andop;
{ {
unsigned shift_mask = ~0; unsigned shift_mask = ~(unsigned)0;
shift_mask >>= INTVAL (shiftop); shift_mask >>= INTVAL (shiftop);
...@@ -2319,13 +2348,29 @@ print_operand (file, x, code) ...@@ -2319,13 +2348,29 @@ print_operand (file, x, code)
return; return;
case 'u': case 'u':
/* High-order 16 bits of constant. */ /* High-order 16 bits of constant for use in unsigned operand. */
if (! INT_P (x)) if (! INT_P (x))
output_operand_lossage ("invalid %%u value"); output_operand_lossage ("invalid %%u value");
fprintf (file, "0x%x", (INT_LOWPART (x) >> 16) & 0xffff); fprintf (file, "0x%x", (INT_LOWPART (x) >> 16) & 0xffff);
return; 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': case 'U':
/* Print `u' if this has an auto-increment or auto-decrement. */ /* Print `u' if this has an auto-increment or auto-decrement. */
if (GET_CODE (x) == MEM if (GET_CODE (x) == MEM
...@@ -2575,13 +2620,15 @@ rs6000_makes_calls () ...@@ -2575,13 +2620,15 @@ rs6000_makes_calls ()
+---------------------------------------+ +---------------------------------------+
| Parameter save area (P) | 24 | 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 | old SP->| back chain to caller's caller |
+---------------------------------------+ +---------------------------------------+
...@@ -2595,17 +2642,19 @@ rs6000_makes_calls () ...@@ -2595,17 +2642,19 @@ rs6000_makes_calls ()
+---------------------------------------+ +---------------------------------------+
| Parameter save area (P) | 8 | 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 | old SP->| back chain to caller's caller |
+---------------------------------------+ +---------------------------------------+
...@@ -2628,21 +2677,23 @@ rs6000_makes_calls () ...@@ -2628,21 +2677,23 @@ rs6000_makes_calls ()
+---------------------------------------+ +---------------------------------------+
| Parameter save area (P) | 24 | 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 | old SP->| back chain to caller's caller |
+---------------------------------------+ +---------------------------------------+
...@@ -2685,6 +2736,9 @@ rs6000_stack_info () ...@@ -2685,6 +2736,9 @@ rs6000_stack_info ()
info_ptr->toc_size = reg_size; 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, /* If this is main and we need to call a function to set things up,
save main's arguments around the call. */ save main's arguments around the call. */
#ifdef TARGET_EABI #ifdef TARGET_EABI
...@@ -2749,6 +2803,7 @@ rs6000_stack_info () ...@@ -2749,6 +2803,7 @@ rs6000_stack_info ()
info_ptr->varargs_size = RS6000_VARARGS_AREA; info_ptr->varargs_size = RS6000_VARARGS_AREA;
info_ptr->vars_size = ALIGN (get_frame_size (), 8); info_ptr->vars_size = ALIGN (get_frame_size (), 8);
info_ptr->parm_size = ALIGN (current_function_outgoing_args_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->save_size = ALIGN (info_ptr->fp_size
+ info_ptr->gp_size + info_ptr->gp_size
+ info_ptr->cr_size + info_ptr->cr_size
...@@ -2758,6 +2813,7 @@ rs6000_stack_info () ...@@ -2758,6 +2813,7 @@ rs6000_stack_info ()
total_raw_size = (info_ptr->vars_size total_raw_size = (info_ptr->vars_size
+ info_ptr->parm_size + info_ptr->parm_size
+ info_ptr->fpmem_size
+ info_ptr->save_size + info_ptr->save_size
+ info_ptr->varargs_size + info_ptr->varargs_size
+ info_ptr->fixed_size); + info_ptr->fixed_size);
...@@ -2785,6 +2841,7 @@ rs6000_stack_info () ...@@ -2785,6 +2841,7 @@ rs6000_stack_info ()
|| info_ptr->total_size > 220); || info_ptr->total_size > 220);
/* Calculate the offsets */ /* Calculate the offsets */
info_ptr->fpmem_offset = info_ptr->total_size - info_ptr->parm_size;
switch (abi) switch (abi)
{ {
case ABI_NONE: case ABI_NONE:
...@@ -2842,6 +2899,16 @@ rs6000_stack_info () ...@@ -2842,6 +2899,16 @@ rs6000_stack_info ()
if (!info_ptr->main_save_p) if (!info_ptr->main_save_p)
info_ptr->main_save_offset = 0; 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; return info_ptr;
} }
...@@ -2899,6 +2966,9 @@ debug_stack_info (info) ...@@ -2899,6 +2966,9 @@ debug_stack_info (info)
if (info->main_save_p) if (info->main_save_p)
fprintf (stderr, "\tmain_save_p = %5d\n", 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) if (info->gp_save_offset)
fprintf (stderr, "\tgp_save_offset = %5d\n", info->gp_save_offset); fprintf (stderr, "\tgp_save_offset = %5d\n", info->gp_save_offset);
...@@ -2920,6 +2990,9 @@ debug_stack_info (info) ...@@ -2920,6 +2990,9 @@ debug_stack_info (info)
if (info->main_save_offset) if (info->main_save_offset)
fprintf (stderr, "\tmain_save_offset = %5d\n", 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) if (info->total_size)
fprintf (stderr, "\ttotal_size = %5d\n", info->total_size); fprintf (stderr, "\ttotal_size = %5d\n", info->total_size);
...@@ -2932,6 +3005,9 @@ debug_stack_info (info) ...@@ -2932,6 +3005,9 @@ debug_stack_info (info)
if (info->parm_size) if (info->parm_size)
fprintf (stderr, "\tparm_size = %5d\n", 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) if (info->fixed_size)
fprintf (stderr, "\tfixed_size = %5d\n", info->fixed_size); fprintf (stderr, "\tfixed_size = %5d\n", info->fixed_size);
...@@ -3619,6 +3695,8 @@ output_epilog (file, size) ...@@ -3619,6 +3695,8 @@ output_epilog (file, size)
/* Reset varargs and save TOC indicator */ /* Reset varargs and save TOC indicator */
rs6000_sysv_varargs_p = 0; rs6000_sysv_varargs_p = 0;
rs6000_save_toc_p = 0; rs6000_save_toc_p = 0;
rs6000_fpmem_size = 0;
rs6000_fpmem_offset = 0;
pic_offset_table_rtx = (rtx)0; pic_offset_table_rtx = (rtx)0;
if (DEFAULT_ABI == ABI_NT) if (DEFAULT_ABI == ABI_NT)
...@@ -4601,7 +4679,6 @@ handle_mac_pragma (finput, t) ...@@ -4601,7 +4679,6 @@ handle_mac_pragma (finput, t)
pname = IDENTIFIER_POINTER (t); pname = IDENTIFIER_POINTER (t);
if (strcmp (pname, "segment") == 0) if (strcmp (pname, "segment") == 0)
{ {
retval = 1;
/* (should collect pbuf + 8 into a segment name) */ /* (should collect pbuf + 8 into a segment name) */
} }
else if (strcmp (pname, "options") == 0) else if (strcmp (pname, "options") == 0)
...@@ -4613,7 +4690,10 @@ handle_mac_pragma (finput, t) ...@@ -4613,7 +4690,10 @@ handle_mac_pragma (finput, t)
/* Return without doing anything if no content. */ /* Return without doing anything if no content. */
if (c == '\n' || c == EOF) if (c == '\n' || c == EOF)
return 0; {
ungetc (c, finput);
return 0;
}
/* Collect the rest of the line. */ /* Collect the rest of the line. */
while (psize < sizeof (pbuf) - 1 && c != '\n') while (psize < sizeof (pbuf) - 1 && c != '\n')
...@@ -4624,14 +4704,21 @@ handle_mac_pragma (finput, t) ...@@ -4624,14 +4704,21 @@ handle_mac_pragma (finput, t)
if (strncmp (pbuf, "align=mac68k", 12) == 0) 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) 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 */ /* END CYGNUS LOCAL mac */
...@@ -618,9 +618,14 @@ extern struct rs6000_cpu_select rs6000_select[]; ...@@ -618,9 +618,14 @@ extern struct rs6000_cpu_select rs6000_select[];
In addition, the difference between the frame and argument pointers is 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 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. 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 /* 1 for registers that have pervasive standard uses
and are not available for the register allocator. and are not available for the register allocator.
...@@ -640,7 +645,7 @@ extern struct rs6000_cpu_select rs6000_select[]; ...@@ -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, 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. /* 1 for registers not available across function calls.
These must include the FIXED_REGISTERS and also any These must include the FIXED_REGISTERS and also any
...@@ -654,7 +659,7 @@ extern struct rs6000_cpu_select rs6000_select[]; ...@@ -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, \ 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, \ 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, \ 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 /* List the order in which to allocate registers. Each register must be
listed once, even those in FIXED_REGISTERS. listed once, even those in FIXED_REGISTERS.
...@@ -691,7 +696,7 @@ extern struct rs6000_cpu_select rs6000_select[]; ...@@ -691,7 +696,7 @@ extern struct rs6000_cpu_select rs6000_select[];
31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, \ 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, \
18, 17, 16, 15, 14, 13, 12, \ 18, 17, 16, 15, 14, 13, 12, \
64, 66, 65, \ 64, 66, 65, \
73, 1, 2, 67} 73, 1, 2, 67, 76}
/* True if register is floating-point. */ /* True if register is floating-point. */
#define FP_REGNO_P(N) ((N) >= 32 && (N) <= 63) #define FP_REGNO_P(N) ((N) >= 32 && (N) <= 63)
...@@ -702,6 +707,10 @@ extern struct rs6000_cpu_select rs6000_select[]; ...@@ -702,6 +707,10 @@ extern struct rs6000_cpu_select rs6000_select[];
/* True if register is an integer register. */ /* True if register is an integer register. */
#define INT_REGNO_P(N) ((N) <= 31 || (N) == 67) #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 /* Return number of consecutive hard regs needed starting at reg REGNO
to hold something of mode MODE. to hold something of mode MODE.
This is ordinarily the length in words of a value 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[]; ...@@ -710,8 +719,8 @@ extern struct rs6000_cpu_select rs6000_select[];
On RS/6000, ordinary registers hold 32 bits worth; On RS/6000, ordinary registers hold 32 bits worth;
a single floating point register holds 64 bits worth. */ a single floating point register holds 64 bits worth. */
#define HARD_REGNO_NREGS(REGNO, MODE) \ #define HARD_REGNO_NREGS(REGNO, MODE) \
(FP_REGNO_P (REGNO) \ (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_FP_WORD - 1) / UNITS_PER_FP_WORD) \
: ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
...@@ -721,13 +730,14 @@ extern struct rs6000_cpu_select rs6000_select[]; ...@@ -721,13 +730,14 @@ extern struct rs6000_cpu_select rs6000_select[];
can hold CC modes. We cannot put TImode anywhere except general can hold CC modes. We cannot put TImode anywhere except general
register and it must be able to fit within the register set. */ register and it must be able to fit within the register set. */
#define HARD_REGNO_MODE_OK(REGNO, MODE) \ #define HARD_REGNO_MODE_OK(REGNO, MODE) \
(FP_REGNO_P (REGNO) ? \ (FP_REGNO_P (REGNO) ? \
(GET_MODE_CLASS (MODE) == MODE_FLOAT \ (GET_MODE_CLASS (MODE) == MODE_FLOAT \
|| (GET_MODE_CLASS (MODE) == MODE_INT \ || (GET_MODE_CLASS (MODE) == MODE_INT \
&& GET_MODE_SIZE (MODE) == UNITS_PER_FP_WORD)) \ && GET_MODE_SIZE (MODE) == UNITS_PER_FP_WORD)) \
: CR_REGNO_P (REGNO) ? GET_MODE_CLASS (MODE) == MODE_CC \ : CR_REGNO_P (REGNO) ? GET_MODE_CLASS (MODE) == MODE_CC \
: ! INT_REGNO_P (REGNO) ? (GET_MODE_CLASS (MODE) == MODE_INT \ : 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) \ && GET_MODE_SIZE (MODE) <= UNITS_PER_WORD) \
: 1) : 1)
...@@ -761,7 +771,7 @@ extern struct rs6000_cpu_select rs6000_select[]; ...@@ -761,7 +771,7 @@ extern struct rs6000_cpu_select rs6000_select[];
|| (CLASS1) == LINK_OR_CTR_REGS) \ || (CLASS1) == LINK_OR_CTR_REGS) \
&& ((CLASS2) == SPECIAL_REGS || (CLASS2) == MQ_REGS \ && ((CLASS2) == SPECIAL_REGS || (CLASS2) == MQ_REGS \
|| (CLASS2) == LINK_REGS || (CLASS2) == CTR_REGS \ || (CLASS2) == LINK_REGS || (CLASS2) == CTR_REGS \
|| (CLASS2) == LINK_OR_CTR_REGS)) ? 10 \ || (CLASS2) == LINK_OR_CTR_REGS)) ? 10 \
: 2) : 2)
/* A C expressions returning the cost of moving data of MODE from a register to /* 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[]; ...@@ -834,6 +844,9 @@ extern struct rs6000_cpu_select rs6000_select[];
/* count register number for special purposes */ /* count register number for special purposes */
#define COUNT_REGISTER_REGNUM 66 #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. /* Place that structure value return address is placed.
On the RS/6000, it is passed as an extra parameter. */ On the RS/6000, it is passed as an extra parameter. */
...@@ -867,7 +880,14 @@ extern struct rs6000_cpu_select rs6000_select[]; ...@@ -867,7 +880,14 @@ extern struct rs6000_cpu_select rs6000_select[];
So make a class for registers valid as base registers. So make a class for registers valid as base registers.
Also, cr0 is the only condition code register that can be used in 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 enum reg_class
{ {
...@@ -885,6 +905,8 @@ enum reg_class ...@@ -885,6 +905,8 @@ enum reg_class
CR0_REGS, CR0_REGS,
CR_REGS, CR_REGS,
NON_FLOAT_REGS, NON_FLOAT_REGS,
FPMEM_REGS,
FLOAT_OR_FPMEM_REGS,
ALL_REGS, ALL_REGS,
LIM_REG_CLASSES LIM_REG_CLASSES
}; };
...@@ -909,6 +931,8 @@ enum reg_class ...@@ -909,6 +931,8 @@ enum reg_class
"CR0_REGS", \ "CR0_REGS", \
"CR_REGS", \ "CR_REGS", \
"NON_FLOAT_REGS", \ "NON_FLOAT_REGS", \
"FPMEM_REGS", \
"FLOAT_OR_FPMEM_REGS", \
"ALL_REGS" \ "ALL_REGS" \
} }
...@@ -932,7 +956,9 @@ enum reg_class ...@@ -932,7 +956,9 @@ enum reg_class
{ 0x00000000, 0x00000000, 0x00000010 }, /* CR0_REGS */ \ { 0x00000000, 0x00000000, 0x00000010 }, /* CR0_REGS */ \
{ 0x00000000, 0x00000000, 0x00000ff0 }, /* CR_REGS */ \ { 0x00000000, 0x00000000, 0x00000ff0 }, /* CR_REGS */ \
{ 0xffffffff, 0x00000000, 0x0000ffff }, /* NON_FLOAT_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: /* The same information, inverted:
...@@ -940,16 +966,17 @@ enum reg_class ...@@ -940,16 +966,17 @@ enum reg_class
reg number REGNO. This could be a conditional expression reg number REGNO. This could be a conditional expression
or could index an array. */ or could index an array. */
#define REGNO_REG_CLASS(REGNO) \ #define REGNO_REG_CLASS(REGNO) \
((REGNO) == 0 ? GENERAL_REGS \ ((REGNO) == 0 ? GENERAL_REGS \
: (REGNO) < 32 ? BASE_REGS \ : (REGNO) < 32 ? BASE_REGS \
: FP_REGNO_P (REGNO) ? FLOAT_REGS \ : FP_REGNO_P (REGNO) ? FLOAT_REGS \
: (REGNO) == 68 ? CR0_REGS \ : (REGNO) == 68 ? CR0_REGS \
: CR_REGNO_P (REGNO) ? CR_REGS \ : CR_REGNO_P (REGNO) ? CR_REGS \
: (REGNO) == 64 ? MQ_REGS \ : (REGNO) == 64 ? MQ_REGS \
: (REGNO) == 65 ? LINK_REGS \ : (REGNO) == 65 ? LINK_REGS \
: (REGNO) == 66 ? CTR_REGS \ : (REGNO) == 66 ? CTR_REGS \
: (REGNO) == 67 ? BASE_REGS \ : (REGNO) == 67 ? BASE_REGS \
: (REGNO) == 76 ? FPMEM_REGS \
: NO_REGS) : NO_REGS)
/* The class value for index registers, and the one for base regs. */ /* The class value for index registers, and the one for base regs. */
...@@ -967,6 +994,7 @@ enum reg_class ...@@ -967,6 +994,7 @@ enum reg_class
: (C) == 'l' ? LINK_REGS \ : (C) == 'l' ? LINK_REGS \
: (C) == 'x' ? CR0_REGS \ : (C) == 'x' ? CR0_REGS \
: (C) == 'y' ? CR_REGS \ : (C) == 'y' ? CR_REGS \
: (C) == 'z' ? FPMEM_REGS \
: NO_REGS) : NO_REGS)
/* The letters I, J, K, L, M, N, and P in a register constraint string /* The letters I, J, K, L, M, N, and P in a register constraint string
...@@ -1033,7 +1061,7 @@ enum reg_class ...@@ -1033,7 +1061,7 @@ enum reg_class
On the RS/6000, we have to return NO_REGS when we want to reload a 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. */ 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_CODE (X) == CONST_DOUBLE \
&& GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) \ && GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) \
? NO_REGS : (CLASS)) ? NO_REGS : (CLASS))
...@@ -1056,15 +1084,16 @@ enum reg_class ...@@ -1056,15 +1084,16 @@ enum reg_class
On RS/6000, this is the size of MODE in words, 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. */ except in the FP regs, where a single reg is enough for two words. */
#define CLASS_MAX_NREGS(CLASS, MODE) \ #define CLASS_MAX_NREGS(CLASS, MODE) \
((CLASS) == FLOAT_REGS \ (((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_FP_WORD - 1) / UNITS_PER_FP_WORD) \
: ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_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 /* If defined, gives a class of registers that cannot be used as the
operand of a SUBREG that changes the size of the object. */ 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. */ /* Stack layout; function entry, exit and calling. */
...@@ -1096,6 +1125,7 @@ typedef struct rs6000_stack { ...@@ -1096,6 +1125,7 @@ typedef struct rs6000_stack {
int calls_p; /* true if the function makes any calls */ int calls_p; /* true if the function makes any calls */
int main_p; /* true if this is main */ int main_p; /* true if this is main */
int main_save_p; /* true if this is main and we need to save args */ 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 */ enum rs6000_abi abi; /* which ABI to use */
int gp_save_offset; /* offset to save GP regs from initial SP */ int gp_save_offset; /* offset to save GP regs from initial SP */
int fp_save_offset; /* offset to save FP regs from initial SP */ int fp_save_offset; /* offset to save FP regs from initial SP */
...@@ -1104,6 +1134,7 @@ typedef struct rs6000_stack { ...@@ -1104,6 +1134,7 @@ typedef struct rs6000_stack {
int toc_save_offset; /* offset to save the TOC pointer */ int toc_save_offset; /* offset to save the TOC pointer */
int varargs_save_offset; /* offset to save the varargs registers */ int varargs_save_offset; /* offset to save the varargs registers */
int main_save_offset; /* offset to save main's args */ 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 reg_size; /* register size (4 or 8) */
int varargs_size; /* size to hold V.4 args passed in regs */ int varargs_size; /* size to hold V.4 args passed in regs */
int vars_size; /* variable save area size */ int vars_size; /* variable save area size */
...@@ -1115,6 +1146,7 @@ typedef struct rs6000_stack { ...@@ -1115,6 +1146,7 @@ typedef struct rs6000_stack {
int fp_size; /* size of saved FP registers */ int fp_size; /* size of saved FP registers */
int cr_size; /* size to hold CR if not in save_size */ 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 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 toc_size; /* size to hold TOC if not in save_size */
int total_size; /* total bytes allocated for stack */ int total_size; /* total bytes allocated for stack */
} rs6000_stack_t; } rs6000_stack_t;
...@@ -1144,6 +1176,11 @@ typedef struct rs6000_stack { ...@@ -1144,6 +1176,11 @@ typedef struct rs6000_stack {
/* Whether a separate TOC save area is needed */ /* Whether a separate TOC save area is needed */
extern int rs6000_save_toc_p; 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 */ /* Size of the V.4 varargs area if needed */
#define RS6000_VARARGS_AREA 0 #define RS6000_VARARGS_AREA 0
...@@ -1158,8 +1195,10 @@ extern int rs6000_sysv_varargs_p; ...@@ -1158,8 +1195,10 @@ extern int rs6000_sysv_varargs_p;
((GP_ARG_NUM_REG * (TARGET_32BIT ? 4 : 8)) + (FP_ARG_NUM_REG * 8) + 8) ((GP_ARG_NUM_REG * (TARGET_32BIT ? 4 : 8)) + (FP_ARG_NUM_REG * 8) + 8)
/* Offset of V.4 varargs area */ /* Offset of V.4 varargs area */
#define RS6000_VARARGS_OFFSET \ #define RS6000_VARARGS_OFFSET \
(ALIGN (current_function_outgoing_args_size, 8) + RS6000_SAVE_AREA) (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. /* Offset within stack frame to start allocating local variables at.
If FRAME_GROWS_DOWNWARD, this is the offset to the END of the If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
...@@ -1170,9 +1209,22 @@ extern int rs6000_sysv_varargs_p; ...@@ -1170,9 +1209,22 @@ extern int rs6000_sysv_varargs_p;
except for dynamic allocations. So we start after the fixed area and except for dynamic allocations. So we start after the fixed area and
outgoing parameter area. */ outgoing parameter area. */
#define STARTING_FRAME_OFFSET (ALIGN (current_function_outgoing_args_size, 8) \ #define STARTING_FRAME_OFFSET \
+ RS6000_VARARGS_AREA \ (ALIGN (current_function_outgoing_args_size, 8) \
+ RS6000_SAVE_AREA) + 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, /* If we generate an insn to push BYTES bytes,
this says how many the stack pointer really advances by. this says how many the stack pointer really advances by.
...@@ -2516,7 +2568,7 @@ toc_section () \ ...@@ -2516,7 +2568,7 @@ toc_section () \
/* How to refer to registers in assembler output. /* How to refer to registers in assembler output.
This sequence is indexed by compiler's hard-register-number (see above). */ 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 \ #define REGISTER_NAMES \
{ \ { \
...@@ -2599,6 +2651,8 @@ extern char rs6000_reg_names[][8]; /* register names (a0 vs. $4). */ ...@@ -2599,6 +2651,8 @@ extern char rs6000_reg_names[][8]; /* register names (a0 vs. $4). */
&rs6000_reg_names[73][0], /* cr5 */ \ &rs6000_reg_names[73][0], /* cr5 */ \
&rs6000_reg_names[74][0], /* cr6 */ \ &rs6000_reg_names[74][0], /* cr6 */ \
&rs6000_reg_names[75][0], /* cr7 */ \ &rs6000_reg_names[75][0], /* cr7 */ \
\
&rs6000_reg_names[76][0], /* fpmem */ \
} }
/* print-rtl can't handle the above REGISTER_NAMES, so define the /* 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). */ ...@@ -2607,16 +2661,17 @@ extern char rs6000_reg_names[][8]; /* register names (a0 vs. $4). */
#define DEBUG_REGISTER_NAMES \ #define DEBUG_REGISTER_NAMES \
{ \ { \
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \
"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", \ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", \
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", \ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", \
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", \ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", \
"mq", "lr", "ctr", "ap", \ "mq", "lr", "ctr", "ap", \
"cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7" \ "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
"fpmem" \
} }
/* Table of additional register names to use in user input. */ /* Table of additional register names to use in user input. */
...@@ -2902,7 +2957,7 @@ do { \ ...@@ -2902,7 +2957,7 @@ do { \
/* Define the codes that are matched by predicates in rs6000.c. */ /* Define the codes that are matched by predicates in rs6000.c. */
#define PREDICATE_CODES \ #define PREDICATE_CODES \
{"short_cint_operand", {CONST_INT}}, \ {"short_cint_operand", {CONST_INT}}, \
{"u_short_cint_operand", {CONST_INT}}, \ {"u_short_cint_operand", {CONST_INT}}, \
{"non_short_cint_operand", {CONST_INT}}, \ {"non_short_cint_operand", {CONST_INT}}, \
...@@ -2928,6 +2983,7 @@ do { \ ...@@ -2928,6 +2983,7 @@ do { \
{"non_logical_cint_operand", {CONST_INT}}, \ {"non_logical_cint_operand", {CONST_INT}}, \
{"mask_operand", {CONST_INT}}, \ {"mask_operand", {CONST_INT}}, \
{"count_register_operand", {REG}}, \ {"count_register_operand", {REG}}, \
{"fpmem_operand", {REG}}, \
{"call_operand", {SYMBOL_REF, REG}}, \ {"call_operand", {SYMBOL_REF, REG}}, \
{"current_file_function_operand", {SYMBOL_REF}}, \ {"current_file_function_operand", {SYMBOL_REF}}, \
{"input_operand", {SUBREG, MEM, REG, CONST_INT, SYMBOL_REF}}, \ {"input_operand", {SUBREG, MEM, REG, CONST_INT, SYMBOL_REF}}, \
...@@ -2983,6 +3039,8 @@ extern int non_logical_operand (); ...@@ -2983,6 +3039,8 @@ extern int non_logical_operand ();
extern int mask_constant (); extern int mask_constant ();
extern int mask_operand (); extern int mask_operand ();
extern int and_operand (); extern int and_operand ();
extern int count_register_operand ();
extern int fpmem_operand ();
extern int non_and_cint_operand (); extern int non_and_cint_operand ();
extern int reg_or_mem_operand (); extern int reg_or_mem_operand ();
extern int lwa_operand (); extern int lwa_operand ();
......
...@@ -867,7 +867,7 @@ ...@@ -867,7 +867,7 @@
{cax|add} %0,%1,%2 {cax|add} %0,%1,%2
{cal %0,%2(%1)|addi %0,%1,%2} {cal %0,%2(%1)|addi %0,%1,%2}
{ai|addic} %0,%1,%2 {ai|addic} %0,%1,%2
{cau|addis} %0,%1,%u2") {cau|addis} %0,%1,%v2")
(define_insn "" (define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x") [(set (match_operand:CC 0 "cc_reg_operand" "=x,x")
...@@ -3543,100 +3543,238 @@ ...@@ -3543,100 +3543,238 @@
[(set_attr "type" "fp")]) [(set_attr "type" "fp")])
;; Conversions to and from floating-point. ;; Conversions to and from floating-point.
(define_expand "floatsidf2" (define_expand "floatsidf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "") [(parallel [(set (match_operand:DF 0 "gpc_reg_operand" "")
(float:DF (match_operand:SI 1 "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" "! TARGET_POWERPC64 && TARGET_HARD_FLOAT"
" "
{ {
if (operands[0]) rtx low = gen_reg_rtx (SImode);
{ /* prevent unused warning messages */ operands[2] = force_reg (SImode, GEN_INT (0x43300000));
rtx high = force_reg (SImode, GEN_INT (0x43300000)); operands[3] = force_reg (DFmode, rs6000_float_const (\"4503601774854144\", DFmode));
rtx low = gen_reg_rtx (SImode);
rtx df = gen_reg_rtx (DFmode); emit_insn (gen_xorsi3 (low, operands[1], GEN_INT (0x80000000)));
rtx adjust = force_reg (DFmode, rs6000_float_const (\"4503601774854144\", DFmode)); operands[1] = low;
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;
}
}") }")
(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" "") [(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" "! TARGET_POWERPC64 && TARGET_HARD_FLOAT"
" "
{ {
if (operands[0]) operands[2] = force_reg (SImode, GEN_INT (0x43300000));
{ /* prevent unused warning messages */ operands[3] = force_reg (DFmode, rs6000_float_const (\"4503599627370496\", DFmode));
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;
}
}") }")
(define_expand "move_to_float" (define_insn "*floatunssidf2_internal"
[(set (match_dup 4) ;; low word [(set (match_operand:DF 0 "gpc_reg_operand" "=&f")
(match_operand:SI 1 "register_operand" "")) (unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))
(set (match_dup 5) ;; high word (use (match_operand:SI 2 "gpc_reg_operand" "r"))
(match_operand:SI 2 "register_operand" "")) (use (match_operand:DF 3 "gpc_reg_operand" "f"))
(set (match_operand:SI 0 "register_operand" "") ;; float value (clobber (reg:DF 76))]
(match_dup 3))]
"! TARGET_POWERPC64 && TARGET_HARD_FLOAT" "! 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) return \"{st|stw} %0,%1\";
{ }"
operands[4] = gen_rtx (SUBREG, SImode, operands[3], 1); [(set_attr "type" "store")])
operands[5] = gen_rtx (SUBREG, SImode, operands[3], 0);
} (define_insn "*floatsidf2_store2"
else [(set (reg:DF 76)
{ (unspec [(match_operand:SI 0 "gpc_reg_operand" "r")
operands[4] = gen_rtx (SUBREG, SImode, operands[3], 0); (reg:SI 1)
operands[5] = gen_rtx (SUBREG, SImode, operands[3], 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" (define_expand "fix_truncdfsi2"
[(set (match_operand:SI 0 "gpc_reg_operand" "") [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "")
(fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))] (fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))
(clobber (match_dup 2))
(clobber (match_dup 3))])]
"TARGET_HARD_FLOAT" "TARGET_HARD_FLOAT"
" "
{ {
if (TARGET_POWER2 || TARGET_POWERPC) 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
{ {
emit_insn (gen_trunc_call (operands[0], operands[1], emit_insn (gen_trunc_call (operands[0], operands[1],
gen_rtx (SYMBOL_REF, Pmode, RS6000_ITRUNC))); gen_rtx (SYMBOL_REF, Pmode, RS6000_ITRUNC)));
DONE; 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") [(set (match_operand:DI 0 "gpc_reg_operand" "=f")
(sign_extend:DI (sign_extend:DI (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))))]
(fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))))]
"(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT" "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT"
"{fcirz|fctiwz} %0,%1" "{fcirz|fctiwz} %0,%1"
[(set_attr "type" "fp")]) [(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" (define_expand "fixuns_truncdfsi2"
[(set (match_operand:SI 0 "gpc_reg_operand" "") [(set (match_operand:SI 0 "gpc_reg_operand" "")
(unsigned_fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))] (unsigned_fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))]
...@@ -3988,7 +4126,7 @@ ...@@ -3988,7 +4126,7 @@
add %0,%1,%2 add %0,%1,%2
addi %0,%1,%2 addi %0,%1,%2
addic %0,%1,%2 addic %0,%1,%2
addis %0,%1,%u2") addis %0,%1,%v2")
(define_insn "" (define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x") [(set (match_operand:CC 0 "cc_reg_operand" "=x,x")
...@@ -5011,7 +5149,7 @@ ...@@ -5011,7 +5149,7 @@
{l%U1%X1|lwz%U1%X1} %0,%1 {l%U1%X1|lwz%U1%X1} %0,%1
{st%U0%X0|stw%U0%X0} %1,%0 {st%U0%X0|stw%U0%X0} %1,%0
{lil|li} %0,%1 {lil|li} %0,%1
{liu|lis} %0,%u1 {liu|lis} %0,%v1
# #
{cal|la} %0,%1(%*) {cal|la} %0,%1(%*)
mf%1 %0 mf%1 %0
...@@ -5288,7 +5426,7 @@ ...@@ -5288,7 +5426,7 @@
{l%U1%X1|lwz%U1%X1} %0,%1 {l%U1%X1|lwz%U1%X1} %0,%1
{st%U0%X0|stw%U0%X0} %1,%0 {st%U0%X0|stw%U0%X0} %1,%0
{lil|li} %0,%1 {lil|li} %0,%1
{liu|lis} %0,%u1 {liu|lis} %0,%v1
{cal|la} %0,%1(%*)" {cal|la} %0,%1(%*)"
[(set_attr "type" "*,load,store,*,*,*")]) [(set_attr "type" "*,load,store,*,*,*")])
...@@ -5691,7 +5829,7 @@ ...@@ -5691,7 +5829,7 @@
ld%U1%X1 %0,%1 ld%U1%X1 %0,%1
std%U0%X0 %1,%0 std%U0%X0 %1,%0
li %0,%1 li %0,%1
lis %0,%u1 lis %0,%v1
# #
{cal|la} %0,%1(%*) {cal|la} %0,%1(%*)
fmr %0,%1 fmr %0,%1
......
...@@ -21,6 +21,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -21,6 +21,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "rs6000/sysv4le.h" #include "rs6000/sysv4le.h"
/* Default ABI to use */
#undef RS6000_ABI_NAME
#define RS6000_ABI_NAME "solaris"
#undef CPP_PREDEFINES #undef CPP_PREDEFINES
#define CPP_PREDEFINES \ #define CPP_PREDEFINES \
"-Dsun=1 -Dunix -D__svr4__ -DSVR4 -DPPC \ "-Dsun=1 -Dunix -D__svr4__ -DSVR4 -DPPC \
...@@ -82,6 +86,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -82,6 +86,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG #define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
#if 0
#undef ASM_OUTPUT_ALIGNED_LOCAL #undef ASM_OUTPUT_ALIGNED_LOCAL
#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ #define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
do { \ do { \
...@@ -89,7 +94,7 @@ do { \ ...@@ -89,7 +94,7 @@ do { \
assemble_name ((FILE), (NAME)); \ assemble_name ((FILE), (NAME)); \
fprintf ((FILE), ",%u,%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \ fprintf ((FILE), ",%u,%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \
} while (0) } while (0)
#endif
/* Like block addresses, stabs line numbers are relative to the /* Like block addresses, stabs line numbers are relative to the
current function. */ current function. */
......
...@@ -795,17 +795,22 @@ do { \ ...@@ -795,17 +795,22 @@ do { \
fputs (_name, FILE); \ fputs (_name, FILE); \
} while (0) } 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 #undef ASM_OUTPUT_CONSTRUCTOR
#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ #define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
do { \ do { \
init_section (); \ if (DEFAULT_ABI != ABI_SOLARIS) \
fputs ("\tbl ", FILE); \ { \
assemble_name (FILE, NAME); \ ctors_section (); \
fputs ((flag_pic) ? "@plt\n" : "\n", FILE); \ 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) } while (0)
/* A C statement (sans semicolon) to output an element in the table of /* A C statement (sans semicolon) to output an element in the table of
...@@ -813,12 +818,20 @@ do { \ ...@@ -813,12 +818,20 @@ do { \
#undef ASM_OUTPUT_DESTRUCTOR #undef ASM_OUTPUT_DESTRUCTOR
#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ #define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
do { \ do { \
fini_section (); \ if (DEFAULT_ABI != ABI_SOLARIS) \
fputs ("\tbl ", FILE); \ { \
assemble_name (FILE, NAME); \ dtors_section (); \
fputs ((flag_pic) ? "@plt\n" : "\n", FILE); \ 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) } while (0)
#endif
/* But, to make this work, we have to output the stabs for the function /* But, to make this work, we have to output the stabs for the function
name *first*... */ name *first*... */
...@@ -836,7 +849,7 @@ do { \ ...@@ -836,7 +849,7 @@ do { \
/* Pass various options to the assembler */ /* Pass various options to the assembler */
#undef ASM_SPEC #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,*:%*} \ %{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \
%{mrelocatable} %{mrelocatable-lib} \ %{mrelocatable} %{mrelocatable-lib} \
%{memb} %{!memb: %{msdata: -memb} %{msdata=eabi: -memb}} \ %{memb} %{!memb: %{msdata: -memb} %{msdata=eabi: -memb}} \
...@@ -856,6 +869,7 @@ do { \ ...@@ -856,6 +869,7 @@ do { \
%{mno-sdata: -msdata=none } \ %{mno-sdata: -msdata=none } \
%{meabi: %{!mcall-*: -mcall-sysv }} \ %{meabi: %{!mcall-*: -mcall-sysv }} \
%{!meabi: %{!mno-eabi: \ %{!meabi: %{!mno-eabi: \
%{mrelocatable: -meabi } \
%{mcall-solaris: -mno-eabi } \ %{mcall-solaris: -mno-eabi } \
%{mcall-linux: -mno-eabi }}}" %{mcall-linux: -mno-eabi }}}"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment