|
|
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.