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

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: 
1.1.1.2 ! root      116: void frndint(const temp_real * a, temp_real * b)
        !           117: {
        !           118:        int shift =  16383 + 63 - (a->exponent & 0x7fff);
        !           119:        unsigned long underflow;
        !           120: 
        !           121:        if ((shift < 0) || (shift == 16383+63)) {
        !           122:                *b = *a;
        !           123:                return;
        !           124:        }
        !           125:        b->a = b->b = underflow = 0;
        !           126:        b->exponent = a->exponent;
        !           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:                b->exponent += 32;
        !           133:        } else if (shift < 96) {
        !           134:                underflow = a->b;
        !           135:                shift -= 64;
        !           136:                b->exponent += 64;
        !           137:        } else {
        !           138:                underflow = 1;
        !           139:                shift = 0;
        !           140:        }
        !           141:        b->exponent += shift;
        !           142:        __asm__("shrdl %2,%1,%0"
        !           143:                :"=r" (underflow),"=r" (b->a)
        !           144:                :"c" ((char) shift),"0" (underflow),"1" (b->a));
        !           145:        __asm__("shrdl %2,%1,%0"
        !           146:                :"=r" (b->a),"=r" (b->b)
        !           147:                :"c" ((char) shift),"0" (b->a),"1" (b->b));
        !           148:        __asm__("shrl %1,%0"
        !           149:                :"=r" (b->b)
        !           150:                :"c" ((char) shift),"0" (b->b));
        !           151:        switch (ROUNDING) {
        !           152:                case ROUND_NEAREST:
        !           153:                        __asm__("addl %4,%5 ; adcl $0,%0 ; adcl $0,%1"
        !           154:                                :"=r" (b->a),"=r" (b->b)
        !           155:                                :"0" (b->a),"1" (b->b)
        !           156:                                ,"r" (0x7fffffff + (b->a & 1))
        !           157:                                ,"m" (*&underflow));
        !           158:                        break;
        !           159:                case ROUND_UP:
        !           160:                        if ((b->exponent >= 0) && underflow)
        !           161:                                __asm__("addl $1,%0 ; adcl $0,%1"
        !           162:                                        :"=r" (b->a),"=r" (b->b)
        !           163:                                        :"0" (b->a),"1" (b->b));
        !           164:                        break;
        !           165:                case ROUND_DOWN:
        !           166:                        if ((b->exponent < 0) && underflow)
        !           167:                                __asm__("addl $1,%0 ; adcl $0,%1"
        !           168:                                        :"=r" (b->a),"=r" (b->b)
        !           169:                                        :"0" (b->a),"1" (b->b));
        !           170:                        break;
        !           171:        }
        !           172:        if (b->a || b->b)
        !           173:                while (b->b >= 0) {
        !           174:                        b->exponent--;
        !           175:                        __asm__("addl %0,%0 ; adcl %1,%1"
        !           176:                                :"=r" (b->a),"=r" (b->b)
        !           177:                                :"0" (b->a),"1" (b->b));
        !           178:                }
        !           179:        else
        !           180:                b->exponent = 0;
        !           181: }
        !           182: 
1.1       root      183: void real_to_int(const temp_real * a, temp_int * b)
                    184: {
                    185:        int shift =  16383 + 63 - (a->exponent & 0x7fff);
                    186:        unsigned long underflow;
                    187: 
                    188:        b->a = b->b = underflow = 0;
                    189:        b->sign = (a->exponent < 0);
                    190:        if (shift < 0) {
                    191:                set_OE();
                    192:                return;
                    193:        }
                    194:        if (shift < 32) {
                    195:                b->b = a->b; b->a = a->a;
                    196:        } else if (shift < 64) {
                    197:                b->a = a->b; underflow = a->a;
                    198:                shift -= 32;
                    199:        } else if (shift < 96) {
                    200:                underflow = a->b;
                    201:                shift -= 64;
1.1.1.2 ! root      202:        } else {
        !           203:                underflow = 1;
        !           204:                shift = 0;
        !           205:        }
1.1       root      206:        __asm__("shrdl %2,%1,%0"
                    207:                :"=r" (underflow),"=r" (b->a)
                    208:                :"c" ((char) shift),"0" (underflow),"1" (b->a));
                    209:        __asm__("shrdl %2,%1,%0"
                    210:                :"=r" (b->a),"=r" (b->b)
                    211:                :"c" ((char) shift),"0" (b->a),"1" (b->b));
                    212:        __asm__("shrl %1,%0"
                    213:                :"=r" (b->b)
                    214:                :"c" ((char) shift),"0" (b->b));
                    215:        switch (ROUNDING) {
                    216:                case ROUND_NEAREST:
                    217:                        __asm__("addl %4,%5 ; adcl $0,%0 ; adcl $0,%1"
                    218:                                :"=r" (b->a),"=r" (b->b)
                    219:                                :"0" (b->a),"1" (b->b)
                    220:                                ,"r" (0x7fffffff + (b->a & 1))
                    221:                                ,"m" (*&underflow));
                    222:                        break;
                    223:                case ROUND_UP:
                    224:                        if (!b->sign && underflow)
                    225:                                __asm__("addl $1,%0 ; adcl $0,%1"
                    226:                                        :"=r" (b->a),"=r" (b->b)
                    227:                                        :"0" (b->a),"1" (b->b));
                    228:                        break;
                    229:                case ROUND_DOWN:
                    230:                        if (b->sign && underflow)
                    231:                                __asm__("addl $1,%0 ; adcl $0,%1"
                    232:                                        :"=r" (b->a),"=r" (b->b)
                    233:                                        :"0" (b->a),"1" (b->b));
                    234:                        break;
                    235:        }
                    236: }
                    237: 
                    238: void int_to_real(const temp_int * a, temp_real * b)
                    239: {
                    240:        b->a = a->a;
                    241:        b->b = a->b;
                    242:        if (b->a || b->b)
                    243:                b->exponent = 16383 + 63 + (a->sign? 0x8000:0);
                    244:        else {
                    245:                b->exponent = 0;
                    246:                return;
                    247:        }
                    248:        while (b->b >= 0) {
                    249:                b->exponent--;
                    250:                __asm__("addl %0,%0 ; adcl %1,%1"
                    251:                        :"=r" (b->a),"=r" (b->b)
                    252:                        :"0" (b->a),"1" (b->b));
                    253:        }
                    254: }

unix.superglobalmegacorp.com

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