        SUBT    System wide macro definitions => &.Hdr.Macros

OldOpt  SETA    {OPT}
        OPT     OptNoList+OptNoP1List

; ***********************************
; ***    C h a n g e   L i s t    ***
; ***********************************

; Date       Name  Description
; ----       ----  -----------
; 28-Sep-87  TMD   Modified CallAVector, VDWS for new soft-load version
; 29-Sep-87  TMD   Modified CallAVector again
; 05-Sep-87  SKS   Removed $hat option from Push
; 22-Oct-87  TMD   Modified CallAVector yet again
; 17-Dec-87  NDR   Modified Swap macro (conditional added)
; 15-Jan-88  BC    Fixed Byte and Word so that the actual parms may be expr.
; 04-Feb-88  SKS   Fixed BYTEWS macro. AAsm thinks :LOR is ok ?!
; 10-Mar-88  NDR   Implemented XError macro
; 11-Mar-88  NDR   Improved XError macro
; 19-Apr-88  SKS   Fixed BYTEWS macro. Added Immediate macro
; 21-Apr-88  SKS   Took debugging out of Immediate macro!. Fixed it to produce
;                  less rubbish in error cases
; 11-May-88  SKS   Added Command_LastName to Command macro
; 16-May-88  SKS   Added optimising addr macro. My apologies to anyone it
;                  screws up! Removed pre-OS 1.20 changes from list.
; 24-May-88  TMD   Added offset to AlignSpace.
; 31-May-88  SKS   addr now does register relative symbols too (need AAsm 1.48)
; 01-Jun-88  SKS   addr now understands different amounts of verbosity
; 03-Jun-88  SKS   make wsaddr to get round absolute problems
; 11-Jun-88  SKS   tweaked |#|
; 18-Jul-88  BC    Made PHPSEI & PLP use a register argument

; =============================================
; Macros should be kept in ALPHABETICAL order !
; =============================================

        MACRO
        AddError $name,$text,$value
   [    "$value" = ""
ErrorNumber_$name # 1
   |
ErrorNumber_$name * $value
   ]
        GBLS ErrorString_$name
ErrorString_$name SETS "$text"
        MEND

; ***************************************************
; ***  Put address of $dest in $reg; $dest > .    ***
; ***  !!! Please use addr wherever possible !!!  ***
; ***************************************************
        MACRO
$label  ADDR    $reg, $dest, $cond
$label  ADR$cond.L $reg, $dest
        MEND

; *****************************************************************************
; ***  Optimising ADR/ADRL for addressing object backwards from current pc  ***
; ***  or register relative symbol. Symbol MUST be defined on first pass    ***
; *****************************************************************************
                GBLA    addr_verbose
addr_verbose    SETA    0

        MACRO
$label  addr    $reg, $object, $cc
        LCLA    value
value   SETA    .-$object+8
        Immediate &$value
 [ immediate
$label  ADR$cc  $reg, $object
  [ addr_verbose :AND: 1 <> 0
 ! 0,"addr saved a word"
  ]
 |
$label  ADR$cc.L $reg, $object
  [ addr_verbose :AND: 2 <> 0
 ! 0,"addr didn't save a word"
  ]
 ]
        MEND

        MACRO
$label  wsaddr    $reg, $object, $cc
        LCLA    value
value   SETA    :INDEX: $object
        Immediate &$value
 [ immediate
$label  ADR$cc  $reg, $object
  [ addr_verbose :AND: 1 <> 0
 ! 0,"wsaddr saved a word"
  ]
 |
$label  ADR$cc.L $reg, $object
  [ addr_verbose :AND: 2 <> 0
 ! 0,"wsaddr didn't save a word"
  ]
 ]
        MEND


; ***************************************************
; ***  Generate SWI labels assuming ^ type defs   ***
; ***  Also assumes the global variable SWIClass  ***
; ***************************************************
        GBLS    SWIClass
        MACRO
        AddSWI  $SWIName,$value
  [     "$value" = ""
$SWIClass._$SWIName # 1
  |
$SWIClass._$SWIName * $value
  ]
X$SWIClass._$SWIName * $SWIClass._$SWIName + Auto_Error_SWI_bit
        MEND


; *******************************************************************
; ***  Align workspace to given power-of-two boundary and offset  ***
; *******************************************************************
        MACRO
$label  AlignSpace $value, $offset
 [ "$value" = ""
$label  #       3 :AND: ($offset-:INDEX: @)
 |
$label  #       (($value)-1) :AND: ($offset-:INDEX: @)
 ]
        MEND

        MACRO
$label  ASL     $reg, $val, $cc
$label  MOV$cc  $reg, $reg, ASL #$val
        MEND

        MACRO
$label  ASR     $reg, $val, $cc
$label  MOV$cc  $reg, $reg, ASR #$val
        MEND

; *************************************************
; ***  Put address of $dest in $reg; $dest < .  ***
; *************************************************
        MACRO
$label  BADDR   $reg, $dest, $cond
$label  ADR$cond.L $reg, $dest
        MEND

; ****************************************************
; ***  Macro BSR - Branch to subroutine saving R14 ***
; ****************************************************
        MACRO
$label  BSR     $dest
$label  Push    R14
        BL      $dest
        Pull    R14
        MEND

; *******************************
; ***  Add byte to workspace  ***
; *******************************
        MACRO
$label  Byte    $value, $count
  [     "$label" = ""
    [   "$count" = ""
$value  # 1
  |
$value  # ($count)
    ]
  |
    [   "$value" = ""
$label  # 1
    |
$label  # ($value)
    ]
  ]
        MEND

; ********************************************
; ***  Macro BYTEWS - Point to OsbyteVars  ***
; ********************************************
        MACRO
        BYTEWS  $reg
        Immediate OsbyteVars
 [ immediate
        MOV     $reg, #OsbyteVars
 |
        MOV     $reg, #(OsbyteVars :AND: &FF)
        ORR     $reg, $reg, #(OsbyteVars :AND: :NOT: &FF)
 ]
        MEND

        MACRO
$label  CallAVector $cond
     [ AssemblingArthur
$label  B$cond   CallVector
     |
      [ Module
$label  B$cond  %FT10
        Push    "R8,R9"
        MOV     R8, PC
        AND     R8, R8, #3              ; just get mode bits
        EOR     R8, R8, #SVC_mode       ; eored with SVC mode
        TEQP    R8, PC
        MOVNV   R0, R0
        Push    R14
        MOV     R9, R10
        SWI     XOS_CallAVector
        Pull    R14
        TEQP    R8, PC
        MOVNV   R0, R0
        Pull    "R8,R9"
        MOV     PC, R14
10
      |
$label  LDR$cond PC, =CallVecAddr
       [ "$cond" = ""
        LTORG     ; Can't conditionally execute constants ! Use your own LTORG
       ]
      ]
     ]
        MEND

; ******************************************
; ***  Clear carry flag - will set nzcv  ***
; ******************************************
        MACRO
$label  CLC     $cond
$label  CMN$cond pc, #0
        MEND

; **************************************************************************
; ***  Clear bits in PSR from the mask in $bits, using register $regtmp  ***
; **************************************************************************
        MACRO
$label  CLRPSR  $bits, $regtmp, $cond
$label  MVN$cond   $regtmp, #$bits
        TST$cond.P $regtmp, pc
        MEND

; *******************************************
; *** Clear overflow flag - will set nzCv ***
; *******************************************
        MACRO
$label  CLRV    $cond
$label  CMP$cond pc, #0
        MEND

; *********************************************
; *** Generates a help/syntax/command block ***
; ***    for a Module star command table    ***
; *** Needs a variable Module_BaseAddr set  ***
; *********************************************
        GBLA    Command_LastName ; Offset to command string within module
        MACRO
        Command $cmd, $max, $min, $optbits, $cmdlabel
        LCLA    temp
        LCLS    cmdlab
 [ "$optbits" = ""
temp    SETA    0
 |
temp    SETA    $optbits
 ]
 [ "$cmdlabel" = ""
cmdlab  SETS    "$cmd"
 |
cmdlab  SETS    "$cmdlabel"
 ]
Command_LastName SETA .-Module_BaseAddr
        DCB     "$cmd", 0
        ALIGN
        DCD     $cmdlab._Code  -Module_BaseAddr
        DCD     ($min) + (($max) :SHL: 16) + temp
        DCD     $cmdlab._Syntax-Module_BaseAddr
        DCD     $cmdlab._Help  -Module_BaseAddr
        MEND

        MACRO
$label  DEC     $reg,$by
        [ "$by" = ""
$label  SUB     $reg,$reg,#1
        |
$label  SUB     $reg,$reg,#$by
        ]
        MEND

        MACRO
$label  DECS    $reg,$by
        [ "$by" = ""
$label  SUBS    $reg,$reg,#1
        |
$label  SUBS    $reg,$reg,#$by
        ]
        MEND

; **********************************************************
; ***   Macro DIVREM - rc := ra DIV rb; ra := ra REM rb  ***
; ***   rb preserved, rtemp corrupt                      ***
; ***   Now up to 37% faster                             ***
; **********************************************************
        MACRO
$label  DivRem  $rc, $ra, $rb, $rtemp
$label
        MOV     $rtemp, $rb
        CMP     $rtemp, $ra, LSR #1
01
        MOVLS   $rtemp, $rtemp, LSL #1
        CMPLS   $rtemp, $ra, LSR #1
        BLS     %BT01
        MOV     $rc, #0
02
        CMP     $ra, $rtemp
        SUBCS   $ra, $ra, $rtemp
        ADC     $rc, $rc, $rc
        MOV     $rtemp, $rtemp, LSR #1
        CMP     $rtemp, $rb
        BCS     %BT02
        MEND

; **********************************************************
; ***   Macro DIVREM - rc := ra DIV rb; ra := ra REM rb  ***
; ***   OLD version NB. rb, rtemp corrupt                ***
; **********************************************************
;        MACRO
;$label  DivRem  $rc, $ra, $rb, $rtemp
;$label  MOV     $rtemp, #1
;01      CMP     $rb, #&80000000
;        CMPCC   $rb, $ra
;        MOVCC   $rb, $rb, ASL #1
;        MOVCC   $rtemp, $rtemp, ASL #1
;        BCC     %BT01
;        MOV     $rc, #0
;02      CMP     $ra, $rb
;        SUBCS   $ra, $ra, $rb
;        ADDCS   $rc, $rc, $rtemp
;        MOVS    $rtemp, $rtemp, LSR #1
;        MOVNE   $rb, $rb, LSR #1
;        BNE     %BT02
;        MEND

        MACRO
$label  DoCallTable $jumpreg, $tablename, $work
$label  Push    "$work, pc"
        ADR     $work, $tablename
        LDR     lr, [$work, $jumpreg, LSL #2]
        ADD     $work, $work, lr
        STR     $work, [stack, #4]
        MOV     lr, pc ; ADR lr, %FT99 with correct mode bits
        Pull    "$work, pc"
;                0      4
        ASSERT $jumpreg <> $work
        ASSERT $jumpreg <> lr
        ASSERT $jumpreg <> pc
99 ; Return here from called routine
        MEND

; ****************************************************************************
; ***  Probably the fastest jump table mechanism for PIC - a mere 4S + 2N  ***
; ***  cycles.  Jump table directly follows the macro, and is a list of    ***
; ***  offsets done by eg.  DCD routine_address-table-4. Needs only one    ***
; ***  register temp (Use lr mostly).                                      ***
; ****************************************************************************
        MACRO
$label  DoFastJumpTable $jumpreg, $trash
$label  LDR     $trash, [pc, $jumpreg, LSL #2]
        ADD     pc, pc, $trash
        MEND

; *********************************************
; ***  Jump table preserving all registers  ***
; *********************************************
        MACRO
$label  DoJumpTable $jumpreg, $tablename, $work1, $work2
$label  Push    "$work1, $work2, pc"      ; pc is just a dummy reg here
        ADR     $work1, $tablename
        LDR     $work2, [$work1, $jumpreg, LSL #2]
        ADD     $work1, $work1, $work2
        STR     $work1, [stack, #8]
        Pull    "$work1, $work2, pc"
;                0       4       8
        ASSERT $jumpreg <> $work1
        ASSERT $jumpreg <> $work2
        ASSERT $jumpreg <> pc
        MEND

        MACRO
$label  DoSVCCallTable $jumpreg, $tablename
$label  ADR     SVCWK1, $tablename
        LDR     SVCWK0, [SVCWK1, $jumpreg, LSL #2]
        MOV     lr, pc ; ADR lr, %FT99 with correct mode bits
        ADD     pc, SVCWK1, SVCWK0
        ASSERT $jumpreg <> lr
        ASSERT $jumpreg <> pc
99 ; Return here from called routine
        MEND

; ***************************************************************************
; ***  Jump table using SVC mode temporary registers. Use with caution !  ***
; ***************************************************************************
        MACRO
$label  DoSVCJumpTable $jumpreg, $tablename
$label  ADR     SVCWK1, $tablename
        LDR     SVCWK0, [SVCWK1, $jumpreg, LSL #2]
        ADD     pc, SVCWK1, SVCWK0
        ASSERT $jumpreg <> lr
        ASSERT $jumpreg <> pc
        MEND

        MACRO
$label  Error   $errno, $errstr
$label  ADR     R0, %FT01
        SWI     OS_GenerateError
01
        &       $errno
        =       "$errstr", 0
        ALIGN
        MEND

        MACRO
$label  XError     $errsym, $c1, $c2
$label  ADR$c1$c2  R0,ErrorBlock_$errsym
        SETV       $c1
        MEND

; ***********************************************************************
; ***  Exit macro for SWI handlers.                                   ***
; ***  Jump to 17M in the Sam-hacked Brazil, for installed handlers.  ***
; ***  Do it directly if really in system                             ***
; ***********************************************************************
SWIHandlerExit * 17*1024*1024
CallVecAddr    * SWIHandlerExit+4
        MACRO
$label  ExitSWIHandler $cond
        [ AssemblingArthur
$label  B$cond   SLVK
        |
        [ Module
$label  LDR$cond PC, =BranchToSWIExit
        |
$label  MOV$cond PC, #SWIHandlerExit
        ]
        ]
        MEND

        MACRO
$label  GRAB    $reglist, $cond, $hat
$label  LDM$cond.FD r13!, {$reglist}$hat
        MEND

; *****************************************************************************
; ***  Pull registers and restore PSR (if R15 loaded). Use with extreme     ***
; ***  caution : there are bugs in 3um ARM with PSR update in non-USR modes.***
; *****************************************************************************
        MACRO
$label  GRABS   $reglist, $cond
$label  LDM$cond.FD r13!, {$reglist}^
        [ :LEN: "$reglist" <= 3
 ! 0,"GRABS used dangerously - check your code !"
        ]
        MEND

        MACRO
$label  INC     $reg,$by
        [ "$by" = ""
$label  ADD     $reg,$reg,#1
        |
$label  ADD     $reg,$reg,#$by
        ]
        MEND

        MACRO
$label  INCS    $reg,$by
        [ "$by" = ""
$label  ADDS    $reg,$reg,#1
        |
$label  ADDS    $reg,$reg,#$by
        ]
        MEND

; ****************************************************
; ***  Generates the InfoWord for a command table  ***
; ****************************************************
        MACRO
        InfoWord $max, $min, $optbits
 [ "$optbits" = ""
        DCD     ($min) + (($max) :SHL: 16)
 |
        DCD     ($min) + (($max) :SHL: 16) + $optbits
 ]
        MEND

; **********************************************************
; ***  Macro Immediate - set flag if value is immediate  ***
; **********************************************************
        GBLL    immediate

        MACRO
        Immediate $var
immediate SETL  {FALSE}
        LCLA    count
        LCLA    varcopy
varcopy SETA    $var
        WHILE   count <= 30
 [ ((varcopy:SHL:count) + (varcopy:SHR:(32-count))) :AND: (:NOT: &FF) = 0
immediate SETL  {TRUE}
        MEXIT
 ]
count   SETA    count + 2
        WEND
        MEND

; *********************************************
; ***  Macro LDROSB - Load Osbyte variable  ***
; *********************************************
        MACRO
$label  LDROSB  $reg, $var, $cond
$label  MOV$cond $reg, #0
        LDR$cond.B $reg, [$reg, #OsbyteVars+$var-OSBYTEFirstVar]
        MEND

; ******************************************************
; ***  Macro LDW - Load word from unknown alignment  ***
; ******************************************************
        MACRO
$label  LDW     $dest, $addr, $temp1, $temp2
        ASSERT  $dest < $temp2
$label  BIC     $temp1, $addr, #3
        LDMIA   $temp1, {$dest, $temp2}
        AND     $temp1, $addr, #3
        MOVS    $temp1, $temp1, LSL #3
        MOVNE   $dest, $dest, LSR $temp1
        RSBNE   $temp1, $temp1, #32
        ORRNE   $dest, $dest, $temp2, LSL $temp1
        MEND

; ***********************************************************************
; ***  Lowercasing macro. Needs temp register; only lowercases A-Z !  ***
; ***********************************************************************
        MACRO
$label  LowerCase $reg, $wrk
$label  CMP     $reg, #"A"
        RSBGES  $wrk, $reg, #"Z"        ; inverse compare
        ADDGE   $reg, $reg, #"a"-"A"
        MEND

        MACRO
$label  LSL     $reg, $val, $cc
$label  MOV$cc  $reg, $reg, LSL #$val
        MEND

        MACRO
$label  LSR     $reg, $val, $cc
$label  MOV$cc  $reg, $reg, LSR #$val
        MEND

        MACRO
$label  MakeErrorBlock $name, $noalign
        ALIGN
$label
ErrorBlock_$name
        DCD     ErrorNumber_$name
        DCB     ErrorString_$name
        DCB     0
    [   "$noalign" = ""
        ALIGN
    ]
        MEND

; ****************************************
; ***  Macro MULTIPLY - rc := ra * rb  ***
; ***       NB. ra, rb corrupt         ***
; ****************************************
        MACRO
$label  MULTIPLY $rc, $ra, $rb

    [ {FALSE}                  ; old boring one
$label  MOV     $rc, #0
01      MOVS    $ra, $ra, LSR #1
        ADDCS   $rc, $rc, $rb
        ADD     $rb, $rb, $rb
        BNE     %BT01
    |
$label  MUL     $rc, $rb, $ra ; sexy 2u version with regs in the right order
    ]
        MEND

; *******************************************************
; ***  Sweet FA macro to keep Tutu out of mischief !  ***
; *******************************************************
        MACRO
$label  NOP
$label  MOVNV   R0, R0
        MEND

        MACRO
$label  Overlap $master, $slave
  [     "$label" = ""

        ^ :INDEX:$master, wp
$slave  # ?$master
  |
        ! 0, "You what?"
  ]
        MEND

; **********************************************************************
; ***  Disable IRQs, saving an old interrupt state indicator in R14  ***
; ***  NB This macro preserves the C and V flags                     ***
; **********************************************************************
        MACRO
$lab    PHPSEI  $register
  [     "$register" = ""
$lab    MOV     R14, #I_bit
        TST     R14, PC                 ; is I_bit set ?
        TEQEQP  R14, PC                 ; no, then set it (and R14 = I_bit)
        MOVNE   R14, #0                 ; yes, then leave alone (and R14=0)
  |
$lab    MOV     $register, #I_bit
        TST     $register, PC           ; is I_bit set ?
        TEQEQP  $register, PC           ; no, then set it (and $reg. = I_bit)
        MOVNE   $register, #0           ; yes, then leave alone (and R14=0)
  ]
        MEND

; ************************************************************************
; ***  Restore IRQ state from the indicator in R14 (set up by PHPSEI)  ***
; ***  NB This macro preserves the C and V flags                       ***
; ************************************************************************
        MACRO
$lab    PLP     $register
  [     "$register" = ""
$lab    TEQP    R14, PC
  |
$lab    TEQP    $register, PC
  ]
        MEND

; *****************************************
; ***  Pull registers given in reglist  ***
; *****************************************
        MACRO
$label  Pull    $reglist, $cond, $hat
$label  LDM$cond.FD r13!, {$reglist}$hat
        MEND

; *****************************************
; ***  Push registers given in reglist  ***
; *****************************************
        MACRO
$label  Push   $reglist, $cond
$label  STM$cond.FD r13!, {$reglist}
        MEND

        MACRO
$label  RETURN  $cond
$label  MOV$cond pc, lr
        MEND

        MACRO
$label  RETURNS $cond
$label  MOV$cond.S pc, lr
        MEND

        MACRO
$label  ROR     $reg, $val, $cc
$label  MOV$cc  $reg, $reg, ROR #$val
        MEND

; **************************************************
; ***  Set and clear bits in PSR from the masks  ***
; ***  $set, $clr, using register $regtmp        ***
; **************************************************
        MACRO
$label  SCPSR   $set, $clr, $regtmp, $cond
$label  MOV$cond   $regtmp, pc
        ORR$cond   $regtmp, $regtmp, #($set) :OR: ($clr)
        TEQ$cond.P $regtmp, #$clr
        MEND

; ****************************************
; ***  Set carry flag - will set nzCv  ***
; ****************************************
        MACRO
$label  SEC     $cond
$label  CMP$cond pc, #0
        MEND

; ************************************************************************
; ***  Set bits in PSR from the mask in $bits, using register $regtmp  ***
; ************************************************************************
        MACRO
$label  SETPSR  $bits, $regtmp, $cond
$label  MOV$cond   $regtmp, pc
        ORR$cond   $regtmp, $regtmp, #$bits
        TEQ$cond.P $regtmp, #0
        MEND

; *******************************************
; ***  Set overflow flag - will set NzcV  ***
; *******************************************
        MACRO
$label  SETV    $cond
$label  CMP$cond pc, #&80000000
        MEND

        MACRO
$label  STASH   $reglist, $cond, $hat
$label  STM$cond.FD r13!, {$reglist}$hat
        MEND

; *******************************
; ***  String immediate out.  ***
; *******************************
        MACRO
$label  STRIM   $string
        [ :LEN: "$string" = 1
$label  SWI     XOS_WriteI+"$string"
        |
$label  SWI     XOS_WriteS
        DCB     "$string", 0
        ALIGN
        ]
        MEND

; **********************************************
; ***  Macro STROSB - Store Osbyte variable  ***
; **********************************************
        MACRO
$label  STROSB  $reg, $var, $temp, $cond
$label  MOV$cond $temp, #0
        STR$cond.B $reg, [$temp, #OsbyteVars+$var-OSBYTEFirstVar]
        MEND

; *****************************************
; ***  Macro Swap - Swap two registers  ***
; *****************************************
        MACRO
$label  Swap    $ra, $rb, $cc
$label  EOR$cc  $ra, $ra, $rb
        EOR$cc  $rb, $ra, $rb
        EOR$cc  $ra, $ra, $rb
        MEND

; ***************************************************************************
; ***  Toggle bits in PSR from the mask in $bits, using register $regtmp  ***
; ***************************************************************************
        MACRO
$label  TOGPSR  $bits, $regtmp, $cond
$label  MOV$cond   $regtmp, pc
        TEQ$cond.P $regtmp, #$bits
        MEND

; ***********************************************************************
; ***  Uppercasing macro. Needs temp register; only uppercases a-z !  ***
; ***********************************************************************
        MACRO
$label  UpperCase $reg, $wrk
$label  CMP     $reg, #"a"
        RSBGES  $wrk, $reg, #"z"        ; inverse compare
        SUBGE   $reg, $reg, #"a"-"A"
        MEND

; **********************************************************
; ***  Macro VDWS - Point to our new VduDriverWorkSpace  ***
; **********************************************************
        MACRO
        VDWS    $reg
 [ AssemblingArthur :LOR: Module
        MOV     $reg, #VduDriverWorkSpace
 |
 ! 0, "This is a real waste if using Hdr.NewSpace"
        MOV     $reg, #(VduDriverWorkSpace :AND: &FF000000)
        ORR     $reg, $reg, #(VduDriverWorkSpace :AND: &00FF0000)
        ORR     $reg, $reg, #(VduDriverWorkSpace :AND: &0000FFFF)
 ]
        MEND

; *******************************
; ***  Add word to workspace  ***
; *******************************
        MACRO
$label  Word    $value, $count
  [     ( ( :INDEX: @ ) :AND: 3 ) <> 0
        #       4 - ( ( :INDEX: @ ) :AND: 3 )
  ]
  [     "$label" = ""
    [   "$count" = ""
      [ "$value" = ""
      |
$value  #       4
      ]
    |
$value  #       ($count) * 4
    ]
  |
    [   "$value" = ""
$label  #       4
    |
$label  #       ($value) * 4
    ]
  ]
        MEND

; *************************
; ***  WriteLn a string ***
; *************************
        MACRO
$label  WRLN    $string
$label  SWI     XOS_WriteS
        DCB     "$string", 10,13, 0
        ALIGN
        MEND

; ****************************************************************************
; ***  |#| - macro for allocating workspace downwards rather than upwards  ***
; ****************************************************************************

        MACRO
$var    |#|     $bytes
 [ "$bytes" = ""
        !       1, "Syntax: [<variable>] |#| <bytes>"
        MEXIT
 ]
        #       -($bytes)
 [ "$var" <> ""
$var    #       $bytes          ; Declare correct size
        #       -($bytes)
 ]
        MEND


        OPT OldOpt
        END
