]> git.sur5r.net Git - cc65/blob - asminc/smc.inc
0583f79e0ba97a3eea7e0e7b2cf9b033fedb1a70
[cc65] / asminc / smc.inc
1 ; smc.mac
2 ; ca65 Macro-Pack for Self Modifying Code (SMC)
3 ;
4 ; (c) Christian Krüger, latest change: 17-Jul-2016
5 ;
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.
9 ;
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:
13 ;
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
21 ;    distribution.
22 ;
23
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
27 .define SMC_ZpAdr       $00
28 .define SMC_Opcode      nop
29 .define SMC_Value       $42
30
31 .macro SMC_OperateOnValue opcode, label
32         opcode _SMCDesignator+1
33 .endmacro
34
35 .macro SMC_OperateOnLowByte opcode, label
36         SMC_OperateOnValue opcode, label
37 .endmacro
38
39 .macro SMC_OperateOnHighByte opcode, label
40         opcode _SMCDesignator + 2
41 .endmacro
42
43 .macro SMC_Import alias
44 .import _SMCAlias
45 .endmacro
46
47 .macro SMC_Export alias, label
48 .export _SMCAlias := _SMCDesignator
49 .endmacro
50
51 .macro  SMC     label, statement
52 _SMCDesignator: statement
53 .endmacro
54
55 .macro SMC_TransferOpcode       label, opcode, register
56 .if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )
57         lda #opcode
58         sta _SMCDesignator
59 .elseif .match ({register}, x)
60         ldx #opcode
61         stx _SMCDesignator
62 .elseif .match ({register}, y)
63         ldy #opcode
64         sty _SMCDesignator
65 .else
66         .error "Invalid usage of macro 'SMC_TransferOpcode'"
67 .endif
68 .endmacro
69
70 .macro SMC_LoadOpcode   label, register
71 .if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )
72         lda _SMCDesignator
73 .elseif .match ({register}, x)
74         ldx _SMCDesignator
75 .elseif .match ({register}, y)
76         ldy _SMCDesignator
77 .else
78         .error "Invalid usage of macro 'SMC_LoadOpcode'"
79 .endif
80 .endmacro
81
82 .macro SMC_StoreOpcode  label, register
83 .if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )
84         sta _SMCDesignator
85 .elseif .match ({register}, x)
86         stx _SMCDesignator
87 .elseif .match ({register}, y)
88         sty _SMCDesignator
89 .else
90         .error "Invalid usage of macro 'SMC_StoreOpcode'"
91 .endif
92 .endmacro
93
94 .macro SMC_ChangeBranch         label, destination, register
95 .if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )
96         lda #(<(destination - _SMCDesignator -2))
97         sta _SMCDesignator+1
98 .elseif .match ({register}, x)
99         ldx #(<(destination - _SMCDesignator - 2))
100         stx _SMCDesignator+1
101 .elseif .match ({register}, y)
102         ldy #(<(destination - _SMCDesignator - 2))
103         sty _SMCDesignator+1
104 .else
105         .error "Invalid usage of macro 'SMC_ChangeBranch'"
106 .endif
107 .endmacro
108
109 .macro SMC_TransferValue        label, value, register
110 .if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )
111         lda value
112         sta _SMCDesignator+1
113 .elseif .match ({register}, x)
114         ldx value
115         stx _SMCDesignator+1
116 .elseif .match ({register}, y)
117         ldy value
118         sty _SMCDesignator+1
119 .else
120         .error "Invalid usage of macro 'SMC_TransferValue'"
121 .endif
122 .endmacro
123
124 .macro SMC_LoadValue    label, register
125 .if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )
126         lda _SMCDesignator+1
127 .elseif .match ({register}, x)
128         ldx _SMCDesignator+1
129 .elseif .match ({register}, y)
130         ldy _SMCDesignator+1
131 .else
132         .error "Invalid usage of macro 'SMC_LoadValue'"
133 .endif
134 .endmacro
135
136 .macro SMC_StoreValue   label, register
137 .if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )
138         sta _SMCDesignator+1
139 .elseif .match ({register}, x)
140         stx _SMCDesignator+1
141 .elseif .match ({register}, y)
142         sty _SMCDesignator+1
143 .else
144         .error "Invalid usage of macro 'SMC_StoreValue'"
145 .endif
146 .endmacro
147
148
149 .macro SMC_TransferLowByte      label, value, register
150 SMC_TransferValue label, value, register
151 .endmacro
152
153 .macro SMC_LoadLowByte  label, register
154 SMC_LoadValue label, register
155 .endmacro
156
157 .macro SMC_StoreLowByte label, register
158 SMC_StoreValue label, register
159 .endmacro
160
161 .macro SMC_TransferHighByte     label, value, register
162 .if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )
163         lda value
164         sta _SMCDesignator+2
165 .elseif .match ({register}, x)
166         ldx value
167         stx _SMCDesignator+2
168 .elseif .match ({register}, y)
169         ldy value
170         sty _SMCDesignator+2
171 .else
172         .error "Invalid usage of macro 'SMC_TransferHighByte'"
173 .endif
174 .endmacro
175
176 .macro SMC_LoadHighByte label, register
177 .if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )
178         lda _SMCDesignator+2
179 .elseif .match ({register}, x)
180         ldx _SMCDesignator+2
181 .elseif .match ({register}, y)
182         ldy _SMCDesignator+2
183 .else
184         .error "Invalid usage of macro 'SMC_LoadHighByte'"
185 .endif
186 .endmacro
187
188 .macro SMC_StoreHighByte        label, register
189 .if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )
190         sta _SMCDesignator+2
191 .elseif .match ({register}, x)
192         stx _SMCDesignator+2
193 .elseif .match ({register}, y)
194         sty _SMCDesignator+2
195 .else
196         .error "Invalid usage of macro 'SMC_StoreHighByte'"
197 .endif
198 .endmacro
199
200 .macro SMC_TransferAddressSingle        label, address, register
201 .if .paramcount = 2 .or .match ((register), a) .or .match ({register}, )
202         .if (.match (.left (1, {address}), #))
203                 ; immediate mode
204                 lda #<(.right (.tcount ({address})-1, {address}))
205                 sta _SMCDesignator+1
206                 lda #>(.right (.tcount ({address})-1, {address}))
207                 sta _SMCDesignator+2
208         .else
209                 ; assume absolute or zero page
210                 lda address
211                 sta _SMCDesignator+1
212                 lda 1+(address)
213                 sta _SMCDesignator+2
214         .endif
215 .elseif .match ((register), x)
216         .if (.match (.left (1, {address}), #))
217                 ; immediate mode
218                 ldx #<(.right (.tcount ({address})-1, {address}))
219                 stx _SMCDesignator+1
220                 ldx #>(.right (.tcount ({address})-1, {address}))
221                 stx _SMCDesignator+2
222         .else
223                 ; assume absolute or zero page
224                 ldx address
225                 stx _SMCDesignator+1
226                 ldx 1+(address)
227                 stx _SMCDesignator+2
228         .endif
229 .elseif .match ((register), y)
230         .if (.match (.left (1, {address}), #))
231                 ; immediate mode
232                 ldy #<(.right (.tcount ({address})-1, {address}))
233                 sty _SMCDesignator+1
234                 ldy #>(.right (.tcount ({address})-1, {address}))
235                 sty _SMCDesignator+2
236         .else
237                 ; assume absolute or zero page
238                 ldy address
239                 sty _SMCDesignator+1
240                 ldy 1+(address)
241                 sty _SMCDesignator+2
242         .endif
243 .else
244         .error "Invalid usage of macro 'SMC_TransferAddressSingle'"
245 .endif
246 .endmacro
247
248 .macro SMC_TransferAddress      label, address
249 .if (.match (.left (1, {address}), #))
250         ; immediate mode
251         lda #<(.right (.tcount ({address})-1, {address}))
252         sta _SMCDesignator+1
253         ldx #>(.right (.tcount ({address})-1, {address}))
254         stx _SMCDesignator+2
255 .else
256         ; assume absolute or zero page
257         lda {address}
258         sta _SMCDesignator+1
259         ldx 1+{address}
260         stx _SMCDesignator)+2
261 .endif
262 .endmacro
263
264 .macro SMC_StoreAddress label
265         sta _SMCDesignator+1
266         stx _SMCDesignator+2
267 .endmacro