]> git.sur5r.net Git - cc65/blob - asminc/smc.inc
Merge pull request #335 from IrgendwerA8/SMC_macro_fixes
[cc65] / asminc / smc.inc
1 ; smc.mac\r
2 ; ca65 Macro-Pack for Self Modifying Code (SMC)\r
3 ;\r
4 ; (c) Christian Krüger, latest change: 17-Jul-2016\r
5 ;\r
6 ; This software is provided 'as-is', without any expressed or implied\r
7 ; warranty.  In no event will the authors be held liable for any damages\r
8 ; arising from the use of this software.\r
9 ;\r
10 ; Permission is granted to anyone to use this software for any purpose,\r
11 ; including commercial applications, and to alter it and redistribute it\r
12 ; freely, subject to the following restrictions:\r
13 ;\r
14 ; 1. The origin of this software must not be misrepresented; you must not\r
15 ;    claim that you wrote the original software. If you use this software\r
16 ;    in a product, an acknowledgment in the product documentation would be\r
17 ;    appreciated but is not required.\r
18 ; 2. Altered source versions must be plainly marked as such, and must not\r
19 ;    be misrepresented as being the original software.\r
20 ; 3. This notice may not be removed or altered from any source\r
21 ;    distribution.\r
22 ;\r
23 \r
24 .define _SMCDesignator  .mid(0, .tcount(label) - 1, label) .ident(.concat(.string(.right(1, label)), "_SMC"))\r
25 .define _SMCAlias       .mid(0, .tcount(alias) - 1, alias) .ident(.concat(.string(.right(1, alias)), "_SMC"))\r
26 .define SMC_AbsAdr      $FADE\r
27 .define SMC_ZpAdr       $00\r
28 .define SMC_Opcode      nop\r
29 .define SMC_Value       $42\r
30 \r
31 .macro SMC_OperateOnValue opcode, label\r
32         opcode _SMCDesignator+1\r
33 .endmacro\r
34 \r
35 .macro SMC_OperateOnLowByte opcode, label\r
36         SMC_OperateOnValue opcode, label\r
37 .endmacro\r
38 \r
39 .macro SMC_OperateOnHighByte opcode, label\r
40         opcode _SMCDesignator + 2\r
41 .endmacro\r
42 \r
43 .macro SMC_Import alias\r
44 .import _SMCAlias\r
45 .endmacro\r
46 \r
47 .macro SMC_Export alias, label\r
48 .export _SMCAlias := _SMCDesignator\r
49 .endmacro\r
50 \r
51 .macro  SMC     label, statement\r
52 _SMCDesignator: statement\r
53 .endmacro\r
54 \r
55 .macro SMC_TransferOpcode       label, opcode, register\r
56 .if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )\r
57         lda #opcode\r
58         sta _SMCDesignator\r
59 .elseif .match ({register}, x)\r
60         ldx #opcode\r
61         stx _SMCDesignator\r
62 .elseif .match ({register}, y)\r
63         ldy #opcode\r
64         sty _SMCDesignator\r
65 .else\r
66         .error "Invalid usage of macro 'SMC_TransferOpcode'"\r
67 .endif\r
68 .endmacro\r
69 \r
70 .macro SMC_LoadOpcode   label, register\r
71 .if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )\r
72         lda _SMCDesignator\r
73 .elseif .match ({register}, x)\r
74         ldx _SMCDesignator\r
75 .elseif .match ({register}, y)\r
76         ldy _SMCDesignator\r
77 .else\r
78         .error "Invalid usage of macro 'SMC_LoadOpcode'"\r
79 .endif\r
80 .endmacro\r
81 \r
82 .macro SMC_StoreOpcode  label, register\r
83 .if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )\r
84         sta _SMCDesignator\r
85 .elseif .match ({register}, x)\r
86         stx _SMCDesignator\r
87 .elseif .match ({register}, y)\r
88         sty _SMCDesignator\r
89 .else\r
90         .error "Invalid usage of macro 'SMC_StoreOpcode'"\r
91 .endif\r
92 .endmacro\r
93 \r
94 .macro SMC_ChangeBranch         label, destination, register\r
95 .if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )\r
96         lda #(<(destination - _SMCDesignator -2))\r
97         sta _SMCDesignator+1\r
98 .elseif .match ({register}, x)\r
99         ldx #(<(destination - _SMCDesignator - 2))\r
100         stx _SMCDesignator+1\r
101 .elseif .match ({register}, y)\r
102         ldy #(<(destination - _SMCDesignator - 2))\r
103         sty _SMCDesignator+1\r
104 .else\r
105         .error "Invalid usage of macro 'SMC_ChangeBranch'"\r
106 .endif\r
107 .endmacro\r
108 \r
109 .macro SMC_TransferValue        label, value, register\r
110 .if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )\r
111         lda value\r
112         sta _SMCDesignator+1\r
113 .elseif .match ({register}, x)\r
114         ldx value\r
115         stx _SMCDesignator+1\r
116 .elseif .match ({register}, y)\r
117         ldy value\r
118         sty _SMCDesignator+1\r
119 .else\r
120         .error "Invalid usage of macro 'SMC_TransferValue'"\r
121 .endif\r
122 .endmacro\r
123 \r
124 .macro SMC_LoadValue    label, register\r
125 .if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )\r
126         lda _SMCDesignator+1\r
127 .elseif .match ({register}, x)\r
128         ldx _SMCDesignator+1\r
129 .elseif .match ({register}, y)\r
130         ldy _SMCDesignator+1\r
131 .else\r
132         .error "Invalid usage of macro 'SMC_LoadValue'"\r
133 .endif\r
134 .endmacro\r
135 \r
136 .macro SMC_StoreValue   label, register\r
137 .if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )\r
138         sta _SMCDesignator+1\r
139 .elseif .match ({register}, x)\r
140         stx _SMCDesignator+1\r
141 .elseif .match ({register}, y)\r
142         sty _SMCDesignator+1\r
143 .else\r
144         .error "Invalid usage of macro 'SMC_StoreValue'"\r
145 .endif\r
146 .endmacro\r
147 \r
148 \r
149 .macro SMC_TransferLowByte      label, value, register\r
150 SMC_TransferValue label, value, register\r
151 .endmacro\r
152 \r
153 .macro SMC_LoadLowByte  label, register\r
154 SMC_LoadValue label, register\r
155 .endmacro\r
156 \r
157 .macro SMC_StoreLowByte label, register\r
158 SMC_StoreValue label, register\r
159 .endmacro\r
160 \r
161 .macro SMC_TransferHighByte     label, value, register\r
162 .if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )\r
163         lda value\r
164         sta _SMCDesignator+2\r
165 .elseif .match ({register}, x)\r
166         ldx value\r
167         stx _SMCDesignator+2\r
168 .elseif .match ({register}, y)\r
169         ldy value\r
170         sty _SMCDesignator+2\r
171 .else\r
172         .error "Invalid usage of macro 'SMC_TransferHighByte'"\r
173 .endif\r
174 .endmacro\r
175 \r
176 .macro SMC_LoadHighByte label, register\r
177 .if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )\r
178         lda _SMCDesignator+2\r
179 .elseif .match ({register}, x)\r
180         ldx _SMCDesignator+2\r
181 .elseif .match ({register}, y)\r
182         ldy _SMCDesignator+2\r
183 .else\r
184         .error "Invalid usage of macro 'SMC_LoadHighByte'"\r
185 .endif\r
186 .endmacro\r
187 \r
188 .macro SMC_StoreHighByte        label, register\r
189 .if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )\r
190         sta _SMCDesignator+2\r
191 .elseif .match ({register}, x)\r
192         stx _SMCDesignator+2\r
193 .elseif .match ({register}, y)\r
194         sty _SMCDesignator+2\r
195 .else\r
196         .error "Invalid usage of macro 'SMC_StoreHighByte'"\r
197 .endif\r
198 .endmacro\r
199 \r
200 .macro SMC_TransferAddressSingle        label, address, register\r
201 .if .paramcount = 2 .or .match ((register), a) .or .match ({register}, )\r
202         .if (.match (.left (1, {address}), #))\r
203                 ; immediate mode\r
204                 lda #<(.right (.tcount ({address})-1, {address}))\r
205                 sta _SMCDesignator+1\r
206                 lda #>(.right (.tcount ({address})-1, {address}))\r
207                 sta _SMCDesignator+2\r
208         .else\r
209                 ; assume absolute or zero page\r
210                 lda address\r
211                 sta _SMCDesignator+1\r
212                 lda 1+(address)\r
213                 sta _SMCDesignator+2\r
214         .endif\r
215 .elseif .match ((register), x)\r
216         .if (.match (.left (1, {address}), #))\r
217                 ; immediate mode\r
218                 ldx #<(.right (.tcount ({address})-1, {address}))\r
219                 stx _SMCDesignator+1\r
220                 ldx #>(.right (.tcount ({address})-1, {address}))\r
221                 stx _SMCDesignator+2\r
222         .else\r
223                 ; assume absolute or zero page\r
224                 ldx address\r
225                 stx _SMCDesignator+1\r
226                 ldx 1+(address)\r
227                 stx _SMCDesignator+2\r
228         .endif\r
229 .elseif .match ((register), y)\r
230         .if (.match (.left (1, {address}), #))\r
231                 ; immediate mode\r
232                 ldy #<(.right (.tcount ({address})-1, {address}))\r
233                 sty _SMCDesignator+1\r
234                 ldy #>(.right (.tcount ({address})-1, {address}))\r
235                 sty _SMCDesignator+2\r
236         .else\r
237                 ; assume absolute or zero page\r
238                 ldy address\r
239                 sty _SMCDesignator+1\r
240                 ldy 1+(address)\r
241                 sty _SMCDesignator+2\r
242         .endif\r
243 .else\r
244         .error "Invalid usage of macro 'SMC_TransferAddressSingle'"\r
245 .endif\r
246 .endmacro\r
247 \r
248 .macro SMC_TransferAddress      label, address\r
249 .if (.match (.left (1, {address}), #))\r
250         ; immediate mode\r
251         lda #<(.right (.tcount ({address})-1, {address}))\r
252         sta _SMCDesignator+1\r
253         ldx #>(.right (.tcount ({address})-1, {address}))\r
254         stx _SMCDesignator+2\r
255 .else\r
256         ; assume absolute or zero page\r
257         lda {address}\r
258         sta _SMCDesignator+1\r
259         ldx 1+{address}\r
260         stx _SMCDesignator)+2\r
261 .endif\r
262 .endmacro\r
263 \r
264 .macro SMC_StoreAddress label\r
265         sta _SMCDesignator+1\r
266         stx _SMCDesignator+2\r
267 .endmacro\r