Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
diff --git a/arch/i386/math-emu/reg_compare.c b/arch/i386/math-emu/reg_compare.c
new file mode 100644
index 0000000..f37c5b5
--- /dev/null
+++ b/arch/i386/math-emu/reg_compare.c
@@ -0,0 +1,381 @@
+/*---------------------------------------------------------------------------+
+ |  reg_compare.c                                                            |
+ |                                                                           |
+ | Compare two floating point registers                                      |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1997                                         |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ | compare() is the core FPU_REG comparison function                         |
+ +---------------------------------------------------------------------------*/
+
+#include "fpu_system.h"
+#include "exception.h"
+#include "fpu_emu.h"
+#include "control_w.h"
+#include "status_w.h"
+
+
+static int compare(FPU_REG const *b, int tagb)
+{
+  int diff, exp0, expb;
+  u_char	  	st0_tag;
+  FPU_REG  	*st0_ptr;
+  FPU_REG	x, y;
+  u_char		st0_sign, signb = getsign(b);
+
+  st0_ptr = &st(0);
+  st0_tag = FPU_gettag0();
+  st0_sign = getsign(st0_ptr);
+
+  if ( tagb == TAG_Special )
+    tagb = FPU_Special(b);
+  if ( st0_tag == TAG_Special )
+    st0_tag = FPU_Special(st0_ptr);
+
+  if ( ((st0_tag != TAG_Valid) && (st0_tag != TW_Denormal))
+       || ((tagb != TAG_Valid) && (tagb != TW_Denormal)) )
+    {
+      if ( st0_tag == TAG_Zero )
+	{
+	  if ( tagb == TAG_Zero ) return COMP_A_eq_B;
+	  if ( tagb == TAG_Valid )
+	    return ((signb == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B);
+	  if ( tagb == TW_Denormal )
+	    return ((signb == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
+	    | COMP_Denormal;
+	}
+      else if ( tagb == TAG_Zero )
+	{
+	  if ( st0_tag == TAG_Valid )
+	    return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B);
+	  if ( st0_tag == TW_Denormal )
+	    return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
+	    | COMP_Denormal;
+	}
+
+      if ( st0_tag == TW_Infinity )
+	{
+	  if ( (tagb == TAG_Valid) || (tagb == TAG_Zero) )
+	    return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B);
+	  else if ( tagb == TW_Denormal )
+	    return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
+	      | COMP_Denormal;
+	  else if ( tagb == TW_Infinity )
+	    {
+	      /* The 80486 book says that infinities can be equal! */
+	      return (st0_sign == signb) ? COMP_A_eq_B :
+		((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B);
+	    }
+	  /* Fall through to the NaN code */
+	}
+      else if ( tagb == TW_Infinity )
+	{
+	  if ( (st0_tag == TAG_Valid) || (st0_tag == TAG_Zero) )
+	    return ((signb == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B);
+	  if ( st0_tag == TW_Denormal )
+	    return ((signb == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
+		| COMP_Denormal;
+	  /* Fall through to the NaN code */
+	}
+
+      /* The only possibility now should be that one of the arguments
+	 is a NaN */
+      if ( (st0_tag == TW_NaN) || (tagb == TW_NaN) )
+	{
+	  int signalling = 0, unsupported = 0;
+	  if ( st0_tag == TW_NaN )
+	    {
+	      signalling = (st0_ptr->sigh & 0xc0000000) == 0x80000000;
+	      unsupported = !((exponent(st0_ptr) == EXP_OVER)
+			      && (st0_ptr->sigh & 0x80000000));
+	    }
+	  if ( tagb == TW_NaN )
+	    {
+	      signalling |= (b->sigh & 0xc0000000) == 0x80000000;
+	      unsupported |= !((exponent(b) == EXP_OVER)
+			       && (b->sigh & 0x80000000));
+	    }
+	  if ( signalling || unsupported )
+	    return COMP_No_Comp | COMP_SNaN | COMP_NaN;
+	  else
+	    /* Neither is a signaling NaN */
+	    return COMP_No_Comp | COMP_NaN;
+	}
+      
+      EXCEPTION(EX_Invalid);
+    }
+  
+  if (st0_sign != signb)
+    {
+      return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
+	| ( ((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ?
+	    COMP_Denormal : 0);
+    }
+
+  if ( (st0_tag == TW_Denormal) || (tagb == TW_Denormal) )
+    {
+      FPU_to_exp16(st0_ptr, &x);
+      FPU_to_exp16(b, &y);
+      st0_ptr = &x;
+      b = &y;
+      exp0 = exponent16(st0_ptr);
+      expb = exponent16(b);
+    }
+  else
+    {
+      exp0 = exponent(st0_ptr);
+      expb = exponent(b);
+    }
+
+#ifdef PARANOID
+  if (!(st0_ptr->sigh & 0x80000000)) EXCEPTION(EX_Invalid);
+  if (!(b->sigh & 0x80000000)) EXCEPTION(EX_Invalid);
+#endif /* PARANOID */
+
+  diff = exp0 - expb;
+  if ( diff == 0 )
+    {
+      diff = st0_ptr->sigh - b->sigh;  /* Works only if ms bits are
+					      identical */
+      if ( diff == 0 )
+	{
+	diff = st0_ptr->sigl > b->sigl;
+	if ( diff == 0 )
+	  diff = -(st0_ptr->sigl < b->sigl);
+	}
+    }
+
+  if ( diff > 0 )
+    {
+      return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
+	| ( ((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ?
+	    COMP_Denormal : 0);
+    }
+  if ( diff < 0 )
+    {
+      return ((st0_sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
+	| ( ((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ?
+	    COMP_Denormal : 0);
+    }
+
+  return COMP_A_eq_B
+    | ( ((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ?
+	COMP_Denormal : 0);
+
+}
+
+
+/* This function requires that st(0) is not empty */
+int FPU_compare_st_data(FPU_REG const *loaded_data, u_char loaded_tag)
+{
+  int f = 0, c;
+
+  c = compare(loaded_data, loaded_tag);
+
+  if (c & COMP_NaN)
+    {
+      EXCEPTION(EX_Invalid);
+      f = SW_C3 | SW_C2 | SW_C0;
+    }
+  else
+    switch (c & 7)
+      {
+      case COMP_A_lt_B:
+	f = SW_C0;
+	break;
+      case COMP_A_eq_B:
+	f = SW_C3;
+	break;
+      case COMP_A_gt_B:
+	f = 0;
+	break;
+      case COMP_No_Comp:
+	f = SW_C3 | SW_C2 | SW_C0;
+	break;
+#ifdef PARANOID
+      default:
+	EXCEPTION(EX_INTERNAL|0x121);
+	f = SW_C3 | SW_C2 | SW_C0;
+	break;
+#endif /* PARANOID */
+      }
+  setcc(f);
+  if (c & COMP_Denormal)
+    {
+      return denormal_operand() < 0;
+    }
+  return 0;
+}
+
+
+static int compare_st_st(int nr)
+{
+  int f = 0, c;
+  FPU_REG *st_ptr;
+
+  if ( !NOT_EMPTY(0) || !NOT_EMPTY(nr) )
+    {
+      setcc(SW_C3 | SW_C2 | SW_C0);
+      /* Stack fault */
+      EXCEPTION(EX_StackUnder);
+      return !(control_word & CW_Invalid);
+    }
+
+  st_ptr = &st(nr);
+  c = compare(st_ptr, FPU_gettagi(nr));
+  if (c & COMP_NaN)
+    {
+      setcc(SW_C3 | SW_C2 | SW_C0);
+      EXCEPTION(EX_Invalid);
+      return !(control_word & CW_Invalid);
+    }
+  else
+    switch (c & 7)
+      {
+      case COMP_A_lt_B:
+	f = SW_C0;
+	break;
+      case COMP_A_eq_B:
+	f = SW_C3;
+	break;
+      case COMP_A_gt_B:
+	f = 0;
+	break;
+      case COMP_No_Comp:
+	f = SW_C3 | SW_C2 | SW_C0;
+	break;
+#ifdef PARANOID
+      default:
+	EXCEPTION(EX_INTERNAL|0x122);
+	f = SW_C3 | SW_C2 | SW_C0;
+	break;
+#endif /* PARANOID */
+      }
+  setcc(f);
+  if (c & COMP_Denormal)
+    {
+      return denormal_operand() < 0;
+    }
+  return 0;
+}
+
+
+static int compare_u_st_st(int nr)
+{
+  int f = 0, c;
+  FPU_REG *st_ptr;
+
+  if ( !NOT_EMPTY(0) || !NOT_EMPTY(nr) )
+    {
+      setcc(SW_C3 | SW_C2 | SW_C0);
+      /* Stack fault */
+      EXCEPTION(EX_StackUnder);
+      return !(control_word & CW_Invalid);
+    }
+
+  st_ptr = &st(nr);
+  c = compare(st_ptr, FPU_gettagi(nr));
+  if (c & COMP_NaN)
+    {
+      setcc(SW_C3 | SW_C2 | SW_C0);
+      if (c & COMP_SNaN)       /* This is the only difference between
+				  un-ordered and ordinary comparisons */
+	{
+	  EXCEPTION(EX_Invalid);
+	  return !(control_word & CW_Invalid);
+	}
+      return 0;
+    }
+  else
+    switch (c & 7)
+      {
+      case COMP_A_lt_B:
+	f = SW_C0;
+	break;
+      case COMP_A_eq_B:
+	f = SW_C3;
+	break;
+      case COMP_A_gt_B:
+	f = 0;
+	break;
+      case COMP_No_Comp:
+	f = SW_C3 | SW_C2 | SW_C0;
+	break;
+#ifdef PARANOID
+      default:
+	EXCEPTION(EX_INTERNAL|0x123);
+	f = SW_C3 | SW_C2 | SW_C0;
+	break;
+#endif /* PARANOID */ 
+      }
+  setcc(f);
+  if (c & COMP_Denormal)
+    {
+      return denormal_operand() < 0;
+    }
+  return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+
+void fcom_st(void)
+{
+  /* fcom st(i) */
+  compare_st_st(FPU_rm);
+}
+
+
+void fcompst(void)
+{
+  /* fcomp st(i) */
+  if ( !compare_st_st(FPU_rm) )
+    FPU_pop();
+}
+
+
+void fcompp(void)
+{
+  /* fcompp */
+  if (FPU_rm != 1)
+    {
+      FPU_illegal();
+      return;
+    }
+  if ( !compare_st_st(1) )
+      poppop();
+}
+
+
+void fucom_(void)
+{
+  /* fucom st(i) */
+  compare_u_st_st(FPU_rm);
+
+}
+
+
+void fucomp(void)
+{
+  /* fucomp st(i) */
+  if ( !compare_u_st_st(FPU_rm) )
+    FPU_pop();
+}
+
+
+void fucompp(void)
+{
+  /* fucompp */
+  if (FPU_rm == 1)
+    {
+      if ( !compare_u_st_st(1) )
+	poppop();
+    }
+  else
+    FPU_illegal();
+}