1 ;
--------------------------------------------------------------------------
4 ; Copyright
(C
) 2000, Michael Hope
5 ; Copyright
(C
) 2021, Sebastian
'basxto' Riedel
(sdcc@basxto.de
)
6 ; Copyright
(c
) 2021, Philipp Klaus Krause
8 ; This library is free software; you can redistribute it
and/or modify it
9 ; under the terms of the GNU General Public License as published by the
10 ; Free Software Foundation; either version
2, or (at your option
) any
13 ; This library is distributed in the hope that it will
be useful
,
14 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ; MERCHANTABILITY
or FITNESS FOR
A PARTICULAR PURPOSE. See the
16 ; GNU General Public License for more details.
18 ; You should have received
a copy of the GNU General Public License
19 ; along with this library; see the file COPYING. If
not, write to the
20 ; Free Software Foundation
, 51 Franklin Street
, Fifth Floor
, Boston
,
23 ; As
a special exception
, if you link this library with other files
,
24 ; some of which are compiled with SDCC
, to produce an executable
,
25 ; this library does
not by itself cause the resulting executable to
26 ;
be covered by the GNU General Public License. This exception does
27 ;
not however invalidate any other reasons why the executable file
28 ; might
be covered by the GNU General Public License.
29 ;
--------------------------------------------------------------------------
31 ;; Originally from GBDK by Pascal Felber.
185 ld a, e ; Sign extend
190 ; Fall through to
.div16
201 ;; If divisor is non-zero
, carry
=0
202 ;; If divisor is
0, carry
=1 and both quotient
and remainder are
0
204 ;; Register used
: AF
,BC,DE
,HL
207 ;; Determine sign of quotient by xor-ing high bytes of dividend
208 ;;
and divisor. Quotient is positive if signs are the same
, negative
209 ;; if signs are different
210 ;; Remainder has same sign as dividend
211 ld a,b ; Get high byte of dividend
212 push af ; Save as sign of remainder
213 xor d ;
Xor with high byte of divisor
214 push af ; Save sign of quotient
216 ;; Take absolute value of divisor
218 jr Z
,.chkde ; Jump if divisor is positive
219 sub a ; Subtract divisor from
0
222 sbc
a ; Propagate borrow
(A=0xFF if borrow
)
225 ;; Take absolute value of dividend
228 jr Z
,.dodiv ; Jump if dividend is positive
229 sub a ; Subtract dividend from
0
232 sbc
a ; Propagate borrow
(A=0xFF if borrow
)
235 ;; Divide absolute values
238 jr C
,.exit ; Exit if divide by zero
239 ;; Negate quotient if it is negative
240 pop af ; recover sign of quotient
242 jr Z
,.dorem ; Jump if quotient is positive
243 sub a ; Subtract quotient from
0
246 sbc
a ; Propagate borrow
(A=0xFF if borrow
)
250 ;; Negate remainder if it is negative
251 pop af ; recover sign of remainder
253 ret Z ; Return if remainder is positive
254 sub a ; Subtract remainder from
0
257 sbc
a ; Propagate remainder
(A=0xFF if borrow
)
270 ; Fall through to divu16
274 ;; Check for division by zero
277 jr NZ
,.divide ; Branch if divisor is non-zero
278 ld bc,#0x00 ; Divide by zero error
281 scf ; Set carry
, invalid result
284 ld l,c ;
L = low byte of dividend
/quotient
285 ld h
,b ; H
= high byte of dividend
/quotient
286 ld bc,#0x00 ; BC = remainder
287 or a ; Clear carry to start
288 ld a,#16 ; 16 bits in dividend
290 ;; Shift next bit of quotient into bit
0 of dividend
291 ;; Shift next MSB of dividend into LSB of remainder
292 ;;
BC holds both dividend
and quotient. While we shift
a bit from
293 ;; MSB of dividend
, we shift next bit of quotient in from carry
294 ;; HL holds remainder
295 ;; Do
a 32-bit left shift
, shifting carry to
L, L to H
,
297 push af ; save number of bits remaining
298 rl
l ; Carry
(next bit of quotient
) to bit
0
299 rl h ; Shift remaining bytes
301 rl
b ; Clears carry since
BC was
0
302 ;; If remainder is
>= divisor
, next bit of quotient is
1. This
304 push
bc ; Save current remainder
305 ld a,c ; Subtract divisor from remainder
311 ccf ; Complement borrow so
1 indicates
a
312 ; successful subtraction
(this is the
313 ; next bit of quotient
)
314 jr C
,.drop ; Jump if remainder is >= dividend
315 pop
bc ; Otherwise
, restore remainder
316 pop af ; recover
# bits remaining, carry flag destroyed
318 or a ; restore
(clear
) the carry flag
322 pop af ; faster
and smaller than
2x inc sp
323 pop af ; recover
# bits remaining, carry flag destroyed
325 scf ; restore
(set
) the carry flag
329 ;; Shift last carry bit into quotient
330 ld d
,b ; DE
= remainder
333 ld c
,l ; C
= low byte of quotient
335 ld b,h ;
B = high byte of quotient
336 or a ; Clear carry
, valid result