| /*---------------------------------------------------------------------------+ | |
| | reg_norm.S | | |
| | | | |
| | Copyright (C) 1992,1993,1994,1995,1997 | | |
| | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | | |
| | Australia. E-mail billm@suburbia.net | | |
| | | | |
| | Normalize the value in a FPU_REG. | | |
| | | | |
| | Call from C as: | | |
| | int FPU_normalize(FPU_REG *n) | | |
| | | | |
| | int FPU_normalize_nuo(FPU_REG *n) | | |
| | | | |
| | Return value is the tag of the answer, or-ed with FPU_Exception if | | |
| | one was raised, or -1 on internal error. | | |
| | | | |
| +---------------------------------------------------------------------------*/ | |
| #include "fpu_emu.h" | |
| .text | |
| ENTRY(FPU_normalize) | |
| pushl %ebp | |
| movl %esp,%ebp | |
| pushl %ebx | |
| movl PARAM1,%ebx | |
| movl SIGH(%ebx),%edx | |
| movl SIGL(%ebx),%eax | |
| orl %edx,%edx /* ms bits */ | |
| js L_done /* Already normalized */ | |
| jnz L_shift_1 /* Shift left 1 - 31 bits */ | |
| orl %eax,%eax | |
| jz L_zero /* The contents are zero */ | |
| movl %eax,%edx | |
| xorl %eax,%eax | |
| subw $32,EXP(%ebx) /* This can cause an underflow */ | |
| /* We need to shift left by 1 - 31 bits */ | |
| L_shift_1: | |
| bsrl %edx,%ecx /* get the required shift in %ecx */ | |
| subl $31,%ecx | |
| negl %ecx | |
| shld %cl,%eax,%edx | |
| shl %cl,%eax | |
| subw %cx,EXP(%ebx) /* This can cause an underflow */ | |
| movl %edx,SIGH(%ebx) | |
| movl %eax,SIGL(%ebx) | |
| L_done: | |
| cmpw EXP_OVER,EXP(%ebx) | |
| jge L_overflow | |
| cmpw EXP_UNDER,EXP(%ebx) | |
| jle L_underflow | |
| L_exit_valid: | |
| movl TAG_Valid,%eax | |
| /* Convert the exponent to 80x87 form. */ | |
| addw EXTENDED_Ebias,EXP(%ebx) | |
| andw $0x7fff,EXP(%ebx) | |
| L_exit: | |
| popl %ebx | |
| leave | |
| ret | |
| L_zero: | |
| movw $0,EXP(%ebx) | |
| movl TAG_Zero,%eax | |
| jmp L_exit | |
| L_underflow: | |
| /* Convert the exponent to 80x87 form. */ | |
| addw EXTENDED_Ebias,EXP(%ebx) | |
| push %ebx | |
| call arith_underflow | |
| pop %ebx | |
| jmp L_exit | |
| L_overflow: | |
| /* Convert the exponent to 80x87 form. */ | |
| addw EXTENDED_Ebias,EXP(%ebx) | |
| push %ebx | |
| call arith_overflow | |
| pop %ebx | |
| jmp L_exit | |
| /* Normalise without reporting underflow or overflow */ | |
| ENTRY(FPU_normalize_nuo) | |
| pushl %ebp | |
| movl %esp,%ebp | |
| pushl %ebx | |
| movl PARAM1,%ebx | |
| movl SIGH(%ebx),%edx | |
| movl SIGL(%ebx),%eax | |
| orl %edx,%edx /* ms bits */ | |
| js L_exit_nuo_valid /* Already normalized */ | |
| jnz L_nuo_shift_1 /* Shift left 1 - 31 bits */ | |
| orl %eax,%eax | |
| jz L_exit_nuo_zero /* The contents are zero */ | |
| movl %eax,%edx | |
| xorl %eax,%eax | |
| subw $32,EXP(%ebx) /* This can cause an underflow */ | |
| /* We need to shift left by 1 - 31 bits */ | |
| L_nuo_shift_1: | |
| bsrl %edx,%ecx /* get the required shift in %ecx */ | |
| subl $31,%ecx | |
| negl %ecx | |
| shld %cl,%eax,%edx | |
| shl %cl,%eax | |
| subw %cx,EXP(%ebx) /* This can cause an underflow */ | |
| movl %edx,SIGH(%ebx) | |
| movl %eax,SIGL(%ebx) | |
| L_exit_nuo_valid: | |
| movl TAG_Valid,%eax | |
| popl %ebx | |
| leave | |
| ret | |
| L_exit_nuo_zero: | |
| movl TAG_Zero,%eax | |
| movw EXP_UNDER,EXP(%ebx) | |
| popl %ebx | |
| leave | |
| ret |