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 ;**********************************************************************
file: /Techref/scenix/lib/math/div/24by24ng_sx.htm, 9KB, , updated: 2004/6/10 14:40, local time: 2024/8/14 15:32,
owner: NG--944,
3.21.97.51: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? <A HREF="http://techref.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> |
Did you find what you needed? |
Welcome to massmind.org! |
Ashley Roll has put together a really nice little unit here. Leave off the MAX232 and keep these handy for the few times you need true RS232! |
.