| /*---------------------------------------------------------------------------+ |
| | 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 |