OSDN Git Service

PR target/27075
[pf3gnuchains/gcc-fork.git] / gcc / config / rs6000 / rs6000.c
index aeecdfe..780e905 100644 (file)
@@ -249,11 +249,12 @@ int rs6000_alignment_flags;
 struct {
   bool aix_struct_ret;         /* True if -maix-struct-ret was used.  */
   bool alignment;              /* True if -malign- was used.  */
-  bool abi;                    /* True if -mabi= was used.  */
+  bool abi;                    /* True if -mabi=spe/nospe was used.  */
   bool spe;                    /* True if -mspe= was used.  */
   bool float_gprs;             /* True if -mfloat-gprs= was used.  */
   bool isel;                   /* True if -misel was used. */
   bool long_double;            /* True if -mlong-double- was used.  */
+  bool ieee;                   /* True if -mabi=ieee/ibmlongdouble used.  */
 } rs6000_explicit_options;
 
 struct builtin_description
@@ -601,6 +602,8 @@ static void rs6000_assemble_visibility (tree, int);
 static int rs6000_ra_ever_killed (void);
 static tree rs6000_handle_longcall_attribute (tree *, tree, tree, int, bool *);
 static tree rs6000_handle_altivec_attribute (tree *, tree, tree, int, bool *);
+static bool rs6000_ms_bitfield_layout_p (tree);
+static tree rs6000_handle_struct_attribute (tree *, tree, tree, int, bool *);
 static void rs6000_eliminate_indexed_memrefs (rtx operands[2]);
 static const char *rs6000_mangle_fundamental_type (tree);
 extern const struct attribute_spec rs6000_attribute_table[];
@@ -931,6 +934,9 @@ static const char alt_reg_names[][8] =
 #define TARGET_BINDS_LOCAL_P darwin_binds_local_p
 #endif
 
+#undef TARGET_MS_BITFIELD_LAYOUT_P
+#define TARGET_MS_BITFIELD_LAYOUT_P rs6000_ms_bitfield_layout_p
+
 #undef TARGET_ASM_OUTPUT_MI_THUNK
 #define TARGET_ASM_OUTPUT_MI_THUNK rs6000_output_mi_thunk
 
@@ -1188,6 +1194,9 @@ rs6000_override_options (const char *default_cpu)
         {"power5+", PROCESSOR_POWER5,
          POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GFXOPT
          | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND},
+        {"power6", PROCESSOR_POWER5,
+         POWERPC_7400_MASK | MASK_POWERPC64 | MASK_MFCRF | MASK_POPCNTB
+         | MASK_FPRND},
         {"powerpc", PROCESSOR_POWERPC, POWERPC_BASE_MASK},
         {"powerpc64", PROCESSOR_POWERPC64,
          POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
@@ -1322,7 +1331,7 @@ rs6000_override_options (const char *default_cpu)
     rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
 
 #ifndef POWERPC_LINUX
-  if (!rs6000_explicit_options.abi)
+  if (!rs6000_explicit_options.ieee)
     rs6000_ieeequad = 1;
 #endif
 
@@ -1344,6 +1353,11 @@ rs6000_override_options (const char *default_cpu)
       rs6000_alignment_flags = MASK_ALIGN_NATURAL;
     }
 
+  /* Place FP constants in the constant pool instead of TOC
+     if section anchors enabled.  */
+  if (flag_section_anchors)
+    TARGET_NO_FP_IN_TOC = 1;
+
   /* Handle -mtls-size option.  */
   rs6000_parse_tls_size_option ();
 
@@ -1615,6 +1629,12 @@ optimization_options (int level ATTRIBUTE_UNUSED, int size ATTRIBUTE_UNUSED)
 
   /* Double growth factor to counter reduced min jump length.  */
   set_param_value ("max-grow-copy-bb-insns", 16);
+
+  /* Enable section anchors by default.
+     Skip section anchors for Objective C and Objective C++
+     until front-ends fixed.  */
+  if (!TARGET_MACHO && lang_hooks.name[4] != 'O')
+    flag_section_anchors = 1;
 }
 
 /* Implement TARGET_HANDLE_OPTION.  */
@@ -1777,23 +1797,31 @@ rs6000_handle_option (size_t code, const char *arg, int value)
 #endif
 
     case OPT_mabi_:
-      rs6000_explicit_options.abi = true;
       if (!strcmp (arg, "altivec"))
        {
+         rs6000_explicit_options.abi = true;
          rs6000_altivec_abi = 1;
          rs6000_spe_abi = 0;
        }
       else if (! strcmp (arg, "no-altivec"))
-       rs6000_altivec_abi = 0;
+       {
+         /* ??? Don't set rs6000_explicit_options.abi here, to allow
+            the default for rs6000_spe_abi to be chosen later.  */
+         rs6000_altivec_abi = 0;
+       }
       else if (! strcmp (arg, "spe"))
        {
+         rs6000_explicit_options.abi = true;
          rs6000_spe_abi = 1;
          rs6000_altivec_abi = 0;
          if (!TARGET_SPE_ABI)
            error ("not configured for ABI: '%s'", arg);
        }
       else if (! strcmp (arg, "no-spe"))
-       rs6000_spe_abi = 0;
+       {
+         rs6000_explicit_options.abi = true;
+         rs6000_spe_abi = 0;
+       }
 
       /* These are here for testing during development only, do not
         document in the manual please.  */
@@ -1810,11 +1838,13 @@ rs6000_handle_option (size_t code, const char *arg, int value)
 
       else if (! strcmp (arg, "ibmlongdouble"))
        {
+         rs6000_explicit_options.ieee = true;
          rs6000_ieeequad = 0;
          warning (0, "Using IBM extended precision long double");
        }
       else if (! strcmp (arg, "ieeelongdouble"))
        {
+         rs6000_explicit_options.ieee = true;
          rs6000_ieeequad = 1;
          warning (0, "Using IEEE extended precision long double");
        }
@@ -1993,11 +2023,12 @@ int
 num_insns_constant_wide (HOST_WIDE_INT value)
 {
   /* signed constant loadable with {cal|addi} */
-  if (satisfies_constraint_I (GEN_INT (value)))
+  if ((unsigned HOST_WIDE_INT) (value + 0x8000) < 0x10000)
     return 1;
 
   /* constant loadable with {cau|addis} */
-  else if (satisfies_constraint_L (GEN_INT (value)))
+  else if ((value & 0xffff) == 0
+          && (value >> 31 == -1 || value >> 31 == 0))
     return 1;
 
 #if HOST_BITS_PER_WIDE_INT == 64
@@ -2091,8 +2122,22 @@ num_insns_constant (rtx op, enum machine_mode mode)
     }
 }
 
+/* Interpret element ELT of the CONST_VECTOR OP as an integer value.
+   If the mode of OP is MODE_VECTOR_INT, this simply returns the
+   corresponding element of the vector, but for V4SFmode and V2SFmode,
+   the corresponding "float" is interpreted as an SImode integer.  */
+
+static HOST_WIDE_INT
+const_vector_elt_as_int (rtx op, unsigned int elt)
+{
+  rtx tmp = CONST_VECTOR_ELT (op, elt);
+  if (GET_MODE (op) == V4SFmode
+      || GET_MODE (op) == V2SFmode)
+    tmp = gen_lowpart (SImode, tmp);
+  return INTVAL (tmp);
+}
 
-/* Return true if OP can be synthesized with a particular vspltisb, vspltish 
+/* Return true if OP can be synthesized with a particular vspltisb, vspltish
    or vspltisw instruction.  OP is a CONST_VECTOR.  Which instruction is used
    depends on STEP and COPIES, one of which will be 1.  If COPIES > 1,
    all items are set to the same value and contain COPIES replicas of the
@@ -2110,8 +2155,7 @@ vspltis_constant (rtx op, unsigned step, unsigned copies)
   unsigned bitsize = GET_MODE_BITSIZE (inner);
   unsigned mask = GET_MODE_MASK (inner);
 
-  rtx last = CONST_VECTOR_ELT (op, nunits - 1);
-  HOST_WIDE_INT val = INTVAL (last);
+  HOST_WIDE_INT val = const_vector_elt_as_int (op, nunits - 1);
   HOST_WIDE_INT splat_val = val;
   HOST_WIDE_INT msb_val = val > 0 ? 0 : -1;
 
@@ -2151,7 +2195,7 @@ vspltis_constant (rtx op, unsigned step, unsigned copies)
       else
        desired_val = msb_val;
 
-      if (desired_val != INTVAL (CONST_VECTOR_ELT (op, i)))
+      if (desired_val != const_vector_elt_as_int (op, i))
        return false;
     }
 
@@ -2159,7 +2203,7 @@ vspltis_constant (rtx op, unsigned step, unsigned copies)
 }
 
 
-/* Return true if OP is of the given MODE and can be synthesized 
+/* Return true if OP is of the given MODE and can be synthesized
    with a vspltisb, vspltish or vspltisw.  */
 
 bool
@@ -3377,6 +3421,7 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
 
   if (GET_CODE (x) == SYMBOL_REF
       && !ALTIVEC_VECTOR_MODE (mode)
+      && !SPE_VECTOR_MODE (mode)
 #if TARGET_MACHO
       && DEFAULT_ABI == ABI_DARWIN
       && (flag_pic || MACHO_DYNAMIC_NO_PIC_P)
@@ -3385,9 +3430,12 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
       && !flag_pic
 #endif
       /* Don't do this for TFmode, since the result isn't offsettable.
-        The same goes for DImode without 64-bit gprs.  */
+        The same goes for DImode without 64-bit gprs and DFmode
+        without fprs.  */
       && mode != TFmode
-      && (mode != DImode || TARGET_POWERPC64))
+      && (mode != DImode || TARGET_POWERPC64)
+      && (mode != DFmode || TARGET_POWERPC64
+         || (TARGET_FPRS && TARGET_HARD_FLOAT)))
     {
 #if TARGET_MACHO
       if (flag_pic)
@@ -3432,7 +3480,7 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
       && constant_pool_expr_p (x)
       && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), mode))
     {
-      (x) = create_TOC_reference (x);
+      x = create_TOC_reference (x);
       *win = 1;
       return x;
     }
@@ -3475,6 +3523,7 @@ rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict)
   if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
       && !ALTIVEC_VECTOR_MODE (mode)
       && !SPE_VECTOR_MODE (mode)
+      && mode != TFmode
       /* Restrict addressing for DI because of our SUBREG hackery.  */
       && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == DImode))
       && TARGET_UPDATE
@@ -4438,7 +4487,12 @@ function_arg_padding (enum machine_mode mode, tree type)
    of an argument with the specified mode and type.  If it is not defined,
    PARM_BOUNDARY is used for all arguments.
 
-   V.4 wants long longs to be double word aligned.
+   V.4 wants long longs and doubles to be double word aligned.  Just
+   testing the mode size is a boneheaded way to do this as it means
+   that other types such as complex int are also double word aligned.
+   However, we're stuck with this because changing the ABI might break
+   existing library interfaces.
+
    Doubleword align SPE vectors.
    Quadword align Altivec vectors.
    Quadword align large synthetic vector types.   */
@@ -4446,7 +4500,11 @@ function_arg_padding (enum machine_mode mode, tree type)
 int
 function_arg_boundary (enum machine_mode mode, tree type)
 {
-  if (DEFAULT_ABI == ABI_V4 && GET_MODE_SIZE (mode) == 8)
+  if (DEFAULT_ABI == ABI_V4
+      && (GET_MODE_SIZE (mode) == 8
+         || (TARGET_HARD_FLOAT
+             && TARGET_FPRS
+             && mode == TFmode)))
     return 64;
   else if (SPE_VECTOR_MODE (mode)
           || (type && TREE_CODE (type) == VECTOR_TYPE
@@ -5041,17 +5099,13 @@ rs6000_mixed_function_arg (enum machine_mode mode, tree type, int align_words)
   if (align_words + n_units > GP_ARG_NUM_REG)
     /* Not all of the arg fits in gprs.  Say that it goes in memory too,
        using a magic NULL_RTX component.
-       FIXME: This is not strictly correct.  Only some of the arg
-       belongs in memory, not all of it.  However, there isn't any way
-       to do this currently, apart from building rtx descriptions for
-       the pieces of memory we want stored.  Due to bugs in the generic
-       code we can't use the normal function_arg_partial_nregs scheme
-       with the PARALLEL arg description we emit here.
-       In any case, the code to store the whole arg to memory is often
-       more efficient than code to store pieces, and we know that space
-       is available in the right place for the whole arg.  */
-    /* FIXME: This should be fixed since the conversion to
-       TARGET_ARG_PARTIAL_BYTES.  */
+       This is not strictly correct.  Only some of the arg belongs in
+       memory, not all of it.  However, the normal scheme using
+       function_arg_partial_nregs can result in unusual subregs, eg.
+       (subreg:SI (reg:DF) 4), which are not handled well.  The code to
+       store the whole arg to memory is often more efficient than code
+       to store pieces, and we know that space is available in the right
+       place for the whole arg.  */
     rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx);
 
   i = 0;
@@ -5293,9 +5347,8 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
                         include the portion actually in registers here.  */
                      enum machine_mode rmode = TARGET_32BIT ? SImode : DImode;
                      rtx off;
-                     int i=0;
-                     if (align_words + n_words > GP_ARG_NUM_REG
-                         && (TARGET_32BIT && TARGET_POWERPC64))
+                     int i = 0;
+                     if (align_words + n_words > GP_ARG_NUM_REG)
                        /* Not all of the arg fits in gprs.  Say that it
                           goes in memory too, using a magic NULL_RTX
                           component.  Also see comment in
@@ -5374,18 +5427,20 @@ rs6000_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
 
   align_words = rs6000_parm_start (mode, type, cum->words);
 
-  if (USE_FP_FOR_ARG_P (cum, mode, type)
+  if (USE_FP_FOR_ARG_P (cum, mode, type))
+    {
       /* If we are passing this arg in the fixed parameter save area
         (gprs or memory) as well as fprs, then this function should
-        return the number of bytes passed in the parameter save area
-        rather than bytes passed in fprs.  */
-      && !(type
-          && (cum->nargs_prototype <= 0
-              || (DEFAULT_ABI == ABI_AIX
-                  && TARGET_XL_COMPAT
-                  && align_words >= GP_ARG_NUM_REG))))
-    {
-      if (cum->fregno + ((GET_MODE_SIZE (mode) + 7) >> 3) > FP_ARG_MAX_REG + 1)
+        return the number of partial bytes passed in the parameter
+        save area rather than partial bytes passed in fprs.  */
+      if (type
+         && (cum->nargs_prototype <= 0
+             || (DEFAULT_ABI == ABI_AIX
+                 && TARGET_XL_COMPAT
+                 && align_words >= GP_ARG_NUM_REG)))
+       return 0;
+      else if (cum->fregno + ((GET_MODE_SIZE (mode) + 7) >> 3)
+              > FP_ARG_MAX_REG + 1)
        ret = (FP_ARG_MAX_REG + 1 - cum->fregno) * 8;
       else if (cum->nargs_prototype >= 0)
        return 0;
@@ -5943,10 +5998,10 @@ rs6000_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
       t = build1 (LABEL_EXPR, void_type_node, lab_false);
       append_to_statement_list (t, pre_p);
 
-      if (n_reg > 2)
+      if ((n_reg == 2 && reg != gpr) || n_reg > 2)
        {
          /* Ensure that we don't find any more args in regs.
-            Alignment has taken care of the n_reg == 2 case.  */
+            Alignment has taken care of the n_reg == 2 gpr case.  */
          t = build2 (MODIFY_EXPR, TREE_TYPE (reg), reg, size_int (8));
          gimplify_and_add (t, pre_p);
        }
@@ -9746,12 +9801,12 @@ effects of instruction do not correspond to semantics of RTL insn.  */
 int
 insvdi_rshift_rlwimi_p (rtx sizeop, rtx startop, rtx shiftop)
 {
-  if (INTVAL (startop) < 64
-      && INTVAL (startop) > 32
-      && (INTVAL (sizeop) + INTVAL (startop) < 64)
-      && (INTVAL (sizeop) + INTVAL (startop) > 33)
-      && (INTVAL (sizeop) + INTVAL (startop) + INTVAL (shiftop) < 96)
-      && (INTVAL (sizeop) + INTVAL (startop) + INTVAL (shiftop) >= 64)
+  if (INTVAL (startop) > 32
+      && INTVAL (startop) < 64
+      && INTVAL (sizeop) > 1
+      && INTVAL (sizeop) + INTVAL (startop) < 64
+      && INTVAL (shiftop) > 0
+      && INTVAL (sizeop) + INTVAL (shiftop) < 32
       && (64 - (INTVAL (shiftop) & 63)) >= INTVAL (sizeop))
     return 1;
 
@@ -10228,13 +10283,14 @@ print_operand (FILE *file, rtx x, int code)
       return;
 
     case 'D':
-      /* Like 'J' but get to the EQ bit.  */
+      /* Like 'J' but get to the GT bit only.  */
       gcc_assert (GET_CODE (x) == REG);
 
-      /* Bit 1 is EQ bit.  */
-      i = 4 * (REGNO (x) - CR0_REGNO) + 2;
+      /* Bit 1 is GT bit.  */
+      i = 4 * (REGNO (x) - CR0_REGNO) + 1;
 
-      fprintf (file, "%d", i);
+      /* Add one for shift count in rlinm for scc.  */
+      fprintf (file, "%d", i + 1);
       return;
 
     case 'E':
@@ -10733,7 +10789,8 @@ print_operand (FILE *file, rtx x, int code)
 
        tmp = XEXP (x, 0);
 
-       if (TARGET_E500)
+       /* Ugly hack because %y is overloaded.  */
+       if (TARGET_E500 && GET_MODE_SIZE (GET_MODE (x)) == 8)
          {
            /* Handle [reg].  */
            if (GET_CODE (tmp) == REG)
@@ -11031,7 +11088,7 @@ rs6000_generate_compare (enum rtx_code code)
   /* First, the compare.  */
   compare_result = gen_reg_rtx (comp_mode);
 
-  /* SPE FP compare instructions on the GPRs.  Yuck!  */
+  /* E500 FP compare instructions on the GPRs.  Yuck!  */
   if ((TARGET_E500 && !TARGET_FPRS && TARGET_HARD_FLOAT)
       && rs6000_compare_fp_p)
     {
@@ -11041,8 +11098,8 @@ rs6000_generate_compare (enum rtx_code code)
       if (op_mode == VOIDmode)
        op_mode = GET_MODE (rs6000_compare_op1);
 
-      /* Note: The E500 comparison instructions set the GT bit (x +
-        1), on success.  This explains the mess.  */
+      /* The E500 FP compare instructions toggle the GT bit (CR bit 1) only.
+        This explains the following mess.  */
 
       switch (code)
        {
@@ -11442,7 +11499,8 @@ output_cbranch (rtx op, const char *label, int reversed, rtx insn)
         mispredicted taken branch is more expensive than a
         mispredicted not-taken branch.  */
       if (rs6000_always_hint
-         || abs (prob) > REG_BR_PROB_BASE / 100 * 48)
+         || (abs (prob) > REG_BR_PROB_BASE / 100 * 48
+             && br_prob_note_reliable_p (note)))
        {
          if (abs (prob) > REG_BR_PROB_BASE / 20
              && ((prob > 0) ^ need_longbranch))
@@ -15309,7 +15367,8 @@ rs6000_output_function_epilogue (FILE *file,
         official way to discover the language being compiled, so we
         use language_string.
         C is 0.  Fortran is 1.  Pascal is 2.  Ada is 3.  C++ is 9.
-        Java is 13.  Objective-C is 14.  */
+        Java is 13.  Objective-C is 14.  Objective-C++ isn't assigned
+        a number, so for now use 9.  */
       if (! strcmp (language_string, "GNU C"))
        i = 0;
       else if (! strcmp (language_string, "GNU F77")
@@ -15319,7 +15378,8 @@ rs6000_output_function_epilogue (FILE *file,
        i = 2;
       else if (! strcmp (language_string, "GNU Ada"))
        i = 3;
-      else if (! strcmp (language_string, "GNU C++"))
+      else if (! strcmp (language_string, "GNU C++")
+              || ! strcmp (language_string, "GNU Objective-C++"))
        i = 9;
       else if (! strcmp (language_string, "GNU Java"))
        i = 13;
@@ -17286,9 +17346,8 @@ rs6000_trampoline_size (void)
 void
 rs6000_initialize_trampoline (rtx addr, rtx fnaddr, rtx cxt)
 {
-  enum machine_mode pmode = Pmode;
   int regsize = (TARGET_32BIT) ? 4 : 8;
-  rtx ctx_reg = force_reg (pmode, cxt);
+  rtx ctx_reg = force_reg (Pmode, cxt);
 
   switch (DEFAULT_ABI)
     {
@@ -17296,15 +17355,15 @@ rs6000_initialize_trampoline (rtx addr, rtx fnaddr, rtx cxt)
       gcc_unreachable ();
 
 /* Macros to shorten the code expansions below.  */
-#define MEM_DEREF(addr) gen_rtx_MEM (pmode, memory_address (pmode, addr))
+#define MEM_DEREF(addr) gen_rtx_MEM (Pmode, memory_address (Pmode, addr))
 #define MEM_PLUS(addr,offset) \
-  gen_rtx_MEM (pmode, memory_address (pmode, plus_constant (addr, offset)))
+  gen_rtx_MEM (Pmode, memory_address (Pmode, plus_constant (addr, offset)))
 
     /* Under AIX, just build the 3 word function descriptor */
     case ABI_AIX:
       {
-       rtx fn_reg = gen_reg_rtx (pmode);
-       rtx toc_reg = gen_reg_rtx (pmode);
+       rtx fn_reg = gen_reg_rtx (Pmode);
+       rtx toc_reg = gen_reg_rtx (Pmode);
        emit_move_insn (fn_reg, MEM_DEREF (fnaddr));
        emit_move_insn (toc_reg, MEM_PLUS (fnaddr, regsize));
        emit_move_insn (MEM_DEREF (addr), fn_reg);
@@ -17316,12 +17375,12 @@ rs6000_initialize_trampoline (rtx addr, rtx fnaddr, rtx cxt)
     /* Under V.4/eabi/darwin, __trampoline_setup does the real work.  */
     case ABI_DARWIN:
     case ABI_V4:
-      emit_library_call (gen_rtx_SYMBOL_REF (SImode, "__trampoline_setup"),
+      emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__trampoline_setup"),
                         FALSE, VOIDmode, 4,
-                        addr, pmode,
+                        addr, Pmode,
                         GEN_INT (rs6000_trampoline_size ()), SImode,
-                        fnaddr, pmode,
-                        ctx_reg, pmode);
+                        fnaddr, Pmode,
+                        ctx_reg, Pmode);
       break;
     }
 
@@ -17337,6 +17396,8 @@ const struct attribute_spec rs6000_attribute_table[] =
   { "altivec",   1, 1, false, true,  false, rs6000_handle_altivec_attribute },
   { "longcall",  0, 0, false, true,  true,  rs6000_handle_longcall_attribute },
   { "shortcall", 0, 0, false, true,  true,  rs6000_handle_longcall_attribute },
+  { "ms_struct", 0, 0, false, false, false, rs6000_handle_struct_attribute },
+  { "gcc_struct", 0, 0, false, false, false, rs6000_handle_struct_attribute },
 #ifdef SUBTARGET_ATTRIBUTE_TABLE
   SUBTARGET_ATTRIBUTE_TABLE,
 #endif
@@ -17507,6 +17568,10 @@ rs6000_set_default_type_attributes (tree type)
     TYPE_ATTRIBUTES (type) = tree_cons (get_identifier ("longcall"),
                                        NULL_TREE,
                                        TYPE_ATTRIBUTES (type));
+
+#if TARGET_MACHO
+  darwin_set_default_type_attributes (type);
+#endif
 }
 
 /* Return a reference suitable for calling a function with the
@@ -17535,6 +17600,54 @@ rs6000_longcall_ref (rtx call_ref)
   return force_reg (Pmode, call_ref);
 }
 \f
+#ifndef TARGET_USE_MS_BITFIELD_LAYOUT
+#define TARGET_USE_MS_BITFIELD_LAYOUT 0
+#endif
+
+/* Handle a "ms_struct" or "gcc_struct" attribute; arguments as in
+   struct attribute_spec.handler.  */
+static tree
+rs6000_handle_struct_attribute (tree *node, tree name,
+                               tree args ATTRIBUTE_UNUSED,
+                               int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+{
+  tree *type = NULL;
+  if (DECL_P (*node))
+    {
+      if (TREE_CODE (*node) == TYPE_DECL)
+        type = &TREE_TYPE (*node);
+    }
+  else
+    type = node;
+
+  if (!(type && (TREE_CODE (*type) == RECORD_TYPE
+                 || TREE_CODE (*type) == UNION_TYPE)))
+    {
+      warning (OPT_Wattributes, "%qs attribute ignored", IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+
+  else if ((is_attribute_p ("ms_struct", name)
+            && lookup_attribute ("gcc_struct", TYPE_ATTRIBUTES (*type)))
+           || ((is_attribute_p ("gcc_struct", name)
+                && lookup_attribute ("ms_struct", TYPE_ATTRIBUTES (*type)))))
+    {
+      warning (OPT_Wattributes, "%qs incompatible attribute ignored",
+               IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
+static bool
+rs6000_ms_bitfield_layout_p (tree record_type)
+{
+  return (TARGET_USE_MS_BITFIELD_LAYOUT &&
+          !lookup_attribute ("gcc_struct", TYPE_ATTRIBUTES (record_type)))
+    || lookup_attribute ("ms_struct", TYPE_ATTRIBUTES (record_type));
+}
+\f
 #ifdef USING_ELFOS_H
 
 /* A get_unnamed_section callback, used for switching to toc_section.  */
@@ -17996,7 +18109,7 @@ machopic_output_stub (FILE *file, const char *symb, const char *stub)
    position-independent addresses go into a reg.  This is REG if non
    zero, otherwise we allocate register(s) as necessary.  */
 
-#define SMALL_INT(X) ((unsigned) (INTVAL (X) + 0x8000) < 0x10000)
+#define SMALL_INT(X) ((UINTVAL (X) + 0x8000) < 0x10000)
 
 rtx
 rs6000_machopic_legitimize_pic_address (rtx orig, enum machine_mode mode,
@@ -18575,28 +18688,25 @@ rs6000_rtx_costs (rtx x, int code, int outer_code, int *total)
       /* FALLTHRU */
 
     case CONST_DOUBLE:
-      if (mode == DImode
-         && ((outer_code == AND
-              && (satisfies_constraint_K (x)
-                  || satisfies_constraint_L (x)
-                  || mask_operand (x, DImode)
-                  || mask64_operand (x, DImode)))
-             || ((outer_code == IOR || outer_code == XOR)
-                 && CONST_DOUBLE_HIGH (x) == 0
-                 && (CONST_DOUBLE_LOW (x)
-                     & ~ (unsigned HOST_WIDE_INT) 0xffff) == 0)))
-       {
-         *total = 0;
-         return true;
-       }
-      else if (mode == DImode
-              && (outer_code == SET
-                  || outer_code == IOR
-                  || outer_code == XOR)
-              && CONST_DOUBLE_HIGH (x) == 0)
+      if (mode == DImode && code == CONST_DOUBLE)
        {
-         *total = COSTS_N_INSNS (1);
-         return true;
+         if ((outer_code == IOR || outer_code == XOR)
+             && CONST_DOUBLE_HIGH (x) == 0
+             && (CONST_DOUBLE_LOW (x)
+                 & ~ (unsigned HOST_WIDE_INT) 0xffff) == 0)
+           {
+             *total = 0;
+             return true;
+           }
+         else if ((outer_code == AND && and64_2_operand (x, DImode))
+                  || ((outer_code == SET
+                       || outer_code == IOR
+                       || outer_code == XOR)
+                      && CONST_DOUBLE_HIGH (x) == 0))
+           {
+             *total = COSTS_N_INSNS (1);
+             return true;
+           }
        }
       /* FALLTHRU */