Applied patch #2762516
[fw/sdcc] / device / lib / z80 / div.s
index 5ef13688034b938d9828736e12914cb41e746c1e..305cd67ab13a1c39bf6d0f790723b975af3ffe0e 100644 (file)
         ;; Originally from GBDK by Pascal Felber.
-        .area   CODE
 
-__divschar_rrx_s::
-        ld      hl,#2+1
-        add     hl,sp
-
-        ld      e,(hl)
-        dec     hl
-        ld      l,(hl)
+        .area   _CODE
 
-        ;; Fall through
-__divschar_rrx_hds::
-        ld      c,l
-
-        call    .div8
+__divuint_rrx_s::
+        pop     af
+        pop     hl
+        pop     de
+        push    de
+        push    hl
+        push    af
 
-        ld      l,c
-        ld      h,b
+        jr      __divu16
 
-        ret
-
-__modschar_rrx_s::
+__divsuchar_rrx_s::
         ld      hl,#2+1
         add     hl,sp
 
         ld      e,(hl)
         dec     hl
         ld      l,(hl)
+        xor     a
 
-        ;; Fall through
-__modschar_rrx_hds::
-        ld      c,l
-
-        call    .div8
-
-        ld      l,e
-        ld      h,d
-
-        ret
-
-__divsint_rrx_s::
-        ld      hl,#2+3
-        add     hl,sp
-
-        ld      d,(hl)
-        dec     hl
-        ld      e,(hl)
-        dec     hl
-        ld      a,(hl)
-        dec     hl
-        ld      l,(hl)
-        ld      h,a
-
-        ;; Fall through
-__divsint_rrx_hds::
-        ld      b,h
-        ld      c,l
-
-        call    .div16
-
-        ld      l,c
-        ld      h,b
-
-        ret
+        jr      signexte
 
-__modsint_rrx_s::
-        ld      hl,#2+3
-        add     hl,sp
-
-        ld      d,(hl)
-        dec     hl
-        ld      e,(hl)
-        dec     hl
-        ld      a,(hl)
-        dec     hl
-        ld      l,(hl)
-        ld      h,a
-
-        ;; Fall through
-__modsint_rrx_hds::
-        ld      b,h
-        ld      c,l
-
-        call    .div16
-
-        ld      l,e
-        ld      h,d
-
-        ret
-
-        ;; Unsigned
-__divuchar_rrx_s::
+__modsuchar_rrx_s::
         ld      hl,#2+1
         add     hl,sp
 
         ld      e,(hl)
         dec     hl
         ld      l,(hl)
+        xor     a
 
-        ;; Fall through
-__divuchar_rrx_hds::
-        ld      c,l
-        call    .divu8
-
-        ld      l,c
-        ld      h,b
+        call    signexte
 
+        ex      de,hl
         ret
 
-__moduchar_rrx_s::
+__divuschar_rrx_s::
         ld      hl,#2+1
+        ld      d, h
         add     hl,sp
 
         ld      e,(hl)
         dec     hl
         ld      l,(hl)
 
-        ;; Fall through
-__moduchar_rrx_hds::
-        ld      c,l
-        call    .divu8
-
-        ld      l,e
-        ld      h,d
-
-        ret
-
-__divuint_rrx_s::
-        ld      hl,#2+3
-        add     hl,sp
-
-        ld      d,(hl)
-        dec     hl
-        ld      e,(hl)
-        dec     hl
-        ld      a,(hl)
-        dec     hl
-        ld      l,(hl)
+        ld      a,l             ; Sign extend
+        rlca
+        sbc     a
         ld      h,a
 
-        ;; Fall through
-__divuint_rrx_hds::
-        ld      b,h
-        ld      c,l
-        call    .divu16
-
-        ld      l,c
-        ld      h,b
+        jr      __div16
 
-        ret
-
-__moduint_rrx_s::
-        ld      hl,#2+3
+__divschar_rrx_s::
+        ld      hl,#2+1
         add     hl,sp
 
-        ld      d,(hl)
-        dec     hl
         ld      e,(hl)
         dec     hl
-        ld      a,(hl)
-        dec     hl
         ld      l,(hl)
-        ld      h,a
-        ;; Fall through
-
-__moduint_rrx_hds::
-        ld      b,h
-        ld      c,l
-
-        call    .divu16
-
-        ld      l,e
-        ld      h,d
-
-        ret
 
-.div8::
-.mod8::
-        ld      a,c             ; Sign extend
+        ;; Fall through
+__divschar_rrx_hds::
+__div8::
+        ld      a,l             ; Sign extend
         rlca
         sbc     a
-        ld      b,a
+signexte:
+        ld      h,a
         ld      a,e             ; Sign extend
         rlca
         sbc     a
         ld      d,a
+        ; Fall through to __div16
 
-        ; Fall through to .div16
-
-        ;; 16-bit division
+        ;; signed 16-bit division
         ;;
         ;; Entry conditions
-        ;;   BC = dividend
+        ;;   HL = dividend
         ;;   DE = divisor
         ;;
         ;; Exit conditions
-        ;;   BC = quotient
+        ;;   HL = quotient
         ;;   DE = remainder
         ;;   If divisor is non-zero, carry=0
         ;;   If divisor is 0, carry=1 and both quotient and remainder are 0
         ;;
         ;; Register used: AF,BC,DE,HL
-.div16::
-.mod16::
+__divsint_rrx_hds::
+__div16::
         ;; Determine sign of quotient by xor-ing high bytes of dividend
         ;;  and divisor. Quotient is positive if signs are the same, negative
         ;;  if signs are different
         ;; Remainder has same sign as dividend
-        ld      a,b             ; Get high byte of dividend
-        ld      (.srem),a       ; Save as sign of remainder
+        ld      a,h             ; Get high byte of dividend
         xor     d               ; Xor with high byte of divisor
-        ld      (.squot),a      ; Save sign of quotient
+        rla                     ; Sign of quotient goes into the carry
+        ld      a,h             ; Get high byte of dividend
+        push    af              ; Save sign of both quotient and reminder
+
+        ;; Take absolute value of dividend
+        rla
+        jr      NC,.chkde       ; Jump if dividend is positive
+        sub     a               ; Substract dividend from 0
+        sub     l
+        ld      l,a
+        sbc     a               ; Propagate borrow (A=0xFF if borrow)
+        sub     h
+        ld      h,a
         ;; Take absolute value of divisor
+.chkde:
         bit     7,d
-        jp      Z,.chkde        ; Jump if divisor is positive
+        jr      Z,.dodiv        ; Jump if divisor is positive
         sub     a               ; Substract divisor from 0
         sub     e
         ld      e,a
         sbc     a               ; Propagate borrow (A=0xFF if borrow)
         sub     d
         ld      d,a
-        ;; Take absolute value of dividend
-.chkde:
-        bit     7,b
-        jp      Z,.dodiv        ; Jump if dividend is positive
-        sub     a               ; Substract dividend from 0
-        sub     c
-        ld      c,a
-        sbc     a               ; Propagate borrow (A=0xFF if borrow)
-        sub     b
-        ld      b,a
         ;; Divide absolute values
 .dodiv:
-        call    .divu16
-        ret     C               ; Exit if divide by zero
+        call    __divu16
+        jr      C,.exit         ; Exit if divide by zero
         ;; Negate quotient if it is negative
-        ld      a,(.squot)
-        and     #0x80
-        jp      Z,.dorem        ; Jump if quotient is positive
+        pop     af              ; recover sign of quotient
+        jr      NC,.dorem       ; Jump if quotient is positive
+        ld      b,a
         sub     a               ; Substract quotient from 0
-        sub     c
-        ld      c,a
+        sub     l
+        ld      l,a
         sbc     a               ; Propagate borrow (A=0xFF if borrow)
-        sub     b
-        ld      b,a
+        sub     h
+        ld      h,a
+        ld      a,b
 .dorem:
         ;; Negate remainder if it is negative
-        ld      a,(.srem)
-        and     #0x80
-        ret     Z               ; Return if remainder is positive
+        rla
+        ret     NC              ; Return if remainder is positive
         sub     a               ; Substract remainder from 0
         sub     e
         ld      e,a
@@ -256,84 +145,86 @@ __moduint_rrx_hds::
         sub     d
         ld      d,a
         ret
+.exit:
+        pop     af
+
+.dividebyzero:
+        ld      h,d             ; Divide by zero error: D=E=0
+        ld      l,e
+        scf                     ; Set carry, invalid result
+        ret
 
-.divu8::
-.modu8::
-        ld      b,#0x00
-        ld      d,b
+        ;; Unsigned
+__divuchar_rrx_s::
+        ld      hl,#2+1
+        add     hl,sp
+
+        ld      e,(hl)
+        dec     hl
+        ld      l,(hl)
+
+        ;; Fall through
+__divuchar_rrx_hds::
+__divu8::
+        ld      h,#0x00
+        ld      d,h
         ; Fall through to divu16
 
-.divu16::
-.modu16::
+        ;; unsigned 16-bit division
+        ;; Restructured on April 2009 by Marco Bodrato(http://bodrato.it/ )
+        ;;
+        ;; Entry conditions
+        ;;   HL = dividend
+        ;;   DE = divisor
+        ;;
+        ;; Exit conditions
+        ;;   HL = quotient
+        ;;   DE = remainder
+        ;;   If divisor is non-zero, carry=0
+        ;;   If divisor is 0, carry=1 and both quotient and remainder are 0
+        ;;
+        ;; Register used: AF,B,DE,HL
+__divuint_rrx_hds::
+__divu16::
         ;; Check for division by zero
         ld      a,e
         or      d
-        jp      NZ,.divide      ; Branch if divisor is non-zero
-        ld      bc,#0x00        ; Divide by zero error
-        ld      d,b
-        ld      e,c
-        scf                     ; Set carry, invalid result
-        ret
-.divide:
+        jr      Z,.dividebyzero ; Branch if divisor is non-zero
+        ld      a,h
+        ld      c,l
         ld      hl,#0
-;       ld      l,c             ; L = low byte of dividend/quotient
-;       ld      h,b             ; H = high byte of dividend/quotient
-;       ld      bc,#0x00        ; BC = remainder
-        or      a               ; Clear carry to start
-        ex      af,af
-        ld      a,#16           ; 16 bits in dividend
+        ;; Carry was cleared by OR, this "0" bit will pass trough AC.[*]
+        ld      b,#16           ; 16 bits in dividend
 .dvloop:
+        ;; Cleaned up on April 2009 by Marco Bodrato(http://bodrato.it/ )
         ;; Shift next bit of quotient into bit 0 of dividend
         ;; Shift next MSB of dividend into LSB of remainder
-        ;; BC holds both dividend and quotient. While we shift a bit from
+        ;; AC holds both dividend and quotient. While we shift a bit from
         ;;  MSB of dividend, we shift next bit of quotient in from carry
         ;; HL holds remainder
-        ;; Do a 32-bit left shift, shifting carry to L, L to H,
-        ;;  H to C, C to B
-        ex      af,af'
+        ;; Do a 32-bit left shift, shifting carry to C, C to A,
+        ;;  A to HL
         rl      c               ; Carry (next bit of quotient) to bit 0
-        rl      b               ; Clears carry since BC was 0
-        adc     hl,hl
+        rla
+        adc     hl,hl           ; HL < 32768 before, no carry, ever.
 
-        ;; If remainder is >= divisor, next bit of quotient is 1. This
-        ;;  bit goes to carry
-        push    hl              ; Save current remainder
+        ;; If remainder is >= divisor, next bit of quotient is 1. We try
+        ;;  to compute the difference.
         sbc     hl,de
-;       ld      a,c             ; Substract divisor from remainder
-;       sbc     e
-;       ld      c,a
-;       ld      a,b
-;       sbc     d
-;       ld      b,a
+        jr      NC,.nodrop      ; Jump if remainder is >= dividend
+        add     hl,de           ; Otherwise, restore remainder
+       ;; The add above sets the carry, because sbc hl,de did set it.
+.nodrop:
         ccf                     ; Complement borrow so 1 indicates a
                                 ;  successful substraction (this is the
                                 ;  next bit of quotient)
-        jp      C,.drop         ; Jump if remainder is >= dividend
-        pop     hl              ; Otherwise, restore remainder
-        jp      .nodrop
-.drop:
-        inc     sp
-        inc     sp
-.nodrop:
-        ex      af,af'
-        dec     a               ; DEC does not affect carry flag
-        jp      NZ,.dvloop
-        ex      af,af'
+        djnz    .dvloop
         ;; Shift last carry bit into quotient
-        ld      d,h             ; DE = remainder
-        ld      e,l
-        rl      c               ; Carry to L
-;       ld      c,l             ; C = low byte of quotient
-        rl      b
-;       ld      b,h             ; B = high byte of quotient
-        or      a               ; Clear carry, valid result
+        rl      c               ; Carry to C
+        rla
+        ;; Carry now contains the same value it contained before
+        ;; entering .dvloop[*]: "0" = valid result.
+        ld      d,a
+        ld      e,c             ; DE = quotient, HL = remainder
+        ex      de,hl           ; HL = quotient, DE = remainder
         ret
-
-        .area   BSS
-
-.srem:
-        .ds 0x01                ; Sign of quotient
-.squot:
-        .ds 0x01                ; Sign of remainder
-.dcnt:
-        .ds 0x01                ; Counter for division