Nick Jensons macros

(a work in progress for the Ubicom IP2k macro assembler)

See also:

Nick Says:

As is, you only get 40 forward labels per assembly. But that could be increased with a bit of cut and paste..
Conditionals are much like yours
   var GE var/val
         GT
         ..

No need for distinguishing constants in the comparison operations

I also added:

    if  flag ZZ
        flag NZ
        flag CC
        flag NC

that generates snz, snc, sz, sc tests

and

  if  Reg WRegEQ
      Reg  WRegNE

that just does a csne / cse generation

and

  if var IsZero
      var IsNotZero

generates a test \var construct

Note the first parameter isn't looked at in the above three constructs. The string "flag" and "Reg" could be anything. I do this because vars can be specified as Offset(DP) or Offset(SP) and the macro processor will puke if is asked to examine a parameter with a parenthesis in it! So if you tried to test for "w" or "Wreg" in the first parameter, the macro would break when you used it with "temp(DP)". The substitution works ok though so I just always use the comparison literal for making the conditional format choice.

The LOOP construct was done before I figured out the labels so it doesn't use the same method as the While, Repeat, IF, For .. Since the IP is so efficient with the Stack loading and usage, the LOOP construct is very useful.

Notice that my Until works with the Repeat. The While ends with endwhile. I didn't need to use "doif" as "if" isn't recognized as a keyword.

I've been thinking about how to do more complex conditionals. Haven't got the answer yet. How about you?? How would you implement something that allowed piecewise compounded AND's & OR's. Obviously AND's can be nested IF's but I suspect we could come with some kind of macros that could be sequenced to provide more complex conditionals. But I need to learn how to start using the darn things.

Love the IP part. Damn expensive development kit but the part is choice. Documentation is poor -- but who am I to complain. Support has not understood a couple of my Bug reports and just blew me off! But the bleeding edge is always this way...

Love your site. An amazing warehouse of very valuable information!

Thank you, Sir Newton.

Nick

;
;
;   Macro idle
;

.macro idle cyc
.set temp,\cyc
.if temp==11
 nop
 nop
 jmp .+2
 jmp .+2
 jmp .+2
.set temp,0
.endif

.if temp==10
 nop
 jmp .+2
 jmp .+2
 jmp .+2
.set temp,0
.endif
.if temp==9
 jmp .+2
 jmp .+2
 jmp .+2
.set temp,0
.endif
.if temp == 4
 nop
 jmp .+2
.set temp,0
.endif
.if temp == 5
 nop
 nop
 jmp .+2
.set temp,0
.endif
.if temp==6
 jmp .+2
 jmp .+2
.set temp,0
.endif
.if temp == 7
 nop
 jmp .+2
 jmp .+2
.set temp,0
.endif

.set fours,temp / 4
.set left,(temp && 0b11)
.if left== 1
 nop
.endif
.if left == 2
 nop
 nop
.endif
.if left == 3
 jmp .+2
.endif
.if left == 4
 nop
 jmp .+2
.endif
.if fours
 push #fours
 decsz 1(SP)
   jmp .-1
 inc SPL
.endif

.endm

.macro stc  ; Set Carry
 setb STATUS,C
.endm
.macro clc  ; Clear Carry
 clrb STATUS,C
.endm

.macro  cwje val,label
 csne w,\val
 jmp \label
.endm

.macro  cwjne val,label
 cse w,\val
 jmp \label
.endm

.macro cje var,val,label
 mov w,\var
 csne w,\val
 jmp \label
.endm

.macro cjne var,val,label
 mov w,\var
 cse w,\val
 jmp \label
.endm

.macro  cjb var,val,label
 mov w,\val
 cmp w,\var ;sub
 sc
 jmp \label
.endm

.macro  cjbe var,val,label
 mov w,\var
 cmp w,\val ;sub var-val
 snc
 jmp \label
.endm

.macro cja var,val,label
 mov w,\var
 cmp w,\val
 sc
 jmp \label
.endm

.macro cjae var,val,label
 mov w,\val
 cmp w,\var
 snc
 jmp \label
.endm

.macro  movSP dst,src
 push \src
 pop \dst
.endm

.macro subw dst,src
 mov w,\src
 sub \dst,w
.endm

.macro djnz var,label
 decsz \var
 jmp \label
.endm

.macro djz var,label
 decsnz \var
 jmp \label
.endm

.macro ijnz var,label
 incsz \var
 jmp \label
.endm

.macro ijz var,label
 incsnz \var
 jmp \label
.endm

.macro  csae var,val
 mov w,\val
 cmp w,\var
 sc
.endm

.macro  jb var,bit,label
 snb \var,\bit
 jmp \label
.endm

.macro jnb var,bit,label
 sb \var,\bit
 jmp \label
.endm

.macro DisableInt
 clrb XCFG,7
.endm
.macro EnableInt
 setb XCFG,7
.endm

.macro loadDP addr
 loadh \addr
 loadl \addr
.endm

.macro loadIP addr
 push #%lo8data(\addr)
 pop IPL
 push #%hi8data(\addr)
 pop IPH
.endm

.macro loadPRAMaddr addr
 clr ADDRX
 inc ADDRX
 mov w,#%hi8inst(\addr)
 mov ADDRH,w
 mov w,#%lo8inst(\addr)
 mov ADDRL
.endm

.macro pushPRAMaddr addr
 push #%lo8data(\addr)
 push #%hi8data(\addr)
.endm

.macro push16BitCnt cnt
 push #(\cnt >> 8)
 push #(\cnt & 0xFF)
.endm

.macro loop cnt
 push \cnt
.ifndef loopcnt
.set loopcnt,0
.endif
.set loopcnt,loopcnt+1
.if loopcnt==1
.set retaddr1,.
.endif
.if loopcnt==2
.set retaddr2,.
.endif
.if loopcnt==3
.set retaddr3,.
.endif
.endm

.macro endloop
.if loopcnt==1
 djnz 1(SP),.-(.-retaddr1)
.endif
.if loopcnt==2
 djnz 1(SP),.-(.-retaddr2)
.endif
.if loopcnt==3
 djnz 1(SP),.-(.-retaddr3)
.endif
 inc SPL ;release temp counter...
.set loopcnt,loopcnt-1
.endm

;
;  Structured Programming Macros
; if ifelse else endif
; while endwhile
; repeat until
; for var, init, last endfor
;
;  Derived from James Newton's Macros at SXLIST.COM
;

.set IsZero, 1
.set IsNotZero, 2
.set EQ,  3
.set NE,  4
.set LT,  5
.set GE, 6
.set LE,  7
.set GT, 8
.set WRegEQ, 9
.set WRegNE, 10
.set ZZ, 11
.set NZ, 12
.set CC, 13
.set NC, 14
.set tst,0

.macro Reverse
.set ntst,0
.if (tst==GT)
.set ntst,LE
.elseif (tst==LE)
.set ntst,GT
.elseif (tst==GE)
.set ntst,LT
.elseif (tst==LT)
.set ntst,GE
.elseif (tst==EQ)
.set ntst,NE
.elseif (tst==NE)
.set ntst,EQ
.elseif (tst==WRegEQ)
.set ntst,WRegNE
.elseif (tst==WRegNE)
.set ntst,WRegEQ
.elseif (tst==ZZ)
.set ntst,NZ
.elseif (tst==NZ)
.set ntst,ZZ
.elseif (tst==CC)
.set ntst,NC
.elseif (tst==NC)
.set ntst,CC
.elseif (tst==IsZero)
.set ntst,IsNotZero
.elseif (tst==IsNotZero)
.set ntst,IsZero
.endif
.set tst,ntst
.endm


.macro Condition var,val
.if (tst==EQ)
 mov w,\var
 csne w,\val
.elseif (tst==NE)
 mov w,\var
 cse w,\val
.elseif (tst==LT)
 mov w,\val
 cmp w,\var ;sub
 sc
.elseif (tst==LE)
 mov w,\var
 cmp w,\val ;sub var-val
 snc
.elseif (tst==GT)
 mov w,\var
 cmp w,\val
 sc
.elseif (tst==GE)
 mov w,\val
 cmp w,\var
 snc
.elseif (tst==WRegEQ)
 csne w,\val
.elseif (tst==WRegNE)
 cse w,\val
.elseif (tst==ZZ)
 snz
.elseif (tst==NZ)
 sz
.elseif (tst==CC)
 snc
.elseif (tst==NC)
 sc
.elseif (tst==IsZero)
 test \var
 snz
.elseif (tst==IsNotZero)
 test \var
 sz
.endif

.endm


doifadr = 0
doendifadr = 0
doifl = 0

.set Label7,0
.set Label6,0
.set Label5,0
.set Label4,0
.set Label3,0
.set Label2,0
.set Label1,1

.set LabelCnt,0

.macro PushLabel
.set Label7,Label6
.set Label6,Label5
.set Label5,Label4
.set Label4,Label3
.set Label3,Label2
.set Label2,Label1
 .ENDM

.MACRO PopLabel
.set Label1,Label2
.set Label2,Label3
.set Label3,Label4
.set Label4,Label5
.set Label5,Label6
.set Label6,Label7
.set Label7,99
 .ENDM

.macro PlantLabel
.if (Label1 == 1)
do1:
.elseif (Label1 == 2)
do2:
.elseif (Label1 == 3)
do3:
.elseif (Label1 == 4)
do4:
.elseif (Label1 == 5)
do5:
.elseif (Label1 == 6)
do6:
.elseif (Label1 == 7)
do7:
.elseif (Label1 == 8)
do8:
.elseif (Label1 == 9)
do9:
.elseif (Label1 == 10)
do10:
.elseif (Label1 == 11)
do11:
.elseif (Label1 == 12)
do12:
.elseif (Label1 == 13)
do13:
.elseif (Label1 == 14)
do14:
.elseif (Label1 == 15)
do15:
.elseif (Label1 == 16)
do16:
.elseif (Label1 == 17)
do17:
.elseif (Label1 == 18)
do18:
.elseif (Label1 == 19)
do19:
.elseif (Label1 == 20)
do20:
.elseif (Label1 == 21)
do21:
.elseif (Label1 == 22)
do22:
.elseif (Label1 == 23)
do23:
.elseif (Label1 == 24)
do24:
.elseif (Label1 == 25)
do25:
.elseif (Label1 == 26)
do26:
.elseif (Label1 == 27)
do27:
.elseif (Label1 == 28)
do28:
.elseif (Label1 == 29)
do29:
.elseif (Label1 == 30)
do30:
.elseif (Label1 == 31)
do31:
.elseif (Label1 == 32)
do32:
.elseif (Label1 == 33)
do33:
.elseif (Label1 == 34)
do34:
.elseif (Label1 == 35)
do35:
.elseif (Label1 == 36)
do36:
.elseif (Label1 == 37)
do37:
.elseif (Label1 == 38)
do38:
.elseif (Label1 == 39)
do39:
.elseif (Label1 == 40)
do40:
.endif

.endm

.macro NewLabel
.set LabelCnt,LabelCnt+1
.set Label1,LabelCnt
.if (LabelCnt>39)
  .err 99
.endif
.endm

.macro PlantJmp
.if (Label1 == 1)
 jmp do1
.elseif (Label1 == 2)
 jmp do2
.elseif (Label1 == 3)
 jmp do3
.elseif (Label1 == 4)
 jmp do4
.elseif (Label1 == 5)
 jmp do5
.elseif (Label1 == 6)
 jmp do6
.elseif (Label1 == 7)
 jmp do7
.elseif (Label1 == 8)
 jmp do8
.elseif (Label1 == 9)
 jmp do9
.elseif (Label1 == 10)
 jmp do10
.elseif (Label1 == 11)
 jmp do11
.elseif (Label1 == 12)
 jmp do12
.elseif (Label1 == 13)
 jmp do13
.elseif (Label1 == 14)
 jmp do14
.elseif (Label1 == 15)
 jmp do15
.elseif (Label1 == 16)
 jmp do16
.elseif (Label1 == 17)
 jmp do17
.elseif (Label1 == 18)
 jmp do18
.elseif (Label1 == 19)
 jmp do19
.elseif (Label1 == 20)
 jmp do20
.elseif (Label1 == 21)
 jmp do21
.elseif (Label1 == 22)
 jmp do22
.elseif (Label1 == 23)
 jmp do23
.elseif (Label1 == 24)
 jmp do24
.elseif (Label1 == 25)
 jmp do25
.elseif (Label1 == 26)
 jmp do26
.elseif (Label1 == 27)
 jmp do27
.elseif (Label1 == 28)
 jmp do28
.elseif (Label1 == 29)
 jmp do29
.elseif (Label1 == 30)
 jmp do30
.elseif (Label1 == 31)
 jmp do31
.elseif (Label1 == 32)
 jmp do32
.elseif (Label1 == 33)
 jmp do33
.elseif (Label1 == 34)
 jmp do34
.elseif (Label1 == 35)
 jmp do35
.elseif (Label1 == 36)
 jmp do36
.elseif (Label1 == 37)
 jmp do37
.elseif (Label1 == 38)
 jmp do38
.elseif (Label1 == 39)
 jmp do39
.elseif (Label1 == 40)
 jmp do40
.endif
.endm

.MACRO Repeat
 Label1 = .
 PushLabel
 .ENDM

.MACRO Until var,cond,val
.set tst,\cond
 Reverse
 Condition \var,\val
 PopLabel
 jmp .-(.-Label1)
 .ENDM

.MACRO while p1,p2,p3
.set tst,\p2
.set Label1,.
 PushLabel ;Save Numeric Address of While Start
 reverse
 condition \p1,\p3
 NewLabel ;Make a Label for endwhile
 PushLabel
 PlantJmp
  .ENDM

.MACRO endwhile
 PopLabel ;Get Label for Beyond endwhile
.set SaveLabel,Label1
 PopLabel ;Get Address of WhileStart
 jmp .-(.-Label1) ;Jmp Back to numeric address
.set Label1,SaveLabel
 PlantLabel ;Label for Beyond endwhile
.endm

.MACRO if p1,p2,p3
 .set tst,\p2
  doifl = doifl + 1
 .IF (doifl > 4)
  .err 23;'Only 4 levels of nested conditions supported by doif macro'
  .ENDIF
 Reverse
 Condition \p1,\p3
 NewLabel ;Get Label for Cond NotTrue
 PushLabel
 PlantJmp
 NewLabel ;Get Label for EndIf
  PushLabel
  .ENDM

.MACRO Else
  .IF (doifl < 1)
   .err 24;'DoElse outside of DoIf/DoEndIf block'
   .ENDIF
     PopLabel  ;Get Label for Endif
.set SaveLabel,Label1
 PlantJmp  ;Plant Jmp to Endif
 PopLabel  ;Get Label for Prior Cond NotTure
 PlantLabel
.set Label1,SaveLabel
 PushLabel ;Again save the Label for EndIf
 .ENDM

.MACRO ElseIf p1,p2,p3
 .set tst,\p2
 .IF (doifl < 1)
  .err 25;'DoElseIf outside of DoIf/DoEndIf block'
  .ENDIF
     PopLabel ;Get Label for Endif
.set SaveLabel,Label1
 PlantJmp ;Plant Jmp to Endif
 PopLabel  ;Get Label for Prior Cond NotTure
 PlantLabel
 Reverse
 Condition \p1,\p3
 NewLabel
 PlantJmp ;Plant Jmp to ElseIF, Else or Endif
 PushLabel

.set Label1,SaveLabel
 PushLabel ;Again Save Label of Endif
 .ENDM

.MACRO EndIf
 .IF (doifl < 1)
  .err 26;'DoEndIf outside of DoIf/DoEndIf block'
 .ENDIF
 doifl = doifl - 1
  PopLabel ;Get Label of EndIf
 PlantLabel
 popLabel
 PlantLabel
 .ENDM

.MACRO for var, startcnt, endcnt
 push \startcnt-1
 pop \var
.set SaveLabel,.
 inc \var
.set tst,GT
 Condition \var,\endcnt
 NewLabel ;Make Label for beyond EndFor
 PushLabel
 PlantJmp
.set Label1,SaveLabel
 PushLabel ;save start loc
.endm

.macro endfor
 PopLabel
 jmp .-(.-Label1)
 PopLabel
 PlantLabel
.endm