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