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 ;**********************************************************************