1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
! bcc 386 floating point routines (version 2) -- _frexp
! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
#include "fplib.h"
.extern fpdenormal
! void frexp(double value, int *exponent);
! splits a double into exponent and fraction (where 0.5 <= fraction < 1.0)
.globl _frexp
.align ALIGNMENT
_frexp:
push ebx
#undef PC_SIZE
#define PC_SIZE 8
mov eax,PC_SIZE+D_LOW[esp] ! lower dword of x
mov ebx,PC_SIZE+D_HIGH[esp] ! upper dword of x
mov edx,PC_SIZE+D_SIZE[esp] ! exponent pointer
mov ecx,ebx ! extract exponent here
and ecx,#D_EXP_MASK
jz exp_x_0
shr ecx,#D_EXP_SHIFT ! exponent + bias
got_x:
sub ecx,#D_EXP_BIAS-1 ! D_EXP_BIAS is for 1.x form, we want 0.1x form
mov [edx],ecx ! return exponent
and ebx,#D_SIGN_MASK | D_FRAC_MASK ! extract sign and fraction
or ebx,#(D_EXP_BIAS-1) << D_EXP_SHIFT ! set new exponent for 0.1x
mov edx,ebx
pop ebx
ret
.align ALIGNMENT
exp_x_0:
test ebx,#D_FRAC_MASK
jnz xu_denorm
test eax,eax
jnz xl_denorm
mov [edx],ecx ! return zero exponent
mov ebx,ecx ! guard against -0 (may not be necessary)
mov edx,ebx
pop ebx
ret
.align ALIGNMENT
xl_denorm:
call fpdenormal
bsr ecx,eax ! zzzz
neg ecx
add ecx,#REG_BIT-1
shl eax,cl
shld ebx,eax,#D_NORM_BIT+1
shl eax,#D_NORM_BIT+1
sub ecx,#D_NORM_BIT+1
jmp got_x
.align ALIGNMENT
xu_denorm:
call fpdenormal
bsr ecx,ebx
neg ecx
add ecx,#D_NORM_BIT
shld ebx,eax,cl
shl eax,cl
jmp got_x
|