; Date:     Wed, 21 Feb 1996 10:09:12 +0100
; From:     Oskar Liljeblad  [oskarl@kajen.com]
; Subject:  Re: LZ: Multiply and divide in ASM

; This message comes from the List-ZShell mailing list:

; I have made 32-bit multiply and divide routines, but they could need some
; optimization:

Mult32:                                 ; arg1 * arg2 -> res1, a=carry (bit 32)
        ld      a,0
        ld      b,32                    ; uses de, b, a, hl
        ld      de,0
        ld      (res1),de
        ld      (res1+2),de
Mult32Loop:
        ld      de,(arg1+2)             ; arg1 << 1 -> arg1
        srl     d
        rr      e
        ld      (arg1+2),de
        ld      de,(arg1)
        rr      d
        rr      e
        ld      (arg1),de
        jr      nc,Mult32NoAdd
        ld      hl,(res1)               ; res1 + arg2 -> res1
        ld      de,(arg2)
        add     hl,de
        ld      (res1),hl
        ld      hl,(res1+2)
        ld      de,(arg2+2)
        adc     hl,de
        ld      (res1+2),hl
        jr      nc,Mult32NoAdd
        ld      a,1
Mult32NoAdd:
        ld      de,(arg2)               ; arg2 << 1 -> arg2
        sla     e
        rl      d
        ld      (arg2),de
        ld      de,(arg2+2)
        rl      e
        rl      d
        ld      (arg2+2),de
        djnz    Mult32Loop
        ret

Div32:                                  ; arg1 / arg2 -> arg1 , res1 = remainder
        ld      de,0                    ; uses de, b, hl
        ld      (res1),de
        ld      (res1+2),de
        ld      b,32
        and     a                       ; clear carry
Div32Loop:
        ld      de,(arg1)               ; arg1 >> 1 -> arg1
        rl      e
        rl      d
        ld      (arg1),de
        ld      de,(arg1+2)
        rl      e
        rl      d
        ld      (arg1+2),de
        ld      de,(res1)               ; res1 >> 1 -> res1
        rl      e
        rl      d
        ld      (res1),de
        ld      de,(res1+2)
        rl      e
        rl      d
        ld      (res1+2),de
        ld      hl,(res1)               ; res1 - arg2 -> res1
        ld      de,(arg2)
        sbc     hl,de
        ld      (res1),hl
        ld      hl,(res1+2)
        ld      de,(arg2+2)
        sbc     hl,de
        ld      (res1+2),hl
        jr      nc,Div32NoAdd
        ld      hl,(res1)               ; res1 + arg2 -> res1
        ld      de,(arg2)
        add     hl,de
        ld      (res1),hl
        ld      hl,(res1+2)
        ld      de,(arg2+2)
        adc     hl,de
        ld      (res1+2),hl
Div32NoAdd:
        ccf
        djnz    Div32Loop
        ld      de,(arg1)               ; arg1 >> 1 -> arg1
        rl      e
        rl      d
        ld      (arg1),de
        ld      de,(arg1+2)
        rl      e
        rl      d
        ld      (arg1+2),de
        ret

