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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
! bcc 386 floating point routines (version 2)
! -- Fpushi, Fpushl, Fpushs, Fpushc, Fpushuc, Fpushui, Fpushul, Fpushus
! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
#include "fplib.h"
! Convert the short in ax to double and push on stack
.globl Fpushs
.align ALIGNMENT
Fpushs:
cwde
add eax,#0 ! fast 3-byte instruction to align
! Convert the int or long in eax to double and push on stack
.globl Fpushi
.globl Fpushl
! .align ALIGNMENT ! don't do this until it pads with nop's
Fpushi:
Fpushl:
test eax,eax
jz return_eax ! got 0 in eax
mov ebx,#(D_EXP_BIAS+D_NORM_BIT) << D_EXP_SHIFT ! set no-sign and exponent
jns normalize ! sign and fraction bits already set up
mov ebx,#D_SIGN_MASK | ((D_EXP_BIAS+D_NORM_BIT) << D_EXP_SHIFT) ! adjust sign
neg eax ! adjust fraction
jmp normalize
.align ALIGNMENT
ret1:
mov eax,#D_EXP_BIAS << D_EXP_SHIFT
add eax,#0 ! fast 3-byte instruction to align
! .align ALIGNMENT ! don't do this until it pads with nop's
return_eax:
pop ecx
push eax ! upper dword
push dword #0 ! lower dword = 0
jmp ecx ! return
! Convert the (unsigned) char in al to double and push on stack
.globl Fpushc
.globl Fpushuc
.align ALIGNMENT
Fpushc:
Fpushuc:
and eax,#(1 << CHAR_BIT)-1
add eax,#0 ! fast 3-byte instruction to align
! Convert the unsigned short in ax to double and push on stack
.globl Fpushus
! .align ALIGNMENT ! don't do this until it pads with nop's
Fpushus:
and eax,#(1 << SHORT_BIT)-1
add eax,#0 ! fast 3-byte instruction to align
! Convert the unsigned int or long in eax to double and push on stack
.globl Fpushui
.globl Fpushul
! .align ALIGNMENT ! don't do this until it pads with nop's
Fpushui:
Fpushul:
cmp eax,#1 ! this tests for both 0 and 1
jb return_eax ! got 0 in eax
jz ret1
mov ebx,#(D_EXP_BIAS+D_NORM_BIT) << D_EXP_SHIFT ! set no-sign and exponent
! .align ALIGNMENT ! don't do this until it pads with nop's
normalize:
sub edx,edx ! clear lower dword of result
! Find first nonzero bit
! Don't use bsr, it is slow (const + 3n on 386, const + n on 486)
sub ecx,ecx ! prepare unsigned extension of cl
test eax,#~D_FRAC_MASK
jnz large
test eax,#0xFF << (D_NORM_BIT-8)
jnz middle
shl eax,#8
sub ebx,#8 << D_EXP_SHIFT
test eax,#0xFF << (D_NORM_BIT-8)
jnz middle
shl eax,#8
sub ebx,#8 << D_EXP_SHIFT
middle:
shld ecx,eax,#D_NORM_BIT
mov cl,bsr_table[ecx]
add ecx,#REG_BIT-D_NORM_BIT-D_NORM_BIT
neg ecx
shl eax,cl
shl ecx,#D_EXP_SHIFT
sub ebx,ecx
return:
and eax,#D_FRAC_MASK ! remove normalization bit
or eax,ebx ! include exponent (and sign) to fraction
pop ecx
push eax ! upper dword
push edx ! lower dword
jmp ecx ! return
.align ALIGNMENT
large:
shld ecx,eax,#REG_BIT-(D_NORM_BIT+8)
jnz huge
shld ecx,eax,#REG_BIT-D_NORM_BIT
mov cl,bsr_table[ecx]
got_shift_right:
shrd edx,eax,cl
shr eax,cl
shl ecx,#D_EXP_SHIFT
add ebx,ecx
jmp return
.align ALIGNMENT
huge:
mov cl,bsr_table[ecx]
add cl,#8
jmp got_shift_right
.data
.extern bsr_table
|