Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/crt/ldivu.src
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@

.else

; REMEMBER to keep ldivu.src, lremu.src, and ldiv.src in sync with this choice
.if 1

__ldivu:
; I: EUHL=dividend, AUBC=divisor
; O: euhl=EUHL/AUBC
push bc

call __ldvrmu
call __ldivu_lremu_common

ld a, b
pop bc
Expand All @@ -26,6 +27,8 @@ __ldivu:
ei
ret

.extern __ldivu_lremu_common

.else

__ldivu:
Expand All @@ -41,8 +44,9 @@ __ldivu:
pop hl

ret
.endif

.extern __ldvrmu

.endif

.endif
86 changes: 86 additions & 0 deletions src/crt/ldivu_lremu_common.src
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
.assume adl=1

.section .text

.global __ldivu_lremu_common
.type __ldivu_lremu_common, @function

;;; struct u32div_t {
;;; uint32_t rem;
;;; uint32_t quot;
;;; };
;;; u32div_t _ldivu_lremu_common(uint32_t dividend, uint32_t divisor) {

__ldivu_lremu_common:
; Similar to __ldvrmu but faster and with a different calling convention.
; Note: Uses shadow registers and disables interrupts.
; I: EUHL=dividend, AUBC=divisor
; O: a[uhl']=EUHL%AUBC, bcu=0, b=A, c=?, euhl=EUHL/AUBC, eubc'=AUBC, zf=!IEF2

;;; u32div_t result;
;;; result.quot = dividend;
; euhl : result.quot

push bc

ld c, a ; c = A
ld a, i ; a = I
; pf = IEF2
di

ld a, c ; a = A
exx
pop bc
ld e, a ; eubc' : divisor

push af

;;; result.rem = 0;
xor a, a
sbc hl, hl ; auhl' : result.rem

;;; int i = 32;
exx
ld b, 32 ; b : i

;;; do {
.L.c.loop:

;;; bool dividendBit = result.quot >> 31;
;;; result.quot <<= 1;
add hl, hl
rl e
;;; result.rem = (result.rem << 1) + dividendBit;
exx
adc hl, hl
adc a, a

;;; bool quotBit = result.rem >= divisor;
;;; result.rem -= divisor;
sbc hl, bc
sbc a, e

;;; if (!quotBit) {
jr nc, .L.c.restore_skip
;;; result.rem += divisor;
add hl, bc
adc a, e
;;; }
.L.c.restore_skip:

;;; if (quotBit) {
exx
jr c, .L.c.skip
;;; result.quot++;
inc l
;;; }
.L.c.skip:

;;; } while (--i != 0);
djnz .L.c.loop

;;; return result;
pop bc
bit 2, c
ret
;;; }
85 changes: 1 addition & 84 deletions src/crt/ldvrmu.src
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
.assume adl=1

.section .text
;;; struct u32div_t {
;;; uint32_t rem;
;;; uint32_t quot;
;;; };
;;; u32div_t _ldvrmu(uint32_t dividend, uint32_t divisor) {

.global __ldvrmu
.type __ldvrmu, @function

Expand All @@ -15,83 +11,6 @@

.else

; REMEMBER to also modify ldivu.src, lremu.src, and ldiv.src if you change this
.if 1

__ldvrmu:
; I: EUHL=dividend, AUBC=divisor
; O: a[uhl']=EUHL%AUBC, bcu=0, b=A, c=?, euhl=EUHL/AUBC, eubc'=AUBC, zf=!IEF2

;;; u32div_t result;
;;; result.quot = dividend;
; euhl : result.quot

push bc

ld c, a ; c = A
ld a, i ; a = I
; pf = IEF2
di

ld a, c ; a = A
exx
pop bc
ld e, a ; eubc' : divisor

push af

;;; result.rem = 0;
xor a, a
sbc hl, hl ; auhl' : result.rem

;;; int i = 32;
exx
ld b, 32 ; b : i

;;; do {
.L.c.loop:

;;; bool dividendBit = result.quot >> 31;
;;; result.quot <<= 1;
add hl, hl
rl e
;;; result.rem = (result.rem << 1) + dividendBit;
exx
adc hl, hl
adc a, a

;;; bool quotBit = result.rem >= divisor;
;;; result.rem -= divisor;
sbc hl, bc
sbc a, e

;;; if (!quotBit) {
jr nc, .L.c.restore_skip
;;; result.rem += divisor;
add hl, bc
adc a, e
;;; }
.L.c.restore_skip:

;;; if (quotBit) {
exx
jr c, .L.c.skip
;;; result.quot++;
inc l
;;; }
.L.c.skip:

;;; } while (--i != 0);
djnz .L.c.loop

;;; return result;
pop bc
bit 2, c
ret
;;; }

.else

__ldvrmu:
; I: EUHL=dividend, AUBC=divisor
; O: auhl=EUHL%AUBC, euix=EUHL/AUBC, iyh=A, iyl=0
Expand Down Expand Up @@ -128,5 +47,3 @@ __ldvrmu:
ret

.endif

.endif
8 changes: 6 additions & 2 deletions src/crt/lremu.src
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@

.else

; REMEMBER to keep ldivu.src, lremu.src, and ldiv.src in sync with this choice
.if 1

__lremu:
; I: EUHL=dividend, AUBC=divisor
; O: euhl=EUHL%AUBC
call __ldvrmu
call __ldivu_lremu_common
ld e, a
push de
exx
Expand All @@ -26,6 +27,8 @@ __lremu:
ei
ret

.extern __ldivu_lremu_common

.else

__lremu:
Expand All @@ -41,8 +44,9 @@ __lremu:
pop iy
pop ix
ret
.endif

.extern __ldvrmu

.endif

.endif
8 changes: 6 additions & 2 deletions src/libc/ldiv.src
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
.global _ldiv
.type _ldiv, @function

; REMEMBER to keep ldivu.src, lremu.src, and ldiv.src in sync with this choice
.if 1

_ldiv:
Expand All @@ -27,7 +28,7 @@ _ldiv:
bit 7, e
call __ldivs_lrems_common

call __ldvrmu
call __ldivu_lremu_common

exx
ld e, a
Expand All @@ -53,6 +54,8 @@ _ldiv:
.L.ei_skip:
jp (hl)

.extern __ldivu_lremu_common

.else

_ldiv:
Expand Down Expand Up @@ -111,8 +114,9 @@ _ldiv:
push de
jp (hl)

.extern __ldvrmu

.endif

.extern __ldivs_lrems_common
.extern __ldvrmu
.extern __lneg
Loading