> From: "Jason A. Farque'" > > All, > [cut] > > My questions are how bad is the following macro, and is there a > "better", more traditional way? Secondarily, is there a source of > such knowledge on the Internet? I've read the FAQ, but it's weak in > regard to code samples (probably owing to the different instruction > sets among the parts). > > ; ================================================================== > ; A macro to compare two unsigned 16 bit integers held in the 16C84's > ; RAM space. > ; Result returned in W: > ; W = 0 indicates that (VALUE1 = VALUE2) > ; W = 1 indicates that (VALUE1 > VALUE2) > ; W = 2 indicates that (VALUE1 < VALUE2) > ; Total of 11 instructions. > > CMP16 MACRO VALUE1,VALUE2 ; Offset RAM addresses, LSBs in > ; VALUEn, MSBs in VALUEn+1 > > MOVF VALUE2+1,W ; Drag MSB of VALUE2 into W > SUBWF VALUE1+1,W ; Subtract MSB of VALUE2 from MSB > ; of VALUE1, result in W > BTFSS STATUS,Z ; If zero, the MSBs are equal so > ; we must compare the LSB pair, > GOTO CMP16FINISH ; otherwise the compare failed > ; on their MSBs > CONT16CMP: MOVF VALUE2,W ; Drag LSB of VALUE2 into W > SUBWF VALUE1,W ; Subtract LSB of VALUE2 from LSB > ; of VALUE1, result in W > BTFSC STATUS,Z ; If zero, then VALUE1 = VALUE2 > ; which has the "side effect" of > ; leaving W = 0 > GOTO CMP16EXIT ; so we exit with W = 0 meaning > ; that VALUE1 = VALUE 2 > CMP16FINISH: MOVLW 02H ; W = 2 means that VALUE1 < VALUE2 > BTFSC STATUS,C ; Test the carry flag > MOVLW 01H ; W = 1 means that VALUE1 > VALUE2 > CMP16EXIT: > ENDM > ; ================================================================== > > [cut] > Jason A. Farque' > CDI - Worldwide Suppliers of Pipeline Pig Location & Tracking Equipment. > Tulsa, Oklahoma, USA > I wouldn't bother putting the 'result' in W, since this forces your code to do yet more tests on W to determine what to do. Normally, this sort of macro will just leave the status bits Z and C set to indicate the result, so the following code can be: btfsc status,Z goto equal btfsc status,C goto less goto greater Also, the macro could be provided with an extra three labels which the macro will automatically branch to depending on the result. This allows the generated code to be faster; and optimisations are possible: cmp16 macro value1,value2,equal,less,greater movf value2+1,w subwf value1+1,w btfsc status,Z goto notequal btfsc status,C goto less goto greater notequal movf value2,w subwf value1,w btfsc status,Z goto equal btfsc status,C goto less goto greater endm This is fully general i.e. doesn't take into account the optimisations possible if, say, two of the labels are the same address. Also, it places a final, redundant, goto in the case that the following code path is the path for 'greater'. Of course, this would require use of more sophisticated macro facilities. Any labels in the macro (e.g. notequal) need to be replaced with uniquely generated symbols so the macro can be invoked more than once! I must admit that I am more familiar with the IBM S/370 macro assembler than the Microchip one. Here's a challenge: write a complete set of macros for 16-bit operations where each 16-bit value is stored in two consecutive file registers (in the same bank). Preferably, the MSB/LSB order should be specified via a global macro symbol. The macros should be optimised for speed. Where applicable, one should be able to specify branch labels, with a special symbol indicating 'following code'. Here is a useful starting set: uadd r1,r2[,carry,nocarry] Unsigned add r1+r2->r1 uadc r1,r2[,carry,nocarry] Unsigned add with carry in status.C+r1+r2->r1 usub r1,r2[,borrow,noborrow] Unsigned subtract r1-r2->r1 usbc r1,r2[,borrow,noborrow] Unsigned subtract with borrow in r1-r2-~C->r1 ucmp r1,r2[,equal,less,greater] Unsigned compare r1-r2 ladd r1,r2[,overflow,nooverflow] Signed add r1+r2->r1 lsub r1,r2[,overflow,nooverflow] Signed subtract r1-r2->r1 lcmp r1,r2[,equal,less,greater] Signed compare r1-r2 lneg r1[,overflow,nooverflow] Signed negation -r1->r1 ucpl r1 1's complement ~r1->r1 lshl r1 Signed shift left r1>>1->r1 ushl r1 Unsigned shift left ushr r1 Shift right Parameters other than r1,r2 are labels which are branched to under the specified condition. In the case of comparisons, if no labels are specified, then the status codes should be set and no further action taken. The above set could be extended by allowing an explicit destination register i.e. not only r1; allowing use of INDF in place of r2 (or r1 for those without r2). If someone did this (for fame, not fortune) then they would earn the eternal gratitude of PIC programmers who daily twist their minds in knots trying to remember the sense in which the status.C bit is set after subtract! Regards, SJH Canberra, Australia