please dont rip this site

SX Microcontroller Math Method

Divide 48 bit int by 24 bit int to 48 bit int

by Nikolai Golovchenko

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


;**********************************************************************
;
;48 BY 24 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, 4 bytes - remainder
;            BitCount, 1 byte - counter
;
;      Size: 59 instructions
;
;Max timing: 3+5+6+32*48-2+7+3=1558 cycles
;
;**********************************************************************

DIVIDE_48by24

        ; 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
	clr	Temp+3

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

DIVIDE_LOOP_48by24
	; shift in next result bit and 
	; shift out next bit of dividend
	; (first time in loop carry is garbage, but
	; it's okay)
	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+3
	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 reminder is positive or zero,
	; subtract divisor from remainder,
	; else add divisor to remainder
	snb	Temp.7
	jmp	Div48by24_add

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

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

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

	mov	w, #1		; if borrow,
	sc                      ; subtract one 
	sub	Temp, w         ; from Temp MSB

	jmp	DIVIDE_NEXT_48by24 ; jump to loop end

Div48by24_add
        ; add 24 bit divisor to 32 bit temp
        ; divisor LSB is in w

	add	Temp+3, 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+2, 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+1, W	; add

	mov	w, #1		; if borrow,
	snc                     ; add one
	add	Temp, w         ; to Temp MSB

DIVIDE_NEXT_48by24
	; carry contains next result bit
	decsz	BitCount	; decrement loop counter (carry not influenced)
	jmp	DIVIDE_LOOP_48by24 ; 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

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





Nikolai Golovchenko says:

In case there is a lot of multi-byte calculations in a program, it might be beneficial to turn on the carry-in option of SX processor. That would increase 8-bit addition/subtraction just by one instruction or less to prepare carry. But for multibyte operations the code size reduction is 2 instructions per each byte, except for the least significant one. In result 16 bit and higher operations will take less space and execute faster.

When the carry-in option is turned on, the original code should be modified a little. Actually, the changes should be made only to the code that uses add/sub instructions. For example, for 8 bit addition


	mov w, x
	add y, w

carry clearing instruction should be inserted before addition (if carry isn't cleared already)


	mov w, x
	clc
	add y, w

And similarly, 8 bit subtraction is changed from


	mov w, x
	sub y, w

to


	mov w, x
	stc
	sub y, w

On the contrary to addition, carry (borrow) should be set for subtraction.

And 16 bit add/sub example:

Change from


	mov w, x0
	add y0, w
	mov w, x1
	skpnc
	movsz w, ++x1
	add y1, w

to


	clc
	mov w, x0
	add y0, w
	mov w, x1
	add y1, w

That saves 1 or 2 (if carry is cleared already) instructions. For 24 bit operations that figure is higher: 3 or 4 instructions.

Here is a division routine rewritten for the case when CARRYX option is used. Now the routine is better by about 13% in both code size and execution speed!


        DEVICE  SX28AC, BANKS8, PAGES4
        DEVICE  OSCHS3, TURBO, OPTIONX, CARRYX
        RESET start

        ORG 8
Dividend        DS 6
Divisor         DS 3
Temp            DS 4
BitCount        DS 1

;6651AF33BC6C = ABCDEF * 987654
        org     1h
start
        mov     Dividend, #$66
        mov     Dividend+1, #$51
        mov     Dividend+2, #$af
        mov     Dividend+3, #$33
        mov     Dividend+4, #$bc
        mov     Dividend+5, #$6c

        mov     Divisor, #$98
        mov     Divisor+1, #$76
        mov     Divisor+2, #$54

        call    DIVIDE_48by24

;**********************************************************************
;
;48 BY 24 BIT DIVISION (Non-restoring method)
; *Using CARRYX option of SX*
;**********************************************************************
;
;     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, 4 bytes - remainder
;            BitCount, 1 byte - counter
;
;      Size: 51 instructions
;
;Max timing: 3+5+6+28*48-2+7+3=1366 cycles
;
;**********************************************************************

DIVIDE_48by24

        ; 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
        clr     Temp+3

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

DIVIDE_LOOP_48by24
        ; shift in next result bit and 
        ; shift out next bit of dividend
        ; (first time in loop carry is garbage, but
        ; it's okay)
        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+3
        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 reminder is positive or zero,
        ; subtract divisor from remainder,
        ; else add divisor to remainder
        snb     Temp.7
        jmp     Div48by24_add

        ; subtract 24 bit divisor from 32 bit temp,
        ; divisor LSB is in w
        stc
        sub     Temp+3, W       ; subtract LSB
        mov     W, Divisor+1    ; get middle byte
        sub     Temp+2, W       ; and subtract from dest.
        mov     W, Divisor      ; get top byte
        sub     Temp+1, W       ; and subtract from dest.
        clr     W               ; subtract borrow
        sub     Temp, w         ; from Temp MSB

        jmp     DIVIDE_NEXT_48by24 ; jump to loop end

Div48by24_add
        ; add 24 bit divisor to 32 bit temp
        ; divisor LSB is in w
        clc
        add     Temp+3, W       ; add LSB of Divisor to Temp+3
        mov     W, Divisor+1    ; 
        add     Temp+2, W       ; 
        mov     W, Divisor      ; 
        add     Temp+1, W       ; add MSB of Divisor to Temp+1
        clr     W               ; add carry to Temp
        add     Temp, w         ;

DIVIDE_NEXT_48by24
        ; carry contains next result bit
        decsz   BitCount        ; decrement loop counter (carry not influenced)
        jmp     DIVIDE_LOOP_48by24 ; 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

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


file: /Techref/scenix/lib/math/div/24by24ng_sx.htm, 9KB, , updated: 2004/6/10 13:40, local time: 2024/11/25 14:15, owner: NG--944,
TOP NEW HELP FIND: 
18.119.192.2:LOG IN

 ©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions?
Please DO link to this page! Digg it! / MAKE!

<A HREF="http://massmind.org/techref/scenix/lib/math/div/24by24ng_sx.htm"> SX Microcontroller Math Method - Divide 48 bit int by 24 bit int to 48 bit int</A>

After you find an appropriate page, you are invited to your to this massmind site! (posts will be visible only to you before review) Just type a nice message (short messages are blocked as spam) in the box and press the Post button. (HTML welcomed, but not the <A tag: Instead, use the link box to link to another page. A tutorial is available Members can login to post directly, become page editors, and be credited for their posts.


Link? Put it here: 
if you want a response, please enter your email address: 
Attn spammers: All posts are reviewed before being made visible to anyone other than the poster.
Did you find what you needed?

 

Welcome to massmind.org!

 

Welcome to massmind.org!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  .