Mercurial > public > hwos_code
diff src/math.asm @ 643:7d8a4c60ec1a
3.15 release
author | heinrichsweikamp |
---|---|
date | Mon, 24 May 2021 18:40:53 +0200 |
parents | 4050675965ea |
children | 75e90cd0c2c3 |
line wrap: on
line diff
--- a/src/math.asm Thu Jan 14 16:24:07 2021 +0100 +++ b/src/math.asm Mon May 24 18:40:53 2021 +0200 @@ -346,6 +346,9 @@ addwfc isr_xC+3,F ; ... return ; done +;============================================================================= +math12 CODE +;============================================================================= ;----------------------------------------------------------------------------- ; Multiply two SIGNED 16 Bit Integers: isr_xC = isr_xA * isr_xB @@ -355,7 +358,7 @@ global isr_signed_mult16x16 isr_signed_mult16x16: ; do an unsigned multiplication first - rcall isr_unsigned_mult16x16 + call isr_unsigned_mult16x16 ; manage sign extension of operand B btfss isr_xB+1,7 ; is B negative ? @@ -364,7 +367,7 @@ 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 +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 @@ -373,6 +376,237 @@ subwfb isr_xC+3,F ; - ... return ; - done +;============================================================================= +math13 CODE +;============================================================================= + +;----------------------------------------------------------------------------- +; Multiply two UNSIGNED 24 Bit Integers: isr_xC = isr_xA * isr_xB +; +; trashes PRODL, PRODH, WREG +; + global isr_unsigned_mult24x24 +isr_unsigned_mult24x24: + call isr_unsigned_mult16x16 ; Do the 16x16 first + clrf isr_xC+4 + clrf isr_xC+5 ; clear upper 16 bit + ; do the remaining three multiplications + movf isr_xA+0,W ; multiply a[0] * b[2] + mulwf isr_xB+2 ; ... + movf PRODL,W ; add cross product to c[4]:c[3]:c[2] + addwf isr_xC+2,F ; ... + movf PRODH,W ; ... + addwfc isr_xC+3,F ; propagate carry + clrf WREG ; ... + addwfc isr_xC+4,F ; ... + addwfc isr_xC+5,F ; ... + + movf isr_xA+2,W ; multiply a[2] * b[0] + mulwf isr_xB+0 ; ... + movf PRODL,W ; add cross product to c[4]:c[3]:c[2] + addwf isr_xC+2,F ; ... + movf PRODH,W ; ... + addwfc isr_xC+3,F ; propagate carry + clrf WREG ; ... + addwfc isr_xC+4,F ; ... + addwfc isr_xC+5,F ; ... + ; isr_xC[2] done. + + movf isr_xA+2,W ; multiply a[2] * b[1] + mulwf isr_xB+1 ; ... + movf PRODL,W ; add cross product to c[5]:c[4]:c[3] + addwf isr_xC+3,F ; ... + movf PRODH,W ; ... + addwfc isr_xC+4,F ; propagate carry + clrf WREG ; ... + addwfc isr_xC+5,F ; ... + + movf isr_xA+1,W ; multiply a[1] * b[2] + mulwf isr_xB+2 ; ... + movf PRODL,W ; add cross product to c[5]:c[4]:c[3] + addwf isr_xC+3,F ; ... + movf PRODH,W ; ... + addwfc isr_xC+4,F ; propagate carry + clrf WREG ; ... + addwfc isr_xC+5,F ; ... + ; isr_xC[3] done. + + movf isr_xA+2,W ; multiply a[2] * b[2] + mulwf isr_xB+2 ; ... + movf PRODL,W ; add cross product to c[5]:c[4] + addwf isr_xC+4,F ; ... + movf PRODH,W ; ... + addwfc isr_xC+5,F ; propagate carry + ; isr_xC[4] done. + ; isr_xC[5] done. + + return ; done + +;============================================================================= +math14 CODE +;============================================================================= + +;----------------------------------------------------------------------------- +; Multiply two UNSIGNED Integers (32 and 24 Bit): isr_xC = isr_xA * isr_xB +; +; trashes PRODL, PRODH, WREG +; + global isr_unsigned_mult32x24 +isr_unsigned_mult32x24: + call isr_unsigned_mult24x24 ; Do the 24x24 first + clrf isr_xC+6 ; clear upper 8 bit + ; do the remaining three multiplications + movf isr_xA+3,W ; multiply a[3] * b[0] + mulwf isr_xB+0 ; ... + movf PRODL,W ; add cross product to c[5]:c[4]:c[3] + addwf isr_xC+3,F ; ... + movf PRODH,W ; ... + addwfc isr_xC+4,F ; propagate carry + clrf WREG ; ... + addwfc isr_xC+5,F ; ... + addwfc isr_xC+6,F ; ... + ; isr_xC[3] done. + + movf isr_xA+3,W ; multiply a[3] * b[1] + mulwf isr_xB+1 ; ... + movf PRODL,W ; add cross product to c[5]:c[4] + addwf isr_xC+4,F ; ... + movf PRODH,W ; ... + addwfc isr_xC+5,F ; propagate carry + clrf WREG ; ... + addwfc isr_xC+6,F ; ... + ; isr_xC[4] done. + + movf isr_xA+3,W ; multiply a[3] * b[2] + mulwf isr_xB+2 ; ... + movf PRODL,W ; add cross product to c[5]:c[4] + addwf isr_xC+5,F ; ... + movf PRODH,W ; ... + addwfc isr_xC+6,F ; propagate carry + ; isr_xC[5] done. + ; isr_xC[6] done. + return ; done + + +;============================================================================= +math15 CODE +;============================================================================= + +;----------------------------------------------------------------------------- +; Multiply two SIGNED 24 Bit Integers: isr_xC = isr_xA * isr_xB +; +; trashes PRODL, PRODH, WREG +; + global isr_signed_mult24x24 +isr_signed_mult24x24: + ; do an unsigned multiplication first + call isr_unsigned_mult24x24 + + ; manage sign extension of operand B + btfss isr_xB+2,7 ; is B negative ? + bra isr_signed24_mult_checkA ; NO - continue checking operand A + movf isr_xA+0,W ; YES - add -16777216 * A + subwf isr_xC+3,F ; - ... + movf isr_xA+1,W ; - ... + subwfb isr_xC+4,F ; - ... + movf isr_xA+2,W ; - ... + subwfb isr_xC+5,F ; - ... +isr_signed24_mult_checkA: ; manage sign extension of operand B + btfss isr_xA+2,7 ; is A negative ? + return ; NO - done + movf isr_xB+0,W ; YES - add -16777216 * B + subwf isr_xC+3,F ; - ... + movf isr_xB+1,W ; - ... + subwfb isr_xC+4,F ; - ... + movf isr_xB+2,W ; - ... + subwfb isr_xC+5,F ; - ... + return + +;============================================================================= +math16 CODE +;============================================================================= + +;----------------------------------------------------------------------------- +; Divide two UNSIGNED 16 Bit Integers: isr_xC:2 = isr_xA:2 / isr_xB:2 with xA as remainder +; +; trashes WREG +; + global isr_div16x16 +isr_div16x16: + movlw .16 ; process 16 bits ... + movwf isr_math_loop ; ... initialize loop counter + movff isr_xA+0,isr_xC+0 ; copy isr_xA to isr_xC + movff isr_xA+1,isr_xC+1 ; ... + clrf isr_xA+0 ; clear isr_xA, will now be used to hold the remainder + clrf isr_xA+1 ; ... +isr_div16x16_1: + bcf STATUS,C ; clear carry flag to shift in a zero bit + rlcf isr_xC+0,F ; shift left isr_xC + rlcf isr_xC+1,F ; ... shifting MSB out of isr_xC... + rlcf isr_xA+0,F ; ... and into LSB of isr_xA + rlcf isr_xA+1,F ; ... + btfsc STATUS,C ; did the remainder overflow (carry set)? + bra isr_div16x16_2 ; YES - directly generate a result bit = 1 + movf isr_xB+0,W ; NO - compute remainder - divisor = isr_xA - isr_xB, trash result to WREG + subwf isr_xA+0,W ; - ... + movf isr_xB+1,W ; - ... + subwfb isr_xA+1,W ; - ... + btfss STATUS,C ; - remainder < divisor (-> borrow flag set, equals carry flag cleared) ? + bra isr_div16x16_3 ; YES - result bit = 0, keep LSB of isr_xC+0 being 0 +isr_div16x16_2: + bsf isr_xC+0,0 ; NO - result bit = 1, set LSB of isr_xC+0 to 1 + movf isr_xB+0,W ; - subtract divisor from remainder "for real": isr_xA = isr_xA - isr_xB + subwf isr_xA+0,F ; - ... + movf isr_xB+1,W ; - ... + subwfb isr_xA+1,F ; - ... +isr_div16x16_3: + decfsz isr_math_loop,F ; decrement loop counter, all bits done? + bra isr_div16x16_1 ; NO - loop + return ; YES - done + +;============================================================================= +math17 CODE +;============================================================================= + +;----------------------------------------------------------------------------- +; Divide a 32 Bit Integer by a 16 Bit Integer: isr_xC:4 = isr_xC:4 / isr_xB:2 with isr_xA as remainder +; +; trashes WREG +; + global isr_div32x16 +isr_div32x16: + movlw .32 ; process 32 bits ... + movwf isr_math_loop ; ... initialize loop counter + clrf isr_xA+0 ; clear isr_xA, will be used to hold the remainder + clrf isr_xA+1 ; ... +isr_div32x16_1: + bcf STATUS,C ; clear carry flag to shift in a zero bit + rlcf isr_xC+0,F ; shift left isr_xC + rlcf isr_xC+1,F ; ... + rlcf isr_xC+2,F ; ... + rlcf isr_xC+3,F ; ... shifting MSB out of isr_xC... + rlcf isr_xA+0,F ; ... and into LSB of isr_xA + rlcf isr_xA+1,F ; ... + btfsc STATUS,C ; did the remainder overflow (carry set)? + bra isr_div32x16_2 ; YES - directly generate a result bit = 1 + movf isr_xB+0,W ; NO - compute remainder - divisor = isr_xA - isr_xB, trash result to WREG + subwf isr_xA+0,W ; - ... + movf isr_xB+1,W ; - ... + subwfb isr_xA+1,W ; - ... + btfss STATUS,C ; - remainder < divisor (-> borrow flag set, equals carry flag cleared) ? + bra isr_div32x16_3 ; YES - result bit = 0, keep LSB of isr_xC+0 being 0 +isr_div32x16_2: + bsf isr_xC+0,0 ; NO - result bit = 1, set LSB of isr_xC+0 to 1 + movf isr_xB+0,W ; - subtract divisor from remainder "for real": isr_xA = isr_xA - isr_xB + subwf isr_xA+0,F ; - ... + movf isr_xB+1,W ; - ... + subwfb isr_xA+1,F ; - ... +isr_div32x16_3: + decfsz isr_math_loop,F ; decrement loop counter, all bits done? + bra isr_div32x16_1 ; NO - loop + return ; YES - done + + ;----------------------------------------------------------------------------- END \ No newline at end of file