#include once <arith/div32.asm>


    push namespace core

__DIVF16:	; 16.16 Fixed point Division (signed)

    ; DE.HL = Dividend, Stack Top = Divisor
    ; A = Dividend, B = Divisor => A / B
    exx
    pop hl   ; return address
    pop de   ; low part
    ex (sp), hl ; CALLEE Convention ; H'L'D'E' => Dividend
    ex de, hl   ; D'E'.H'L' Dividend

__DIVF16START: ; FAST Entry: DEHL => Dividend, D'E'H'L' => Divisor
    ld a, d	 ; Save sign
    ex af, af'
    bit 7, d ; Negative?
    call nz, __NEG32 ; Negates DEHL

    exx		; Now works with D'E'.H'L'
    ex af, af'
    xor d
    ex af, af'  ; Stores sign of the result for later

    bit 7, d ; Negative?
    call nz, __NEG32
    exx		 ; Now we have DE.HL => Dividend

    ld b, 16

__SHIFTALOOP:		; Tries to shift Dividend to the left
    bit 7, d
    jp nz, __SHIFTB
    add hl, hl
    ex de, hl
    adc hl, hl
    ex de, hl
    djnz __SHIFTALOOP
    jp __DOF16_DIVRDY

__SHIFTB:       ; Cannot shift Dividend more to the left, try to shift Divisor to the right
    ld a, b
    exx
    ld b, a
    ; Divisor is in DEHL
__SHIFTBLOOP:
    bit 1, l
    jp nz, __DOF16_DIVIDE
    sra d
    rr e
    rr h
    rr l
    djnz __SHIFTBLOOP

__DOF16_DIVIDE:
    ld a, b
    exx
    ld b, a

__DOF16_DIVRDY:
    exx
    ex de, hl
    push bc
    call __DIVU32START
    pop bc

    xor a
    or b
    jp z, __ENDF16DIV

__SHIFTCLOOP:
    add hl, hl	; Shift DECIMAL PART << 1
    ex de, hl
    adc hl, hl  ; Shift INTEGER PART << 1 Plus Carry
    ex de, hl
    djnz __SHIFTCLOOP

__ENDF16DIV: 	   ; Put the sign on the result
    ex af, af' ; Recovers sign
    and 128	   ; positive?
    ret z
    jp __NEG32 ; Negates DEHL and returns from there

    pop namespace
