Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ; CA65 HLA macro pack v5
- ; Copyright Movax big.jay.tee@gmail.com
- ; You are free: to Share — to copy, distribute and transmit the work
- ; to Remix — to adapt the work
- ; to make commercial use of the work
- ; Under the following conditions:
- ; Attribution — You must attribute the work to big.jay.tee@gmail.com in documentation or with any other credits.
- ;
- ; And you must read and be aware of the implications here: http://creativecommons.org/licenses/by/3.0/us/
- ;
- ;
- ;---------------------------------------------------------------------------------------------------------------------------------------------------
- ;
- ; Adds IF-ELSE-ENDIF, DO-WHILE, WHILE-DO-ENDWHILE,REPEAT-UNTIL
- ; As well as the ability to use a 'function' macro to call other code in a way compatible with the above
- ; Included is an expression evaluation for unsigned (comp) and signed (scomp) comparisons. Note that any comparison using greater (>) or less (<) cannot also include a
- ; low or high byte operator (< or > ) unless it is enclosed in brackets.
- ;
- ; Please send any bugs to the above email or message Movax12 at forums.nesdev.com
- ; As well there are two macros named mb, mw for (m)ove (b)yte (m)ove (w)ord that use an := assingment operator
- ;
- ; Expression to test represents the flags of the 6502
- ; All expressions evaluate into a singe branch instruction with the exception of 'greater' and 'not greater'/'lessORequal'
- ; which is handled with two small macros
- ;
- ; Only simple flag name is evaluated (ie C,Z,N,V) along with no/not before and set/clear after
- ; a second 'clear' will negate the flag check, a not will negate the entire expression and is applied last
- ;
- ; FORMAT
- ; In order: Optional: 'no' OR 'not'', Required: <flag alias> or <flag set/clear>, Optional: 'clear' or 'set'
- ; Some strict sytax and error checking.
- ;
- ;
- ; More documentation http://mynesdev.blogspot.ca/
- ; BELOW: .defines for recognized flag tests. Format: Flag to test for and default setting. Add or remove from this block at will
- .define less C clear
- .define greaterORequal C set
- .define carry C set
- .define zero Z set
- .define equal Z set
- .define plus N clear
- .define positive N clear
- .define minus N set
- .define negative N set
- .define bit7 N set
- .define overflow V set
- .define bit6 V set
- .define true Z clear ; NON-ZERO is TRUE - Use after AND instruction (any bits set = true)
- .define false Z set ; ZERO is false
- .define greater G set ; Use greater and less/equal macros to simulate
- .define lessORequal G clear
- ; define symbols for AND, OR, NOT
- .define _USER_AND_DEFINITION_ && ; '&&' will match '.and'
- .define _USER_OR_DEFINITION_ || ; '||' will match '.or'
- .define _USER_NOT_DEFINITION1 not
- .define _USER_NOT_DEFINITION2 !
- .define _USER_GOTO_DEFINITION goto ; if condition goto label
- ; No changes past this line ..etc.. unless you know what you are doing
- ; BELOW HERE IS HIGH LEVEL LANGUAGE FUNCTIONS
- ; branch array
- ; instruction 0 means flag clear, 1 means set
- .define FLAG_1_1 bcs
- .define FLAG_1_2 beq
- .define FLAG_1_3 bmi
- .define FLAG_1_4 bvs
- .define FLAG_0_1 bcc
- .define FLAG_0_2 bne
- .define FLAG_0_3 bpl
- .define FLAG_0_4 bvc
- .define FLAG_1_5 branch_if_greater
- .define FLAG_0_5 branch_if_less_or_equal
- _EXP_ERROR .set 0
- _IF_ENDIF__IF_label .set 0 ; total number of IFs used
- _IF_ENDIF__SP .set 0 ; Stack Pointer
- _IF_ENDIF__END_label .set 0
- _IF_ENDIF__flagnum .set 0
- _IF_ENDIF__flagset .set 0
- _DO_WHILE__DO_label .set 0
- _DO_WHILE__SP .set 0 ; Stack Pointer
- _DO_WHILE__WHILE_label .set 0
- _DO_WHILE__flagnum .set 0
- _DO_WHILE__flagset .set 0
- _WHILE_ENDWHILE__WHILE_label .set 0
- _WHILE_ENDWHILE__SP .set 0 ; Stack Pointer
- _WHILE_ENDWHILE__END_label .set 0
- _WHILE_ENDWHILE__flagnum .set 0
- _WHILE_ENDWHILE__flagset .set 0
- __MACRO_FUNCTION_COMPLETE_ .set 0 ; signal back to the "process_expression_FLAGS" that function is done sucessfully
- ; temp variables for parsing strings / tokens
- _AND_POS_ .set 0
- _OR_POS_ .set 0
- _AND_POS_copy .set 0
- _OR_POS_copy .set 0
- _LONG_JUMP_ .set 0 ; options for generating long jumps
- _BRANCH_LENGTH_CHECKING_ .set 1
- ;----------------------------------------------------------------------------
- .macro branch_if_greater label
- .local over
- beq over
- bcs label
- over:
- .endmacro
- .macro branch_if_less_or_equal label
- beq label
- bcc label
- .endmacro
- ; Set options
- .macro set_long_branch option, messages
- .if .xmatch(option, +)
- ::_LONG_JUMP_ .set 1
- .elseif .xmatch(option,-)
- ::_LONG_JUMP_ .set 0
- .else
- .out "Unknown branch setting, branches are set to LONG."
- ::_LONG_JUMP_ .set 1
- .endif
- .if .xmatch(messages, +)
- ::_BRANCH_LENGTH_CHECKING_ .set 1
- .elseif .xmatch(messages,-) .or .xmatch(option,-)
- ::_BRANCH_LENGTH_CHECKING_.set 0
- .else
- .out "Unknown branch message setting, set to ON"
- ::_BRANCH_LENGTH_CHECKING_.set 1
- .endif
- .endmacro
- ; Common macro 'sub' routines
- .macro checkbrackets flagtest ; this can't error check too many closing brackets, it will match first properly closed bracket that matches the starting bracket
- ::_OR_POS_ .set 0 ; use as temp
- ::_AND_POS_ .set 0
- findposition {flagtest}, (, ::_OR_POS_
- .if ::_OR_POS_ = -1 ; if bracket is on very left side, look for matching close, otherwise ignore
- ::_OR_POS_ .set 0
- matchbrackets {flagtest}, ::_OR_POS_, (,)
- .if ::_OR_POS_ = .tcount({flagtest}) - 1 ; if bracket is on the very outside:
- ::_AND_POS_ .set -1
- .exitmacro
- .else
- .if ::_OR_POS_ = 0 ; not found
- .error " Brackets do not match."
- ::_EXP_ERROR .set 1
- .endif
- .endif
- .endif
- .endmacro
- ; Find the position and exact value of a token 'tok' in 'exp' and change the value of 'position' whilst skipping any tokens
- ; inside matching openskip and closeskip - nested
- ; Does not match very 1st character at pos 0, beacuse 0 means not found
- ; will return -1 if character found at pos 0 (this is better generally for using wih .mid() )
- .macro findposition exp, tok, position, openskip, closeskip
- .if .xmatch({.mid(position,1,{exp})},{tok})
- .if position = 0
- position .set -1
- .endif
- .exitmacro
- .else
- ; no match yet:
- .ifnblank {openskip} ; if open bracket then expand a new macro to find close bracket honoring other brackets
- .if .xmatch({.mid(position,1,{exp})},{openskip})
- position .set position + 1
- findposition {exp}, {closeskip}, position , openskip, closeskip
- .endif
- .endif
- .if (position >= .tcount({exp}))
- ; no more tokens, not found, set pos to 0
- position .set 0
- .exitmacro
- .endif
- position .set position + 1
- findposition {exp}, {tok}, position, openskip, closeskip
- .endif
- .endmacro
- ; given position of left bracket, matches right bracket, skipping other bracket pairs of the same kind
- .macro matchbrackets exp, position, openbracket, closebracket, openskip, closeskip
- ; assume position is at left bracket first time:
- position .set position + 1
- .if .xmatch({.mid(position,1,{exp})},{closebracket})
- .exitmacro
- .else
- ; no match yet:
- .ifnblank {openskip} ; if open bracket then expand a new macro to find close bracket honoring other open/closeskip
- .if .xmatch({.mid(position,1,{exp})},{openskip})
- matchbrackets {exp}, position, openskip, closeskip
- .endif
- .endif
- .if .xmatch({.mid(position,1,{exp})},{openbracket})
- matchbrackets {exp}, position, openbracket, closebracket, openskip, closeskip
- .endif
- .if (position >= .tcount({exp}))
- ; no more tokens, not found, set pos to 0
- position .set 0 ; no matching closing bracket - not there or mismatched
- .exitmacro
- .endif
- matchbrackets {exp}, position, openbracket, closebracket, openskip, closeskip
- .endif
- .endmacro
- ; stack macros:
- .macro push stackname, value, sp ; stackname, valuetoassign, stackpointer
- .ident( .sprintf("%s_%04X_",stackname,sp)) .set value
- sp .set sp + 1
- .endmacro
- .macro pop stackname, var, sp
- sp .set sp - 1
- var .set .ident( .sprintf("%s_%04X_",stackname,sp))
- .endmacro
- .macro codeout I,O ; wrap an ident into an instruction
- .ifnblank O
- I O
- .else
- I
- .endif
- .endmacro
- .macro codeout_recursive I
- ; I can contain a macro + options or any number of instructions seperated by +
- ; it must end with a macro that sets the flags via set_flag_test or set the flags with ==
- .local pos, flag, plus_pos, equal_pos
- plus_pos .set 0
- equal_pos .set 0
- findposition {I}, +,plus_pos , (,)
- findposition {I},=,equal_pos , (,)
- ; only match double equal:
- .if .not .xmatch( {.mid(equal_pos+ (equal_pos = - 1) +1,1,{I})},=) ; If second equal doesn't exsit
- equal_pos .set 0
- .endif
- .if plus_pos
- codeout {.mid(0, plus_pos, {I}) }
- codeout_recursive {.mid(plus_pos+1, .tcount({I}) - plus_pos - 1,{I})}
- .elseif equal_pos ; no more plus
- codeout {.mid(0, equal_pos, {I}) }
- .define _CPU_FLAGS_ .mid(equal_pos + 2 ,.tcount({I}) - equal_pos -2,{I})
- ::__MACRO_FUNCTION_COMPLETE_ .set 1
- .else ; no plus, no equal, should be a macro:
- I
- .endif
- .endmacro
- .macro process_expression_FLAGS flagtest, flag, flagisset, negatefunction
- ; Find a value for which flag we are checking and return:
- ; format of flagtest = [no OR not] flag 'set' OR 'clear' ['set' OR 'clear' ]
- ; If flag is not recognized, attempt to expand the macro and test if it completed
- ; if so, test the flag it set
- ::_EXP_ERROR .set 0
- _n_ .set ( (.xmatch(.left(1, {flagtest}) , _USER_NOT_DEFINITION1)) .or (.xmatch(.left(1, {flagtest}) , _USER_NOT_DEFINITION2)) ) ; not or no prefix
- ; Which flag are we testing? HAS to be a real flag, with the exception of G = greater
- flag .set (.xmatch(.mid(_n_,1, {flagtest}) , C)) * 1 + (.xmatch(.mid(_n_,1, {flagtest}) , Z)) * 2 + (.xmatch(.mid(_n_,1,{flagtest}) , N)) * 3 + (.xmatch(.mid(_n_,1,{flagtest}) , V)) * 4 + (.xmatch(.mid(_n_,1,{flagtest}) , G)) * 5
- .if (flag = 0) ; No flag found, Assume we should be calling a macro, or executing code .. ca65 needs a try command
- ::__MACRO_FUNCTION_COMPLETE_ .set 0
- codeout_recursive {.mid(_n_,.tcount({flagtest}) - _n_ , {flagtest})}
- .if .not ::__MACRO_FUNCTION_COMPLETE_
- .error .sprintf("%s","Error in or unrecognized conditional function or instruction.")
- ::_EXP_ERROR .set 1
- .else
- _negate_next_ .set _n_ ; pass not to the recursion
- process_expression_FLAGS {_CPU_FLAGS_}, flag, flagisset, _negate_next_
- .undefine _CPU_FLAGS_
- .endif
- .exitmacro
- .endif
- __flag_set_default .set (.xmatch(.mid(_n_+1,1, {flagtest}), set)) * 1 + (.xmatch(.mid(_n_+1,1, {flagtest}), clear)) * -1
- .ifnblank .mid(_n_+2,1, {flagtest}) ; user added clear or set, if token exsits here it must be a clear or set, any other is error
- __invert_flag .set .xmatch(.mid(_n_+2,1, {flagtest}), clear) * -1 + .xmatch(.mid(_n_+2,1, {flagtest}), set) * 1
- .else
- __invert_flag .set 1 ; no clear or set added, that's okay make it a 1
- .endif
- __invert_flag .set __invert_flag * (_n_ * -2 + 1)
- .ifnblank negatefunction ; support for recursive expansion and honor the original NOT operator
- __invert_flag .set __invert_flag * (negatefunction * -2 + 1)
- .endif
- flagisset .set ((__flag_set_default * __invert_flag) > 0) ; This will always result in a negative or positive, positive means if flag is set then we branch
- .if (flag = 0)
- ::_EXP_ERROR .set 1
- .error .concat( "Unknow flag: ", .string(.mid(_n_,1, flagtest)))
- .endif
- .if (__invert_flag * __flag_set_default) = 0
- ::_EXP_ERROR .set 1
- .error .concat ( "Unknow flag condition: " , .string(.mid(_n_+1 + (__flag_set_default <> 0),1, {flagtest})))
- .endif
- .endmacro
- .macro checkORAND flagtest ; 'or' was found, make sure no 'or' after any 'and'
- findposition {flagtest}, _USER_OR_DEFINITION_, ::_OR_POS_, (,) ; look for or
- .if (::_AND_POS_ < ::_OR_POS_) .and (::_AND_POS_ > 0)
- .error " AND before OR in conditional expression, will not be parsed properly."
- ::_EXP_ERROR .set 1
- .exitmacro
- .elseif .not ::_OR_POS_
- checkORAND {flagtest}
- .endif
- .endmacro
- ; *************************IF**********************
- ; User is expected to only pass flagtest, and nothing more
- .macro if flagtest
- findposition {flagtest}, _USER_GOTO_DEFINITION,::_OR_POS_ , (,)
- .if ::_OR_POS_
- ; small error check:
- .if .tcount({flagtest}) > ::_OR_POS_ + 2
- .error "Label expected after goto"
- .endif
- if_macro {.mid(0,::_OR_POS_ ,{flagtest})},,,,,{.right(1,{flagtest})}
- .else
- if_macro {flagtest}
- .endif
- .endmacro
- .macro if_macro flagtest, lastrecursive, recursive, leftsideOR, leftsideAND, gotolabel
- ; added to help show where an error is due to the error line displayed staying in the macro
- .ifdef ::_EXP_ERROR
- .if ::_EXP_ERROR
- .error " HINT: HL macpac error is in previous conditional expression."
- .fatal ""
- .endif
- .endif
- ; First, if there are brackets on the very outside of the expression, remove them and try again
- checkbrackets {flagtest} ; Uses _AND_POS_ and _OR_POS_ as temps
- ; try again with brackets removed
- .if ::_AND_POS_ = -1 ; indicates we matched outside bracket
- if_macro {.mid(1,::_OR_POS_ -1,{flagtest})}, lastrecursive, recursive, leftsideOR, leftsideAND, gotolabel
- .exitmacro
- .endif
- ; end brackets
- .if (.blank (recursive) .and .blank(lastrecursive)) ; this means only first call to this macro does this block get executed
- ::_IF_ENDIF__IF_label .set ::_IF_ENDIF__IF_label + 1
- .ifblank gotolabel ; do not save to endif stack if there is no endif
- push "IF_ENDIF_STACK",::_IF_ENDIF__IF_label, ::_IF_ENDIF__SP
- .endif
- .endif
- ::_AND_POS_ .set 0
- ::_OR_POS_ .set 0
- ; findposition exp, tok, position, openskip, closeskip
- findposition {flagtest}, _USER_OR_DEFINITION_, ::_OR_POS_, (,) ; look for or
- .if ::_OR_POS_
- ::_OR_POS_copy .set ::_OR_POS_
- findposition {flagtest}, _USER_AND_DEFINITION_, ::_AND_POS_, (,) ; look for and in the entire enrty
- checkORAND {flagtest} ; make sure there are no ORs after the first AND
- if_macro {.mid(0,::_OR_POS_copy,{flagtest})},,1,1,, gotolabel
- findposition {.mid(::_OR_POS_copy+1, .tcount({flagtest})-::_OR_POS_copy-1,{flagtest})}, _USER_OR_DEFINITION_, ::_OR_POS_, (,) ; look for or
- findposition {.mid(::_OR_POS_copy+1, .tcount({flagtest})-::_OR_POS_copy-1,{flagtest})}, _USER_AND_DEFINITION_, ::_AND_POS_, (,) ; look for and
- .if (.not ::_OR_POS_ ) .and (.not ::_AND_POS_)
- if_macro {.mid(::_OR_POS_copy+1, .tcount({flagtest})-::_OR_POS_copy-1,{flagtest})},1, , , , gotolabel ; last recursive call
- .else
- if_macro {.mid(::_OR_POS_copy+1, .tcount({flagtest})-::_OR_POS_copy-1,{flagtest})},,1, , , gotolabel
- .endif
- .exitmacro
- .endif
- findposition {flagtest}, _USER_AND_DEFINITION_, ::_AND_POS_, (,) ; look for and
- .if ::_AND_POS_
- ::_AND_POS_copy .set ::_AND_POS_
- if_macro {.mid(0,::_AND_POS_,{flagtest})},,1,,1, gotolabel
- findposition {.mid(::_AND_POS_copy+1, .tcount({flagtest})-::_AND_POS_copy-1,{flagtest})}, _USER_OR_DEFINITION_, ::_OR_POS_, (,) ; look for or
- findposition {.mid(::_AND_POS_copy+1, .tcount({flagtest})-::_AND_POS_copy-1,{flagtest})}, _USER_AND_DEFINITION_, ::_AND_POS_, (,) ; look for and
- .if (.not ::_OR_POS_ ) .and (.not ::_AND_POS_)
- if_macro {.mid(::_AND_POS_copy+1, .tcount({flagtest})-::_AND_POS_copy-1,{flagtest})},1, , , , gotolabel
- .else
- if_macro {.mid(::_AND_POS_copy+1, .tcount({flagtest})-::_AND_POS_copy-1,{flagtest})},,1, , , gotolabel
- .endif
- .exitmacro
- .endif
- process_expression_FLAGS {flagtest}, ::_IF_ENDIF__flagnum, ::_IF_ENDIF__flagset
- .ifblank gotolabel
- ; normal if-endif
- .if (.not .blank(leftsideOR)) .or ( ::_LONG_JUMP_ .and .blank(recursive))
- codeout .ident (.sprintf("FLAG_%01X_%01X", ::_IF_ENDIF__flagset, ::_IF_ENDIF__flagnum )), .ident ( .sprintf ("%s%04X", "IF_CODE_BLOCK_START_LABEL_", ::_IF_ENDIF__IF_label))
- .else
- ::_IF_ENDIF__flagset .set .not ::_IF_ENDIF__flagset
- .if (.not .blank(leftsideAND)) .and ::_LONG_JUMP_ ; If Leftside and and long jump on
- codeout .ident (.sprintf("FLAG_%01X_%01X", ::_IF_ENDIF__flagset, ::_IF_ENDIF__flagnum )), .ident ( .sprintf ("%s%04X", "_IF_ENDIF_JMP_", ::_IF_ENDIF__IF_label))
- .else
- codeout .ident (.sprintf("FLAG_%01X_%01X", ::_IF_ENDIF__flagset, ::_IF_ENDIF__flagnum )), .ident ( .sprintf ("%s%04X", "_END_IF_", ::_IF_ENDIF__IF_label))
- .endif
- .endif
- .else
- ; branch to label
- .if (.not .blank(leftsideAND)) .or ( ::_LONG_JUMP_ .and .blank(recursive))
- ::_IF_ENDIF__flagset .set .not ::_IF_ENDIF__flagset
- codeout .ident (.sprintf("FLAG_%01X_%01X", ::_IF_ENDIF__flagset, ::_IF_ENDIF__flagnum )), .ident ( .sprintf ("%s%04X", "IF_CODE_BLOCK_START_LABEL_", ::_IF_ENDIF__IF_label))
- .else
- .if (.not .blank(leftsideOR)) .and ::_LONG_JUMP_
- codeout .ident (.sprintf("FLAG_%01X_%01X", ::_IF_ENDIF__flagset, ::_IF_ENDIF__flagnum )), .ident ( .sprintf ("%s%04X", "_IF_ENDIF_JMP_", ::_IF_ENDIF__IF_label))
- .else
- codeout .ident (.sprintf("FLAG_%01X_%01X", ::_IF_ENDIF__flagset, ::_IF_ENDIF__flagnum )), gotolabel
- .endif
- .endif
- .endif
- .if .blank (recursive) ; no more branches:
- .if ::_LONG_JUMP_
- .ident ( .sprintf ("%s%04X", "_IF_ENDIF_JMP_", ::_IF_ENDIF__IF_label)):
- .if ::_BRANCH_LENGTH_CHECKING_
- .assert (.ident ( .sprintf ("%s%04X", "_END_IF_", ::_IF_ENDIF__IF_label)) ) - (.ident ( .sprintf ("%s%04X", "IF_CODE_BLOCK_START_LABEL_", ::_IF_ENDIF__IF_label))) > 127, warning, .sprintf("JMP in IF macro could have been reached with a branch at IF block %d",::_IF_ENDIF__IF_label)
- .endif
- .ifblank gotolabel
- jmp .ident ( .sprintf ("%s%04X", "_END_IF_", ::_IF_ENDIF__IF_label))
- .else
- jmp gotolabel
- .endif
- .endif
- .ident ( .sprintf ("%s%04X", "IF_CODE_BLOCK_START_LABEL_", ::_IF_ENDIF__IF_label)):
- .endif
- .endmacro
- ; Create a label that will point to the next ENDIF and create an ENDIF/IF for the ELSE
- .macro else
- .ifndef ::_IF_ENDIF__IF_label
- .error "ELSE without IF"
- .fatal ""
- .endif
- ::_IF_ENDIF__IF_label .set ::_IF_ENDIF__IF_label + 1 ; add one to IF count
- jmp .ident ( .sprintf ("%s%04X", "_END_IF_", ::_IF_ENDIF__IF_label)) ; jump to the next endif (this is like a IF false - it will always jump)
- endif ; end if for the IF before this
- push "IF_ENDIF_STACK",::_IF_ENDIF__IF_label, ::_IF_ENDIF__SP ; next endif will use this label
- .endmacro
- ; Pop if address from the IF stack and make a label
- .macro endif
- .if (.not (.defined(::_IF_ENDIF__IF_label))) .or ((::_IF_ENDIF__SP - 1) < 0)
- .error "ENDIF or ELSE without IF"
- .fatal ""
- .endif
- pop "IF_ENDIF_STACK",::_IF_ENDIF__END_label, ::_IF_ENDIF__SP
- .ident ( .sprintf ("%s%04X", "_END_IF_", ::_IF_ENDIF__END_label)):
- .endmacro
- ; *************************END IF**********************
- .macro do ; for do - while
- ::_DO_WHILE__DO_label .set ::_DO_WHILE__DO_label + 1
- push "_DO_WHILE_STACK_",::_DO_WHILE__DO_label, ::_DO_WHILE__SP
- .ident ( .sprintf ("%s%04X", "_DO_WHILE_", ::_DO_WHILE__DO_label)):
- .endmacro
- .macro while_DO_WHILE flagtest, lastrecursive, recursive, leftsideOR, leftsideAND, INV
- .local long_jump
- .ifdef ::_EXP_ERROR ; added to help show where an error is due to the error line displayed staying in the macro
- .if ::_EXP_ERROR
- .error " HINT: Error is in previous flag expression."
- .fatal ""
- .endif
- .endif
- ::_AND_POS_ .set 0
- ::_OR_POS_ .set 0
- checkbrackets {flagtest} ; Uses _AND_POS_ and _OR_POS_ as temps
- ; try again with brackets removed
- .if ::_AND_POS_ = -1
- while_DO_WHILE {.mid(1,::_OR_POS_ -1,{flagtest})}, lastrecursive, recursive, leftsideOR, leftsideAND, INV
- .exitmacro
- .endif
- ; end brackets
- .if (.blank (recursive) .and .blank(lastrecursive)) ; this will only be executed on first call to this macro
- .if ((::_DO_WHILE__SP - 1) < 0) ; if accessing the stack will result in a negative value, there are too many whiles
- .error "WHILE/UNTIL without DO/REPEAT."
- .fatal ""
- .endif
- pop "_DO_WHILE_STACK_", :: _DO_WHILE__WHILE_label, ::_DO_WHILE__SP
- .endif
- ; do and / or
- ::_AND_POS_ .set 0
- ::_OR_POS_ .set 0
- ; findposition exp, tok, position, openskip, closeskip
- findposition {flagtest}, _USER_OR_DEFINITION_, ::_OR_POS_, (,) ; look for or
- .if ::_OR_POS_
- ::_OR_POS_copy .set ::_OR_POS_
- findposition {flagtest}, _USER_AND_DEFINITION_, ::_AND_POS_, (,) ; look for and in the entire enrty
- checkORAND {flagtest} ; make sure there are no ORs after the first AND
- while_DO_WHILE {.mid(0,::_OR_POS_copy,{flagtest})},,1,1,,INV
- findposition {.mid(::_OR_POS_copy+1, .tcount({flagtest})-::_OR_POS_copy-1,{flagtest})}, _USER_OR_DEFINITION_, ::_OR_POS_, (,) ; look for or
- findposition {.mid(::_OR_POS_copy+1, .tcount({flagtest})-::_OR_POS_copy-1,{flagtest})}, _USER_AND_DEFINITION_, ::_AND_POS_, (,) ; look for and
- .if (.not ::_OR_POS_ ) .and (.not ::_AND_POS_)
- while_DO_WHILE {.mid(::_OR_POS_copy+1, .tcount({flagtest})-::_OR_POS_copy-1,{flagtest})},1 ,,,,INV ; last recursive call
- .else
- while_DO_WHILE {.mid(::_OR_POS_copy+1, .tcount({flagtest})-::_OR_POS_copy-1,{flagtest})},,1,,,INV
- .endif
- .exitmacro
- .endif
- findposition {flagtest}, _USER_AND_DEFINITION_, ::_AND_POS_, (,) ; look for and
- .if ::_AND_POS_
- ::_AND_POS_copy .set ::_AND_POS_
- while_DO_WHILE {.mid(0,::_AND_POS_,{flagtest})},,1,,1,INV
- findposition {.mid(::_AND_POS_copy+1, .tcount({flagtest})-::_AND_POS_copy-1,{flagtest})}, _USER_OR_DEFINITION_, ::_OR_POS_, (,) ; look for or
- findposition {.mid(::_AND_POS_copy+1, .tcount({flagtest})-::_AND_POS_copy-1,{flagtest})}, _USER_AND_DEFINITION_, ::_AND_POS_, (,) ; look for and
- .if (.not ::_OR_POS_ ) .and (.not ::_AND_POS_)
- while_DO_WHILE {.mid(::_AND_POS_copy+1, .tcount({flagtest})-::_AND_POS_copy-1,{flagtest})},1, , , ,INV
- .else
- while_DO_WHILE {.mid(::_AND_POS_copy+1, .tcount({flagtest})-::_AND_POS_copy-1,{flagtest})},,1, , ,INV
- .endif
- .exitmacro
- .endif
- ; We only get here if there are no AND or ORS left in the current expansion:
- ; guess if we need long jump:
- .if .not ::_LONG_JUMP_
- .if * - .ident ( .sprintf ("%s%04X", "_DO_WHILE_", ::_DO_WHILE__WHILE_label)) > 128 ; for sure we need a long jump, but we might need one even if this fails if too many branches
- long_jump .set 1
- .else
- long_jump .set 0
- .endif
- .else
- long_jump .set ::_LONG_JUMP_
- .endif
- process_expression_FLAGS {flagtest}, ::_DO_WHILE__flagnum, ::_DO_WHILE__flagset
- ;-------------------------------------------------PROCESS UNTIL
- .ifnblank INV ; this block of code copied from IF since an UNTIL is just like an IF with different labels
- ; IF True BRANCH out of loop
- .if (.not .blank(leftsideOR)) .or ( long_jump .and .blank(recursive))
- codeout .ident (.sprintf("FLAG_%01X_%01X", ::_DO_WHILE__flagset, ::_DO_WHILE__flagnum )), .ident ( .sprintf ("%s%04X", "_END_LOOP_CONTINUE_", ::_DO_WHILE__WHILE_label))
- .else
- ::_DO_WHILE__flagset .set .not ::_DO_WHILE__flagset
- .if (.not .blank(leftsideAND)) .and long_jump ; If Leftside and and long jump on
- codeout .ident (.sprintf("FLAG_%01X_%01X", ::_DO_WHILE__flagset, ::_DO_WHILE__flagnum )), .ident ( .sprintf ("%s%04X", "_DO_WHILE_JMP_", ::_DO_WHILE__WHILE_label))
- .else
- codeout .ident (.sprintf("FLAG_%01X_%01X", ::_DO_WHILE__flagset, ::_DO_WHILE__flagnum )), .ident ( .sprintf ("%s%04X", "_DO_WHILE_", ::_DO_WHILE__WHILE_label))
- .endif
- .endif
- ;-------------------------------------------------PROCESS WHILE: ( IF true GOTO begining)
- .else
- .if (.not .blank(leftsideAND)) .or ( long_jump .and .blank(recursive))
- ::_DO_WHILE__flagset .set .not ::_DO_WHILE__flagset
- codeout .ident (.sprintf("FLAG_%01X_%01X", ::_DO_WHILE__flagset, ::_DO_WHILE__flagnum )), .ident ( .sprintf ("%s%04X", "_END_LOOP_CONTINUE_", ::_DO_WHILE__WHILE_label))
- .else
- .if (.not .blank(leftsideOR)) .and long_jump
- codeout .ident (.sprintf("FLAG_%01X_%01X", ::_DO_WHILE__flagset, ::_DO_WHILE__flagnum )), .ident ( .sprintf ("%s%04X", "_DO_WHILE_JMP_", ::_DO_WHILE__WHILE_label))
- .else
- codeout .ident (.sprintf("FLAG_%01X_%01X", ::_DO_WHILE__flagset, ::_DO_WHILE__flagnum )), .ident ( .sprintf ("%s%04X", "_DO_WHILE_", ::_DO_WHILE__WHILE_label))
- .endif
- .endif
- .endif
- .ifblank recursive
- .if long_jump
- .ident ( .sprintf ("%s%04X", "_DO_WHILE_JMP_", ::_DO_WHILE__WHILE_label)) :
- .if ::_BRANCH_LENGTH_CHECKING_
- .assert (.ident ( .sprintf ("%s%04X", "_DO_WHILE_", ::_DO_WHILE__WHILE_label)) ) - (.ident ( .sprintf ("%s%04X", "_END_LOOP_CONTINUE_", ::_DO_WHILE__WHILE_label))) > 127, warning, .sprintf("JMP in do-while loop could have been reached with a branch at do-while block %d",::_DO_WHILE__WHILE_label)
- .endif
- jmp .ident ( .sprintf ("%s%04X", "_DO_WHILE_", ::_DO_WHILE__WHILE_label))
- .endif
- .ident ( .sprintf ("%s%04X", "_END_LOOP_CONTINUE_",::_DO_WHILE__WHILE_label)):
- .endif
- .endmacro
- .macro while_WHILE_ENDWHILE flagtest, lastrecursive, recursive, leftsideOR, leftsideAND, INV
- ; while for starting a while - endwhile block, if N exists it will negate the test to emulate an 'until'
- ; added to help show where an error is due to the error line displayed staying in the macro
- .ifdef ::_EXP_ERROR
- .if ::_EXP_ERROR
- .error " HINT: HL macpac error is in previous conditional expression."
- .fatal ""
- .endif
- .endif
- ; First, if there are brackets on the very outside of the expression, remove them and try again
- checkbrackets {flagtest} ; Uses _AND_POS_ and _OR_POS_ as temps
- ; try again with brackets removed
- .if ::_AND_POS_ = -1 ; indicates we matched outside bracket
- while_WHILE_ENDWHILE {.mid(1,::_OR_POS_ -1,{flagtest})}, lastrecursive, recursive, leftsideOR, leftsideAND
- .exitmacro
- .endif
- ; end brackets
- .if (.blank (recursive) .and .blank(lastrecursive))
- ::_WHILE_ENDWHILE__WHILE_label .set ::_WHILE_ENDWHILE__WHILE_label + 1
- push "WHILE_ENDWHILE_STACK_",::_WHILE_ENDWHILE__WHILE_label, ::_WHILE_ENDWHILE__SP
- .ident ( .sprintf ("%s%04X", "_WHILE_ENDWHILE_REPEAT_", ::_WHILE_ENDWHILE__WHILE_label)):
- .endif
- ::_AND_POS_ .set 0
- ::_OR_POS_ .set 0
- ; findposition exp, tok, position, openskip, closeskip
- findposition {flagtest}, _USER_OR_DEFINITION_, ::_OR_POS_, (,) ; look for or
- .if ::_OR_POS_
- ::_OR_POS_copy .set ::_OR_POS_
- findposition {flagtest}, _USER_AND_DEFINITION_, ::_AND_POS_, (,) ; look for and in the entire enrty
- checkORAND {flagtest} ; make sure there are no ORs after the first AND
- while_WHILE_ENDWHILE {.mid(0,::_OR_POS_copy,{flagtest})},,1,1
- findposition {.mid(::_OR_POS_copy+1, .tcount({flagtest})-::_OR_POS_copy-1,{flagtest})}, _USER_OR_DEFINITION_, ::_OR_POS_, (,) ; look for or
- findposition {.mid(::_OR_POS_copy+1, .tcount({flagtest})-::_OR_POS_copy-1,{flagtest})}, _USER_AND_DEFINITION_, ::_AND_POS_, (,) ; look for and
- .if (.not ::_OR_POS_ ) .and (.not ::_AND_POS_)
- while_WHILE_ENDWHILE {.mid(::_OR_POS_copy+1, .tcount({flagtest})-::_OR_POS_copy-1,{flagtest})},1 ; last recursive call
- .else
- while_WHILE_ENDWHILE {.mid(::_OR_POS_copy+1, .tcount({flagtest})-::_OR_POS_copy-1,{flagtest})},,1
- .endif
- .exitmacro
- .endif
- findposition {flagtest}, _USER_AND_DEFINITION_, ::_AND_POS_, (,) ; look for and
- .if ::_AND_POS_
- ::_AND_POS_copy .set ::_AND_POS_
- while_WHILE_ENDWHILE {.mid(0,::_AND_POS_,{flagtest})},,1,,1
- findposition {.mid(::_AND_POS_copy+1, .tcount({flagtest})-::_AND_POS_copy-1,{flagtest})}, _USER_OR_DEFINITION_, ::_OR_POS_, (,) ; look for or
- findposition {.mid(::_AND_POS_copy+1, .tcount({flagtest})-::_AND_POS_copy-1,{flagtest})}, _USER_AND_DEFINITION_, ::_AND_POS_, (,) ; look for and
- .if (.not ::_OR_POS_ ) .and (.not ::_AND_POS_)
- while_WHILE_ENDWHILE {.mid(::_AND_POS_copy+1, .tcount({flagtest})-::_AND_POS_copy-1,{flagtest})},1
- .else
- while_WHILE_ENDWHILE {.mid(::_AND_POS_copy+1, .tcount({flagtest})-::_AND_POS_copy-1,{flagtest})},,1
- .endif
- .exitmacro
- .endif
- process_expression_FLAGS {flagtest}, ::_WHILE_ENDWHILE__flagnum, ::_WHILE_ENDWHILE__flagset
- ; process special case of unsigned Greater or lessORequal
- .if (.not .blank(leftsideOR)) .or ( ::_LONG_JUMP_ .and .blank(recursive))
- codeout .ident (.sprintf("FLAG_%01X_%01X", ::_WHILE_ENDWHILE__flagset, ::_WHILE_ENDWHILE__flagnum )), .ident ( .sprintf ("%s%04X", "_WHILE_ENDWHILE_CODE_BLOCK_START", ::_WHILE_ENDWHILE__WHILE_label))
- .else
- ::_WHILE_ENDWHILE__flagset .set .not ::_WHILE_ENDWHILE__flagset
- .if (.not .blank(leftsideAND)) .and ::_LONG_JUMP_ ; If Leftside and and long jump on
- codeout .ident (.sprintf("FLAG_%01X_%01X", ::_WHILE_ENDWHILE__flagset, ::_WHILE_ENDWHILE__flagnum )), .ident ( .sprintf ("%s%04X", "_WHILE_ENDWHILE_JMP_", ::_WHILE_ENDWHILE__WHILE_label))
- .else
- codeout .ident (.sprintf("FLAG_%01X_%01X", ::_WHILE_ENDWHILE__flagset, ::_WHILE_ENDWHILE__flagnum )), .ident ( .sprintf ("%s%04X", "_WHILE_ENDWHILE_EXIT_", ::_WHILE_ENDWHILE__WHILE_label))
- .endif
- .endif
- .if .blank (recursive) ; no more branches:
- .if ::_LONG_JUMP_
- .ident ( .sprintf ("%s%04X", "_WHILE_ENDWHILE_JMP_", ::_WHILE_ENDWHILE__WHILE_label)):
- .if ::_BRANCH_LENGTH_CHECKING_
- .assert (.ident ( .sprintf ("%s%04X", "_WHILE_ENDWHILE_EXIT_", ::_WHILE_ENDWHILE__WHILE_label)) ) - (.ident ( .sprintf ("%s%04X", "_WHILE_ENDWHILE_CODE_BLOCK_START", ::_WHILE_ENDWHILE__WHILE_label))) > 127, warning, .sprintf("JMP in IF macro could have been reached with a branch at IF block %d",::_WHILE_ENDWHILE__WHILE_label)
- .endif
- jmp .ident ( .sprintf ("%s%04X", "_WHILE_ENDWHILE_EXIT_", ::_WHILE_ENDWHILE__WHILE_label))
- .endif
- .ident ( .sprintf ("%s%04X", "_WHILE_ENDWHILE_CODE_BLOCK_START", ::_WHILE_ENDWHILE__WHILE_label)):
- .endif
- .endmacro
- .macro endwhile
- .if (::_WHILE_ENDWHILE__SP - 1) < 0 ; if accessing the stack will result in a negative value
- .error "ENDWHILE without WHILE"
- .fatal ""
- .endif
- pop "WHILE_ENDWHILE_STACK_",::_WHILE_ENDWHILE__END_label, ::_WHILE_ENDWHILE__SP
- jmp .ident ( .sprintf ("%s%04X", "_WHILE_ENDWHILE_REPEAT_", ::_WHILE_ENDWHILE__END_label))
- .ident ( .sprintf ("%s%04X", "_WHILE_ENDWHILE_EXIT_", ::_WHILE_ENDWHILE__END_label)):
- .endmacro
- .macro while flagtest, INV
- .if .xmatch(.right(1,{flagtest}),do) ; Is a "while <cond> do" -endwhile
- while_WHILE_ENDWHILE {.mid (0,.tcount({flagtest})-1,{flagtest})} ,,,,,INV ; send without 'do' on the end
- .else
- while_DO_WHILE {flagtest},,,,,INV
- .endif
- .endmacro
- .macro until flagtest
- .if .xmatch(.right(1,{flagtest}),do) ; Is a "while <cond> do" -endwhile
- .error "until (condition) do - enduntil not supported in this version"
- .fatal
- .endif
- while {flagtest},1 ; invert while test for repeat-until
- .endmacro
- .macro enduntil
- endwhile
- .endmacro
- .macro repeat
- do
- .endmacro
- .macro set_flag_test testflags
- ::__MACRO_FUNCTION_COMPLETE_ .set 1
- .define _CPU_FLAGS_ testflags
- .endmacro
- ;*************************************************************************************************************************
- ; function for use with the above:
- .scope _COMP_MACRO_
- INVLAID = 0
- GREATER = 1
- LESS = -1
- GREATEREQUAL = 2
- LESSEQUAL = -2
- EQUAL = 3
- NOTEQUAL = 4
- REGX = 1
- REGY = 2
- REGA = 3
- .endscope
- .macro find_operator exp, _pos_, _op_
- findposition exp, =, _pos_
- .if _pos_
- _op_ .set _COMP_MACRO_::EQUAL
- .else
- findposition exp, <>, _pos_
- .if _pos_
- _op_ .set _COMP_MACRO_::NOTEQUAL
- .else
- findposition exp, >=, _pos_
- .if _pos_
- _op_ .set _COMP_MACRO_::GREATEREQUAL
- .else
- findposition exp, <=, _pos_
- .if _pos_
- _op_ .set _COMP_MACRO_::LESSEQUAL
- .else
- findposition exp, >, _pos_,(,)
- .if _pos_
- _op_ .set _COMP_MACRO_::GREATER
- .else
- findposition exp, <, _pos_,(,)
- .if _pos_
- _op_ .set _COMP_MACRO_::LESS
- .endif
- .endif
- .endif
- .endif
- .endif
- .endif
- .endmacro
- .macro comp exp, withreg
- ; if immediate or absolute/zero is used, this macro will use reg a to compare
- _pos_ .set _COMP_MACRO_::INVLAID
- _op_ .set _COMP_MACRO_::INVLAID
- find_operator exp, _pos_, _op_
- .if (.not _pos_ ).or (.not _op_)
- .error "Unknow operator in comparison macro."
- .fatal ""
- .endif
- ; Check for register on the right side of the expression and adjust (pretend it is always on the left)
- _left_ .set _COMP_MACRO_::INVLAID
- .if .xmatch(.mid((_pos_+1), .tcount({exp}) - _pos_ - 1 , {exp}),x) ; reg x
- _left_ .set _COMP_MACRO_::REGX
- .elseif .xmatch(.mid((_pos_+1), .tcount({exp}) - _pos_ - 1 , {exp}),y) ; reg y
- _left_ .set _COMP_MACRO_::REGY
- .elseif .xmatch(.mid((_pos_+1), .tcount({exp}) - _pos_ - 1 , {exp}),a) ; reg a
- _left_ .set _COMP_MACRO_::REGA
- .endif
- .if .not (_left_ = _COMP_MACRO_::INVLAID) ; if we found a match on the right side, pretend it is on the left by switching _op_
- .if _op_ < 3
- _op_ .set _op_ * -1 ; don't switch equal or not equal
- .endif
- _right_pos_ .set 0
- _right_pos_count_ .set _pos_
- .else ; right side normal values:
- _right_pos_ .set _pos_ + 1
- _right_pos_count_ .set .tcount({exp}) - _pos_ - 1
- .endif
- .if _left_ = _COMP_MACRO_::INVLAID ; There could be a register on the left side of the expression- find it
- .if .xmatch(.mid(0,_pos_,{exp}),x) ; reg x
- _left_ .set _COMP_MACRO_::REGX
- .elseif .xmatch(.mid(0,_pos_,{exp}),y) ; reg y
- _left_ .set _COMP_MACRO_::REGY
- .elseif .xmatch(.mid(0,_pos_,{exp}),a) ; reg a
- _left_ .set _COMP_MACRO_::REGA
- .endif
- .endif
- .if _left_ = _COMP_MACRO_::INVLAID ; no registers found, so first we will load a register
- .ifnblank withreg
- .if xmatch(withreg, x)
- ldx .mid(0,_pos_,{exp})
- _left_ .set _COMP_MACRO_::REGX
- .elseif xmatch(withreg, y)
- ldy .mid(0,_pos_,{exp})
- _left_ .set _COMP_MACRO_::REGY
- .else
- lda .mid(0,_pos_,{exp})
- _left_ .set _COMP_MACRO_::REGA
- .endif
- .else
- lda .mid(0,_pos_,{exp})
- _left_ .set _COMP_MACRO_::REGA
- .out "WARNING: Reg a value assigned in comparison macro."
- .endif
- .endif
- .if _left_ = _COMP_MACRO_::REGX
- cpx .mid(_right_pos_,_right_pos_count_, {exp})
- .elseif _left_ = _COMP_MACRO_::REGY
- cpy .mid(_right_pos_,_right_pos_count_, {exp})
- .elseif _left_ = _COMP_MACRO_::REGA
- cmp .mid(_right_pos_,_right_pos_count_, {exp})
- .endif
- .if _op_ = _COMP_MACRO_::GREATER
- set_flag_test G set
- .elseif _op_ = _COMP_MACRO_::LESS
- set_flag_test C clear
- .elseif _op_ = _COMP_MACRO_::EQUAL
- set_flag_test Z set
- .elseif _op_= _COMP_MACRO_::GREATEREQUAL
- set_flag_test C set
- .elseif _op_= _COMP_MACRO_::LESSEQUAL
- set_flag_test G clear
- .elseif _op_= _COMP_MACRO_::NOTEQUAL
- set_flag_test Z clear
- .endif
- .endmacro
- .macro scomp exp
- ; code algorithm for signed comparision from : Beyond 8-bit Unsigned Comparisons by Bruce Clark , http://www.6502.org/tutorials/compare_beyond.html
- .local jmp_over, jmp_over2
- _pos_ .set _COMP_MACRO_::INVLAID
- _op_ .set _COMP_MACRO_::INVLAID
- find_operator exp, _pos_, _op_
- .if (.not _pos_ ).or (_op_ = _COMP_MACRO_::INVLAID)
- .error "Unknow operator in signed comparison macro."
- .fatal ""
- .endif
- ; Check for register on the right side of the expression and adjust (pretend it is always on the left)
- _left_ .set _COMP_MACRO_::INVLAID
- .if .xmatch(.mid((_pos_+1), .tcount({exp}) - _pos_ - 1 , {exp}),x) ; reg x
- _left_ .set _COMP_MACRO_::REGX
- .elseif .xmatch(.mid((_pos_+1), .tcount({exp}) - _pos_ - 1 , {exp}),y) ; reg y
- _left_ .set _COMP_MACRO_::REGY
- .elseif .xmatch(.mid((_pos_+1), .tcount({exp}) - _pos_ - 1 , {exp}),a) ; reg a
- _left_ .set _COMP_MACRO_::REGA
- .endif
- .if .not (_left_ = _COMP_MACRO_::INVLAID) ; if we found a match on the right side, pretend it is on the left by switching _op_
- .if _op_ < 3
- _op_ .set _op_ * -1 ; only switch if not ( equal or not equal)
- .endif
- _right_pos_ .set 0
- _right_pos_count_ .set _pos_
- .else ; right side normal values:
- _right_pos_ .set _pos_ + 1
- _right_pos_count_ .set .tcount({exp}) - _pos_ - 1
- .endif
- .if _left_ = _COMP_MACRO_::INVLAID ; There could be a register on the left side of the expression- find it
- .if .xmatch(.mid(0,_pos_,{exp}),x) ; reg x
- _left_ .set _COMP_MACRO_::REGX
- .elseif .xmatch(.mid(0,_pos_,{exp}),y) ; reg y
- _left_ .set _COMP_MACRO_::REGY
- .elseif .xmatch(.mid(0,_pos_,{exp}),a) ; reg a
- _left_ .set _COMP_MACRO_::REGA
- .endif
- .endif
- .if _left_ = _COMP_MACRO_::INVLAID ; no registers found, so first we will load a register
- lda .mid(0,_pos_,{exp})
- _left_ .set _COMP_MACRO_::REGA
- .out "WARNING: Reg a value assigned in signed comparison macro."
- .endif
- .if _op_ > 2 ; EQUAL or NOTEQUAL
- .if _left_ = _COMP_MACRO_::REGX
- cpx .mid(_right_pos_,_right_pos_count_, {exp})
- .elseif _left_ = _COMP_MACRO_::REGY
- cpy .mid(_right_pos_,_right_pos_count_, {exp})
- .elseif _left_ = _COMP_MACRO_::REGA
- cmp .mid(_right_pos_,_right_pos_count_, {exp})
- .endif
- .if _op_ = _COMP_MACRO_::EQUAL
- set_flag_test Z set
- .elseif _op_= _COMP_MACRO_::NOTEQUAL
- set_flag_test Z clear
- .endif
- .else
- .out "WARNING: Reg a value changed in signed comparison macro."
- .if _left_ = _COMP_MACRO_::REGX
- txa
- .elseif _left_ = _COMP_MACRO_::REGY
- tya
- .endif
- .if (_op_ = _COMP_MACRO_::LESS) .or (_op_ = _COMP_MACRO_::GREATEREQUAL) ; less or greaterorequal
- sec ; prepare carry for SBC
- sbc .mid(_right_pos_,_right_pos_count_, {exp}) ; A-NUM
- bvc jmp_over ; if V is 0, N eor V = N, otherwise N eor V = N eor 1
- eor #$80 ; A = A eor $80, and N = N eor 1
- jmp_over:
- ; If the N flag is 1, then A (signed) < NUM (signed) and BMI will branch
- ; If the N flag is 0, then A (signed) >= NUM (signed) and BPL will branch
- .if _op_ = _COMP_MACRO_::LESS
- set_flag_test N set
- .elseif _op_= _COMP_MACRO_::GREATEREQUAL
- set_flag_test N clear
- .endif
- .endif
- .if (_op_ = _COMP_MACRO_::GREATER) .or (_op_ = _COMP_MACRO_::LESSEQUAL)
- clc ; Note: CLC, not SEC
- sbc .mid(_right_pos_,_right_pos_count_, {exp})
- bvc jmp_over2
- eor #$80
- jmp_over2:
- ; If the N flag is 1, then A (signed) <= NUM (signed) and BMI will branch
- ; If the N flag is 0, then A (signed) > NUM (signed) and BPL will branch
- .if _op_ = _COMP_MACRO_::GREATER
- set_flag_test N clear
- .elseif _op_= _COMP_MACRO_::LESSEQUAL
- set_flag_test N set
- .endif
- .endif
- .endif
- .endmacro
- ;*************************************************************************************************************************
- .macro mb exp
- _equalpos_ .set 1 ; first check at token 1
- findposition exp, :=, _equalpos_
- .if (_equalpos_ = 0)
- .error "No assignment found in byte assignment macro."
- .exitmacro
- .endif
- .if .xmatch(.mid((_equalpos_+1), .tcount({exp}) - _equalpos_ - 1 , {exp}),x) ; assign reg x
- stx .mid(0,_equalpos_,{exp})
- .elseif .xmatch(.mid((_equalpos_+1), .tcount({exp}) - _equalpos_ - 1 , {exp}),y) ; assign reg y
- sty .mid(0,_equalpos_,{exp})
- .elseif .xmatch(.mid((_equalpos_+1), .tcount({exp}) - _equalpos_ - 1 , {exp}),a) ; assign reg a
- sta .mid(0,_equalpos_,{exp})
- .else
- lda .mid((_equalpos_+1), .tcount({exp}) - _equalpos_ - 1 , {exp})
- sta .mid(0,_equalpos_,{exp})
- .endif
- .endmacro
- .macro mw exp
- _equalpos_ .set 1 ; first check at token 1 since there should be something on the left
- findposition exp, :=, _equalpos_
- .if (_equalpos_ = 0)
- .error "No assignment found in word assignment macro."
- .exitmacro
- .endif
- .if .xmatch(.mid((_equalpos_+1),1, {exp}), #) ; immeidate mode
- lda #<.mid((_equalpos_+2), .tcount({exp}) - _equalpos_ - 2 , {exp})
- sta .mid(0,_equalpos_,{exp})
- lda #>.mid((_equalpos_+2), .tcount({exp}) - _equalpos_ - 2 , {exp})
- sta .mid(0,_equalpos_,{exp}) + 1
- .else
- lda .mid((_equalpos_+1), .tcount({exp}) - _equalpos_ - 1 , {exp})
- sta .mid(0,_equalpos_,{exp})
- lda .mid((_equalpos_+1), .tcount({exp}) - _equalpos_ - 1 , {exp})+1
- sta .mid(0,_equalpos_,{exp}) + 1
- .endif
- .endmacro
- ;*************************************************************************************************************************
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement