/*======================================================================* | Planet Fastest Unsigned PICmicro Math | | (c) 1999 Jose Luiz Pinto Souto | | souto@cryogen.com | | | | Loop version, smallest code. All timming includes CALL and | | RETURN instructions. | | | | Compiled with CC5X, see also CC5xfree, a free 1K limited | | C compiler from B. Knudsen Data - www.bknd.com. | | | | For algorithm details see Microchip's application note AN617. | | PICmicro is registered Trademark of Microchip Technology Inc. | | Alpha version - please report any bug to e-mail above. | | If any faster algorithm is found, please report. | *======================================================================*/ /* this software has been released to increase critical-mass PIC usage */ /* YOU MAY USE THIS SOFTWARE OR PART OF IT AS LONG AS YOU KEEP THE COPYRIGHT NOTICE. COMERCIAL PRODUCTS SHOULD HAVE A PUBLIC REFERENCE TO AUTHOR. THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESSED, IMPLIED OR OTHERWISE, INCLUDING AND WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, LOSS OF INFORMATION, OR ANY OTHER LOSS) , WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR INABILITY TO USE THIS SOFTWARE. */ #include <16c62a.h> #pragma update_RP 0 // OFF #define uns40 unsigned int #define uns48 unsigned int #define uns56 unsigned int #define uns64 unsigned int uns8 a8; // Load the 1st operand ( 8 bits ) uns16 a16; // Load the 1st operand ( 16 bits ) uns24 a24; // Load the 1st operand ( 24 bits ) uns32 a32; // Load the 1st operand ( 32 bits ) uns8 b8; // Load the 2nd operand ( 8 bits ) uns16 b16; // Load the 2nd operand ( 16 bits ) uns24 b24; // Load the 2nd operand ( 24 bits ) uns32 b32; // Load the 2nd operand ( 32 bits ) uns8 r8; // The 8 bits result uns16 r16; // The 16 bits result uns24 r24; // The 24 bits result uns32 r32; // The 32 bits result uns40 r40[5]; // The 40 bits result uns48 r48[6]; // The 48 bits result uns64 r64[8]; // The 64 bits result bit Overflow; // Division Overflow flag bit ZeroDiv; // Division Divisin by Zero flag uns8 q8; // The 8 bits quotient uns16 q16; // The 16 bits quotient uns24 q24; // The 24 bits quotient /*======================================================================*/ /* Prototypes */ /*======================================================================*/ void negate8 (void); void negate16 (void); void negate24 (void); void negate32 (void); void negate8a (void); void negate16a (void); void negate24a (void); void negate32a (void); void negate8b (void); void negate16b (void); void negate24b (void); void negate32b (void); /*----------------*/ void add8 (void); void add16 (void); void add24 (void); void add32 (void); void add8a (void); void add16a (void); void add24a (void); void add32a (void); void add8b (void); void add16b (void); void add24b (void); void add32b (void); /*----------------*/ void sub8 (void); void sub16 (void); void sub24 (void); void sub32 (void); void sub8a (void); void sub16a (void); void sub24a (void); void sub32a (void); /*-------------------*/ void mpy8x8 (void); void mpy16x8 (void); void mpy24x8 (void); void mpy32x8 (void); void mpy16x8a (void); void mpy24x8a (void); void mpy32x8a (void); void mpy16x16 (void); void mpy24x16 (void); void mpy32x16 (void); void mpy16x16a (void); void mpy24x16a (void); void mpy32x16a (void); void mpy32x32 (void); void mpy32x32a (void); /*======================================================================*/ void negate8 (void) // r8 = -b8 /*======================================================================*/ { r8 = ~b8; r8++; } // 4 instructions, 5 cycles /*======================================================================*/ void negate8a (void) // b8 = -b8 /*======================================================================*/ { b8 = ~b8; b8++; } // 3 instructions, 4 cycles /*======================================================================*/ void negate8b (void) // INDF = -b8 /*======================================================================*/ { INDF = ~b8; INDF++; } // 4 instructions, 5 cycles /*======================================================================*/ void negate16 (void) // r16 = -b16 /*======================================================================*/ { r16.high8 = ~b16.high8; r16.low8 = ~b16.low8; r16.low8 = incsz(r16.low8); return; r16.high8++; } // 8 instructions, min:7 max:9 cycles /*======================================================================*/ void negate16a (void) // b16 = -b16 /*======================================================================*/ { b16.high8 = ~b16.high8; b16.low8 = ~b16.low8; b16.low8 = incsz(b16.low8); return; b16.high8++; } // 6 instructions, min:5 max:7 cycles /*======================================================================*/ void negate16b (void) // INDF = -INDF /*======================================================================*/ { INDF = ~INDF; FSR++; INDF = ~INDF; FSR--; INDF = incsz(INDF); return; FSR++; INDF++; } // 9 instructions, min:7 max:10 cycles /*======================================================================*/ void negate24 (void) // r24 = -b24 /*======================================================================*/ { r24.high8 = ~b24.high8; r24.midL8 = ~b24.midL8; r24.low8 = ~b24.low8; r24.low8 = incsz(r24.low8); return; r24.midL8 = incsz(r24.midL8); return; r24.high8++; } // 12 instructions, min:12 max:16 cycles /*======================================================================*/ void negate24a (void) // b24 = -b24 /*======================================================================*/ { b24.high8 = ~b24.high8; b24.midL8 = ~b24.midL8; b24.low8 = ~b24.low8; b24.low8 = incsz(b24.low8); return; b24.midL8 = incsz(b24.midL8); return; b24.high8++; } // 9 instructions, min:6 max:10 cycles /*======================================================================*/ void negate24b (void) // INDF = -INDF /*======================================================================*/ { W = FSR; INDF = ~INDF; FSR++; INDF = ~INDF; FSR++; INDF = ~INDF; FSR = W; INDF = incsz(INDF); return; FSR++; INDF = incsz(INDF); return; FSR++; INDF++; } // 15 instructions, min:10 max:16 cycles /*======================================================================*/ void negate32 (void) // r32 = -b32 /*======================================================================*/ { r32.high8 = ~b32.high8; r32.midH8 = ~b32.midH8; r32.midL8 = ~b32.midL8; r32.low8 = ~b32.low8; r32.low8 = incsz(r32.low8); return; r32.midL8 = incsz(r32.midL8); return; r32.midH8 = incsz(r32.midH8); return; r32.high8++; } // 16 instructions, min:14 max:20 cycles /*======================================================================*/ void negate32a (void) // b32 = -b32 /*======================================================================*/ { b32.high8 = ~b32.high8; b32.midH8 = ~b32.midH8; b32.midL8 = ~b32.midL8; b32.low8 = ~b32.low8; b32.low8 = incsz(b32.low8); return; b32.midL8 = incsz(b32.midL8); return; b32.midH8 = incsz(b32.midH8); return; b32.high8++; } // 12 instructions, min:10 max:16 cycles /*======================================================================*/ void negate32b (void) // INDF = -b32 /*======================================================================*/ { uns8 ww; ww = FSR; INDF = ~b32.low8; FSR++; INDF = ~b32.midL8; FSR++; INDF = ~b32.midH8; FSR++; INDF = ~b32.high8; FSR = ww; INDF = incsz(INDF); return; FSR++; INDF = incsz(INDF); return; FSR++; INDF = incsz(INDF); return; FSR++; INDF++; } // 27 instructions, min:18 max:27 cycles /*======================================================================*/ void add8 (void) // r8 = a8 + b8 /*======================================================================*/ { W = b8; W = a8 + W; r8 = W; } // 4 instructions, 5 cycles /*======================================================================*/ void add8a (void) // a8 += b8 /*======================================================================*/ { W = b8; a8 += W; } // 3 instructions, 4 cycles /*======================================================================*/ void add8b (void) // INDF += b8 /*======================================================================*/ { INDF += b8; } // 3 instructions, 4 cycles /*======================================================================*/ void add16 (void) // r16 = a16 + b16 /*======================================================================*/ { r16.low8 = a16.low8 + b16.low8; r16.high8 = a16.high8; W = b16.high8; if (Carry) W = incsz(b16.high8); r16.high8 += W; } // 10 instructions, 11 cycles /*======================================================================*/ void add16a (void) // a16 += b16 /*======================================================================*/ { a16.low8 += b16.low8; W = b16.high8; if (Carry) W = incsz(b16.high8); a16.high8 += W; } // 7 instructions, 8 cycles /*======================================================================*/ void add16b (void) // INDF += b16 /*======================================================================*/ { INDF += b16.low8; FSR++; W = b16.high8; if (Carry) W = incsz(b16.high8); INDF += W; } // 8 instructions, 9 cycles /*======================================================================*/ void add24 (void) // r24 = a24 + b24 /*======================================================================*/ { r24.low8 = a24.low8 + b24.low8; r24.midL8 = a24.midL8; W = b24.midL8; if (Carry) W = incsz(b24.midL8); r24.midL8 += W; r24.high8 = a24.high8; W = b24.high8; if (Carry) W = incsz(b24.high8); r24.high8 += W; } // 16 instructions, 17 cycles /*======================================================================*/ void add24a (void) // a24 += b24 /*======================================================================*/ { a24.low8 += b24.low8; W = b24.midL8; if (Carry) W = incsz(b24.midL8); a16.midL8 += W; W = b24.high8; if (Carry) W = incsz(b24.high8); a16.high8 += W; } // 11 instructions, 12 cycles /*======================================================================*/ void add24b (void) // INDF += b24 /*======================================================================*/ { INDF += b24.low8; FSR++; W = b24.midL8; if (Carry) W = incsz(b24.midL8); INDF += W; FSR++; W = b24.high8; if (Carry) W = incsz(b24.high8); INDF += W; } // 13 instructions, 14 cycles /*======================================================================*/ void add32 (void) // r32 = a32 + b32 /*======================================================================*/ { r32.low8 = a32.low8 + b32.low8; r32.midL8 = a32.midL8; W = b32.midL8; if (Carry) W = incsz(b32.midL8); r32.midL8 += W; r32.midH8 = a32.midH8; W = b32.midH8; if (Carry) W = incsz(b32.midH8); r32.midH8 += W; r32.high8 = a32.high8; W = b32.high8; if (Carry) W = incsz(b32.high8); r32.high8 += W; } // 22 instructions, 23 cycles /*======================================================================*/ void add32a (void) // a32 += b32 /*======================================================================*/ { a32.low8 += b32.low8; W = b32.midL8; if (Carry) W = incsz(b32.midL8); a32.midL8 += W; W = b32.midH8; if (Carry) W = incsz(b32.midH8); a32.midH8 += W; W = b32.high8; if (Carry) W = incsz(b32.high8); a32.high8 += W; } // 15 instructions, 16 cycles /*======================================================================*/ void add32b (void) // INDF += b32 /*======================================================================*/ { INDF += b32.low8; FSR++; W = b32.midL8; if (Carry) W = incsz(b32.midL8); INDF += W; FSR++; W = b32.midH8; if (Carry) W = incsz(b32.midH8); INDF += W; FSR++; W = b32.high8; if (Carry) W = incsz(b32.high8); INDF += W; } // 18 instructions, 19 cycles /*======================================================================*/ void sub8 (void) // r8 = a8 - b8 /*======================================================================*/ { r8 = a8 - b8; } // 4 instructions, 5 cycles /*======================================================================*/ void sub8a (void) // a8 -= b8 /*======================================================================*/ { a8 -= b8; } // 3 instructions, 4 cycles /*======================================================================*/ void sub8b (void) // INDF -= b8 /*======================================================================*/ { INDF -= b8; } // 3 instructions, 4 cycles /*======================================================================*/ void sub16 (void) // r16 = a16 - b16 /*======================================================================*/ { r16.low8 = a16.low8 - b16.low8; r16.high8 = a16.high8; W = b16.high8; if (!Carry) W = incsz(b16.high8); r16.high8 -= W; } // 10 instructions, 11 cycles /*======================================================================*/ void sub16a (void) // a16 -= b16 /*======================================================================*/ { a16.low8 -= b16.low8; W = b16.high8; if (!Carry) W = incsz(b16.high8); a16.high8 -= W; } // 7 instructions, 8 cycles /*======================================================================*/ void sub16b (void) // INDF -= b16 /*======================================================================*/ { INDF -= b16.low8; FSR++; W = b16.high8; if (!Carry) W = incsz(b16.high8); INDF -= W; } // 8 instructions, 9 cycles /*======================================================================*/ void sub24 (void) // r24 = a24 - b24 /*======================================================================*/ { r24.low8 = a24.low8 - b24.low8; r24.midL8 = a24.midL8; W = b24.midL8; if (!Carry) W = incsz(b24.midL8); r24.midL8 -= W; r24.high8 = a24.high8; W = b24.high8; if (!Carry) W = incsz(b24.high8); r24.high8 -= W; } // 16 instructions, 17 cycles /*======================================================================*/ void sub24a (void) // a24 -= b24 /*======================================================================*/ { a24.low8 -= b24.low8; W = b24.midL8; if (!Carry) W = incsz(b24.midL8); a24.midL8 -= W; W = b24.high8; if (!Carry) W = incsz(b24.high8); a24.high8 -= W; } // 11 instructions, 12 cycles /*======================================================================*/ void sub24b (void) // INDF -= b24 /*======================================================================*/ { INDF -= b24.low8; FSR++; W = b24.midL8; if (!Carry) W = incsz(b24.midL8); INDF -= W; FSR++; W = b24.high8; if (!Carry) W = incsz(b24.high8); INDF -= W; } // 13 instructions, 14 cycles /*======================================================================*/ void sub32 (void) // r32 = a32 - b32 /*======================================================================*/ { r32.low8 = a32.low8 - b32.low8; r32.midL8 = a32.midL8; W = b32.midL8; if (!Carry) W = incsz(b32.midL8); r32.midL8 -= W; r32.midH8 = a32.midH8; W = b32.midH8; if (!Carry) W = incsz(b32.midH8); r32.midH8 -= W; r32.high8 = a32.high8; W = b32.high8; if (!Carry) W = incsz(b32.high8); r32.high8 -= W; } // 22 instructions, 23 cycles /*======================================================================*/ void sub32a (void) // a32 -= b32 /*======================================================================*/ { a32.low8 -= b32.low8; W = b32.midL8; if (!Carry) W = incsz(b32.midL8); a32.midL8 -= W; W = b32.midH8; if (!Carry) W = incsz(b32.midH8); a32.midH8 -= W; W = b32.high8; if (!Carry) W = incsz(b32.high8); a32.high8 -= W; } // 15 instructions, 19 cycles /*======================================================================*/ void sub32b (void) // INDF -= b32 /*======================================================================*/ { INDF -= b32.low8; FSR++; W = b32.midL8; if (!Carry) W = incsz(b32.midL8); INDF -= W; FSR++; W = b32.midH8; if (!Carry) W = incsz(b32.midH8); INDF -= W; FSR++; W = b32.high8; if (!Carry) W = incsz(b32.high8); INDF -= W; } // 18 instructions, 19 cycles /*======================================================================*/ void mpy8x8 (void) // r16 = a8 * b8 /*======================================================================*/ { uns8 ix; r16 = 0; W = b8; if (W) { r16.low8 = W; ix = 8; W = a8; do { Carry = 0; if (r16.0) r16.high8 += W; r16.high8 = rr (r16.high8); r16.low8 = rr (r16.low8); } while (--ix); } } // 17 instructions, min:11, max:77 cycles /*======================================================================*/ void mpy8x8a (void) // INDF = a8 * b8 /*======================================================================*/ { uns8 ix, m; INDF = 0; FSR++; INDF = 0; W = b8; if (W) { m = W; ix = 8; W = a8; do { Carry = 0; if (m.0) INDF += W; INDF = rr (INDF); FSR--; INDF = rr (INDF); FSR++; m = rr (m); } while (--ix); } } // 21 instructions, min:8, max:?? cycles /*======================================================================*/ void mpy16x8 (void) // r24 = a16 * b8 /*======================================================================*/ { uns8 ix; W = b8; if (!W) { r24.high8 = 0; r24.low16 = 0; } else { r24.low8 = W ^ 1; r24.high16 = a16; ix = 8; do { W = rr(r24.low8); if (Carry) { r24.midL8 += a16.low8; W = a16.high8; if (Carry) W = incsz(a16.high8); r24.high8 += W; } r24.high8 = rr(r24.high8); r24.midL8 = rr(r24.midL8); r24.low8 = rr(r24.low8); } while (--ix); } } // 30 instructions, min:10, max:131 cycles /*======================================================================*/ void mpy16x8a (void) // INDF = a16 * b8 /*======================================================================*/ { uns8 ix, m; INDF = 0; FSR++; // 1 INDF = 0; FSR++; // 2 INDF = 0; W = b8; if (W) { m = W; FSR--; // 1 ix = 8; do { Carry = 0; if (m.0) { INDF += a16.low8; FSR++; // 2 W = a16.high8; if (Carry) W = incsz(a16.high8); INDF += W; FSR--; // 1 } FSR++; // 2 INDF = rr(INDF); FSR--; // 1 INDF = rr(INDF); FSR--; // 0 INDF = rr(INDF); FSR++; // 1 m = rr(m); } while (--ix); } } // 34 instructions, min:??, max:??? cycles /*======================================================================*/ void mpy24x8 (void) // r32 = a24 * b8 /*======================================================================*/ { uns8 ix; W = b8; if (!W) { r32.high16 = 0; r32.low16 = 0; } else { r32.low8 = W ^ 1; r32.midL8 = a24.low8; r32.high16 = a24.high16; ix = 8; do { W = rr(r32.low8); if (Carry) { r32.midL8 += a24.low8; W = a24.midL8; if (Carry) W = incsz(a24.midL8); r32.midH8 += W; W = a24.high8; if (Carry) W = incsz(a24.high8); r32.high8 += W; } r32.high8 = rr(r32.high8); r32.midH8 = rr(r32.midH8); r32.midL8 = rr(r32.midL8); r32.low8 = rr(r32.low8); } while (--ix); } } // 38 instructions, min:14, max:169 cycles /*======================================================================*/ void mpy24x8a (void) // INDF = a24 * b8 /*======================================================================*/ { uns8 ix, m, p; INDF = 0; FSR++; // 1 INDF = 0; FSR++; // 2 INDF = 0; FSR++; // 3 INDF = 0; W = b8; if (W) { m = W; ix = 8; p = FSR; FSR--; // 2 FSR--; // 1 do { W = rr(m); if (Carry) { INDF += a24.low8; FSR++; // 2 W = a24.midL8; if (Carry) W = incsz(a24.midL8); INDF += W; FSR++; // 3 W = a24.high8; if (Carry) W = incsz(a24.high8); INDF += W; } // else !Carry FSR = p; INDF = rr(INDF); FSR--; // 2 INDF = rr(INDF); FSR--; // 1 INDF = rr(INDF); FSR--; // 0 INDF = rr(INDF); FSR++; // 1 m = rr(m); } while (--ix); } } // 46 instructions, min:13, max:??? cycles /*======================================================================*/ void mpy32x8 (void) // r40 = a32 * b8 /*======================================================================*/ { uns8 ix; W = b8; if (!W) { r40[4] = 0; r40[3] = 0; r40[2] = 0; r40[1] = 0; r40[0] = 0; } else { r40[0] = a32.high8; r40[1] = a32.midH8; r40[2] = a32.midL8; r40[3] = a32.low8; r40[4] = b8 ^ 1; ix = 8; do { Carry = 0; { if (r40[4].0) { r40[3] += a32.low8; W = a32.midL8; if (Carry) W = incsz(a32.midL8); r40[2] += W; W = a32.midH8; if (Carry) W = incsz(a32.midH8); r40[1] += W; W = a32.high8; if (Carry) W = incsz(a32.high8); r40[0] += W; } } #asm rrf r40+0,F ; r40[0] = rr(r40[0]); rrf r40+1,F ; r40[1] = rr(r40[1]); rrf r40+2,F ; r40[2] = rr(r40[2]); rrf r40+3,F ; r40[3] = rr(r40[3]); rrf r40+4,F ; r40[4] = rr(r40[4]); #endasm } while (--ix); } } // 47 instructions, min:15, max:208 cycles /*======================================================================*/ void mpy32x8a (void) // INDF = a32 * b8 /*======================================================================*/ { uns8 ix, m, p; INDF = 0; FSR++; // 1 INDF = 0; FSR++; // 2 INDF = 0; FSR++; // 3 INDF = 0; FSR++; // 4 INDF = 0; W = b8; if (W) { m = W; ix = 8; p = FSR; FSR--; // 3 FSR--; // 2 FSR--; // 1 do { W = rr(m); { if (Carry) { INDF += a32.low8; FSR++; // 2 W = a32.midL8; if (Carry) W = incsz(a32.midL8); INDF += W; FSR++; // 3 W = a32.midH8; if (Carry) W = incsz(a32.midH8); INDF += W; FSR++; // 4 W = a32.high8; if (Carry) W = incsz(a32.high8); INDF += W; } } // else !Carry FSR = p; // 4 #asm rrf INDF,F decf FSR,f ; 3 rrf INDF,F decf FSR,f ; 2 rrf INDF,F decf FSR,f ; 1 rrf INDF,F decf FSR,f ; 0 rrf INDF,F incf FSR,f ; 1 #endasm } while (--ix); } } // 55 instructions, min:15, max:??? cycles /*======================================================================*/ void mpy16x16 (void) // r32 = a16 * b16 /*======================================================================*/ { uns8 ix; // temporary if (!b16) { r32.high16 = 0; r32.low16 = 0; } else { r32.high16 = a16; r32.midL8 = b16.high8; r32.low8 = b16.low8 ^ 1; ix = 16; do { Carry = 0; if (r32.0) { r32.midH8 += a16.low8; W = b16.high8; if (Carry) W = incsz(a16.high8); r32.high8 += W; } r32.high8 = rr(r32.high8); r32.midH8 = rr(r32.midH8); r32.midL8 = rr(r32.midL8); r32.low8 = rr(r32.low8); } while (--ix); } } // 36 instructions, min:15, max:271 cycles /*======================================================================*/ void mpy16x16a (void) // r32 = a16 * b16 /*======================================================================*/ { uns8 ix; // temporary r32.high16 = 0; r32.low16 = 0; if (b16) { r32.low16 = b16; ix = 16; do { W = rr(r32.low8); if (Carry) { r32.midH8 += a16.low8; W = b16.high8; if (Carry) W = incsz(a16.high8); r32.high8 += W; } r32.high8 = rr(r32.high8); r32.midH8 = rr(r32.midH8); r32.midL8 = rr(r32.midL8); r32.low8 = rr(r32.low8); } while (--ix); } } // 30 instructions, min:14, max:274 cycles /*======================================================================*/ void mpy24x16 (void) // r40 = a24 * b16 /*======================================================================*/ { uns8 ix; // temporary if (!b16) { r40[4] = 0; r40[3] = 0; r40[2] = 0; r40[1] = 0; r40[0] = 0; } else { r40[0] = a24.high8; r40[1] = a24.midL8; r40[2] = a24.low8; r40[3] = b16.high8; r40[4] = b16.low8 ^ 1; ix = 16; do { Carry = 0; { if (r40[4].0) { r40[2] += a24.low8; W = a24.midL8; if (Carry) W = incsz(a24.midL8); r40[1] += W; W = a24.high8; if (Carry) W = incsz(a24.high8); r40[0] += W; } } #asm rrf r40+0,F ; r40[0] = rr(r40[0]); rrf r40+1,F ; r40[1] = rr(r40[1]); rrf r40+2,F ; r40[2] = rr(r40[2]); rrf r40+3,F ; r40[3] = rr(r40[3]); rrf r40+4,F ; r40[4] = rr(r40[4]); #endasm } while (--ix); } } // 44 instructions, min:16, max:349 cycles /*======================================================================*/ void mpy24x16a (void) // r40 = a24 * b16 /*======================================================================*/ { uns8 ix; // temporary r40[4] = 0; r40[3] = 0; r40[2] = 0; r40[1] = 0; r40[0] = 0; if (b16) { r40[3] = b16.high8; r40[4] = b16.low8 ^ 1; ix = 16; do { Carry = 0; { if (r40[4].0) { r40[2] += a24.low8; W = a24.midL8; if (Carry) W = incsz(a24.midL8); r40[1] += W; W = a24.high8; if (Carry) W = incsz(a24.high8); r40[0] += W; } } #asm rrf r40+0,F ; r40[0] = rr(r40[0]); rrf r40+1,F ; r40[1] = rr(r40[1]); rrf r40+2,F ; r40[2] = rr(r40[2]); rrf r40+3,F ; r40[3] = rr(r40[3]); rrf r40+4,F ; r40[4] = rr(r40[4]); #endasm } while (--ix); } } // ?? instructions, min:15, max:347 cycles /*======================================================================*/ void mpy32x16 (void) // r48 = a32 * b16 /*======================================================================*/ { uns8 ix; if (!b16) { r48[0] = 0; r48[1] = 0; r48[2] = 0; r48[3] = 0; r48[4] = 0; r48[5] = 0; } else { r48[0] = a32.high8; r48[1] = a32.midH8; r48[2] = a32.midL8; r48[3] = a32.low8; r48[4] = b16.high8; r48[5] = b16.low8 ^ 1; ix = 16; do { Carry = 0; { if (r48[5].0) { r48[3] += a32.low8; W = a32.midL8; if (Carry) W = incsz(a32.midL8); r48[2] += W; W = a32.midH8; if (Carry) W = incsz(a32.midH8); r48[1] += W; W = a32.high8; if (Carry) W = incsz(a32.high8); r48[0] += W; } } #asm rrf r48+0,F ; r48[0] = rr(r48[0]); rrf r48+1,F ; r48[1] = rr(r48[1]); rrf r48+2,F ; r48[2] = rr(r48[2]); rrf r48+3,F ; r48[3] = rr(r48[3]); rrf r48+4,F ; r48[4] = rr(r48[4]); rrf r48+5,F ; r48[5] = rr(r48[5]); #endasm } while (--ix); } } // 52 instructions, min:17, max:427 cycles /*======================================================================*/ void mpy32x16a (void) // r48 = a32 * b16 /*======================================================================*/ { uns8 ix; r48[0] = 0; r48[1] = 0; r48[2] = 0; r48[3] = 0; r48[4] = 0; r48[5] = 0; if (b16) { r48[4] = b16.high8; r48[5] = b16.low8; ix = 16; do { Carry = 0; { if (r48[5].0) { r48[3] += a32.low8; W = a32.midL8; if (Carry) W = incsz(a32.midL8); r48[2] += W; W = a32.midH8; if (Carry) W = incsz(a32.midH8); r48[1] += W; W = a32.high8; if (Carry) W = incsz(a32.high8); r48[0] += W; } } #asm rrf r48+0,F ; r48[0] = rr(r48[0]); rrf r48+1,F ; r48[1] = rr(r48[1]); rrf r48+2,F ; r48[2] = rr(r48[2]); rrf r48+3,F ; r48[3] = rr(r48[3]); rrf r48+4,F ; r48[4] = rr(r48[4]); rrf r48+5,F ; r48[5] = rr(r48[5]); #endasm } while (--ix); } } // 42 instructions, min:16, max:436 cycles /*======================================================================*/ void mpy32x32 (void) // r64 = a32 * b32 /*======================================================================*/ { uns8 ix; W = b32.high8 | b32.midH8; W = b32.midL8 | W; W = b32.low8 | W; if (Zero_) { r64[0] = 0; r64[1] = 0; r64[2] = 0; r64[3] = 0; r64[4] = 0; r64[5] = 0; r64[6] = 0; r64[7] = 0; } else { r64[0] = a32.high8; r64[1] = a32.midH8; r64[2] = a32.midL8; r64[3] = a32.low8; r64[4] = b32.high8; r64[5] = b32.midH8; r64[6] = b32.midL8; r64[7] = b32.low8 ^ 1; ix = 32; do { Carry = 0; { if (r64[7].0) { r64[3] += a32.low8; W = a32.midL8; if (Carry) W = incsz(a32.midL8); r64[2] += W; W = a32.midH8; if (Carry) W = incsz(a32.midH8); r64[1] += W; W = a32.high8; if (Carry) W = incsz(a32.high8); r64[0] += W; } } #asm rrf r64+0,F // r64[0] = rr(r64[0]); rrf r64+1,F // r64[1] = rr(r64[1]); rrf r64+2,F // r64[2] = rr(r64[2]); rrf r64+3,F // r64[3] = rr(r64[3]); rrf r64+4,F // r64[4] = rr(r64[4]); rrf r64+5,F // r64[5] = rr(r64[5]); rrf r64+6,F // r64[6] = rr(r64[6]); rrf r64+7,F // r64[7] = rr(r64[7]); #endasm } while (--ix); } } // 62 instructions, min:21, max:913 cycles /*======================================================================*/ void mpy32x32a (void) // r64 = a32 * b32 /*======================================================================*/ { uns8 ix; r64[0] = 0; r64[1] = 0; r64[2] = 0; r64[3] = 0; r64[4] = 0; r64[5] = 0; r64[6] = 0; r64[7] = 0; W = b32.high8 | b32.midH8; W = b32.midL8 | W; W = b32.low8 | W; if (!Zero_) { r64[4] = b32.high8; r64[5] = b32.midH8; r64[6] = b32.midL8; r64[7] = b32.low8; ix = 32; do { Carry = 0; { if (r64[7].0) { r64[3] += a32.low8; W = a32.midL8; if (Carry) W = incsz(a32.midL8); r64[2] += W; W = a32.midH8; if (Carry) W = incsz(a32.midH8); r64[1] += W; W = a32.high8; if (Carry) W = incsz(a32.high8); r64[0] += W; } } #asm rrf r64+0,F // r64[0] = rr(r64[0]); rrf r64+1,F // r64[1] = rr(r64[1]); rrf r64+2,F // r64[2] = rr(r64[2]); rrf r64+3,F // r64[3] = rr(r64[3]); rrf r64+4,F // r64[4] = rr(r64[4]); rrf r64+5,F // r64[5] = rr(r64[5]); rrf r64+6,F // r64[6] = rr(r64[6]); rrf r64+7,F // r64[7] = rr(r64[7]); #endasm } while (--ix); } } // 52 instructions, min:20, max:924 cycles /*======================================================================*/ void div16x8 (void) // q8,r8 = a16 / b8 /*======================================================================*/ { char ix, oldCy; ZeroDiv = 1; W = b8; if (!Zero_) { Overflow = 1; // assume error if (a16.high8