summaryrefslogtreecommitdiff
path: root/gcc/config/rs6000/rs6000.c
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/rs6000/rs6000.c
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/rs6000/rs6000.c')
-rw-r--r--gcc/config/rs6000/rs6000.c179
1 files changed, 133 insertions, 46 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 */