2 ; ca65 Macro-Pack for Self Modifying Code (SMC)
4 ; (c) Christian Krüger, latest change: 17-Jul-2016
6 ; This software is provided 'as-is', without any expressed or implied
7 ; warranty. In no event will the authors be held liable for any damages
8 ; arising from the use of this software.
10 ; Permission is granted to anyone to use this software for any purpose,
11 ; including commercial applications, and to alter it and redistribute it
12 ; freely, subject to the following restrictions:
14 ; 1. The origin of this software must not be misrepresented; you must not
15 ; claim that you wrote the original software. If you use this software
16 ; in a product, an acknowledgment in the product documentation would be
17 ; appreciated but is not required.
18 ; 2. Altered source versions must be plainly marked as such, and must not
19 ; be misrepresented as being the original software.
20 ; 3. This notice may not be removed or altered from any source
24 .define _SMCDesignator .mid(0, .tcount(label) - 1, label) .ident(.concat(.string(.right(1, label)), "_SMC"))
25 .define _SMCAlias .mid(0, .tcount(alias) - 1, alias) .ident(.concat(.string(.right(1, alias)), "_SMC"))
26 .define SMC_AbsAdr $FADE
28 .define SMC_Opcode nop
31 .macro SMC_OperateOnValue opcode, label
32 opcode _SMCDesignator+1
35 .macro SMC_OperateOnLowByte opcode, label
36 SMC_OperateOnValue opcode, label
39 .macro SMC_OperateOnHighByte opcode, label
40 opcode _SMCDesignator + 2
43 .macro SMC_Import alias
47 .macro SMC_Export alias, label
48 .export _SMCAlias := _SMCDesignator
51 .macro SMC label, statement
52 _SMCDesignator: statement
55 .macro SMC_TransferOpcode label, opcode, register
56 .if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )
59 .elseif .match ({register}, x)
62 .elseif .match ({register}, y)
66 .error "Invalid usage of macro 'SMC_TransferOpcode'"
70 .macro SMC_LoadOpcode label, register
71 .if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )
73 .elseif .match ({register}, x)
75 .elseif .match ({register}, y)
78 .error "Invalid usage of macro 'SMC_LoadOpcode'"
82 .macro SMC_StoreOpcode label, register
83 .if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )
85 .elseif .match ({register}, x)
87 .elseif .match ({register}, y)
90 .error "Invalid usage of macro 'SMC_StoreOpcode'"
94 .macro SMC_ChangeBranch label, destination, register
95 .if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )
96 lda #(<(destination - _SMCDesignator -2))
98 .elseif .match ({register}, x)
99 ldx #(<(destination - _SMCDesignator - 2))
101 .elseif .match ({register}, y)
102 ldy #(<(destination - _SMCDesignator - 2))
105 .error "Invalid usage of macro 'SMC_ChangeBranch'"
109 .macro SMC_TransferValue label, value, register
110 .if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )
113 .elseif .match ({register}, x)
116 .elseif .match ({register}, y)
120 .error "Invalid usage of macro 'SMC_TransferValue'"
124 .macro SMC_LoadValue label, register
125 .if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )
127 .elseif .match ({register}, x)
129 .elseif .match ({register}, y)
132 .error "Invalid usage of macro 'SMC_LoadValue'"
136 .macro SMC_StoreValue label, register
137 .if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )
139 .elseif .match ({register}, x)
141 .elseif .match ({register}, y)
144 .error "Invalid usage of macro 'SMC_StoreValue'"
149 .macro SMC_TransferLowByte label, value, register
150 SMC_TransferValue label, value, register
153 .macro SMC_LoadLowByte label, register
154 SMC_LoadValue label, register
157 .macro SMC_StoreLowByte label, register
158 SMC_StoreValue label, register
161 .macro SMC_TransferHighByte label, value, register
162 .if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )
165 .elseif .match ({register}, x)
168 .elseif .match ({register}, y)
172 .error "Invalid usage of macro 'SMC_TransferHighByte'"
176 .macro SMC_LoadHighByte label, register
177 .if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )
179 .elseif .match ({register}, x)
181 .elseif .match ({register}, y)
184 .error "Invalid usage of macro 'SMC_LoadHighByte'"
188 .macro SMC_StoreHighByte label, register
189 .if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )
191 .elseif .match ({register}, x)
193 .elseif .match ({register}, y)
196 .error "Invalid usage of macro 'SMC_StoreHighByte'"
200 .macro SMC_TransferAddressSingle label, address, register
201 .if .paramcount = 2 .or .match ((register), a) .or .match ({register}, )
202 .if (.match (.left (1, {address}), #))
204 lda #<(.right (.tcount ({address})-1, {address}))
206 lda #>(.right (.tcount ({address})-1, {address}))
209 ; assume absolute or zero page
215 .elseif .match ((register), x)
216 .if (.match (.left (1, {address}), #))
218 ldx #<(.right (.tcount ({address})-1, {address}))
220 ldx #>(.right (.tcount ({address})-1, {address}))
223 ; assume absolute or zero page
229 .elseif .match ((register), y)
230 .if (.match (.left (1, {address}), #))
232 ldy #<(.right (.tcount ({address})-1, {address}))
234 ldy #>(.right (.tcount ({address})-1, {address}))
237 ; assume absolute or zero page
244 .error "Invalid usage of macro 'SMC_TransferAddressSingle'"
248 .macro SMC_TransferAddress label, address
249 .if (.match (.left (1, {address}), #))
251 lda #<(.right (.tcount ({address})-1, {address}))
253 ldx #>(.right (.tcount ({address})-1, {address}))
256 ; assume absolute or zero page
260 stx _SMCDesignator)+2
264 .macro SMC_StoreAddress label