Fix problems in float/int conversion in inline functions
authorMichael Meissner <meissner@gcc.gnu.org>
Tue, 28 May 1996 19:58:24 +0000 (19:58 +0000)
committerMichael Meissner <meissner@gcc.gnu.org>
Tue, 28 May 1996 19:58:24 +0000 (19:58 +0000)
From-SVN: r12122

gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/config/rs6000/rs6000.md
gcc/config/rs6000/sol2.h
gcc/config/rs6000/sysv4.h

index 9fcb101..276008b 100644 (file)
@@ -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;
+
 \f
 /* 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
 \f
@@ -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 */
index e4857c6..5f0d7b9 100644 (file)
@@ -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
 \f
 /* 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 ();
index cc84394..0dc5f4c 100644 (file)
    {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")
   [(set_attr "type" "fp")])
 \f
 ;; 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" "")))]
    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")
    {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
    {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,*,*,*")])
 
    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
index 9ed7ac2..357e21c 100644 (file)
@@ -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.  */
index eb352ad..aa556b6 100644 (file)
@@ -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 }}}"