Implement hi bit set divisor for long division, fix long negative dividend bug
authorNick Downing <nick@ndcode.org>
Tue, 25 Jun 2019 11:38:42 +0000 (21:38 +1000)
committerNick Downing <nick@ndcode.org>
Tue, 25 Jun 2019 11:38:42 +0000 (21:38 +1000)
sm3.asm

diff --git a/sm3.asm b/sm3.asm
index aed29a1..f8866db 100644 (file)
--- a/sm3.asm
+++ b/sm3.asm
@@ -2379,17 +2379,6 @@ math_sdiv_uw: ; hl, de = de % hl, de / hl, unsigned
        ld      b,h
        ld      hl,0
 math_div_uw: ; hl, de = hl:de % bc, hl:de / bc, unsigned
- ld a,'X
- call print_char
- call print_word
- ex de,hl
- call print_word
- ex de,hl
- push hl
- ld l,c
- ld h,b
- call print_word
- pop hl
        ld      a,d
 div_w_pp: ; positive dividend, positive divisor
        call    div_w0
@@ -2435,9 +2424,9 @@ div_w_pp: ; positive dividend, positive divisor
 
 ; now optimized to only inc/dec a when doing zero-crossing, fix above analysis
 
+.if 1 ; temporary
 div_wcf:
        jr      c,div_w1
-.if 1 ; temporary
 div_w0: ; above
        push    de
        ld      d,8
@@ -2484,7 +2473,58 @@ div_w12:
        scf
        pop     de
        ret
+
+div_w_ncf:
+       jr      c,div_w_n1
+div_w_n0: ; above
+       push    de
+       ld      d,8
+       scf
+       rla
+div_w_n00:
+       adc     hl,hl
+       jr      nc,div_w_n01
+       or      a
+       sbc     hl,bc
+       jr      c,div_w_n02
+       dec     a
+       jr      div_w_n12
+div_w_n01:
+       sbc     hl,bc
+div_w_n02:
+       add     a,a
+       dec     d
+       jr      nz,div_w_n00
+       dec     a
+       or      a
+       pop     de
+       ret
+
+div_w_n1: ; below
+       push    de
+       ld      d,8
+       add     a,a
+div_w_n10:
+       adc     hl,hl
+       jr      c,div_w_n11
+       add     hl,bc
+       jr      c,div_w_n12
+       inc     a
+       jr      div_w_n02
+div_w_n11:
+       add     hl,bc
+div_w_n12:
+       add     a,a
+       dec     d
+       jr      nz,div_w_n10
+       ;inc    a
+       ;dec    a                       ; compensation
+       scf
+       pop     de
+       ret
 .else
+div_wcf:
+       jr      c,div_w1
 div_w0: ; bit 0, above
        scf
        rla
@@ -2594,7 +2634,6 @@ div_w18: ; done, below
        ;dec    a                       ; compensation
        scf
        ret
-.endif
 
 ; divn0/1 are the same as div0/1 but carry reversed after add/subtract divisor
 ; this is for negative divisors where we expect carry (means no zero crossing)
@@ -2604,54 +2643,6 @@ div_w18: ; done, below
 
 div_w_ncf:
        jr      c,div_w_n1
-.if 1 ; temporary
-div_w_n0: ; above
-       push    de
-       ld      d,8
-       scf
-       rla
-div_w_n00:
-       adc     hl,hl
-       jr      nc,div_w_n01
-       or      a
-       sbc     hl,bc
-       jr      c,div_w_n02
-       dec     a
-       jr      div_w_n12
-div_w_n01:
-       sbc     hl,bc
-div_w_n02:
-       add     a,a
-       dec     d
-       jr      nz,div_w_n00
-       dec     a
-       or      a
-       pop     de
-       ret
-
-div_w_n1: ; below
-       push    de
-       ld      d,8
-       add     a,a
-div_w_n10:
-       adc     hl,hl
-       jr      c,div_w_n11
-       add     hl,bc
-       jr      c,div_w_n12
-       inc     a
-       jr      div_w_n02
-div_w_n11:
-       add     hl,bc
-div_w_n12:
-       add     a,a
-       dec     d
-       jr      nz,div_w_n10
-       ;inc    a
-       ;dec    a                       ; compensation
-       scf
-       pop     de
-       ret
-.else
 div_w_n0: ; bit 0, above
        scf
        rla
@@ -2795,13 +2786,11 @@ math_div_sl:
        exx
        ld      a,h
        or      a
-       ld      a,b
-       rla
-       ;exx
        jp      m,div_l_n               ; positive dividend
 
        ; positive dividend
-       ;exx
+       ld      a,b
+       rla
        ld      a,d
        exx
        jr      nc,div_l_pp             ; positive dividend, positive divisor
@@ -2830,16 +2819,17 @@ math_div_sl:
        exx
        ret
 
-div_l_n:
- exx
-       ; negative dividend
+div_l_n: ; negative dividend
+       exx
        ld      a,e
        or      d
        dec     de                      ; reduces remainder by 1 (we inc later)
        exx
        jr      nz,1$
        dec     de
-1$:    ld      a,d
+1$:    ld      a,b
+       rla
+       ld      a,d
        exx
        jr      c,div_l_nn              ; negative dividend, negative divisor 
 
@@ -2952,6 +2942,141 @@ div_l_nn: ; negative dividend, negative divisor
 ; non-restoring division routine
 ; see earlier comments for the word version, this extends the concept to long
 
+.if 1 ; temporary
+div_lcf:
+       jr      c,div_l1
+div_l0: ; above
+       push    de
+       ld      d,8
+       scf
+       rla
+div_l00:
+       adc     hl,hl
+       exx
+       adc     hl,hl
+       exx
+       jr      c,div_l01
+       sbc     hl,bc
+       exx
+       sbc     hl,bc
+       exx
+       jr      nc,div_l02
+       dec     a
+       jr      div_l12
+div_l01:
+       or      a
+       sbc     hl,bc
+       exx
+       sbc     hl,bc
+       exx
+div_l02:
+       add     a,a
+       dec     d
+       jr      nz,div_l00
+       dec     a
+       or      a
+       pop     de
+       ret
+
+div_l1: ; below
+       push    de
+       ld      d,8
+       add     a,a
+div_l10:
+       adc     hl,hl
+       exx
+       adc     hl,hl
+       exx
+       jr      nc,div_l11
+       add     hl,bc
+       exx
+       adc     hl,bc
+       exx
+       jr      nc,div_l12
+       inc     a
+       jr      div_l02
+div_l11:
+       add     hl,bc
+       exx
+       adc     hl,bc
+       exx
+div_l12:
+       add     a,a
+       dec     d
+       jr      nz,div_l10
+       ;inc    a
+       ;dec    a                       ; compensation
+       scf
+       pop     de
+       ret
+
+div_l_ncf:
+       jr      c,div_l_n1
+div_l_n0: ; above
+       push    de
+       ld      d,8
+       scf
+       rla
+div_l_n00:
+       adc     hl,hl
+       exx
+       adc     hl,hl
+       exx
+       jr      nc,div_l_n01
+       or      a
+       sbc     hl,bc
+       exx
+       sbc     hl,bc
+       exx
+       jr      c,div_l_n02
+       dec     a
+       jr      div_l_n12
+div_l_n01:
+       sbc     hl,bc
+       exx
+       sbc     hl,bc
+       exx
+div_l_n02:
+       add     a,a
+       dec     d
+       jr      nz,div_l_n00
+       dec     a
+       or      a
+       pop     de
+       ret
+
+div_l_n1: ; below
+       push    de
+       ld      d,8
+       add     a,a
+div_l_n10:
+       adc     hl,hl
+       exx
+       adc     hl,hl
+       exx
+       jr      c,div_l_n11
+       add     hl,bc
+       exx
+       adc     hl,bc
+       exx
+       jr      c,div_l_n12
+       inc     a
+       jr      div_l_n02
+div_l_n11:
+       add     hl,bc
+       exx
+       adc     hl,bc
+       exx
+div_l_n12:
+       add     a,a
+       dec     d
+       jr      nz,div_l_n10
+       ;inc    a
+       ;dec    a                       ; compensation
+       scf
+       pop     de
+       ret
+.else
 ; changed all jr to jp, revisit this
 
 div_lcf:
@@ -3380,6 +3505,7 @@ div_l_n18: ; done, below
        ;dec    a                       ; compensation
        scf
        ret
+.endif
 
 ; debugging