                        ; by Soji Yamakawa 2017/10/24
                        ; Division 32-bit/16-bit -> 16bit Quotient, 16bit Remainder
                        EXPORT  DIV32_16_NUMER
                        EXPORT  DIV32_16_DENOM
                        EXPORT  DIV32_16
                        EXPORT  UDIV32_16

DIV32_16_NUMER          RZB     4       ; Input Numerator
DIV32_16_NUMER_HI       EQU     DIV32_16_NUMER      ; Output Undefined
DIV32_16_NUMER_LO       EQU     DIV32_16_NUMER+2    ; Output Remainder
DIV32_16_DENOM          RZB     2       ; Input Denominator, Output Quotient
DIV32_16_SUM            EQU     DIV32_16_DENOM
DIV32_16_REM_HI EQU     DIV32_16_NUMER_HI
DIV32_16_REM_LO EQU     DIV32_16_NUMER_LO

DIV32_16                PSHS    A,B,X,U

                        LDD     DIV32_16_DENOM,PCR
                        STA     DIV32_16_DENSIGN,PCR
                        BPL     DIV32_16_DENOMSIGNSET
                        COMA
                        COMB
                        ADDD    #1
DIV32_16_DENOMSIGNSET   STD     DIV32_16_DENOM,PCR

                        LDD     DIV32_16_NUMER_HI,PCR
                        STA     DIV32_16_NUMSIGN,PCR
                        BPL     DIV32_16_NUMERSIGNSET

                        COMA
                        COMB
                        STD     DIV32_16_REM_HI,PCR
                        LDD     DIV32_16_NUMER_LO,PCR
                        COMA
                        COMB
                        ADDD    #1
                        STD     DIV32_16_REM_LO,PCR
                        BCC     DIV32_16_NUMERSIGNSET
                        ; Added 1, Carry Set -> D=0
                        INCB
                        ADDD    DIV32_16_REM_HI,PCR
                        STD     DIV32_16_REM_HI,PCR
DIV32_16_NUMERSIGNSET
                        BSR     UDIV32_16

                        LDD     #0
                        TST     DIV32_16_NUMSIGN,PCR
                        BPL     DIV32_16_REM_SIGNSET
                        ; Already A==0 && B==0
                        SUBD    DIV32_16_REM_LO,PCR
                        STD     DIV32_16_REM_LO,PCR
                        ; Remainder may be zero.  Then the flag of A register
                        ; may not reflect the sign of the numerator.
                        ; Therefore, A must be reset with a negative number.
                        LDA     #-1

DIV32_16_REM_SIGNSET    ; A=0 if jumped from BPL, A=-1 if not.
                        EORA    DIV32_16_DENSIGN,PCR
                        BPL     DIV32_16_QUO_SIGNSET
                        LDD     #0
                        SUBD    DIV32_16_SUM,PCR
                        STD     DIV32_16_SUM,PCR
DIV32_16_QUO_SIGNSET
                        PULS    A,B,X,U,PC



UDIV32_16               PSHS    A,B,X,Y,U

                        LDX     DIV32_16_DENOM,PCR
                        STX     DIV32_16_SCA_LO,PCR

                        LDD     #0
                        STD     DIV32_16_SCA_HI,PCR

                        INCB
                        LDU     DIV32_16_REM_HI,PCR
                        LDX     DIV32_16_REM_LO,PCR

UDIV32_16_UPSHIFTLP     CMPU    DIV32_16_SCA_HI,PCR
                        BLO     UDIV32_16_UPSHIFTEND
                        BHI     UDIV32_16_UPSHIFTNEXT
                        CMPX    DIV32_16_SCA_LO,PCR
                        BLO     UDIV32_16_UPSHIFTEND
UDIV32_16_UPSHIFTNEXT
                        LSL     DIV32_16_SCA_LO+1,PCR
                        ROL     DIV32_16_SCA_LO,PCR
                        ROL     DIV32_16_SCA_HI+1,PCR
                        ROL     DIV32_16_SCA_HI,PCR

                        LSLB
                        ROLA
                        BPL     UDIV32_16_UPSHIFTLP

UDIV32_16_UPSHIFTEND    STD     DIV32_16_MUL,PCR

                        LDX     #0

UDIV32_16_LOOP          LDU     DIV32_16_REM_HI,PCR
                        BEQ     UDIV32_16_LAST16BIT
                        CMPU    DIV32_16_SCA_HI,PCR
                        BLO     UDIV32_16_DONTADD
                        BHI     UDIV32_16_ADD
                        LDU     DIV32_16_REM_LO,PCR
                        CMPU    DIV32_16_SCA_LO,PCR
                        BLO     UDIV32_16_DONTADD

UDIV32_16_ADD           LDD     DIV32_16_MUL,PCR
                        LEAX    D,X

                        LDD     DIV32_16_REM_LO,PCR
                        SUBD    DIV32_16_SCA_LO,PCR
                        STD     DIV32_16_REM_LO,PCR
                        LDD     DIV32_16_REM_HI,PCR
                        SBCB    DIV32_16_SCA_HI+1,PCR
                        SBCA    DIV32_16_SCA_HI,PCR
                        STD     DIV32_16_REM_HI,PCR

UDIV32_16_DONTADD       LSR     DIV32_16_SCA_HI,PCR
                        ROR     DIV32_16_SCA_HI+1,PCR
                        ROR     DIV32_16_SCA_LO,PCR
                        ROR     DIV32_16_SCA_LO+1,PCR

                        LSR     DIV32_16_MUL,PCR
                        ROR     DIV32_16_MUL+1,PCR
                        BCC     UDIV32_16_LOOP
                        BRA     UDIV32_16_LOOPEND


UDIV32_16_LAST16BIT
                        LDD     DIV32_16_MUL,PCR
UDIV32_16_LAST16BIT_MAKE_SCA_HI_ZERO
                        LDU     DIV32_16_SCA_HI,PCR
                        BEQ     UDIV32_16_LAST16BIT_LOOP_IN

                        LSR     DIV32_16_SCA_HI,PCR
                        ROR     DIV32_16_SCA_HI+1,PCR
                        ROR     DIV32_16_SCA_LO,PCR
                        ROR     DIV32_16_SCA_LO+1,PCR

                        LSRA
                        RORB
                        BCC     UDIV32_16_LAST16BIT_MAKE_SCA_HI_ZERO
                        BRA     UDIV32_16_LOOPEND   ; D=0

UDIV32_16_LAST16BIT_LOOP_IN
                        STD     DIV32_16_MUL,PCR
                        LDD     DIV32_16_REM_LO,PCR
UDIV32_16_LAST16BIT_LOOP

DIV32_16_SCA_LO_MINUS2  CMPD    #$7FFF  ; #$7FFF will be replaced with DIV32_16_SCA_LO
DIV32_16_SCA_LO         EQU     DIV32_16_SCA_LO_MINUS2+2
                        BLO     UDIV32_16_LAST16BIT_DONTADD

DIV32_16_MUL_MINUS2     LEAX    $7FFF,X ; $7FFF will be replaced with DIV32_16_MUL
DIV32_16_MUL            EQU     DIV32_16_MUL_MINUS2+2

                        SUBD    DIV32_16_SCA_LO,PCR

UDIV32_16_LAST16BIT_DONTADD
                        LSR     DIV32_16_SCA_LO,PCR
                        ROR     DIV32_16_SCA_LO+1,PCR
                        LSR     DIV32_16_MUL,PCR
                        ROR     DIV32_16_MUL+1,PCR
                        BCC     UDIV32_16_LAST16BIT_LOOP
                        STD     DIV32_16_REM_LO,PCR
UDIV32_16_LOOPEND       STX     DIV32_16_SUM,PCR

                        PULS    A,B,X,Y,U,PC

DIV32_16_SCA_HI         RZB     2

DIV32_16_SIGN           RZB     2
DIV32_16_NUMSIGN        EQU     DIV32_16_SIGN
DIV32_16_DENSIGN        EQU     DIV32_16_SIGN+1
