-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmath.asm
More file actions
265 lines (237 loc) · 4.36 KB
/
math.asm
File metadata and controls
265 lines (237 loc) · 4.36 KB
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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
;-------------------------------------------------------------------------------
; z80 Math Helper Routines
#data _RAM
MATH32_ACCL: DW 0
MATH32_ACCH: DW 0
#code _ROM
#local
;=======================================================================
;; Internal helper functions for accumulator
; Load 32-bit value at (HL) into ACC
; Corrupts BC, DE, HL
LOAD_ACC:
LD DE, MATH32_ACCL
LDI ; Low byte, low word
LDI
LDI
LDI ; High byte, high word
RET
; Save 32-bit value from ACC to (DE)
; Corrupts BC, DE, HL
SAVE_ACC:
LD HL, MATH32_ACCL
LDI
LDI
LDI
LDI
RET
; Clear ACC
; Corrupts NONE
CLEAR_ACC:
PUSH HL
LD HL, 0
LD (MATH32_ACCL), HL
LD (MATH32_ACCH), HL
POP HL
RET
;=======================================================================
;--------------------------------------------------------
;
; 32-bit Add
; Pointer arguments
; Add LONG (HL) to LONG (DE)
; Corrupts DE, HL
ADD32::
AND A ; Clear carry
; Skip clearing carry for ADC32
ADC32::
PUSH BC
LD B, 4 ; 4 bytes to add
ADD32_LOOP:
LD A, (DE)
ADC A, (HL)
LD (DE), A
INC DE
INC HL
DJNZ ADD32_LOOP
POP BC
RET
;--------------------------------------------------------
; 32-bit sub
; Pointer arguments
; Subtracts LONG (HL) from LONG (DE)
; Corrupts DE, HL, A
SUB32::
AND A ; Clear carry (borrow)
; Skip clearing carry for SBC32
SBC32::
PUSH BC ; Save B
LD B, 4
SUB32_LOOP:
LD A, (DE)
SBC A, (HL)
LD (DE), A
INC DE
INC HL
DJNZ SUB32_LOOP
POP BC
RET
;--------------------------------------------------------
; Add a 16-bit value to a 32-bit value
; Adds DE to LONG (HL)
; Corrupts HL, A
ADD32_16::
AND A ; Clear carry
ADC32_16::
LD A, (HL) ; Low byte
ADC A, E
LD (HL), A
INC HL
LD A, (HL) ; High byte
ADC A, D
LD (HL), A
INC HL
LD A, (HL) ; Propgate carries
ADC 0
LD (HL), A
INC HL
LD A, (HL) ; Propogate carries
ADC 0
LD (HL), A
INC HL
RET
;--------------------------------------------------------
; Subtract a 16-bit value from a 32-bit value
; Subtracts DE from LONG (HL)
; Corrupts HL, A
SUB32_16::
AND A ; Clear carry
SBC32_16::
LD A, (HL) ; Low byte
SBC A, E
LD (HL), A
INC HL
LD A, (HL) ; High byte
SBC A, D
LD (HL), A
INC HL
LD A, (HL) ; Propgate carries
SBC 0
LD (HL), A
INC HL
LD A, (HL) ; Propogate carries
SBC 0
LD (HL), A
INC HL
RET
;--------------------------------------------------------
; Shift LONG (HL) right by 1 (into carry)
; Corrupts NONE
SRL32::
INC HL ;+1
INC HL ;+2
INC HL ;+3 Start with most significant byte
SRL (HL) ; Shift top
DEC HL
RR (HL) ; Rotate next
DEC HL
RR (HL) ; Rotate next
DEC HL
RR (HL) ; Rotate last
RET
;--------------------------------------------------------
; Shift LONG (HL) left by 1 (into carry)
; Corrupts HL
SLL32::
SLA (HL) ; Shift bottom
INC HL
RL (HL) ; Rotate next
INC HL
RL (HL) ; Rotate next
INC HL
RL (HL) ; Rotate top
RET
;--------------------------------------------------------
; Check if LONG (HL) is 0
; Corrupts A
CHKCLR32::
INC HL
INC HL
INC HL ; Start with MSB so we don't corrupt HL
LD A, (HL)
DEC HL
OR (HL)
DEC HL
OR (HL)
DEC HL
OR (HL)
RET
;--------------------------------------------------------
; 32-bit Multiply
; Multiplies LONG (HL) by LONG (BC), result in LONG (HL)
; Upper 32-bits of result discarded
MUL32::
CALL CLEAR_ACC ; Clear accumulator
MUL32_LOOP:
CALL SRL32 ; Get next bit of multiplier (HL)
PUSH HL ; Preserve HL
JR NC, MUL32_NOADD ; If 0 then don't add
PUSH BC ; Move
POP HL ; Current multiplicand (addr) into HL
LD DE, MATH32_ACCL ; Accumulator for result
CALL ADD32 ; Add current value to ACC
MUL32_NOADD:
; Need to shift (BC) to the left by one
PUSH BC
POP HL ; Current multiplicand (addr) into HL
CALL SLL32 ; Shift left
POP HL ; Restore HL
CALL CHKCLR32 ; Check if (HL) is 0 yet
JR NZ, MUL32_LOOP
; We're done, multiplier contains no more bits
EX DE, HL ; Address of where to store result
CALL SAVE_ACC ; Save accumulator to result
RET
;-----
; Copy 32-bit values
; Copy LONG (HL) into LONG (DE)
COPY32::
PUSH BC
LDI
LDI
LDI
LDI
POP BC
RET
; Copy 16-bit value
; Copy WORD (HL) into WORD (DE)
COPY16::
PUSH BC
LDI
LDI
POP BC
RET
; Copy WORD DE into LONG (HL)
; Corrupts DE and HL
COPY32_16::
LD (HL), E
INC HL
LD (HL), D
INC HL
LD D, 0
LD (HL), D
INC HL
LD (HL), D
RET
CLEAR32::
XOR A
LD (HL), A
INC HL
LD (HL), A
INC HL
LD (HL), A
INC HL
LD (HL), A
INC HL
RET
#endlocal