-
Notifications
You must be signed in to change notification settings - Fork 11
/
f64tof32.z80
151 lines (145 loc) · 2.09 KB
/
f64tof32.z80
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#ifndef included_f64tof32
#define included_f64tof32
#include "routines/rl64.z80"
#include "mov.z80"
#include "pushpop.z80"
f64tof32:
;Inputs:
; HL points to the input double-precision float
; BC points to where to output the result
;Outputs:
; The double-precision float (binary64) is converted to an extended-precision
; float at BC.
;
call pushpop
f64tof32_nopush:
; we don't need the bottom 3 bytes except if we need to distinguish between inf
; and NaN.
push bc ;save the pointer to the output
ld a,(hl)
inc hl
or (hl)
inc hl
or (hl)
inc hl
ld e,(hl)
inc hl
ld d,(hl)
inc hl
ld c,(hl)
inc hl
ld b,(hl)
inc hl
ld h,(hl)
ld l,a ;save the OR of the bottom 3 bytes
;HBCDE is the top 5 bytes of the f64 float
ld a,h
add a,a
jr z,f64tof32_check_0
add a,2
jr nz,f64tof32_continue
f64tof32_check_infnan:
ld a,b
add a,16
jr nc,f64tof32_continue
f64tof32_infnan:
ld a,b
and %00001111
or c
or d
or e
or l
ld d,h
pop hl
ld (hl),a
inc hl
ld (hl),a
inc hl
or %10000000
ld (hl),a
inc hl
ld a,d
or %01111111
ld (hl),a
ret
f64tof32_check_0:
ld a,b
and %11110000
jr z,f64tof32_zero
f64tof32_continue:
; We need to scale down the exponent, subtract 1023 and add 127, net -896
ld a,h
add a,a
rrca
sub 56
jr c,f64tof32_zero_setA
cp 16
jr nc,f64tof32_inf1
ex de,hl
;DBCHL
add hl,hl
rl c
rl b
rla
add hl,hl
rl c
rl b
rla
add hl,hl
rl c
rl b
rla
xor d
and %01111111
xor d
;ABCHL
; round befoe writing out
sla l
jr nc,f64tof32_rounded
inc h
jr nz,f64tof32_rounded
inc c
jr nz,f64tof32_rounded
inc b
jr nz,f64tof32_rounded
inc a
jr z,f64tof32_inf
f64tof32_rounded:
ld d,h
pop hl
ld (hl),d
inc hl
ld (hl),c
inc hl
ld (hl),b
inc hl
ld (hl),a
ret
f64tof32_zero_setA:
xor a
f64tof32_zero:
ld d,h
pop hl
ld (hl),a
inc hl
ld (hl),a
inc hl
ld (hl),a
inc hl
ld a,d
and %10000000
ld (hl),a
ret
f64tof32_inf1:
ld a,h
f64tof32_inf:
pop hl
ld (hl),0
inc hl
ld (hl),0
inc hl
ld (hl),80h
inc hl
or %01111111
ld (hl),a
#endif