-
Notifications
You must be signed in to change notification settings - Fork 0
/
sam.inc
393 lines (389 loc) · 11.3 KB
/
sam.inc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
;***************************************************************
;
; structured assembly macros (SAM)
;
;***************************************************************
; Copyright (C) 2010-2015 Klaus Dormann
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
;
; contact info at http://2m5.de or email [email protected]
;
; Version: 16.08.2015 - now avoids mix of DO and IF statements
; requires a current version of AVRASM2
;
;
;----------------------------------------------------------------
;
; IF-(THEN)-ELSE-END
;
; All need a common label as the last and mostly only parameter.
; Further if-then-else-end can be nested by asigning a different label.
; The macros create additional labels as needed:
; for example @0 = test creates
; t_test = begin of the THEN case
; e_test = end of the THEN case
; l_test = end of the ELSE case
; Condition dependent code execution:
; true = code after the IFxx or IFxx_far macro is executed
; false = code after the ELSE macro is executed, if ELSE exists
; all = remainder of the code is skipped up to the END macro
;
;
; IFxx(_yy) (<bit>,)<label>
; label of the next matching ELSE or END macro
; bit = on IFBS or IFBC - bit # in SREG
; _yy nothing = last or only IF implying THEN
; _far = THEN with long code (branch would be out of range)
; _and = multiple conditions, immediately jumps to END/ELSE if false
; _or = multiple conditions, immediately jumps to THEN if true
; xx ... = identical to BRxx instruction used with compares or any
; instruction altering the SREG
; s = skip - used with SBIx, SBRx or CPSE
;
;
; IFxx <label> translated to the underlying IFBS or IFBC
;
; SREG.C - bit 0, carry, no carry, lower, same or higher
;
#define ifcs ifbs 0,
#define ifcs_far ifbs_far 0,
#define ifcs_and ifbs_and 0,
#define ifcs_or ifbs_or 0,
#define ifcc ifbc 0,
#define ifcc_far ifbc_far 0,
#define ifcc_and ifbc_and 0,
#define ifcc_or ifbc_or 0,
#define iflo ifbs 0,
#define iflo_far ifbs_far 0,
#define iflo_and ifbs_and 0,
#define iflo_or ifbs_or 0,
#define ifsh ifbc 0,
#define ifsh_far ifbc_far 0,
#define ifsh_and ifbc_and 0,
#define ifsh_or ifbc_or 0,
;
; SREG.Z - bit 1, equal, not equal
;
#define ifeq ifbs 1,
#define ifeq_far ifbs_far 1,
#define ifeq_and ifbs_and 1,
#define ifeq_or ifbs_or 1,
#define ifne ifbc 1,
#define ifne_far ifbc_far 1,
#define ifne_and ifbc_and 1,
#define ifne_or ifbc_or 1,
;
; SREG.N - bit 2, minus, plus
;
#define ifmi ifbs 2,
#define ifmi_far ifbs_far 2,
#define ifmi_and ifbs_and 2,
#define ifmi_or ifbs_or 2,
#define ifpl ifbc 2,
#define ifpl_far ifbc_far 2,
#define ifpl_and ifbc_and 2,
#define ifpl_or ifbc_or 2,
;
; SREG.V - bit 3, overflow, no overflow
;
#define ifvs ifbs 3,
#define ifvs_far ifbs_far 3,
#define ifvs_and ifbs_and 3,
#define ifvs_or ifbs_or 3,
#define ifvc ifbc 3,
#define ifvc_far ifbc_far 3,
#define ifvc_and ifbc_and 3,
#define ifvc_or ifbc_or 3,
;
; SREG.S - bit 4, less than (signed), greater or equal (signed)
;
#define iflt ifbs 4,
#define iflt_far ifbs_far 4,
#define iflt_and ifbs_and 4,
#define iflt_or ifbs_or 4,
#define ifge ifbc 4,
#define ifge_far ifbc_far 4,
#define ifge_and ifbc_and 4,
#define ifge_or ifbc_or 4,
;
; SREG.H - bit 5, half carry, no half carry
;
#define ifhs ifbs 5,
#define ifhs_far ifbs_far 5,
#define ifhs_and ifbs_and 5,
#define ifhs_or ifbs_or 5,
#define ifhc ifbc 5,
#define ifhc_far ifbc_far 5,
#define ifhc_and ifbc_and 5,
#define ifhc_or ifbc_or 5,
;
; SREG.T - bit 6, T flag set, T flag clear
;
#define ifts ifbs 6,
#define ifts_far ifbs_far 6,
#define ifts_and ifbs_and 6,
#define ifts_or ifbs_or 6,
#define iftc ifbc 6,
#define iftc_far ifbc_far 6,
#define iftc_and ifbc_and 6,
#define iftc_or ifbc_or 6,
;
; SREG.I - bit 7, interrupt enabled, interrupt disabled
;
#define ifie ifbs 7,
#define ifie_far ifbs_far 7,
#define ifie_and ifbs_and 7,
#define ifie_or ifbs_or 7,
#define ifid ifbc 7,
#define ifid_far ifbc_far 7,
#define ifid_and ifbc_and 7,
#define ifid_or ifbc_or 7,
;
; IFBC <bit>,<label> - if bit is clear in SREG
;
.macro ifbc
brbs @0,e_@1
.equ t_@1 = PC
.endmacro
.macro ifbc_far
brbc @0,pc+2
rjmp e_@1
.equ t_@1 = PC
.endmacro
.macro ifbc_and
brbs @0,e_@1
.endmacro
.macro ifbc_or
brbc @0,t_@1
.endmacro
;
; IFBS <bit>,<label> - if bit is set in SREG
;
.macro ifbs
brbc @0,e_@1
.equ t_@1 = PC
.endmacro
.macro ifbs_far
brbs @0,pc+2
rjmp e_@1
.equ t_@1 = PC
.endmacro
.macro ifbs_and
brbc @0,e_@1
.endmacro
.macro ifbs_or
brbs @0,t_@1
.endmacro
;
; IFS <label> - if skip
;
.macro ifs
rjmp e_@0
.equ t_@0 = PC
.endmacro
; ifs is always far - just for completeness
.macro ifs_far
rjmp e_@0
.equ t_@0 = PC
.endmacro
.macro ifs_and
rjmp e_@0
.endmacro
.macro ifs_or
rjmp pc+2
rjmp t_@0
.endmacro
;
; ELSE <label>
; label of the matching IFxx & END macro
;
.macro else
.if !defined(t_@0)
.error "SAM: Else without If"
.endif
rjmp l_@0
.equ e_@0 = PC
.endmacro
;
; END <label>
; label of the previous matching IFxx or ELSE macro
;
.macro end
.if !defined(t_@0)
.error "SAM: End without If"
.endif
.if defined(e_@0)
.equ l_@0 = PC
.else
.equ e_@0 = PC
.endif
.endmacro
;
;----------------------------------------------------------------
;
; DO-LOOPxx or DO-(EXIT|EXITxx)-LOOP
;
; All need a common label as the last and mostly only parameter.
; Further do-loops can be nested by asigning a different label.
; The macros create an additional label as needed:
; for example <label> = main creates
; d_main = begin of loop
; x_main = end of loop (set by unconditional LOOP only)
;
; LOOPxx can only be used at the end of the do as an immediate
; loop, if condition xx is true similar to a loop-while statement.
; Multiple LOOPxx can be used to loop on multiple conditions. LOOPxx
; is suitable to construct typical FOR-NEXT loops and WHILE cases.
;
; To be able to exit a loop at any point, you need to use the EXITxx macro.
; This allows the construction of typical UNTIL cases. For everything else
; including anded conditions to loop or exit and whenever LOOPxx or EXITxx
; branches are out of range, use EXIT inside an if-block. Multiple EXITxx
; or EXIT macros can be used and mixed in one loop.
;
; EXITxx or EXIT require one and only one LOOP macro (not LOOPxx) to set
; the exit label. LOOPxx and LOOP can not be mixed.
;
;
;
; DO <label>
; label of the matching EXIT & LOOP or LOOPxx macros
;
.macro do
.equ d_@0 = PC
.endmacro
;
; EXIT <label>
; label of the matching DO & LOOP macros
;
.macro exit
.if !defined(d_@0)
.error "SAM: Exit without Do"
.endif
rjmp x_@0
.endmacro
;
; LOOP <label>
; label of the matching DO & EXIT macros
;
.macro loop
.if !defined(d_@0)
.error "SAM: Loop without Do"
.endif
rjmp d_@0
.equ x_@0 = PC
.endmacro
;
;
; LOOPxx <label> translated to the underlying LOOPBS or LOOPBC
; label of the matching DO macro
; EXITxx <label> translated to the underlying EXITBS or EXITBC
; label of the matching LOOP macro
;
; SREG.C - bit 0, carry, no carry, lower, same or higher
;
#define loopcs loopbs 0,
#define loopcc loopbc 0,
#define looplo loopbs 0,
#define loopsh loopbc 0,
#define exitcs exitbs 0,
#define exitcc exitbc 0,
#define exitlo exitbs 0,
#define exitsh exitbc 0,
;
; SREG.Z - bit 1, equal, not equal
;
#define loopeq loopbs 1,
#define loopne loopbc 1,
#define exiteq exitbs 1,
#define exitne exitbc 1,
;
; SREG.N - bit 2, minus, plus
;
#define loopmi loopbs 2,
#define looppl loopbc 2,
#define exitmi exitbs 2,
#define exitpl exitbc 2,
;
; SREG.V - bit 3, overflow, no overflow
;
#define loopvs loopbs 3,
#define loopvc loopbc 3,
#define exitvs exitbs 3,
#define exitvc exitbc 3,
;
; SREG.S - bit 4, less than (signed), greater or equal (signed)
;
#define looplt loopbs 4,
#define loopge loopbc 4,
#define exitlt exitbs 4,
#define exitge exitbc 4,
;
; SREG.H - bit 5, half carry, no half carry
;
#define loophs loopbs 5,
#define loophc loopbc 5,
#define exiths exitbs 5,
#define exithc exitbc 5,
;
; SREG.T - bit 6, T flag set, T flag clear
;
#define loopts loopbs 6,
#define looptc loopbc 6,
#define exitts exitbs 6,
#define exittc exitbc 6,
;
; SREG.I - bit 7, interrupt enabled, interrupt disabled
;
#define loopie loopbs 7,
#define loopid loopbc 7,
#define exitie exitbs 7,
#define exitid exitbc 7,
;
; LOOPBC <bit>,<label> - loop if bit is clear in SREG
;
.macro loopbc
.if !defined(d_@1)
.error "SAM: Loop without Do"
.endif
brbc @0,d_@1
.endmacro
;
; LOOPBS <bit>,<label> - loop if bit is set in SREG
;
.macro loopbs
.if !defined(d_@1)
.error "SAM: Loop without Do"
.endif
brbs @0,d_@1
.endmacro
;
; EXITBC <bit>,<label> - exit if bit is clear in SREG
;
.macro exitbc
.if !defined(d_@1)
.error "SAM: Exit without Do"
.endif
brbc @0,x_@1
.endmacro
;
; EXITBS <bit>,<label> - exit if bit is set in SREG
;
.macro exitbs
.if !defined(d_@1)
.error "SAM: Exit without Do"
.endif
brbs @0,x_@1
.endmacro