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.mov w, x add y, wcarry clearing instruction should be inserted before addition (if carry isn't cleared already)
mov w, x clc add y, wAnd similarly, 8 bit subtraction is changed from
mov w, x sub y, wmov w, x stc sub y, wOn the contrary to addition, carry (borrow) should be set for subtraction.
mov w, x0 add y0, w mov w, x1 skpnc movsz w, ++x1 add y1, wclc mov w, x0 add y0, w mov w, x1 add y1, wDEVICE 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 ;**********************************************************************