OSDN Git Service

Some SSE fixes
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / i386.c
index 6be389c..caccc7e 100644 (file)
@@ -375,6 +375,7 @@ const int x86_memory_mismatch_stall = m_ATHLON | m_PENT4;
 const int x86_accumulate_outgoing_args = m_ATHLON | m_PENT4 | m_PPRO;
 const int x86_prologue_using_move = m_ATHLON | m_PENT4 | m_PPRO;
 const int x86_epilogue_using_move = m_ATHLON | m_PENT4 | m_PPRO;
+const int x86_decompose_lea = m_PENT4;
 
 /* In case the avreage insn count for single function invocation is
    lower than this constant, emit fast (but longer) prologue and
@@ -695,10 +696,7 @@ static tree ix86_handle_regparm_attribute PARAMS ((tree *, tree, tree, int, bool
 #ifdef DO_GLOBAL_CTORS_BODY
 static void ix86_svr3_asm_out_constructor PARAMS ((rtx, int));
 #endif
-#if defined(TARGET_ELF) && defined(TARGET_COFF)
-static void sco_asm_named_section PARAMS ((const char *, unsigned int));
-static void sco_asm_out_constructor PARAMS ((rtx, int));
-#endif
+
 /* Register class used for passing given 64bit part of the argument.
    These represent classes as documented by the PS ABI, with the exception
    of SSESF, SSEDF classes, that are basically SSE class, just gcc will
@@ -798,19 +796,21 @@ override_options ()
       const int target_enable;                 /* Target flags to enable.  */
       const int target_disable;                        /* Target flags to disable.  */
       const int align_loop;                    /* Default alignments.  */
+      const int align_loop_max_skip;
       const int align_jump;
+      const int align_jump_max_skip;
       const int align_func;
       const int branch_cost;
     }
   const processor_target_table[PROCESSOR_max] =
     {
-      {&i386_cost, 0, 0, 2, 2, 2, 1},
-      {&i486_cost, 0, 0, 4, 4, 4, 1},
-      {&pentium_cost, 0, 0, -4, -4, -4, 1},
-      {&pentiumpro_cost, 0, 0, 4, -4, 4, 1},
-      {&k6_cost, 0, 0, -5, -5, 4, 1},
-      {&athlon_cost, 0, 0, 4, -4, 4, 1},
-      {&pentium4_cost, 0, 0, 2, 2, 2, 1}
+      {&i386_cost, 0, 0, 4, 3, 4, 3, 4, 1},
+      {&i486_cost, 0, 0, 16, 15, 16, 15, 16, 1},
+      {&pentium_cost, 0, 0, 16, 7, 16, 7, 16, 1},
+      {&pentiumpro_cost, 0, 0, 16, 15, 16, 7, 16, 1},
+      {&k6_cost, 0, 0, 32, 7, 32, 7, 32, 1},
+      {&athlon_cost, 0, 0, 16, 7, 64, 7, 16, 1},
+      {&pentium4_cost, 0, 0, 0, 0, 0, 0, 0, 1}
     };
 
   static struct pta
@@ -969,20 +969,32 @@ override_options ()
   /* Default align_* from the processor table.  */
 #define abs(n) (n < 0 ? -n : n)
   if (align_loops == 0)
-    align_loops = 1 << abs (processor_target_table[ix86_cpu].align_loop);
+    {
+      align_loops = processor_target_table[ix86_cpu].align_loop;
+      align_loops_max_skip = processor_target_table[ix86_cpu].align_loop_max_skip;
+    }
   if (align_jumps == 0)
-    align_jumps = 1 << abs (processor_target_table[ix86_cpu].align_jump);
+    {
+      align_jumps = processor_target_table[ix86_cpu].align_jump;
+      align_jumps_max_skip = processor_target_table[ix86_cpu].align_jump_max_skip;
+    }
   if (align_functions == 0)
-    align_functions = 1 << abs (processor_target_table[ix86_cpu].align_func);
+    {
+      align_functions = processor_target_table[ix86_cpu].align_func;
+    }
 
   /* Validate -mpreferred-stack-boundary= value, or provide default.
-     The default of 128 bits is for Pentium III's SSE __m128.  */
-  ix86_preferred_stack_boundary = 128;
+     The default of 128 bits is for Pentium III's SSE __m128, but we
+     don't want additional code to keep the stack aligned when
+     optimizing for code size.  */
+  ix86_preferred_stack_boundary = (optimize_size
+                                  ? TARGET_64BIT ? 64 : 32
+                                  : 128);
   if (ix86_preferred_stack_boundary_string)
     {
       i = atoi (ix86_preferred_stack_boundary_string);
-      if (i < (TARGET_64BIT ? 3 : 2) || i > 31)
-       error ("-mpreferred-stack-boundary=%d is not between %d and 31", i,
+      if (i < (TARGET_64BIT ? 3 : 2) || i > 12)
+       error ("-mpreferred-stack-boundary=%d is not between %d and 12", i,
               TARGET_64BIT ? 3 : 2);
       else
        ix86_preferred_stack_boundary = (1 << i) * BITS_PER_UNIT;
@@ -1061,7 +1073,10 @@ optimization_options (level, size)
   if (TARGET_64BIT && optimize >= 1)
     flag_omit_frame_pointer = 1;
   if (TARGET_64BIT)
-    flag_pcc_struct_return = 0;
+    {
+      flag_pcc_struct_return = 0;
+      flag_asynchronous_unwind_tables = 1;
+    }
 }
 \f
 /* Table of valid machine attributes.  */
@@ -1174,8 +1189,8 @@ ix86_osf_output_function_prologue (file, size)
      FILE *file;
      HOST_WIDE_INT size;
 {
-  char *prefix = "";
-  char *lprefix = LPREFIX;
+  const char *prefix = "";
+  const char *const lprefix = LPREFIX;
   int labelno = profile_label_no;
 
 #ifdef OSF_OS
@@ -1414,7 +1429,7 @@ init_cumulative_args (cum, fntype, libname)
 }
 
 /* x86-64 register passing impleemntation.  See x86-64 ABI for details.  Goal
-   of this code is to classify each 8bytes of incomming argument by the register
+   of this code is to classify each 8bytes of incoming argument by the register
    class and assign registers accordingly.  */
 
 /* Return the union class of CLASS1 and CLASS2.
@@ -1612,7 +1627,7 @@ classify_argument (mode, type, classes, bit_offset)
        mode_alignment = 128;
       else if (mode == XCmode)
        mode_alignment = 256;
-      /* Missalignmed fields are always returned in memory.  */
+      /* Misaligned fields are always returned in memory.  */
       if (bit_offset % mode_alignment)
        return 0;
     }
@@ -1674,7 +1689,7 @@ classify_argument (mode, type, classes, bit_offset)
 }
 
 /* Examine the argument and return set number of register required in each
-   class.  Return 0 ifif parameter should be passed in memory.  */
+   class.  Return 0 iff parameter should be passed in memory.  */
 static int
 examine_argument (mode, type, in_return, int_nregs, sse_nregs)
      enum machine_mode mode;
@@ -2056,7 +2071,7 @@ ix86_function_value (valtype)
     return gen_rtx_REG (TYPE_MODE (valtype), VALUE_REGNO (TYPE_MODE (valtype)));
 }
 
-/* Return false ifif type is returned in memory.  */
+/* Return false iff type is returned in memory.  */
 int
 ix86_return_in_memory (type)
      tree type;
@@ -2245,14 +2260,16 @@ ix86_setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl)
         pointing 127 bytes after first byte to store - this is needed to keep
         instruction size limited by 4 bytes.  */
       tmp_reg = gen_reg_rtx (Pmode);
-      emit_insn (gen_rtx_SET(VOIDmode, tmp_reg,
-                            plus_constant (save_area, 8 * REGPARM_MAX + 127)));
+      emit_insn (gen_rtx_SET (VOIDmode, tmp_reg,
+                             plus_constant (save_area,
+                                            8 * REGPARM_MAX + 127)));
       mem = gen_rtx_MEM (BLKmode, plus_constant (tmp_reg, -127));
       set_mem_alias_set (mem, set);
+      set_mem_align (mem, BITS_PER_WORD);
 
       /* And finally do the dirty job!  */
-      emit_insn (gen_sse_prologue_save (mem, nsse_reg, GEN_INT (next_cum.sse_regno),
-                label));
+      emit_insn (gen_sse_prologue_save (mem, nsse_reg,
+                                       GEN_INT (next_cum.sse_regno), label));
     }
 
 }
@@ -2331,7 +2348,7 @@ ix86_va_arg (valist, type)
   static int intreg[6] = { 0, 1, 2, 3, 4, 5 };
   tree f_gpr, f_fpr, f_ovf, f_sav;
   tree gpr, fpr, ovf, sav, t;
-  int indirect_p = 0, size, rsize;
+  int size, rsize;
   rtx lab_false, lab_over = NULL_RTX;
   rtx addr_rtx, r;
   rtx container;
@@ -2427,7 +2444,7 @@ ix86_va_arg (valist, type)
                                   (gpr, NULL_RTX, SImode, EXPAND_NORMAL),
                                   GEN_INT ((REGPARM_MAX - needed_intregs +
                                             1) * 8), GE, const1_rtx, SImode,
-                                  1, 1, lab_false);
+                                  1, lab_false);
        }
       if (needed_sseregs)
        {
@@ -2436,7 +2453,7 @@ ix86_va_arg (valist, type)
                                   GEN_INT ((SSE_REGPARM_MAX -
                                             needed_sseregs + 1) * 16 +
                                            REGPARM_MAX * 8), GE, const1_rtx,
-                                  SImode, 1, 1, lab_false);
+                                  SImode, 1, lab_false);
        }
 
       /* Compute index to start of area used for integer regs.  */
@@ -2459,9 +2476,12 @@ ix86_va_arg (valist, type)
          int i;
          rtx mem;
 
-         mem = assign_temp (type, 0, 1, 0);
+         /* Never use the memory itself, as it has the alias set.  */
+         addr_rtx = XEXP (assign_temp (type, 0, 1, 0), 0);
+         mem = gen_rtx_MEM (BLKmode, addr_rtx);
          set_mem_alias_set (mem, get_varargs_alias_set ());
-         addr_rtx = XEXP (mem, 0);
+         set_mem_align (mem, BITS_PER_UNIT);
+
          for (i = 0; i < XVECLEN (container, 0); i++)
            {
              rtx slot = XVECEXP (container, 0, i);
@@ -2486,8 +2506,6 @@ ix86_va_arg (valist, type)
              set_mem_alias_set (src_mem, get_varargs_alias_set ());
              src_mem = adjust_address (src_mem, mode, src_offset);
              dest_mem = adjust_address (mem, mode, INTVAL (XEXP (slot, 1)));
-             PUT_MODE (dest_mem, mode);
-             /* ??? Break out TImode moves from integer registers?  */
              emit_move_insn (dest_mem, src_mem);
            }
        }
@@ -2543,14 +2561,6 @@ ix86_va_arg (valist, type)
   if (container)
     emit_label (lab_over);
 
-  if (indirect_p)
-    {
-      abort ();
-      r = gen_rtx_MEM (Pmode, addr_rtx);
-      set_mem_alias_set (r, get_varargs_alias_set ());
-      emit_move_insn (addr_rtx, r);
-    }
-
   return addr_rtx;
 }
 \f
@@ -2854,7 +2864,7 @@ incdec_operand (op, mode)
      register rtx op;
      enum machine_mode mode ATTRIBUTE_UNUSED;
 {
-  /* On Pentium4, the inc and dec operations causes extra dependancy on flag
+  /* On Pentium4, the inc and dec operations causes extra dependency on flag
      registers, since carry flag is not set.  */
   if (TARGET_PENTIUM4 && !optimize_size)
     return 0;
@@ -3802,7 +3812,7 @@ ix86_compute_frame_layout (frame)
 
   /* Do some sanity checking of stack_alignment_needed and
      preferred_alignment, since i386 port is the only using those features
-     that may break easilly.  */
+     that may break easily.  */
 
   if (size && !stack_alignment_needed)
     abort ();
@@ -4175,7 +4185,7 @@ ix86_expand_epilogue (style)
          }
       if (frame_pointer_needed)
        {
-         /* Leave results in shorter depdendancy chains on CPUs that are
+         /* Leave results in shorter dependency chains on CPUs that are
             able to grok it fast.  */
          if (TARGET_USE_LEAVE)
            emit_insn (TARGET_64BIT ? gen_leave_rex64 () : gen_leave ());
@@ -4697,7 +4707,7 @@ legitimate_address_p (mode, addr, strict)
 
             This code is nonsensical, but results in addressing
             GOT table with pic_offset_table_rtx base.  We can't
-            just refuse it easilly, since it gets matched by
+            just refuse it easily, since it gets matched by
             "addsi3" pattern, that later gets split to lea in the
             case output register differs from input.  While this
             can be handled by separate addsi pattern for this case
@@ -5202,11 +5212,11 @@ i386_dwarf_output_addr_const (file, x)
      rtx x;
 {
 #ifdef ASM_QUAD
-  fprintf (file, "%s", TARGET_64BIT ? ASM_QUAD : INT_ASM_OP);
+  fprintf (file, "%s", TARGET_64BIT ? ASM_QUAD : ASM_LONG);
 #else
   if (TARGET_64BIT)
     abort ();
-  fprintf (file, "%s", INT_ASM_OP);
+  fprintf (file, "%s", ASM_LONG);
 #endif
   if (flag_pic)
     output_pic_addr_const (file, x, '\0');
@@ -5931,27 +5941,23 @@ split_di (operands, num, lo_half, hi_half)
   while (num--)
     {
       rtx op = operands[num];
-      if (CONSTANT_P (op))
-       split_double (op, &lo_half[num], &hi_half[num]);
-      else if (! reload_completed)
-       {
-         lo_half[num] = gen_lowpart (SImode, op);
-         hi_half[num] = gen_highpart (SImode, op);
-       }
-      else if (GET_CODE (op) == REG)
-       {
-         if (TARGET_64BIT)
-           abort();
-         lo_half[num] = gen_rtx_REG (SImode, REGNO (op));
-         hi_half[num] = gen_rtx_REG (SImode, REGNO (op) + 1);
-       }
-      else if (offsettable_memref_p (op))
+
+      /* simplify_subreg refuse to split volatile memory addresses,
+         but we still have to handle it.  */
+      if (GET_CODE (op) == MEM)
        {
          lo_half[num] = adjust_address (op, SImode, 0);
          hi_half[num] = adjust_address (op, SImode, 4);
        }
       else
-       abort ();
+       {
+         lo_half[num] = simplify_gen_subreg (SImode, op,
+                                             GET_MODE (op) == VOIDmode
+                                             ? DImode : GET_MODE (op), 0);
+         hi_half[num] = simplify_gen_subreg (SImode, op,
+                                             GET_MODE (op) == VOIDmode
+                                             ? DImode : GET_MODE (op), 4);
+       }
     }
 }
 /* Split one or more TImode RTL references into pairs of SImode
@@ -5969,40 +5975,19 @@ split_ti (operands, num, lo_half, hi_half)
   while (num--)
     {
       rtx op = operands[num];
-      if (CONSTANT_P (op))
-       {
-         if (GET_CODE (op) == CONST_INT)
-           {
-             lo_half[num] = GEN_INT (trunc_int_for_mode (INTVAL (op), SImode));
-             hi_half[num] = (1 << (HOST_BITS_PER_WIDE_INT -1)) != 0 ? constm1_rtx : const0_rtx;
-           }
-         else if (GET_CODE (op) == CONST_DOUBLE && HOST_BITS_PER_WIDE_INT == 64)
-           {
-             lo_half[num] = GEN_INT (trunc_int_for_mode (CONST_DOUBLE_LOW (op), SImode));
-             hi_half[num] = GEN_INT (trunc_int_for_mode (CONST_DOUBLE_HIGH (op), SImode));
-           }
-         else
-           abort ();
-       }
-      else if (! reload_completed)
-       {
-         lo_half[num] = gen_lowpart (DImode, op);
-         hi_half[num] = gen_highpart (DImode, op);
-       }
-      else if (GET_CODE (op) == REG)
-       {
-         if (TARGET_64BIT)
-           abort();
-         lo_half[num] = gen_rtx_REG (DImode, REGNO (op));
-         hi_half[num] = gen_rtx_REG (DImode, REGNO (op) + 1);
-       }
-      else if (offsettable_memref_p (op))
+
+      /* simplify_subreg refuse to split volatile memory addresses, but we
+         still have to handle it.  */
+      if (GET_CODE (op) == MEM)
        {
          lo_half[num] = adjust_address (op, DImode, 0);
          hi_half[num] = adjust_address (op, DImode, 8);
        }
       else
-       abort ();
+       {
+         lo_half[num] = simplify_gen_subreg (DImode, op, TImode, 0);
+         hi_half[num] = simplify_gen_subreg (DImode, op, TImode, 8);
+       }
     }
 }
 \f
@@ -6694,6 +6679,35 @@ ix86_output_addr_diff_elt (file, value, rel)
                 ASM_LONG, LPREFIX, value);
 }
 \f
+/* Generate either "mov $0, reg" or "xor reg, reg", as appropriate
+   for the target.  */
+
+void
+ix86_expand_clear (dest)
+     rtx dest;
+{
+  rtx tmp;
+
+  /* We play register width games, which are only valid after reload.  */
+  if (!reload_completed)
+    abort ();
+
+  /* Avoid HImode and its attendant prefix byte.  */
+  if (GET_MODE_SIZE (GET_MODE (dest)) < 4)
+    dest = gen_rtx_REG (SImode, REGNO (dest));
+
+  tmp = gen_rtx_SET (VOIDmode, dest, const0_rtx);
+
+  /* This predicate should match that for movsi_xor and movdi_xor_rex64.  */
+  if (reload_completed && (!TARGET_USE_MOV0 || optimize_size))
+    {
+      rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, 17));
+      tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
+    }
+
+  emit_insn (tmp);
+}
+
 void
 ix86_expand_move (mode, operands)
      enum machine_mode mode;
@@ -7860,54 +7874,19 @@ ix86_expand_setcc (code, dest)
 {
   rtx ret, tmp, tmpreg;
   rtx second_test, bypass_test;
-  int type;
 
   if (GET_MODE (ix86_compare_op0) == DImode
       && !TARGET_64BIT)
     return 0; /* FAIL */
 
-  /* Three modes of generation:
-     0 -- destination does not overlap compare sources:
-          clear dest first, emit strict_low_part setcc.
-     1 -- destination does overlap compare sources:
-          emit subreg setcc, zero extend.
-     2 -- destination is in QImode:
-          emit setcc only.
-
-     We don't use mode 0 early in compilation because it confuses CSE.
-     There are peepholes to turn mode 1 into mode 0 if things work out
-     nicely after reload.  */
-
-  type = cse_not_expected ? 0 : 1;
-
-  if (GET_MODE (dest) == QImode)
-    type = 2;
-  else if (reg_overlap_mentioned_p (dest, ix86_compare_op0)
-          || reg_overlap_mentioned_p (dest, ix86_compare_op1))
-    type = 1;
-
-  if (type == 0)
-    emit_move_insn (dest, const0_rtx);
+  if (GET_MODE (dest) != QImode)
+    abort ();
 
   ret = ix86_expand_compare (code, &second_test, &bypass_test);
   PUT_MODE (ret, QImode);
 
   tmp = dest;
   tmpreg = dest;
-  if (type == 0)
-    {
-      tmp = gen_lowpart (QImode, dest);
-      tmpreg = tmp;
-      tmp = gen_rtx_STRICT_LOW_PART (VOIDmode, tmp);
-    }
-  else if (type == 1)
-    {
-      if (!cse_not_expected)
-       tmp = gen_reg_rtx (QImode);
-      else
-        tmp = gen_lowpart (QImode, dest);
-      tmpreg = tmp;
-    }
 
   emit_insn (gen_rtx_SET (VOIDmode, tmp, ret));
   if (bypass_test || second_test)
@@ -7932,17 +7911,6 @@ ix86_expand_setcc (code, dest)
        emit_insn (gen_iorqi3 (tmp, tmpreg, tmp2));
     }
 
-  if (type == 1)
-    {
-      rtx clob;
-
-      tmp = gen_rtx_ZERO_EXTEND (GET_MODE (dest), tmp);
-      tmp = gen_rtx_SET (VOIDmode, dest, tmp);
-      clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
-      tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
-      emit_insn (tmp);
-    }
-
   return 1; /* DONE */
 }
 
@@ -7953,6 +7921,7 @@ ix86_expand_int_movcc (operands)
   enum rtx_code code = GET_CODE (operands[1]), compare_code;
   rtx compare_seq, compare_op;
   rtx second_test, bypass_test;
+  enum machine_mode mode = GET_MODE (operands[0]);
 
   /* When the compare code is not LTU or GEU, we can not use sbbl case.
      In case comparsion is done with immediate, we can convert it to LTU or
@@ -7960,7 +7929,7 @@ ix86_expand_int_movcc (operands)
 
   if ((code == LEU || code == GTU)
       && GET_CODE (ix86_compare_op1) == CONST_INT
-      && GET_MODE (operands[0]) != HImode
+      && mode != HImode
       && (unsigned int)INTVAL (ix86_compare_op1) != 0xffffffff
       && GET_CODE (operands[2]) == CONST_INT
       && GET_CODE (operands[3]) == CONST_INT)
@@ -7982,8 +7951,8 @@ ix86_expand_int_movcc (operands)
   /* Don't attempt mode expansion here -- if we had to expand 5 or 6
      HImode insns, we'd be swallowed in word prefix ops.  */
 
-  if (GET_MODE (operands[0]) != HImode
-      && (GET_MODE (operands[0]) != DImode || TARGET_64BIT)
+  if (mode != HImode
+      && (mode != DImode || TARGET_64BIT)
       && GET_CODE (operands[2]) == CONST_INT
       && GET_CODE (operands[3]) == CONST_INT)
     {
@@ -8012,10 +7981,10 @@ ix86_expand_int_movcc (operands)
 
          if (reg_overlap_mentioned_p (out, ix86_compare_op0)
              || reg_overlap_mentioned_p (out, ix86_compare_op1))
-           tmp = gen_reg_rtx (GET_MODE (operands[0]));
+           tmp = gen_reg_rtx (mode);
 
          emit_insn (compare_seq);
-         if (GET_MODE (tmp) == DImode)
+         if (mode == DImode)
            emit_insn (gen_x86_movdicc_0_m1_rex64 (tmp));
          else
            emit_insn (gen_x86_movsicc_0_m1 (tmp));
@@ -8030,12 +7999,9 @@ ix86_expand_int_movcc (operands)
               * Size 5 - 8.
               */
              if (ct)
-               {
-                 if (GET_MODE (tmp) == DImode)
-                   emit_insn (gen_adddi3 (tmp, tmp, GEN_INT (ct)));
-                 else
-                   emit_insn (gen_addsi3 (tmp, tmp, GEN_INT (ct)));
-               }
+               tmp = expand_simple_binop (mode, PLUS,
+                                          tmp, GEN_INT (ct),
+                                          tmp, 1, OPTAB_DIRECT);
            }
          else if (cf == -1)
            {
@@ -8046,10 +8012,9 @@ ix86_expand_int_movcc (operands)
               *
               * Size 8.
               */
-             if (GET_MODE (tmp) == DImode)
-               emit_insn (gen_iordi3 (tmp, tmp, GEN_INT (ct)));
-             else
-               emit_insn (gen_iorsi3 (tmp, tmp, GEN_INT (ct)));
+             tmp = expand_simple_binop (mode, IOR,
+                                        tmp, GEN_INT (ct),
+                                        tmp, 1, OPTAB_DIRECT);
            }
          else if (diff == -1 && ct)
            {
@@ -8061,18 +8026,11 @@ ix86_expand_int_movcc (operands)
               *
               * Size 8 - 11.
               */
-             if (GET_MODE (tmp) == DImode)
-               {
-                 emit_insn (gen_one_cmpldi2 (tmp, tmp));
-                 if (cf)
-                   emit_insn (gen_adddi3 (tmp, tmp, GEN_INT (cf)));
-               }
-             else
-               {
-                 emit_insn (gen_one_cmplsi2 (tmp, tmp));
-                 if (cf)
-                   emit_insn (gen_addsi3 (tmp, tmp, GEN_INT (cf)));
-               }
+             tmp = expand_simple_unop (mode, NOT, tmp, tmp, 1);
+             if (cf)
+               tmp = expand_simple_binop (mode, PLUS,
+                                          tmp, GEN_INT (cf),
+                                          tmp, 1, OPTAB_DIRECT);
            }
          else
            {
@@ -8084,20 +8042,15 @@ ix86_expand_int_movcc (operands)
               *
               * Size 8 - 11.
               */
-             if (GET_MODE (tmp) == DImode)
-               {
-                 emit_insn (gen_anddi3 (tmp, tmp, GEN_INT (trunc_int_for_mode
-                                                           (cf - ct, DImode))));
-                 if (ct)
-                   emit_insn (gen_adddi3 (tmp, tmp, GEN_INT (ct)));
-               }
-             else
-               {
-                 emit_insn (gen_andsi3 (tmp, tmp, GEN_INT (trunc_int_for_mode
-                                                           (cf - ct, SImode))));
-                 if (ct)
-                   emit_insn (gen_addsi3 (tmp, tmp, GEN_INT (ct)));
-               }
+             tmp = expand_simple_binop (mode, AND,
+                                        tmp,
+                                        GEN_INT (trunc_int_for_mode
+                                                 (cf - ct, mode)),
+                                        tmp, 1, OPTAB_DIRECT);
+             if (ct)
+               tmp = expand_simple_binop (mode, PLUS,
+                                          tmp, GEN_INT (ct),
+                                          tmp, 1, OPTAB_DIRECT);
            }
 
          if (tmp != out)
@@ -8127,8 +8080,9 @@ ix86_expand_int_movcc (operands)
              code = reverse_condition (code);
            }
        }
-      if (diff == 1 || diff == 2 || diff == 4 || diff == 8
-         || diff == 3 || diff == 5 || diff == 9)
+      if ((diff == 1 || diff == 2 || diff == 4 || diff == 8
+          || diff == 3 || diff == 5 || diff == 9)
+         && (mode != DImode || x86_64_sign_extended_value (GEN_INT (cf))))
        {
          /*
           * xorl dest,dest
@@ -8156,17 +8110,17 @@ ix86_expand_int_movcc (operands)
            {
              rtx out1;
              out1 = out;
-             tmp = gen_rtx_MULT (GET_MODE (out), out1, GEN_INT (diff & ~1));
+             tmp = gen_rtx_MULT (mode, out1, GEN_INT (diff & ~1));
              nops++;
              if (diff & 1)
                {
-                 tmp = gen_rtx_PLUS (GET_MODE (out), tmp, out1);
+                 tmp = gen_rtx_PLUS (mode, tmp, out1);
                  nops++;
                }
            }
          if (cf != 0)
            {
-             tmp = gen_rtx_PLUS (GET_MODE (out), tmp, GEN_INT (cf));
+             tmp = gen_rtx_PLUS (mode, tmp, GEN_INT (cf));
              nops++;
            }
          if (tmp != out
@@ -8236,11 +8190,17 @@ ix86_expand_int_movcc (operands)
          out = emit_store_flag (out, code, ix86_compare_op0,
                                 ix86_compare_op1, VOIDmode, 0, 1);
 
-         emit_insn (gen_addsi3 (out, out, constm1_rtx));
-         emit_insn (gen_andsi3 (out, out, GEN_INT (trunc_int_for_mode
-                                                   (cf - ct, SImode))));
-         if (ct != 0)
-           emit_insn (gen_addsi3 (out, out, GEN_INT (ct)));
+         out = expand_simple_binop (mode, PLUS,
+                                    out, constm1_rtx,
+                                    out, 1, OPTAB_DIRECT);
+         out = expand_simple_binop (mode, AND,
+                                    out,
+                                    GEN_INT (trunc_int_for_mode
+                                             (cf - ct, mode)),
+                                    out, 1, OPTAB_DIRECT);
+         out = expand_simple_binop (mode, PLUS,
+                                    out, GEN_INT (ct),
+                                    out, 1, OPTAB_DIRECT);
          if (out != operands[0])
            emit_move_insn (operands[0], out);
 
@@ -8285,7 +8245,7 @@ ix86_expand_int_movcc (operands)
         return 0; /* FAIL */
 
       orig_out = operands[0];
-      tmp = gen_reg_rtx (GET_MODE (orig_out));
+      tmp = gen_reg_rtx (mode);
       operands[0] = tmp;
 
       /* Recurse to get the constant loaded.  */
@@ -8293,7 +8253,7 @@ ix86_expand_int_movcc (operands)
         return 0; /* FAIL */
 
       /* Mask in the interesting variable.  */
-      out = expand_binop (GET_MODE (orig_out), op, var, tmp, orig_out, 0,
+      out = expand_binop (mode, op, var, tmp, orig_out, 0,
                          OPTAB_WIDEN);
       if (out != orig_out)
        emit_move_insn (orig_out, out);
@@ -8312,41 +8272,41 @@ ix86_expand_int_movcc (operands)
    * Size 15.
    */
 
-  if (! nonimmediate_operand (operands[2], GET_MODE (operands[0])))
-    operands[2] = force_reg (GET_MODE (operands[0]), operands[2]);
-  if (! nonimmediate_operand (operands[3], GET_MODE (operands[0])))
-    operands[3] = force_reg (GET_MODE (operands[0]), operands[3]);
+  if (! nonimmediate_operand (operands[2], mode))
+    operands[2] = force_reg (mode, operands[2]);
+  if (! nonimmediate_operand (operands[3], mode))
+    operands[3] = force_reg (mode, operands[3]);
 
   if (bypass_test && reg_overlap_mentioned_p (operands[0], operands[3]))
     {
-      rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
+      rtx tmp = gen_reg_rtx (mode);
       emit_move_insn (tmp, operands[3]);
       operands[3] = tmp;
     }
   if (second_test && reg_overlap_mentioned_p (operands[0], operands[2]))
     {
-      rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
+      rtx tmp = gen_reg_rtx (mode);
       emit_move_insn (tmp, operands[2]);
       operands[2] = tmp;
     }
   if (! register_operand (operands[2], VOIDmode)
       && ! register_operand (operands[3], VOIDmode))
-    operands[2] = force_reg (GET_MODE (operands[0]), operands[2]);
+    operands[2] = force_reg (mode, operands[2]);
 
   emit_insn (compare_seq);
   emit_insn (gen_rtx_SET (VOIDmode, operands[0],
-                         gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
+                         gen_rtx_IF_THEN_ELSE (mode,
                                                compare_op, operands[2],
                                                operands[3])));
   if (bypass_test)
     emit_insn (gen_rtx_SET (VOIDmode, operands[0],
-                           gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
+                           gen_rtx_IF_THEN_ELSE (mode,
                                  bypass_test,
                                  operands[3],
                                  operands[0])));
   if (second_test)
     emit_insn (gen_rtx_SET (VOIDmode, operands[0],
-                           gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
+                           gen_rtx_IF_THEN_ELSE (mode,
                                  second_test,
                                  operands[2],
                                  operands[0])));
@@ -9011,7 +8971,7 @@ ix86_expand_aligntest (variable, value)
   else
     emit_insn (gen_andsi3 (tmpcount, variable, GEN_INT (value)));
   emit_cmp_and_jump_insns (tmpcount, const0_rtx, EQ, 0, GET_MODE (variable),
-                          1, 0, label);
+                          1, label);
   return label;
 }
 
@@ -9059,7 +9019,7 @@ ix86_expand_movstr (dst, src, count_exp, align_exp)
   if (GET_CODE (align_exp) == CONST_INT)
     align = INTVAL (align_exp);
 
-  /* This simple hack avoids all inlining code and simplifies code bellow.  */
+  /* This simple hack avoids all inlining code and simplifies code below.  */
   if (!TARGET_ALIGN_STRINGOPS)
     align = 64;
 
@@ -9178,7 +9138,7 @@ ix86_expand_movstr (dst, src, count_exp, align_exp)
        {
          label = gen_label_rtx ();
          emit_cmp_and_jump_insns (countreg, GEN_INT (UNITS_PER_WORD - 1),
-                                  LEU, 0, counter_mode, 1, 0, label);
+                                  LEU, 0, counter_mode, 1, label);
        }
       if (align <= 1)
        {
@@ -9280,7 +9240,7 @@ ix86_expand_clrstr (src, count_exp, align_exp)
   if (GET_CODE (align_exp) == CONST_INT)
     align = INTVAL (align_exp);
 
-  /* This simple hack avoids all inlining code and simplifies code bellow.  */
+  /* This simple hack avoids all inlining code and simplifies code below.  */
   if (!TARGET_ALIGN_STRINGOPS)
     align = 32;
 
@@ -9374,7 +9334,7 @@ ix86_expand_clrstr (src, count_exp, align_exp)
        {
          label = gen_label_rtx ();
          emit_cmp_and_jump_insns (countreg, GEN_INT (UNITS_PER_WORD - 1),
-                                  LEU, 0, counter_mode, 1, 0, label);
+                                  LEU, 0, counter_mode, 1, label);
        }
       if (align <= 1)
        {
@@ -9580,11 +9540,11 @@ ix86_expand_strlensi_unroll_1 (out, align_rtx)
                                    NULL_RTX, 0, OPTAB_WIDEN);
 
          emit_cmp_and_jump_insns (align_rtx, const0_rtx, EQ, NULL,
-                                  Pmode, 1, 0, align_4_label);
+                                  Pmode, 1, align_4_label);
          emit_cmp_and_jump_insns (align_rtx, GEN_INT (2), EQ, NULL,
-                                  Pmode, 1, 0, align_2_label);
+                                  Pmode, 1, align_2_label);
          emit_cmp_and_jump_insns (align_rtx, GEN_INT (2), GTU, NULL,
-                                  Pmode, 1, 0, align_3_label);
+                                  Pmode, 1, align_3_label);
        }
       else
         {
@@ -9595,7 +9555,7 @@ ix86_expand_strlensi_unroll_1 (out, align_rtx)
                                    NULL_RTX, 0, OPTAB_WIDEN);
 
          emit_cmp_and_jump_insns (align_rtx, const0_rtx, EQ, NULL,
-                                  Pmode, 1, 0, align_4_label);
+                                  Pmode, 1, align_4_label);
         }
 
       mem = gen_rtx_MEM (QImode, out);
@@ -9604,7 +9564,7 @@ ix86_expand_strlensi_unroll_1 (out, align_rtx)
 
       /* Compare the first n unaligned byte on a byte per byte basis.  */
       emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL,
-                              QImode, 1, 0, end_0_label);
+                              QImode, 1, end_0_label);
 
       /* Increment the address.  */
       if (TARGET_64BIT)
@@ -9617,8 +9577,8 @@ ix86_expand_strlensi_unroll_1 (out, align_rtx)
        {
          emit_label (align_2_label);
 
-         emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL,
-                                  QImode, 1, 0, end_0_label);
+         emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL, QImode, 1,
+                                  end_0_label);
 
          if (TARGET_64BIT)
            emit_insn (gen_adddi3 (out, out, const1_rtx));
@@ -9628,8 +9588,8 @@ ix86_expand_strlensi_unroll_1 (out, align_rtx)
          emit_label (align_3_label);
        }
 
-      emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL,
-                              QImode, 1, 0, end_0_label);
+      emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL, QImode, 1,
+                              end_0_label);
 
       if (TARGET_64BIT)
        emit_insn (gen_adddi3 (out, out, const1_rtx));
@@ -9658,8 +9618,8 @@ ix86_expand_strlensi_unroll_1 (out, align_rtx)
   emit_insn (gen_andsi3 (tmpreg, tmpreg,
                         GEN_INT (trunc_int_for_mode
                                  (0x80808080, SImode))));
-  emit_cmp_and_jump_insns (tmpreg, const0_rtx, EQ, 0,
-                          SImode, 1, 0, align_4_label);
+  emit_cmp_and_jump_insns (tmpreg, const0_rtx, EQ, 0, SImode, 1,
+                          align_4_label);
 
   if (TARGET_CMOVE)
     {
@@ -9959,7 +9919,7 @@ ix86_flags_dependant (insn, dep_insn, insn_type)
   if (GET_CODE (set) != REG || REGNO (set) != FLAGS_REG)
     return 0;
 
-  /* This test is true if the dependant insn reads the flags but
+  /* This test is true if the dependent insn reads the flags but
      not any other potentially set register.  */
   if (!reg_overlap_mentioned_p (set, PATTERN (insn)))
     return 0;
@@ -11688,7 +11648,11 @@ ix86_expand_sse_comi (d, arglist, target)
   if (! pat)
     return 0;
   emit_insn (pat);
-  emit_insn (gen_setcc_2 (target, op2));
+  emit_insn (gen_rtx_SET (VOIDmode,
+                         gen_rtx_STRICT_LOW_PART (VOIDmode, target),
+                         gen_rtx_fmt_ee (comparison, QImode,
+                                         gen_rtx_REG (CCmode, FLAGS_REG),
+                                         const0_rtx)));
 
   return target;
 }
@@ -11976,12 +11940,12 @@ ix86_expand_builtin (exp, target, subtarget, mode, ignore)
       op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
       op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
       tmode = insn_data[icode].operand[0].mode;
-      mode0 = insn_data[icode].operand[2].mode;
-      mode1 = insn_data[icode].operand[3].mode;
+      mode1 = insn_data[icode].operand[1].mode;
+      mode2 = insn_data[icode].operand[2].mode;
 
-      if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
-       op0 = copy_to_mode_reg (mode0, op0);
-      if (! (*insn_data[icode].operand[3].predicate) (op1, mode1))
+      if (! (*insn_data[icode].operand[1].predicate) (op0, mode1))
+       op0 = copy_to_mode_reg (mode1, op0);
+      if (! (*insn_data[icode].operand[2].predicate) (op1, mode2))
        {
          /* @@@ better error message */
          error ("mask must be an immediate");
@@ -11991,7 +11955,7 @@ ix86_expand_builtin (exp, target, subtarget, mode, ignore)
          || GET_MODE (target) != tmode
          || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
        target = gen_reg_rtx (tmode);
-      pat = GEN_FCN (icode) (target, target, op0, op1);
+      pat = GEN_FCN (icode) (target, op0, op1);
       if (! pat)
        return 0;
       emit_insn (pat);
@@ -12184,7 +12148,7 @@ ix86_expand_builtin (exp, target, subtarget, mode, ignore)
 }
 
 /* Store OPERAND to the memory after reload is completed.  This means
-   that we can't easilly use assign_stack_local.  */
+   that we can't easily use assign_stack_local.  */
 rtx
 ix86_force_to_memory (mode, operand)
      enum machine_mode mode;
@@ -12291,7 +12255,7 @@ ix86_free_from_memory (mode)
 /* Put float CONST_DOUBLE in the constant pool instead of fp regs.
    QImode must go into class Q_REGS.
    Narrow ALL_REGS to GENERAL_REGS.  This supports allowing movsf and
-   movdf to do mem-to-mem moves through integer regs. */
+   movdf to do mem-to-mem moves through integer regs.  */
 enum reg_class
 ix86_preferred_reload_class (x, class)
      rtx x;
@@ -12531,27 +12495,3 @@ ix86_svr3_asm_out_constructor (symbol, priority)
   fputc ('\n', asm_out_file);
 }
 #endif
-
-#if defined(TARGET_ELF) && defined(TARGET_COFF)
-static void
-sco_asm_named_section (name, flags)
-     const char *name;
-     unsigned int flags;
-{
-  if (TARGET_ELF)
-    default_elf_asm_named_section (name, flags);
-  else
-    default_coff_asm_named_section (name, flags);
-}
-
-static void
-sco_asm_out_constructor (symbol, priority)
-     rtx symbol;
-     int priority;
-{
-  if (TARGET_ELF)
-    default_named_section_asm_out_constrctor (symbol, priority);
-  else
-    ix86_svr3_asm_out_constructor (symbol, priority);
-}
-#endif