Mercurial > public > hwos_code
diff src/math.asm @ 634:4050675965ea
3.10 stable release
author | heinrichsweikamp |
---|---|
date | Tue, 28 Apr 2020 17:34:31 +0200 |
parents | cd58f7fc86db |
children | 7d8a4c60ec1a |
line wrap: on
line diff
--- a/src/math.asm Thu Mar 05 15:06:14 2020 +0100 +++ b/src/math.asm Tue Apr 28 17:34:31 2020 +0200 @@ -1,6 +1,6 @@ ;============================================================================= ; -; File math.asm combined next generation V3.04.3 +; File math.asm * combined next generation V3.09.4k ; ; Math subroutines ; @@ -12,28 +12,17 @@ #include "hwos.inc" ; mandatory header -math CODE ;============================================================================= +math1 CODE +;============================================================================= - global convert_time ; converts hi:lo in minutes to hours (up:hi) and minutes (lo) - ; also usable for conversion of seconds to minutes and seconds - ; trashes xA, xB, xC -convert_time: - movff lo,xA+0 ; copy hi:lo to xA - movff hi,xA+1 ; - movlw d'60' ; set divisor to 60 - movwf xB+0 ; write 60 to xB - clrf xB+1 ; - rcall div16x16 ; xC = xA / xB with xA as remainder - movff xC+1,up ; result is hours / minutes, copy to up (high byte) - movff xC+0,hi ; result is hours / minutes, copy to hi (low byte) - movff xA+0,lo ; remainder is minutes / seconds, copy to lo - return - - - global div16 ; divA:2 = divA:2 / 2^WREG - ; trashes WREG +;----------------------------------------------------------------------------- +; Divide a 16 Bit Integer by a Power of 2: divA:2 = divA:2 / 2^WREG +; +; trashes WREG +; + global div16 div16: bcf STATUS,C ; clear carry rrcf divA+1 ; rotate right high byte, carry into MSB, LSB into carry @@ -43,8 +32,16 @@ return ; YES - done - global mult16 ; xA:2 = xA:2 * 2^WREG - ; trashes WREG +;============================================================================= +math2 CODE +;============================================================================= + +;----------------------------------------------------------------------------- +; Multiply a 16 bit Integer by a Power of 2: xA:2 = xA:2 * 2^WREG +; +; trashes WREG +; + global mult16 mult16: bcf STATUS,C ; clear carry rlcf divA+0,F ; rotate left low byte, carry into LSB, MSB into carry @@ -54,8 +51,16 @@ return ; YES - done - global addU16 ; ; sub_c:2 = sub_a:2 + sub_b:2 with USIGNED values - ; trashes WREG +;============================================================================= +math3 CODE +;============================================================================= + +;----------------------------------------------------------------------------- +; Add two UNSIGNED 16 bit Integers: sub_c:2 = sub_a:2 + sub_b:2 +; +; trashes WREG +; + global addU16 addU16: movf sub_a+0,W ; get 1st summand (low byte) to WREG addwf sub_b+0,W ; add 2nd summand (low byte) and store result in WREG @@ -66,9 +71,16 @@ return ; done - global sub16 ; sub_c:2 = sub_a:2 - sub_b:2 with SIGNED values - ; sets neg_flag if result is < 0 - ; trashes WREG +;============================================================================= +math4 CODE +;============================================================================= + +;----------------------------------------------------------------------------- +; Subtract two SIGNED 16 Bit Integers: sub_c:2 = sub_a:2 - sub_b:2 +; +; sets neg_flag if result is < 0, trashes WREG +; + global sub16 sub16: bcf neg_flag ; clear flag which will indicate if result is negative movf sub_b+0,W ; get value to be subtracted, low byte @@ -87,9 +99,16 @@ return ; - done - global subU16 ; sub_c:2 = sub_a:2 - sub_b:2 with UNSIGNED values - ; sets neg_flag if result is < 0 - ; trashes WREG +;============================================================================= +math5 CODE +;============================================================================= + +;----------------------------------------------------------------------------- +; Subtract two UNSIGNED 16 Bit Integers: sub_c:2 = sub_a:2 - sub_b:2 +; +; sets neg_flag if result is < 0, trashes WREG +; + global subU16 subU16: bcf neg_flag ; clear flag which will indicate if result is negative movf sub_b+0,W ; get value to be subtracted, low byte @@ -108,9 +127,17 @@ return ; - done - global cmpU16 ; sub_a:2 - sub_b:2 with UNSIGNED values - ; sets neg_flag if result is < 0, but does not store result itself - ; trashes WREG +;============================================================================= +math6 CODE +;============================================================================= + +;----------------------------------------------------------------------------- +; Compare two UNSIGNED 16 Bit Integers: sub_a:2 - sub_b:2 +; +; sets neg_flag if result is < 0, trashes WREG +; the subtraction result is not stored +; + global cmpU16 cmpU16: bcf neg_flag ; clear flag which will indicate if result is negative movf sub_b+0,W ; get value to be subtracted, low byte @@ -122,44 +149,61 @@ return ; done - global mult16x16 ; xC:4 = xA:2 * xB:2 with UNSIGNED values - ; trashes PRODL, PRODH, WREG +;============================================================================= +math7 CODE +;============================================================================= + +;----------------------------------------------------------------------------- +; Multiply two UNSIGNED 16 bit Integers: xC:4 = xA:2 * xB:2 +; +; trashes PRODL, PRODH, WREG +; + global mult16x16 mult16x16: clrf xC+2 ; clear the high-order bits - clrf xC+3 - ; + clrf xC+3 ; ... + movf xA+0,W ; do the "L" multiplication mulwf xB+0 movff PRODL,xC+0 ; copy result to xC movff PRODH,xC+1 - ; + movf xA+0,W ; do the "I" multiplication mulwf xB+1 movf PRODL,W ; get the product's low byte... addwf xC+1,F ; ... and add it to xC+1 movf PRODH,W ; get the product's high byte... addwfc xC+2,F ; ... and add it to xC+2 obeying carry bit from xC+1 - ; + movf xA+1,W ; do the "O" multiplication mulwf xB+0 - movf PRODL,W ; get the product's low byte... + movf PRODL,W ; get the product's low byte... addwf xC+1,F ; ... and add it to xC+1 movf PRODH,W ; get the product's high byte... addwfc xC+2,F ; ... and add it to xC+2 obeying carry bit from xC+1 clrf WREG ; clear WREG... addwfc xC+3,F ; ... add add it to xC+3 obeying carry bit from xC+2 (can only happen in "O" multiplication) - ; + movf xA+1,W ; do the "F" multiplication mulwf xB+1 - movf PRODL,W ; get the product's low byte... + movf PRODL,W ; get the product's low byte... addwf xC+2,F ; ... and add it to xC+2 movf PRODH,W ; get the product's high byte... addwfc xC+3,F ; ... and add it to xC+3 obeying carry bit from xC+2 - return + + return ; done - global div16x16 ; xC:2 = xA:2 / xB:2 with xA as remainder - ; trashes WREG +;============================================================================= +math8 CODE +;============================================================================= + +;----------------------------------------------------------------------------- +; Divide two UNSIGNED 16 Bit Integers: xC:2 = xA:2 / xB:2 with xA as remainder +; +; trashes WREG +; + global div16x16 div16x16: movlw .16 ; process 16 bits ... movwf math_loop ; ... initialize loop counter @@ -193,8 +237,16 @@ return ; YES - done - global div32x16 ; xC:4 = xC:4 / xB:2 with xA as remainder - ; trashes WREG +;============================================================================= +math9 CODE +;============================================================================= + +;----------------------------------------------------------------------------- +; Divide a 32 Bit Integer by a 16 Bit Integer: xC:4 = xC:4 / xB:2 with xA as remainder +; +; trashes WREG +; + global div32x16 div32x16: movlw .32 ; process 32 bits ... movwf math_loop ; ... initialize loop counter @@ -228,73 +280,99 @@ return ; YES - done +;----------------------------------------------------------------------------- +; +; ISR math functions +; +;----------------------------------------------------------------------------- + +;============================================================================= +math10 CODE ;============================================================================= -; ISR math functions - - global isr_shift_C31 ; 24 bit shift, repeated WREG times, dedicated to a specific usage: - ; Because less than 8 bits are shifted and only C[2:1] is needed, - ; we don't care what bit is inserted. +;----------------------------------------------------------------------------- +; 24 Bit Shift, repeated WREG Times, dedicated to a specific Usage +; +; Because less than 8 bits are shifted and only C[2:1] is needed, +; we don't care what bit is inserted. +; + global isr_shift_C31 isr_shift_C31: rrcf isr_xC+3,F ; shift three bytes - rrcf isr_xC+2,F - rrcf isr_xC+1,F + rrcf isr_xC+2,F ; ... + rrcf isr_xC+1,F ; ... decfsz WREG ; decrement loop counter, done? bra isr_shift_C31 ; NO - loop return ; YES - done - global isr_unsigned_mult16x16 ; isr_xC = isr_xA * _isr_xB with UNSIGNED values - ; trashes PRODL, PRODH, WREG +;============================================================================= +math11 CODE +;============================================================================= + +;----------------------------------------------------------------------------- +; Multiply two UNSIGNED 16 Bit Integers: isr_xC = isr_xA * isr_xB +; +; trashes PRODL, PRODH, WREG +; + global isr_unsigned_mult16x16 isr_unsigned_mult16x16: movf isr_xA+0,W ; multiply a[0] * b[0] - mulwf isr_xB+0 + mulwf isr_xB+0 ; ... movff PRODL,isr_xC+0 ; store product to c[1]:c[0] - movff PRODH,isr_xC+1 - ; + movff PRODH,isr_xC+1 ; ... + movf isr_xA+1,W ; multiply a[1] * b[1] - mulwf isr_xB+1 + mulwf isr_xB+1 ; ... movff PRODL, isr_xC+2 ; store product to c[3]:c[2] - movff PRODH, isr_xC+3 - ; + movff PRODH, isr_xC+3 ; ... + movf isr_xA+0,W ; multiply a[0] * b[1] - mulwf isr_xB+1 + mulwf isr_xB+1 ; ... movf PRODL,W ; add cross product to c[3]:c[2]:c[1] - addwf isr_xC+1,F - movf PRODH,W + addwf isr_xC+1,F ; ... + movf PRODH,W ; ... addwfc isr_xC+2,F ; propagate carry - clrf WREG - addwfc isr_xC+3,F ; propagate carry - ; + clrf WREG ; ... + addwfc isr_xC+3,F ; ... + movf isr_xA+1,W ; multiply a[1] * b[0] - mulwf isr_xB+0 + mulwf isr_xB+0 ; ... movf PRODL,W ; add cross product - addwf isr_xC+1,F - movf PRODH,W + addwf isr_xC+1,F ; ... + movf PRODH,W ; ... addwfc isr_xC+2,F ; propagate carry - clrf WREG - addwfc isr_xC+3,F ; propagate carry - return + clrf WREG ; ... + addwfc isr_xC+3,F ; ... + return ; done - global isr_signed_mult16x16 ; isr_xC = isr_xA * isr_xB with SIGNED values - ; trashes PRODL, PRODH, WREG +;----------------------------------------------------------------------------- +; Multiply two SIGNED 16 Bit Integers: isr_xC = isr_xA * isr_xB +; +; trashes PRODL, PRODH, WREG +; + global isr_signed_mult16x16 isr_signed_mult16x16: - rcall isr_unsigned_mult16x16 ; do an unsigned multiplication first - ; ; manage sign extension of operand B + ; do an unsigned multiplication first + rcall isr_unsigned_mult16x16 + + ; manage sign extension of operand B btfss isr_xB+1,7 ; is B negative ? bra isr_signed_mult_checkA ; NO - continue checking operand A - movf isr_xA+0,W ; Yes - add -65536 * A - subwf isr_xC+2,F - movf isr_xA+1,W - subwfb isr_xC+3,F + movf isr_xA+0,W ; YES - add -65536 * A + subwf isr_xC+2,F ; - ... + movf isr_xA+1,W ; - ... + subwfb isr_xC+3,F ; - ... isr_signed_mult_checkA ; manage sign extension of operand B btfss isr_xA+1,7 ; is A negative ? return ; NO - done - movf isr_xB+0,W ; Yes - add -65536 * B - subwf isr_xC+2,F - movf isr_xB+1,W - subwfb isr_xC+3,F - return + movf isr_xB+0,W ; YES - add -65536 * B + subwf isr_xC+2,F ; - ... + movf isr_xB+1,W ; - ... + subwfb isr_xC+3,F ; - ... + return ; - done + +;----------------------------------------------------------------------------- END \ No newline at end of file