SX Microcontroller Math Method

Divide 48 bit int by 23 bit int to 48 bit int

by Nikolai Golovchenko

Dividend	DS 6
Divisor		DS 3
Temp		DS 3
BitCount	DS 1


;**********************************************************************
;
;48 BY 23 BIT UNSIGNED DIVISION (Non-restoring method)
;
;**********************************************************************
;
;     Input: Dividend, 6 bytes (Dividend+0 MSB, ... , Dividend+5 LSB)
;            Divisor, 3 bytes (Divisor+0 MSB, ... , Divisor+2 LSB)
;
;    Output: Dividend, 6 bytes (Dividend = Dividend / Divisor)
;            Z  - division by zero
;            NZ - okay
;
; Temporary: Temp, 3 bytes - remainder
;            BitCount, 1 byte - counter
;
;      Size: 52 instructions
;
;Max timing: 3+5+6+28*48-2+7+3=1366 cycles
;
;**********************************************************************

DIVIDE_48by23

        ; Test for zero division
	mov	W, Divisor
	or	W, Divisor+1
	or	W, Divisor+2
	snz
	ret			; divisor = zero, not possible to calculate -
				; return with set zero flag (Z)

        ; clear remainder
	clr	Temp
	clr	Temp+1
	clr	Temp+2

	mov	W, #48		; initialize bit counter
	mov	BitCount, W

	stc			; set carry to perform subtraction
				; first in the following loop
DIVIDE_LOOP_48by23
	; shift in next result bit and
	; shift out next bit of dividend
	rl	Dividend+5
	rl	Dividend+4
	rl	Dividend+3
	rl	Dividend+2
	rl	Dividend+1
	rl	Dividend
        ; shift in highest bit from dividend through carry in temp
	rl	Temp+2
	rl	Temp+1
	rl	Temp

	mov	W, Divisor+2	; load w with LSB of divisor
				; to use it in subtraction or
				; addition afterwards

	; If previous result bit was set (subtraction was performed
	; without borrow or addition made the remainder positive),
	; subtract divisor from remainder,
	; else add divisor to remainder
	sb	Dividend+5.0
	jmp	Div48by23_add

        ; subtract 23 bit divisor from 24 bit temp,
        ; divisor LSB is in w
        sub	Temp+2, W	; subtract LSB

	mov	W, Divisor+1	; get middle byte
	sc			;  if overflow ( from prev. subtraction )
	movsz	W, ++Divisor+1	; incresase source
	sub	Temp+1, W	; and subtract from dest.

	mov	W, Divisor	; get top byte
	sc			;  if overflow ( from prev. subtraction )
	movsz	W, ++Divisor	; increase source
	sub	Temp, W		; and subtract from dest.

	jmp	DIVIDE_NEXT_48by23 ; jump to loop end

Div48by23_add
        ; add 23 bit divisor to 24 bit temp
        ; divisor LSB is in w

	add	Temp+2, W	; add LSB

	mov	W, Divisor+1	; middle byte
	snc 			; check carry for overflow from previous addition
	movsz	W, ++Divisor+1	; if carry set we add 1 to the source
	add	Temp+1, W	; and add it if not zero

	mov	W, Divisor	; MSB byte
	snc			; check carry for overflow from previous addition
	movsz	W, ++Divisor
	add	Temp, W		; add

DIVIDE_NEXT_48by23
	; carry contains next result bit
	decsz	BitCount	; decrement loop counter (carry not influenced)
	jmp	DIVIDE_LOOP_48by23 ; another run

        ; finally shift in the last carry
	rl	Dividend+5
	rl	Dividend+4
	rl	Dividend+3
	rl	Dividend+2
	rl	Dividend+1
	rl	Dividend

	clz                     ; done, clear zero flag (NZ) and
	ret			; return

;**********************************************************************