|
|
1.1 ! root 1: /* ! 2: * linux/kernel/math/add.c ! 3: * ! 4: * (C) 1991 Linus Torvalds ! 5: */ ! 6: ! 7: /* ! 8: * temporary real addition routine. ! 9: * ! 10: * NOTE! These aren't exact: they are only 62 bits wide, and don't do ! 11: * correct rounding. Fast hack. The reason is that we shift right the ! 12: * values by two, in order not to have overflow (1 bit), and to be able ! 13: * to move the sign into the mantissa (1 bit). Much simpler algorithms, ! 14: * and 62 bits (61 really - no rounding) accuracy is usually enough. The ! 15: * only time you should notice anything weird is when adding 64-bit ! 16: * integers together. When using doubles (52 bits accuracy), the ! 17: * 61-bit accuracy never shows at all. ! 18: */ ! 19: ! 20: #include <linux/math_emu.h> ! 21: ! 22: #define NEGINT(a) \ ! 23: __asm__("notl %0 ; notl %1 ; addl $1,%0 ; adcl $0,%1" \ ! 24: :"=r" (a->a),"=r" (a->b) \ ! 25: :"0" (a->a),"1" (a->b)) ! 26: ! 27: static void signify(temp_real * a) ! 28: { ! 29: a->exponent += 2; ! 30: __asm__("shrdl $2,%1,%0 ; shrl $2,%1" ! 31: :"=r" (a->a),"=r" (a->b) ! 32: :"0" (a->a),"1" (a->b)); ! 33: if (a->exponent < 0) ! 34: NEGINT(a); ! 35: a->exponent &= 0x7fff; ! 36: } ! 37: ! 38: static void unsignify(temp_real * a) ! 39: { ! 40: if (!(a->a || a->b)) { ! 41: a->exponent = 0; ! 42: return; ! 43: } ! 44: a->exponent &= 0x7fff; ! 45: if (a->b < 0) { ! 46: NEGINT(a); ! 47: a->exponent |= 0x8000; ! 48: } ! 49: while (a->b >= 0) { ! 50: a->exponent--; ! 51: __asm__("addl %0,%0 ; adcl %1,%1" ! 52: :"=r" (a->a),"=r" (a->b) ! 53: :"0" (a->a),"1" (a->b)); ! 54: } ! 55: } ! 56: ! 57: void fadd(const temp_real * src1, const temp_real * src2, temp_real * result) ! 58: { ! 59: temp_real a,b; ! 60: int x1,x2,shift; ! 61: ! 62: x1 = src1->exponent & 0x7fff; ! 63: x2 = src2->exponent & 0x7fff; ! 64: if (x1 > x2) { ! 65: a = *src1; ! 66: b = *src2; ! 67: shift = x1-x2; ! 68: } else { ! 69: a = *src2; ! 70: b = *src1; ! 71: shift = x2-x1; ! 72: } ! 73: if (shift >= 64) { ! 74: *result = a; ! 75: return; ! 76: } ! 77: if (shift >= 32) { ! 78: b.a = b.b; ! 79: b.b = 0; ! 80: shift -= 32; ! 81: } ! 82: __asm__("shrdl %4,%1,%0 ; shrl %4,%1" ! 83: :"=r" (b.a),"=r" (b.b) ! 84: :"0" (b.a),"1" (b.b),"c" ((char) shift)); ! 85: signify(&a); ! 86: signify(&b); ! 87: __asm__("addl %4,%0 ; adcl %5,%1" ! 88: :"=r" (a.a),"=r" (a.b) ! 89: :"0" (a.a),"1" (a.b),"g" (b.a),"g" (b.b)); ! 90: unsignify(&a); ! 91: *result = a; ! 92: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.