Optimize layout of division code
authorNick Downing <nick@ndcode.org>
Thu, 13 Jun 2019 15:47:15 +0000 (01:47 +1000)
committerNick Downing <nick@ndcode.org>
Thu, 13 Jun 2019 15:47:15 +0000 (01:47 +1000)
sm.asm

diff --git a/sm.asm b/sm.asm
index c19d8f4..02f3b2b 100644 (file)
--- a/sm.asm
+++ b/sm.asm
@@ -911,39 +911,22 @@ mul_hl_de:
        pop     bc
        ret
 
-div_hl_de:
-       push    bc
-divu:  ld      a,h
-       ld      c,l
-       ld      hl,0
-       call    div0
-       ld      b,a
-       ld      a,c
-       ld      c,b
-       call    div
-       jr      nc,1$
-       add     hl,de
-1$:    ld      d,c
-       ld      e,a
-       pop     bc
-       ret
-
 div_hl_de_signed:
        push    bc
        ld      a,h
        or      a
        ld      a,d
        rla
-       jr      c,4$                    ; negative divisor
+       jp      p,4$                    ; positive dividend
 
-       ; positive divisor
-       jp      p,divu                  ; positive dividend, positive divisor
-
-       ; negative dividend, positive divisor
+       ; negative dividend
        dec     hl                      ; reduces remainder by 1 (we inc later)
        ld      a,h
        ld      c,l
        ld      hl,-1
+       jr      c,2$                    ; negative dividend, negative divisor
+
+       ; negative dividend, positive divisor
        call    div1
        ld      b,a
        ld      a,c
@@ -958,40 +941,55 @@ div_hl_de_signed:
        pop     bc
        ret
 
-2$:    ; positive dividend, negative divisor
+2$:    ; negative dividend, negative divisor
+       call    divn0
+       ld      b,a
+       ld      a,c
+       ld      c,b
+       call    divn
+       jr      nc,3$
+       add     hl,de
+3$:    inc     hl                      ; get into range divisor+1..0
+       ld      d,c
+       ld      e,a
+       pop     bc
+       ret
+
+4$:    ; positive dividend
        ld      a,h
        ld      c,l
        ld      hl,0
+       jr      nc,divu                 ; positive dividend, positive divisor
+
+       ; positive dividend, negative divisor
        call    divn1
        ld      b,a
        ld      a,c
        ld      c,b
        call    divn
        inc     a
-       jr      c,3$
+       jr      c,5$
        sbc     hl,de
-3$:    ld      d,c
+5$:    ld      d,c
        ld      e,a
        pop     bc
        ret
 
-4$:    ; negative divisor
-       jp      p,2$
-
-       ; negative dividend, negative divisor
-       dec     hl                      ; reduces remainder by 1 (we inc later)
+div_hl_de:
+       push    bc
        ld      a,h
        ld      c,l
-       ld      hl,-1
-       call    divn0
+       ld      hl,0
+
+divu:  ; positive dividend, positive divisor
+       call    div0
        ld      b,a
        ld      a,c
        ld      c,b
-       call    divn
-       jr      nc,5$
+       call    div
+       jr      nc,1$
        add     hl,de
-5$:    inc     hl                      ; get into range divisor+1..0
-       ld      d,c
+1$:    ld      d,c
        ld      e,a
        pop     bc
        ret
@@ -1031,25 +1029,7 @@ div_hl_de_signed:
 ; now optimized to only inc/dec a when doing zero-crossing, fix above analysis
 
 div:   jr      c,div1
-div0:
- ;push af
- ;ld a,'A
- ;call print_char
- ;pop af
- ;call print_word
- ;push af
- ;ld a,':
- ;call print_char
- ;pop af
- ;call print_byte
- ;push af
- ;ld a,'/
- ;call print_char
- ;pop af
- ;ex de,hl
- ;call print_word
- ;ex de,hl
-       ld      b,8
+div0:  ld      b,8
        scf
        rla
 div00: adc     hl,hl
@@ -1061,44 +1041,9 @@ div01:   add     a,a
        djnz    div00
        dec     a
        or      a
- ;push af
- ;ld a,'B
- ;call print_char
- ;pop af
- ;push af
- ;ld a,'0
- ;adc a,0
- ;call print_char
- ;ld a,':
- ;call print_char
- ;pop af
- ;call print_byte
- ;push af
- ;ld a,',
- ;call print_char
- ;pop af
- ;call print_word
- ;call print_crlf
        ret
 
 div1:  ; enter with cf=0
- ;push af
- ;ld a,'C
- ;call print_char
- ;pop af
- ;call print_word
- ;push af
- ;ld a,':
- ;call print_char
- ;pop af
- ;call print_byte
- ;push af
- ;ld a,'/
- ;call print_char
- ;pop af
- ;ex de,hl
- ;call print_word
- ;ex de,hl
        ld      b,8
        add     a,a
 div10: adc     hl,hl
@@ -1111,48 +1056,16 @@ div11:  add     a,a
        ;inc    a
        ;dec    a                       ; compensation
        scf
- ;push af
- ;ld a,'D
- ;call print_char
- ;pop af
- ;push af
- ;ld a,'0
- ;adc a,0
- ;call print_char
- ;ld a,':
- ;call print_char
- ;pop af
- ;call print_byte
- ;push af
- ;ld a,',
- ;call print_char
- ;pop af
- ;call print_word
- ;call print_crlf
        ret
 
-; divn0/3 are the same as div0/1 but carry reversed after add/subtract divisor
+; 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)
+
+; when divisor negated, remainder also negated, so we expect to do subtraction
+; when remainder negative and vice versa, need to clear carry after add hl,hl
 
 divn:  jr      c,divn1
-divn0:
- ;push af
- ;ld a,'A
- ;call print_char
- ;pop af
- ;call print_word
- ;push af
- ;ld a,':
- ;call print_char
- ;pop af
- ;call print_byte
- ;push af
- ;ld a,'/
- ;call print_char
- ;pop af
- ;ex de,hl
- ;call print_word
- ;ex de,hl
-       ld      b,8
+divn0: ld      b,8
        scf
        rla
 divn00:        adc     hl,hl
@@ -1165,45 +1078,9 @@ divn01:  add     a,a
        djnz    divn00
        dec     a
        or      a
- ;push af
- ;ld a,'B
- ;call print_char
- ;pop af
- ;push af
- ;ld a,'0
- ;adc a,0
- ;call print_char
- ;ld a,':
- ;call print_char
- ;pop af
- ;call print_byte
- ;push af
- ;ld a,',
- ;call print_char
- ;pop af
- ;call print_word
- ;call print_crlf
        ret
 
-divn1:
- ;push af
- ;ld a,'C
- ;call print_char
- ;pop af
- ;call print_word
- ;push af
- ;ld a,':
- ;call print_char
- ;pop af
- ;call print_byte
- ;push af
- ;ld a,'/
- ;call print_char
- ;pop af
- ;ex de,hl
- ;call print_word
- ;ex de,hl
-       ld      b,8
+divn1: ld      b,8
        add     a,a
 divn10:        adc     hl,hl
        add     hl,de
@@ -1215,22 +1092,4 @@ divn11:  add     a,a
        ;inc    a
        ;dec    a                       ; compensation
        scf
- ;push af
- ;ld a,'D
- ;call print_char
- ;pop af
- ;push af
- ;ld a,'0
- ;adc a,0
- ;call print_char
- ;ld a,':
- ;call print_char
- ;pop af
- ;call print_byte
- ;push af
- ;ld a,',
- ;call print_char
- ;pop af
- ;call print_word
- ;call print_crlf
        ret