Annotation of linux/kernel/math/convert.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * linux/kernel/math/convert.c
                      3:  *
                      4:  * (C) 1991 Linus Torvalds
                      5:  */
                      6: 
                      7: #include <linux/math_emu.h>
                      8: 
                      9: /*
                     10:  * NOTE!!! There is some "non-obvious" optimisations in the temp_to_long
                     11:  * and temp_to_short conversion routines: don't touch them if you don't
                     12:  * know what's going on. They are the adding of one in the rounding: the
                     13:  * overflow bit is also used for adding one into the exponent. Thus it
                     14:  * looks like the overflow would be incorrectly handled, but due to the
                     15:  * way the IEEE numbers work, things are correct.
                     16:  *
                     17:  * There is no checking for total overflow in the conversions, though (ie
                     18:  * if the temp-real number simply won't fit in a short- or long-real.)
                     19:  */
                     20: 
                     21: void short_to_temp(const short_real * a, temp_real * b)
                     22: {
                     23:        if (!(*a & 0x7fffffff)) {
                     24:                b->a = b->b = 0;
                     25:                if (*a)
                     26:                        b->exponent = 0x8000;
                     27:                else
                     28:                        b->exponent = 0;
                     29:                return;
                     30:        }
                     31:        b->exponent = ((*a>>23) & 0xff)-127+16383;
                     32:        if (*a<0)
                     33:                b->exponent |= 0x8000;
                     34:        b->b = (*a<<8) | 0x80000000;
                     35:        b->a = 0;
                     36: }
                     37: 
                     38: void long_to_temp(const long_real * a, temp_real * b)
                     39: {
                     40:        if (!a->a && !(a->b & 0x7fffffff)) {
                     41:                b->a = b->b = 0;
                     42:                if (a->b)
                     43:                        b->exponent = 0x8000;
                     44:                else
                     45:                        b->exponent = 0;
                     46:                return;
                     47:        }
                     48:        b->exponent = ((a->b >> 20) & 0x7ff)-1023+16383;
                     49:        if (a->b<0)
                     50:                b->exponent |= 0x8000;
                     51:        b->b = 0x80000000 | (a->b<<11) | (((unsigned long)a->a)>>21);
                     52:        b->a = a->a<<11;
                     53: }
                     54: 
                     55: void temp_to_short(const temp_real * a, short_real * b)
                     56: {
                     57:        if (!(a->exponent & 0x7fff)) {
                     58:                *b = (a->exponent)?0x80000000:0;
                     59:                return;
                     60:        }
                     61:        *b = ((((long) a->exponent)-16383+127) << 23) & 0x7f800000;
                     62:        if (a->exponent < 0)
                     63:                *b |= 0x80000000;
                     64:        *b |= (a->b >> 8) & 0x007fffff;
                     65:        switch (ROUNDING) {
                     66:                case ROUND_NEAREST:
                     67:                        if ((a->b & 0xff) > 0x80)
                     68:                                ++*b;
                     69:                        break;
                     70:                case ROUND_DOWN:
                     71:                        if ((a->exponent & 0x8000) && (a->b & 0xff))
                     72:                                ++*b;
                     73:                        break;
                     74:                case ROUND_UP:
                     75:                        if (!(a->exponent & 0x8000) && (a->b & 0xff))
                     76:                                ++*b;
                     77:                        break;
                     78:        }
                     79: }
                     80: 
                     81: void temp_to_long(const temp_real * a, long_real * b)
                     82: {
                     83:        if (!(a->exponent & 0x7fff)) {
                     84:                b->a = 0;
                     85:                b->b = (a->exponent)?0x80000000:0;
                     86:                return;
                     87:        }
                     88:        b->b = (((0x7fff & (long) a->exponent)-16383+1023) << 20) & 0x7ff00000;
                     89:        if (a->exponent < 0)
                     90:                b->b |= 0x80000000;
                     91:        b->b |= (a->b >> 11) & 0x000fffff;
                     92:        b->a = a->b << 21;
                     93:        b->a |= (a->a >> 11) & 0x001fffff;
                     94:        switch (ROUNDING) {
                     95:                case ROUND_NEAREST:
                     96:                        if ((a->a & 0x7ff) > 0x400)
                     97:                                __asm__("addl $1,%0 ; adcl $0,%1"
                     98:                                        :"=r" (b->a),"=r" (b->b)
                     99:                                        :"0" (b->a),"1" (b->b));
                    100:                        break;
                    101:                case ROUND_DOWN:
                    102:                        if ((a->exponent & 0x8000) && (a->b & 0xff))
                    103:                                __asm__("addl $1,%0 ; adcl $0,%1"
                    104:                                        :"=r" (b->a),"=r" (b->b)
                    105:                                        :"0" (b->a),"1" (b->b));
                    106:                        break;
                    107:                case ROUND_UP:
                    108:                        if (!(a->exponent & 0x8000) && (a->b & 0xff))
                    109:                                __asm__("addl $1,%0 ; adcl $0,%1"
                    110:                                        :"=r" (b->a),"=r" (b->b)
                    111:                                        :"0" (b->a),"1" (b->b));
                    112:                        break;
                    113:        }
                    114: }
                    115: 
                    116: void real_to_int(const temp_real * a, temp_int * b)
                    117: {
                    118:        int shift =  16383 + 63 - (a->exponent & 0x7fff);
                    119:        unsigned long underflow;
                    120: 
                    121:        b->a = b->b = underflow = 0;
                    122:        b->sign = (a->exponent < 0);
                    123:        if (shift < 0) {
                    124:                set_OE();
                    125:                return;
                    126:        }
                    127:        if (shift < 32) {
                    128:                b->b = a->b; b->a = a->a;
                    129:        } else if (shift < 64) {
                    130:                b->a = a->b; underflow = a->a;
                    131:                shift -= 32;
                    132:        } else if (shift < 96) {
                    133:                underflow = a->b;
                    134:                shift -= 64;
                    135:        } else
                    136:                return;
                    137:        __asm__("shrdl %2,%1,%0"
                    138:                :"=r" (underflow),"=r" (b->a)
                    139:                :"c" ((char) shift),"0" (underflow),"1" (b->a));
                    140:        __asm__("shrdl %2,%1,%0"
                    141:                :"=r" (b->a),"=r" (b->b)
                    142:                :"c" ((char) shift),"0" (b->a),"1" (b->b));
                    143:        __asm__("shrl %1,%0"
                    144:                :"=r" (b->b)
                    145:                :"c" ((char) shift),"0" (b->b));
                    146:        switch (ROUNDING) {
                    147:                case ROUND_NEAREST:
                    148:                        __asm__("addl %4,%5 ; adcl $0,%0 ; adcl $0,%1"
                    149:                                :"=r" (b->a),"=r" (b->b)
                    150:                                :"0" (b->a),"1" (b->b)
                    151:                                ,"r" (0x7fffffff + (b->a & 1))
                    152:                                ,"m" (*&underflow));
                    153:                        break;
                    154:                case ROUND_UP:
                    155:                        if (!b->sign && underflow)
                    156:                                __asm__("addl $1,%0 ; adcl $0,%1"
                    157:                                        :"=r" (b->a),"=r" (b->b)
                    158:                                        :"0" (b->a),"1" (b->b));
                    159:                        break;
                    160:                case ROUND_DOWN:
                    161:                        if (b->sign && underflow)
                    162:                                __asm__("addl $1,%0 ; adcl $0,%1"
                    163:                                        :"=r" (b->a),"=r" (b->b)
                    164:                                        :"0" (b->a),"1" (b->b));
                    165:                        break;
                    166:        }
                    167: }
                    168: 
                    169: void int_to_real(const temp_int * a, temp_real * b)
                    170: {
                    171:        b->a = a->a;
                    172:        b->b = a->b;
                    173:        if (b->a || b->b)
                    174:                b->exponent = 16383 + 63 + (a->sign? 0x8000:0);
                    175:        else {
                    176:                b->exponent = 0;
                    177:                return;
                    178:        }
                    179:        while (b->b >= 0) {
                    180:                b->exponent--;
                    181:                __asm__("addl %0,%0 ; adcl %1,%1"
                    182:                        :"=r" (b->a),"=r" (b->b)
                    183:                        :"0" (b->a),"1" (b->b));
                    184:        }
                    185: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.