#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; }