This work is based on SX Microcontroller Comparison Math Methods - Compare values from the SXList routine library.
;KeyMacs.src by James Newton 2000.08.03 @ 14:26:34 ;Structured programming macros for the SXKey ;Implements: ; Compairison enum (IsZero,Eq,Lt,LE,IsNotZero,NE,Gt,GE) ; SkipIf Conditions ; Condition1 item, Compairison ; Condition2 item1, Compairison, item2 ; Repeat <statements> [forever, while Condition, until Condition] ; DoIf Condition <statements> [DoElse <statements>] DoEndIf ; ;See lable "Main" for start of examples RESET MAIN CpuCarry = 0 IF CpuCarry = 1 DEVICE CARRYX ENDIF org 10 StackPtr ds 1 IntI ds 1 IntJ ds 1 errat ds 1 watch StackPtr,8,UHEX watch IntI,8,UHEX watch IntJ,8,UHEX ConditionBase equ $ABCDEF0 ;to make it more likely that these are unique IsZero equ ConditionBase + 0 Eq equ ConditionBase + 1 Lt equ ConditionBase + 2 LE equ ConditionBase + 3 IsNotZero equ ConditionBase + 8 Ne equ ConditionBase + 9 Gt equ ConditionBase + 10 Ge equ ConditionBase + 11 Const equ ConditionBase + 12 SkipWhile MACRO 2 noexpand IF \1>$0F expand bank \1 ;non-global noexpand ENDIF expand test \1 noexpand IF \2 = IsZero expand sz noexpand ELSE IF \2 = IsNotZero expand snz noexpand ELSE error 'Usage: SkipWhen register, [IsZero | IsNotZero]' ENDIF ENDIF ENDM SkipIf MACRO 3 noexpand IF \3 = WReg IF \1 = WReg error 'can not compare w with w' ELSE error 'code as SkipIf w, <cond>, <value>' ENDIF ENDIF IF \3 >= Const ;compareing a register with a constant IF \2 = eq or \2 = ne or \2 = ge or \2 = lt expand mov w,#(\3-Const)-1 noexpand ELSE mov w,#\3-Const ENDIF IF \1>$0F expand bank \1 ;non-global noexpand ENDIF IF CpuCarry=1 expand clc ;carryx,clear carry noexpand ENDIF expand mov w,\1-w ;subtract noexpand IF \2 = eq or \2 = ne IF \2 = eq expand snz noexpand ELSE expand sz noexpand ENDIF ELSE IF \2 = lt or \2 = le expand sc noexpand ELSE expand snc noexpand ENDIF ENDIF ELSE ;compaireing a register with a register IF \2 = gt or \2 = le expand tst = \2^8 SkipIf \3, \2^8, \1 ELSE IF \1>$0F expand bank \1 ;non-global noexpand ENDIF IF \1 <> WReg expand mov w,\1;load w noexpand ENDIF IF \3 > 15 AND \1/$10 <> \3/$10 expand bank \3 ;non-global,new bank noexpand ENDIF IF CpuCarry=1 expand clc ;carryx,clear carry noexpand ENDIF expand mov w,\3-w ;subtract noexpand IF \2 = eq or \2 = ne IF \2 = eq expand sz noexpand ELSE expand snz noexpand ENDIF ELSE IF \2 = lt expand sc noexpand ELSE expand snc noexpand ENDIF ENDIF ENDIF ENDIF ENDM Repeat MACRO noexpand ;incase expand was already on. expand RepeatLabel = $ noexpand ENDM Until MACRO noexpand IF \0 = 2 SkipWhile \1,\2 ELSE SkipIf \1,\2,\3 ENDIF expand jmp @RepeatLabel noexpand ENDM While MACRO noexpand IF \0 = 2 SkipWhile \1,\2^8 ;the ^8 toggles to negative logic. sz to snz, snz to sz, etc... ELSE SkipIf \1,\2^8,\3 ;the ^8 toggles to negative logic. sz to snz, snz to sz, etc... ENDIF expand jmp @RepeatLabel noexpand ENDM Forever MACRO noexpand ;incase expand was already on. expand jmp @RepeatLabel noexpand ENDM doifl = 0 doif MACRO noexpand doifl = doifl + 1 IF doifl > 1 error 'nested conditions not support by doif macro' ENDIF IF \0 = 2 SkipWhile \1,\2^8 ;the ^8 toggles to negative logic. sz to snz, snz to sz, etc... ELSE SkipIf \1,\2^8,\3 ;the ^8 toggles to negative logic. sz to snz, snz to sz, etc... ENDIF expand doifadr = $ ;save space here for a jmp noexpand ;figure out where the jmp will be from org $+2 ; and leave space for it ENDM DoElse MACRO noexpand IF doifl <> 1 error 'DoElse outside of DoIf/DoEndIf block' ENDIF ;remember where we were, ;go back to where the jmp needs to be ;jmp to where we were ;go back to where we were expand doendifadr = $ org doifadr ; go back jmp @doendifadr; do the jmp org doendifadr ; come forward doifadr = $ ;save space here for a jmp noexpand ;figure out where the jmp will be from org $+2 ; and leave space for it ENDM DoElseIf MACRO noexpand IF doifl <> 1 error 'DoElseIf outside of DoIf/DoEndIf block' ENDIF ;remember where we were, ;go back to where the jmp needs to be ;jmp to where we were ;go back to where we were expand doendifadr = $ org doifadr ; go back jmp @doendifadr; do the jmp org doendifadr ; come forward noexpand IF \0 = 2 SkipWhile \1,\2^8 ;the ^8 toggles to negative logic. sz to snz, snz to sz, etc... ELSE SkipIf \1,\2^8,\3 ;the ^8 toggles to negative logic. sz to snz, snz to sz, etc... ENDIF expand doifadr = $ ;save space here for a jmp noexpand ;figure out where the jmp will be from org $+2 ; and leave space for it ENDM DoEndIf MACRO noexpand doifl = doifl - 1 ;remember where we were, ;go back to where the jmp needs to be ;jmp to where we were ;go back to where we were expand doendifadr = $ org doifadr ; go back jmp @doendifadr; do the jmp org doendifadr ; come forward noexpand ENDM Push MACRO 1 noexpand expand inc StackPtr ;could use incsz rather than inc to avoid modifying Z noexpand IF \1=Wreg expand mov fsr, \1 ;fsr could be anything (due to bank etc..) so use for parm mov w, StackPtr ;get the StackPtr into w xor fsr, w ;swap w with fsr xor w, fsr xor fsr, w mov ind, w ;store w to Top Of Stack. noexpand ELSE expand mov fsr, StackPtr ;W used mov ind, \1 noexpand ENDIF ENDM Pop MACRO 1 noexpand expand mov fsr, StackPtr ;fsr could be anything (due to bank etc..) so reload it via W dec StackPtr ;point to valid data at new Top Of Stack mov \1, ind ;load Parm from Old Top Of Stack noexpand ENDM org 100 Main clr IntI :zeroloop test IntI jnz :notzero :zero mov errat,#$ SkipWhile IntI,IsZero jmp :bogus mov errat,#$ SkipWhile IntI,IsNotZero skip jmp :bogus djnz IntI, :zeroloop jmp :done :notzero mov errat,#$ SkipWhile IntI,IsZero skip jmp :bogus mov errat,#$ SkipWhile IntI,IsNotZero jmp :bogus djnz intI,:zeroloop :done clr IntI :outsideloop clr IntJ :insideloop mov w, IntI mov w, IntJ-w snc jmp :ILTJOut :ILTJ ;yess mov errat,#$ SkipIf IntI,NE,IntJ jmp :bogus mov errat,#$ SkipIf IntI,Lt,IntJ jmp :bogus mov errat,#$ SkipIf IntI,LE,IntJ jmp :bogus ;nos mov errat,#$ SkipIf IntI,Eq,IntJ skip jmp :bogus mov errat,#$ SkipIf IntI,Gt,IntJ skip jmp :bogus mov errat,#$ SkipIf IntI,GE,IntJ skip jmp :bogus :ILTJOut mov w, IntJ mov w, IntI-w sz jmp :IEQJOut ;IEQJ ;yess mov errat,#$ SkipIf IntI,Eq,IntJ jmp :bogus mov errat,#$ SkipIf IntI,LE,IntJ jmp :bogus mov errat,#$ SkipIf IntI,GE,IntJ jmp :bogus ;nos mov errat,#$ SkipIf IntI,NE,IntJ skip jmp :bogus mov errat,#$ SkipIf IntI,Lt,IntJ skip jmp :bogus mov errat,#$ SkipIf IntI,Gt,IntJ skip jmp :bogus :IEQJOut mov w, IntI mov w, IntJ-w sc jmp :IGTJOut :IGTJ ;yess mov errat,#$ SkipIf IntI,NE,IntJ jmp :bogus mov errat,#$ SkipIf IntI,Gt,IntJ jmp :bogus mov errat,#$ SkipIf IntI,GE,IntJ jmp :bogus ;nos mov errat,#$ SkipIf IntI,Eq,IntJ skip jmp :bogus mov errat,#$ SkipIf IntI,Lt,IntJ skip jmp :bogus mov errat,#$ SkipIf IntI,LE,IntJ skip jmp :bogus :IGTJOut djnz IntJ,:insideloop djnz IntI,:outsideloop DoIf 1,eq,0 ;1=WReg or RTCC. RTCC is only going to get used in ISRs so just assume its W clr 1 doendif clr 2 doif 2,eq,0 ;Bank 0 registers so no bank but do load W. clr 3 doendif clr 4 doif 5,IsZero clr 6 doendif clr 7 repeat clr 8 until 9,IsNotZero repeat clr 10 while 11,IsZero repeat clr 12 forever doif 16,eq,17 ;two registers in same (non zero) bank. One bank needed. clr 18 doendif clr 19 doif 20,eq,$30 ;two registers in two different banks. clr 21 doendif clr 22 doif 23,eq,24 clr 25 doelseif 26,lt,27 doelse clr 28 doendif clr 29 push WReg push 30 pop 31 pop PC doif 32,lt,33+const clr 34 doelseif 35,gt,36+const clr 37 doendif clr errat :bogus break