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