-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathfaddsub-fast.asm
187 lines (178 loc) · 2.99 KB
/
faddsub-fast.asm
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
; Add two positive floating-point numbers
; In: HL,DE numbers to add
; Out: HL = sum HL + DE
; Pollutes: AF,DE
FADDP: LD A,H
SUB D
JR NC,FADDPL
EX DE,HL
NEG
FADDPL: JR Z,FADD0 ; same magnitude
CP 10
RET NC ; magnitude too different, just return the bigger number
ADD A,ADDTAB/$100 - 1
LD D,A
LD A,(DE)
OR A
JR Z,FADD2
ADD A,L
LD L,A
RET NC
SRL A
FADD1: ADC A,0
LD L,A
INC H
BIT 7,H ; check overflow
RET Z
FINFTY: LD HL,MAXF ; positive maxfloat
RET
FADD2: LD E,A
FADD0: LD A,L
ADD A,E
RRA
JR FADD1
; Round towards zero
; In: HL any floating-point number
; Out: HL same number rounded towards zero
; Pollutes: AF,B
FINT: LD A,H
AND $7F
SUB $40
JR C,FZERO ; Completely fractional
FINT2: SUB 8
RET NC ; Already integer
NEG
AND 7
JR Z,FINT0
LD B,A
LD A,$FF
FINTL: ADD A,A
DJNZ FINTL
AND L
FINT0: LD L,A
RET
FZERO: LD HL,MINF
RET
; Fractional part, remainder after division by 1
; In: HL any floating-point number
; Out: HL fractional part, with sign intact
; Pollutes: AF,AF',BC,DE
FRAC: LD A,H
AND $7F
SUB $40
RET C ; Pure fraction
PUSH HL
CALL FINT2
EX DE,HL
POP HL
JR FSUB
; Remainder after division
; In: BC dividend, HL modulus
; Out: HL remainder
; Pollutes: AF,AF',BC,DE
FMOD: PUSH BC ; Stack: dividend
PUSH HL ; Stack: dividend, modulus
CALL FDIV
CALL FINT ; integer ratio
EX DE,HL ; DE = int(BC/HL)
POP BC ; Stack: dividend; BC = modulus
CALL FMUL ; Stack: dividend
EX DE,HL
POP HL
; continue with FSUB
; Subtract two floating-point numbers
; In: HL,DE numbers to subtract, no restrictions
; Out: HL = difference HL - DE
; Pollutes: AF,AF',BC,DE
FSUB: LD A,D
XOR $80
LD D,A ; DE = -DE
; continue with FADD
; Add two floating-point numbers
; In: HL,DE numbers to add, no restrictions
; Out: HL = sum HL + DE
; Pollutes: AF,AF',BC,DE
FADD: LD B,H
LD C,D
LD A,B
XOR C
ADD A,A
EX AF,AF'
RES 7,H
RES 7,D
CALL FCPP
JR NC,FADDNS ; no swap
EX DE,HL
LD B,C
FADDNS: EX AF,AF'
JR C,FADDS
CALL FADDP
JR FADDHB
FADDS: CALL FSUBP
FADDHB: LD A,B
AND $80
OR H
LD H,A
RET
; Compare two positive floating point numbers
; In: HL,DE numbers to compare
; Out: C flag if DE>HL, Z flag if DE=HL
; Pollutes: A
FCPP: LD A,H
CP D
RET NZ
LD A,L
CP E
RET
; Subtract two positive floating-point numbers
; In: HL,DE numbers to subtract, HL >= DE
; Out: HL = difference HL - DE
; Pollutes: AF,DE,HL'
FSUBP: LD A,H
SUB D
JR Z,FSUB0 ; same magnitude, cleared C flag
CP 10
RET NC ; magnitude too different, just return the bigger number
EXX
LD H,BITTAB/$100
LD L,A
DEC L
EX AF,AF'
LD A,(HL)
EXX
AND E
EX AF,AF'
ADD A,ADDTAB/$100 - 1
LD D,A
LD A,(DE)
OR A
JR Z,FSUB2 ; $1.FF / 2 = $1.00 (SBC A,$FF with C=1 does not change A, but sets carry)
NEG
ADD A,L
LD L,A
RET C
FSUB2: LD A,L
OR A
JR Z,FZERO3 ; $1.00 - $1.00 = 0
FSUBL2: LD D,H
LD H,SUBTAB/$100
LD A,(HL)
INC H
EX AF,AF'
JR Z,FSUB1
INC H
FSUB1: EX AF,AF'
LD L,(HL)
ADD A,D
JR NC,FZERO2 ; underflow
LD H,A
RET
FSUB0: LD A,L
SUB A,E
LD L,A
JR NZ,FSUBL2
FZERO3: LD H,L
RET
; Return epsilon
FZERO2: LD HL,MINF
RET