OSDN Git Service

* i386/i386.c (output_fp_conditional_move): New function
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / i386.c
index 7634e13..73d89dc 100644 (file)
@@ -332,7 +332,11 @@ override_options ()
               i386_align_loops, MAX_CODE_ALIGN);
     }
   else
+#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
+    i386_align_loops = 4;
+#else
     i386_align_loops = 2;
+#endif
 
   /* Validate -malign-jumps= value, or provide default.  */
   if (i386_align_jumps_string)
@@ -343,7 +347,11 @@ override_options ()
               i386_align_jumps, MAX_CODE_ALIGN);
     }
   else
+#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
+    i386_align_jumps = 4;
+#else
     i386_align_jumps = def_align;
+#endif
 
   /* Validate -malign-functions= value, or provide default. */
   if (i386_align_funcs_string)
@@ -1892,7 +1900,7 @@ static char pic_label_name [256];
 static int pic_label_no = 0;
 
 /* This function generates code for -fpic that loads %ebx with
-   with the return address of the caller and then returns.  */
+   the return address of the caller and then returns.  */
 
 void
 asm_output_function_prefix (file, name)
@@ -3089,7 +3097,10 @@ put_condition_code (code, reverse_cc, mode, file)
        return;
 
       case GE:
-       fputs ("ge", file);
+       if (cc_prev_status.flags & CC_NO_OVERFLOW)
+         fputs ("ns", file);
+       else
+         fputs ("ge", file);
        return;
 
       case GT:
@@ -3101,7 +3112,10 @@ put_condition_code (code, reverse_cc, mode, file)
        return;
 
       case LT:
-       fputs ("l", file);
+       if (cc_prev_status.flags & CC_NO_OVERFLOW)
+         fputs ("s", file);
+       else
+         fputs ("l", file);
        return;
 
       case GEU:
@@ -3683,7 +3697,7 @@ notice_update_cc (exp)
           if (stack_regs_mentioned_p (SET_SRC (XVECEXP (exp, 0, 0))))
            {
               cc_status.flags |= CC_IN_80387;
-             if (TARGET_CMOVE && stack_regs_mentioned_p
+             if (0 && TARGET_CMOVE && stack_regs_mentioned_p
                  (XEXP (SET_SRC (XVECEXP (exp, 0, 0)), 1)))
                cc_status.flags |= CC_FCOMI;
            }
@@ -4013,7 +4027,7 @@ output_float_compare (insn, operands)
   int unordered_compare = GET_MODE (SET_SRC (body)) == CCFPEQmode;
   rtx tmp;
 
-  if (TARGET_CMOVE && STACK_REG_P (operands[1]))
+  if (0 && TARGET_CMOVE && STACK_REG_P (operands[1]))
     {
       cc_status.flags |= CC_FCOMI;
       cc_prev_status.flags &= ~CC_TEST_AX;
@@ -5124,3 +5138,124 @@ output_strlen_unroll (operands)
 
   return "";
 }
+
+char *
+output_fp_conditional_move (which_alternative, operands)
+     int which_alternative;
+     rtx operands[];
+{
+  int code = GET_CODE (operands[1]);
+
+  /* This is very tricky. We have to do it right. For a code segement
+     like:
+
+       int foo;
+       double bar;
+       ....
+       foo = foo - x;
+       if (foo >= 0)
+         bar = y;
+
+     final_scan_insn () may delete the insn which sets CC. We have to
+     tell final_scan_insn () if it should be reinserted. When CODE is
+     GT or LE, we have to check the CC_NO_OVERFLOW bit and return
+     NULL_PTR to tell final to reinsert the test insn because the
+     conditional move cannot be handled properly without it. */
+  if ((code == GT || code == LE)
+      && (cc_prev_status.flags & CC_NO_OVERFLOW))
+    return NULL_PTR;
+
+  switch (which_alternative)
+    {
+    case 0:
+      /* r <- cond ? arg : r */
+      output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
+      break;
+  
+    case 1:
+      /* r <- cond ? r : arg */
+      output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
+      break;
+
+    case 2:
+      /* r <- cond ? r : arg */
+      output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
+      output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
+      break;
+
+    default:
+      abort ();
+    }
+
+  return "";
+}
+
+char *
+output_int_conditional_move (which_alternative, operands)
+     int which_alternative;
+     rtx operands[];
+{
+  int code = GET_CODE (operands[1]);
+  enum machine_mode mode;
+  rtx xops[4];
+
+  /* This is very tricky. We have to do it right. For a code segement
+     like:
+
+       int foo, bar;
+       ....
+       foo = foo - x;
+       if (foo >= 0)
+         bar = y;
+
+     final_scan_insn () may delete the insn which sets CC. We have to
+     tell final_scan_insn () if it should be reinserted. When CODE is
+     GT or LE, we have to check the CC_NO_OVERFLOW bit and return
+     NULL_PTR to tell final to reinsert the test insn because the
+     conditional move cannot be handled properly without it. */
+  if ((code == GT || code == LE)
+      && (cc_prev_status.flags & CC_NO_OVERFLOW))
+    return NULL_PTR;
+
+  mode = GET_MODE (operands [0]);
+  if (mode == DImode)
+    {
+      xops [0] = gen_rtx_SUBREG (SImode, operands [0], 1);
+      xops [1] = operands [1];
+      xops [2] = gen_rtx_SUBREG (SImode, operands [2], 1);
+      xops [3] = gen_rtx_SUBREG (SImode, operands [3], 1);
+    }
+
+  switch (which_alternative)
+    {
+    case 0:
+      /* r <- cond ? arg : r */
+      output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
+      if (mode == DImode)
+       output_asm_insn (AS2 (cmov%C1,%2,%0), xops);
+      break;
+
+    case 1:
+      /* r <- cond ? r : arg */
+      output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
+      if (mode == DImode)
+       output_asm_insn (AS2 (cmov%c1,%3,%0), xops);
+      break;
+
+    case 2:
+      /* rm <- cond ? arg1 : arg2 */
+      output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
+      output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
+      if (mode == DImode)
+       {
+         output_asm_insn (AS2 (cmov%C1,%2,%0), xops);
+         output_asm_insn (AS2 (cmov%c1,%3,%0), xops);
+       }
+      break;
+
+    default:
+      abort ();
+    }
+
+  return "";
+}