|
|
1.1 ! root 1: /*---------------------------------------------------------------------------+ ! 2: | reg_add_sub.c | ! 3: | | ! 4: | Functions to add or subtract two registers and put the result in a third. | ! 5: | | ! 6: | Copyright (C) 1992 W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | ! 7: | Australia. E-mail [email protected] | ! 8: | | ! 9: | | ! 10: +---------------------------------------------------------------------------*/ ! 11: ! 12: /*---------------------------------------------------------------------------+ ! 13: | For each function, the destination may be any FPU_REG, including one of | ! 14: | the source FPU_REGs. | ! 15: +---------------------------------------------------------------------------*/ ! 16: ! 17: #include "fpu_system.h" ! 18: #include "exception.h" ! 19: #include "reg_constant.h" ! 20: #include "fpu_emu.h" ! 21: ! 22: ! 23: ! 24: void reg_add(FPU_REG *a, FPU_REG *b, FPU_REG *dest) ! 25: { ! 26: int diff; ! 27: ! 28: if ( !(a->tag | b->tag) ) ! 29: { ! 30: /* Both registers are valid */ ! 31: if (!(a->sign ^ b->sign)) ! 32: { ! 33: /* signs are the same */ ! 34: reg_u_add(a, b, dest); ! 35: dest->sign = a->sign; ! 36: return; ! 37: } ! 38: ! 39: /* The signs are different, so do a subtraction */ ! 40: diff = a->exp - b->exp; ! 41: if (!diff) ! 42: { ! 43: diff = a->sigh - b->sigh; /* Works only if ms bits are identical */ ! 44: if (!diff) ! 45: diff = a->sigl > b->sigl; ! 46: } ! 47: ! 48: if (diff > 0) ! 49: { ! 50: reg_u_sub(a, b, dest); ! 51: dest->sign = a->sign; ! 52: return; ! 53: } ! 54: else ! 55: { ! 56: reg_u_sub(b, a, dest); ! 57: dest->sign = b->sign; ! 58: return; ! 59: } ! 60: } ! 61: else ! 62: { ! 63: if ( (a->tag == TW_NaN) || (b->tag == TW_NaN) ) ! 64: { real_2op_NaN(a, b, dest); return; } ! 65: else if (a->tag == TW_Zero) ! 66: { reg_move(b, dest); return; } ! 67: else if (b->tag == TW_Zero) ! 68: { reg_move(a, dest); return; } ! 69: else if (a->tag == TW_Infinity) ! 70: { ! 71: if (b->tag != TW_Infinity) ! 72: { reg_move(a, dest); return; } ! 73: /* They are both + or - infinity */ ! 74: if (a->sign == b->sign) ! 75: { reg_move(a, dest); return; } ! 76: reg_move(&CONST_QNaN, dest); /* inf - inf is undefined. */ ! 77: return; ! 78: } ! 79: else if (b->tag == TW_Infinity) ! 80: { reg_move(b, dest); return; } ! 81: } ! 82: #ifdef PARANOID ! 83: EXCEPTION(EX_INTERNAL|0x101); ! 84: #endif ! 85: } ! 86: ! 87: ! 88: /* Subtract b from a. (a-b) -> dest */ ! 89: void reg_sub(FPU_REG *a, FPU_REG *b, FPU_REG *dest) ! 90: { ! 91: int diff; ! 92: ! 93: if ( !(a->tag | b->tag) ) ! 94: { ! 95: /* Both registers are valid */ ! 96: diff = a->exp - b->exp; ! 97: if (!diff) ! 98: { ! 99: diff = a->sigh - b->sigh; /* Works only if ms bits are identical */ ! 100: if (!diff) ! 101: diff = a->sigl > b->sigl; ! 102: } ! 103: ! 104: switch (a->sign*2 + b->sign) ! 105: { ! 106: case 0: /* P - P */ ! 107: case 3: /* N - N */ ! 108: if (diff > 0) ! 109: { ! 110: reg_u_sub(a, b, dest); ! 111: dest->sign = a->sign; ! 112: } ! 113: else ! 114: { ! 115: reg_u_sub(b, a, dest); ! 116: dest->sign = a->sign ^ SIGN_POS^SIGN_NEG; ! 117: } ! 118: return; ! 119: case 1: /* P - N */ ! 120: reg_u_add(a, b, dest); ! 121: dest->sign = SIGN_POS; ! 122: return; ! 123: case 2: /* N - P */ ! 124: reg_u_add(a, b, dest); ! 125: dest->sign = SIGN_NEG; ! 126: return; ! 127: } ! 128: } ! 129: else ! 130: { ! 131: if ( (a->tag == TW_NaN) || (b->tag == TW_NaN) ) ! 132: { real_2op_NaN(a, b, dest); return; } ! 133: else if (b->tag == TW_Zero) ! 134: { reg_move(a, dest); return; } ! 135: else if (a->tag == TW_Zero) ! 136: { ! 137: reg_move(b, dest); ! 138: dest->sign ^= SIGN_POS^SIGN_NEG; ! 139: return; ! 140: } ! 141: else if (a->tag == TW_Infinity) ! 142: { ! 143: if (b->tag != TW_Infinity) ! 144: { reg_move(a, dest); return; } ! 145: if (a->sign == b->sign) ! 146: { reg_move(&CONST_QNaN, dest); return; } ! 147: reg_move(a, dest); ! 148: return; ! 149: } ! 150: else if (b->tag == TW_Infinity) ! 151: { ! 152: reg_move(b, dest); ! 153: dest->sign ^= SIGN_POS^SIGN_NEG; ! 154: return; ! 155: } ! 156: } ! 157: #ifdef PARANOID ! 158: EXCEPTION(EX_INTERNAL|0x110); ! 159: #endif ! 160: } ! 161:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.