### 8x8 Multiply (shift and ADD) Subroutine

You can find many 8x8 multiply methods (for example, see piclist math methods), however implementation is typically 'left up to the user' :-). Generating 'optimum' code depends on your goal, either max. speed or minimum code space. My 'new PIC 33 instruction set (macros)' (above) contains a MUL macro that implements a 'maximum speed' approach, so this subroutine is aimed at 'minimum code space' approach (i.e. it takes longer because it loops). Method The basic 'shift and add' method uses one value to control the add of the second into the 'top' result, after which the result is shifted down 1 bit (so any Cy from the ADD is shifted into the msb) and the next control bit is checked. The sequence always ends on a final shift. The subroutine will multiply 2 8bit values, passed in a register pair. To save on register space, the same register pair will be used to hold the (16bit) result. To control the loop, rTemp is used = DECFSZ is the fastest possible way to control a loop as it's a single instruction to 'Decrement and skip if zero', however it must be combined with 'Jump loop' i.e. be positioned at the end of the loop. Start by setting up the loop, then copy mRegHi to Acc, which frees the register for reuse To start the loop, shift mRegLo to get lsb into Cy Do the ADD (if Cy) Shift the result (puts next lsb into Cy) Dec the loop coutn and loop if nonZero Return with 16 bit result. Note that the final bit shifted out of mRegLo is ignored == so we don't care what's shifted in at the start ``` ; MULTIPLY ;Unsigned multiply subroutine ; Called with the multiplier (control) in mRegLo, multiplicand (ADDed) in mRegHi ; Returns with result mRegHi,mRegLo. ; Acc and rTemp (count) are used LOAD 0x0F ;loop count COPY Acc,rTemp ;set count COPY mRegHi,Acc ;get Hi to Acc CLR mRegHi ;clear for reuse RRF mRegLo,1 ;lsb b0 to Cy (don't care what's shifted in as it will be discarded at end) mLoop ;arrive here with Cy set for ADD (loop is 8*7 = 56 CLK's) Skip nCy ;skip no carry ADDWF mRegHi,1 ;Cy, add (Acc) to msb, may set new Cy RRF mRegHi,1 ; nCy (skip add) or cy from add to b15 RRF mRegLo,1 ; .. b7 is msb b0, b0 to Cy (last shift is discarded) DECFSZ rTemp ;dec count (no effect on Cy) JMP mLoop ;nZ, keep looping (no effect on Cy) RETURN ;Z=exit, all done ``` Total 12 instructions, 5+ 56 +2(return) = 63 CLK cycles (compared to MUL macro which is 33/35 CLK's (Acc not saved/saved)). At the cost of a few extra instructions, multiply can be 'short circuited' with tests for 0 (and/or 1), however this adds overhead to ALL multiplies so is only 'worth it' if your application is likley to result in many *0 or *1 cases