Metropoli BBS
VIEWER: compare.cc MODE: TEXT (ASCII)
#include "emu.h"
#include "compare.h"
#include "const.h"

#define NAN_NONE 0
#define NAN_SNAN 1
#define NAN_QNAN 2

extern "C" void shld(void *);

int nan_type(reg& r)
{
  if (r.exp != EXP_MAX)
    return NAN_NONE;
  if (r.sigh & 0x40000000)
    return NAN_QNAN;
  return NAN_SNAN;
}

int compare(reg& a, reg& b)
{
  int a_inf, b_inf; // 0=no, 1=pos, -1=neg
  a_inf = 0;
  if (val_same(a, CONST_PINF))
    a_inf = 1;
  else if (val_same(a, CONST_NINF))
    a_inf = -1;
  b_inf = 0;
  if (val_same(b, CONST_PINF))
    b_inf = 1;
  else if (val_same(b, CONST_NINF))
    b_inf = -1;
  if (a_inf || b_inf)
  {
    if (a_inf == 1)
      if (b_inf == 1)
        return COMP_A_EQ_B;
      else
        return COMP_A_GT_B;
    if (b_inf == 1)
      return COMP_A_LT_B;

    if (a_inf == -1)
      if (b_inf == -1)
        return COMP_A_EQ_B;
      else
        return COMP_A_LT_B;
    if (b_inf == -1)
      return COMP_A_GT_B;
  }
  int a_nan = nan_type(a);
  int b_nan = nan_type(b);
  if (a_nan || b_nan)
  {
    if ((a_nan == NAN_SNAN) || (b_nan == NAN_SNAN))
      return COMP_NOCOMP | COMP_SNAN | COMP_NAN;
    return COMP_NOCOMP | COMP_NAN;
  }
  if (a.sign != b.sign)
  {
    if ((a.tag == TW_Z) && (b.tag == TW_Z))
      return COMP_A_EQ_B;
    if (a.sign == SIGN_POS)
      return COMP_A_GT_B;
    return COMP_A_LT_B;
  }
  while (!(a.sigh & 0x80000000))
  {
    if (!a.exp)
      break;
    shld(&a.sigl);
    a.exp--;
  }
  while (!(b.sigh & 0x80000000))
  {
    if (!b.exp)
      break;
    shld(&b.sigl);
    b.exp--;
  }
  int diff = a.exp - b.exp;
  if (diff == 0) diff = a.sigh - b.sigh;
  if (diff == 0) diff = a.sigl - b.sigl;
  if (diff > 0) return COMP_A_GT_B;
  if (diff < 0) return COMP_A_LT_B;
  return COMP_A_EQ_B;
}
[ RETURN TO DIRECTORY ]