-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathf32_muli16.z80
162 lines (157 loc) · 2.45 KB
/
f32_muli16.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
152
153
154
155
156
157
158
159
160
161
162
#ifndef included_f32_muli16
#define included_f32_muli16
#include "pushpop.z80"
#include "C_Times_BDE.z80"
;
; This is a special-purpose routine for multiplying an f32 float (x):
; x * DE
; where DE is a signed 16-bit integer.
f32_muli16:
;Inputs:
; HL points to the float
; DE is the (signed) multiplier
; BC points to the output
;Destroys:
; None
call pushpop
push bc
push de ; multiplier
ld e,(hl)
inc hl
ld d,(hl)
inc hl
ld b,(hl)
inc hl
ld c,(hl)
pop hl
; adjust the sign of the float
ld a,h
and %10000000
xor c
ld c,a
ld a,b
add a,a
ld a,c
adc a,a
jr z,f32_muli16_return_pop1
inc a
jr z,f32_muli16_infnan
ld a,h
or l
jr z,f32_muli16_zero
; put abs(HL) ==> AL
ld a,h
or a
jp p,f32_muli16_pos
xor a
sub l
ld l,a
sbc a,a
sub h
f32_muli16_pos:
; uint16(AL) * f32(CBDE)
push bc
set 7,b
ld c,a
push hl
call C_Times_BDE ;CAHL
ex (sp),hl
; need to push CA, preserving BDE, and put L in C
ld h,c
ld c,l
ld l,a
push hl
call C_Times_BDE ;CAHL
pop de
pop ix
; 0CAHL
;+DEIX0
ld b,a
ld a,c
ld c,h
add ix,bc
adc a,e
ld e,a
adc a,d
sub e
push ix
pop bc
ld h,c
ld d,e
ld e,b
pop bc
sla b
rl c ; C is the exponent
push af ; save the sign, also A
; add 16+1 to the sign. Later we check for overflow, the +1 makes it so we don't
; need to check for 0xFF, we just need to decrement later
ld a,17
add a,c
ld c,a
ld a,0
rla
ld b,a
pop af ; restore A
push af ; but save the sign
;ADEHL is the denormalized significand, need to normalize it. BC is the exponent
or a
jr f32_muli16_norm_loop_start
f32_muli16_norm_loop:
dec bc
add hl,hl
rl e
rl d
adc a,a
f32_muli16_norm_loop_start:
jp p,f32_muli16_norm_loop
; C is the exponent, ADEHL is the significand
sla h
jr nc,f32_muli16_rounded
inc e
jr nz,f32_muli16_rounded
inc d
jr nz,f32_muli16_rounded
inc a
jr nz,f32_muli16_rounded
inc bc
f32_muli16_rounded:
ld h,a
pop af
dec b
jr z,f32_muli16_inf
dec c
ld a,h
rr c
rla
rrca
ld b,a
jr f32_muli16_return_pop1
f32_muli16_infnan:
ld a,h
or l
jr nz,f32_muli16_return_pop1
ld b,-1
jr f32_muli16_return_pop1
f32_muli16_zero:
ld b,a
ld c,a
ld d,a
ld e,a
f32_muli16_return_pop1:
pop hl
f32_muli16_return:
ld (hl),e
inc hl
ld (hl),d
inc hl
ld (hl),b
inc hl
ld (hl),c
ret
f32_muli16_inf:
ld d,b
ld e,b
ld bc,%1000000011111110
rr c
jr f32_muli16_return_pop1
#endif