Linux 0.12 OS. math - convert.c
2013-05-25 09:11
381 查看
convert.c提供了多种数据格式转换的功能,包含了单精度实数、双精度实数、临时实数和整数。
I. short_to_temp
单精度实数的格式:符号位/bit31指数/bit30~23 尾数/bit22~0
临时实数的格式:符号位/bit79指数/bit78~64 尾数/bit63~0
II. long_to_temp
双精度实数的格式:符号位/bit63指数/bit62~52 尾数/bit51~0
III. temp_to_short
IV. temp_to_long
V. real_to_int
VI. int_to_real
I. short_to_temp
单精度实数的格式:符号位/bit31指数/bit30~23 尾数/bit22~0
临时实数的格式:符号位/bit79指数/bit78~64 尾数/bit63~0
void short_to_temp(const short_real * a, temp_real * b) { if (!(*a & 0x7fffffff)) { /* if =0 */ b->a = b->b = 0; if (*a) /* sign =1 */ b->exponent = 0x8000; else b->exponent = 0; return; } b->exponent = ((*a>>23) & 0xff)-127+16383; /* 计算指数, 注意单精度的指数的偏置数是127 */ if (*a<0) /* 负数 */ b->exponent |= 0x8000; b->b = (*a<<8) | 0x80000000; /* 尾数部分,注意临时实数 的尾数最高位为1 */ b->a = 0; }
II. long_to_temp
双精度实数的格式:符号位/bit63指数/bit62~52 尾数/bit51~0
void long_to_temp(const long_real * a, temp_real * b) { if (!a->a && !(a->b & 0x7fffffff)) { /* if =0 */ b->a = b->b = 0; if (a->b) /* sign =1 */ b->exponent = 0x8000; else b->exponent = 0; return; } b->exponent = ((a->b >> 20) & 0x7ff)-1023+16383; /* 计算指数,注意双精度实数的指数的偏置数是1023 */ if (a->b<0) /* 负数 */ b->exponent |= 0x8000; b->b = 0x80000000 | (a->b<<11) | (((unsigned long)a->a)>>21); /*尾数部分,注意双精度的尾数是bit51~0,(a>b<<11)表示bit52~32, (a->a>>21)表示bit31~21 */ b->a = a->a<<11; /* (a->a<<11)表示bit20~0 */ }
III. temp_to_short
void temp_to_short(const temp_real * a, short_real * b) { if (!(a->exponent & 0x7fff)) { /* if =0 */ *b = (a->exponent)?0x80000000:0; return; } *b = ((((long) a->exponent)-16383+127) << 23) & 0x7f800000; /* 计算指数,注意单精度实数的指令部分在bit30~23 */ if (a->exponent < 0) /* 负数 */ *b |= 0x80000000; *b |= (a->b >> 8) & 0x007fffff; /* 尾数部分,注意单精度的尾数 部分在bit22~0 */ switch (ROUNDING) { /* rounding,四舍五入,读取控制寄存器 */ case ROUND_NEAREST: if ((a->b & 0xff) > 0x80) /* 用剩余的8位来做判断即可 */ ++*b; /* 单精度实数加1 */ break; case ROUND_DOWN: if ((a->exponent & 0x8000) && (a->b & 0xff)) ++*b; break; case ROUND_UP: if (!(a->exponent & 0x8000) && (a->b & 0xff)) ++*b; break; } }
IV. temp_to_long
void temp_to_long(const temp_real * a, long_real * b) { if (!(a->exponent & 0x7fff)) { /* if =0 */ b->a = 0; b->b = (a->exponent)?0x80000000:0; return; } b->b = (((0x7fff & (long) a->exponent)-16383+1023) << 20) & 0x7ff00000; /* 计算指数,注意双精度的指数部分在bit62~52 */ if (a->exponent < 0) /* 负数 */ b->b |= 0x80000000; b->b |= (a->b >> 11) & 0x000fffff; /* 尾数部分,先赋值临时实数 的bit62~43给双精度实数的bit51~32 */ b->a = a->b << 21; /* 在赋值临时实数的bit42~32给双精度实数的bit31~21 */ b->a |= (a->a >> 11) & 0x001fffff; /*最后赋值临时实数的bit31~11给双精度 实数的bit20~0 */ switch (ROUNDING) { /*rounding,四舍五入,读取控制寄存器 */ case ROUND_NEAREST: if ((a->a & 0x7ff) > 0x400) /* 用剩余的11位来做判断即可 */ __asm__("addl $1,%0 ; adcl $0,%1" :"=r" (b->a),"=r" (b->b) :"0" (b->a),"1" (b->b)); /* 双精度实数加1 */ break; case ROUND_DOWN: if ((a->exponent & 0x8000) && (a->b & 0xff)) __asm__("addl $1,%0 ; adcl $0,%1" :"=r" (b->a),"=r" (b->b) :"0" (b->a),"1" (b->b)); break; case ROUND_UP: if (!(a->exponent & 0x8000) && (a->b & 0xff)) __asm__("addl $1,%0 ; adcl $0,%1" :"=r" (b->a),"=r" (b->b) :"0" (b->a),"1" (b->b)); break; } }
V. real_to_int
void real_to_int(const temp_real * a, temp_int * b) { int shift = 16383 + 63 - (a->exponent & 0x7fff); /* shift表示1xxx...xxx(尾数部分小数点向右移动了63位), 的小数点向左移动的位数 */ unsigned long underflow; b->a = b->b = underflow = 0; b->sign = (a->exponent < 0); if (shift < 0) { /* shift为负数,表示1xxx...xxx小数点 还要向右移动至少一位,必然溢出了对于64位整数(temp_int)范围 */ set_OE(); /* 8.5.4 Numeric overflow exception (#O) */ return; } if (shift < 32) { /* 保证0~31位的shift范围 */ b->b = a->b; b->a = a->a; } else if (shift < 64) { /* 保证0~31位的shift范围 */ b->a = a->b; underflow = a->a; /* 把位移出去的做四舍五入用 */ shift -= 32; } else if (shift < 96) { /* 虽然已经超出了64位的范围,不过 位移出去的可以做可以四舍五入用,毕竟a->b最高位为1哟~ */ underflow = a->b; shift -= 64; } else return; /* 开始shift,shift完后,可以把underflow看成小数部分 */ __asm__("shrdl %2,%1,%0" :"=r" (underflow),"=r" (b->a) :"c" ((char) shift),"0" (underflow),"1" (b->a)); /* shift underflow */ __asm__("shrdl %2,%1,%0" :"=r" (b->a),"=r" (b->b) :"c" ((char) shift),"0" (b->a),"1" (b->b)); /* shift 低32位 */ __asm__("shrl %1,%0" :"=r" (b->b) :"c" ((char) shift),"0" (b->b)); /* shift 高32位 */ switch (ROUNDING) { /* rounding,四舍五入,读取控制寄存器 */ case ROUND_NEAREST: /* 两种情况: 1. 整数部分的最低位为1,那么underflow >= 0x80000000则进位 2. 整数部分的最低位为0,那么underflow > 0x80000000则进位 这个和实数的进位方式有区别。 */ __asm__("addl %4,%5 ; adcl $0,%0 ; adcl $0,%1" :"=r" (b->a),"=r" (b->b) :"0" (b->a),"1" (b->b) ,"r" (0x7fffffff + (b->a & 1)) ,"m" (*&underflow)); break; case ROUND_UP: if (!b->sign && underflow) __asm__("addl $1,%0 ; adcl $0,%1" :"=r" (b->a),"=r" (b->b) :"0" (b->a),"1" (b->b)); break; case ROUND_DOWN: if (b->sign && underflow) __asm__("addl $1,%0 ; adcl $0,%1" :"=r" (b->a),"=r" (b->b) :"0" (b->a),"1" (b->b)); break; } }
VI. int_to_real
void int_to_real(const temp_int * a, temp_real * b) { b->a = a->a; b->b = a->b; if (b->a || b->b) /* 把偏移和符号位加上 */ b->exponent = 16383 + 63 + (a->sign? 0x8000:0); else { b->exponent = 0; return; } while (b->b >= 0) { /* 然后进行规范化 */ b->exponent--; __asm__("addl %0,%0 ; adcl %1,%1" :"=r" (b->a),"=r" (b->b) :"0" (b->a),"1" (b->b)); } }
相关文章推荐
- Linux 0.12 OS. math - mul.c
- Linux 0.12 OS. math - div.c
- Linux 0.12 OS. math - compare.c
- Linux 0.12 OS. math - math_emulate.c
- Linux 0.12 OS. math - math_emu.h
- Linux 0.12 OS. math - error.c
- Linux 0.12 OS. math - ea.c
- Linux 0.12 OS. math - get_put.c
- Linux 0.12 OS. math - add.c
- Linux 0.12 OS. math - CR0
- Linux 0.12 OS. block - blk.h
- Linux 0.12 OS. block - ll_rw_blk.c
- Convert HTML Page To a PDF Using Open Source Tool [ Linux / OS X / Windows ]
- Linux(ubuntu)下30天自制os学习引导,第2天(gas汇编语言)
- Linux0.12内核之内存管理(2)
- build android os ubuntu Setting up a Linux build environment
- Linux0.12内核之内存管理(3)
- hidden symbol `pthread_atfork' in /usr/lib/x86_64-linux-gnu/libpthread_nonshared.a(pthread_atfork.oS
- 我-linux-自己的os(演示版)-(类似linux 0.01)
- rman convert 迁移win64位oracle 到linux oracle+asm 手稿