-
Notifications
You must be signed in to change notification settings - Fork 74
/
s2.macrosetup.asm
319 lines (283 loc) · 6.96 KB
/
s2.macrosetup.asm
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
padding off ; we don't want AS padding out dc.b instructions
;listing off ; We don't need to generate anything for a listing file
;listing on ; Want full listing file
;listing noskipped ; Want listing file, but only the non-skipped part of conditional assembly
listing purecode ; Want listing file, but only the final code in expanded macros
page 0 ; Don't want form feeds
supmode on ; we don't need warnings about privileged instructions
paddingSoFar set 0
; 128 = 80h = z80, 32988 = 80DCh = z80unDoC
notZ80 function cpu,(cpu<>128)&&(cpu<>32988)
; make org safer (impossible to overwrite previously assembled bytes) and count padding
; and also make it work in Z80 code without creating a new segment
org macro address
if notZ80(MOMCPU)
if address < *
error "too much stuff before org $\{address} ($\{(*-address)} bytes)"
elseif address > *
paddingSoFar set paddingSoFar + address - *
!org address
endif
else
if address < $
error "too much stuff before org 0\{address}h (0\{($-address)}h bytes)"
else
while address > $
db 0
endm
endif
endif
endm
; define the cnop pseudo-instruction
cnop macro offset,alignment
if notZ80(MOMCPU)
org (*-1+(alignment)-((*-1+(-(offset)))#(alignment)))
else
org ($-1+(alignment)-(($-1+(-(offset)))#(alignment)))
endif
endm
; redefine align in terms of cnop, for the padding counter
align macro alignment
cnop 0,alignment
endm
; define the even pseudo-instruction
even macro
if notZ80(MOMCPU)
if (*)&1
paddingSoFar set paddingSoFar+1
dc.b 0 ;ds.b 1
endif
else
if ($)&1
db 0
endif
endif
endm
; make ds work in Z80 code without creating a new segment
ds macro
if notZ80(MOMCPU)
!ds.ATTRIBUTE ALLARGS
else
rept ALLARGS
db 0
endm
endif
endm
if TRUE
; define a trace macro
; lets you easily check what address a location in this disassembly assembles to
; if used in Z80 code, the displayed PC will be relative to the start of Z80 RAM
trace macro optionalMessageWithoutQuotes
if MOMPASS=1
if notZ80(MOMCPU)
if ("ALLARGS"<>"")
message "#\{tracenum/1.0}: line=\{MOMLINE/1.0} PC=$\{*} msg=ALLARGS"
else
message "#\{tracenum/1.0}: line=\{MOMLINE/1.0} PC=$\{*}"
endif
else
if ("ALLARGS"<>"")
message "#\{tracenum/1.0}: line=\{MOMLINE/1.0} PC=\{$}h msg=ALLARGS"
else
message "#\{tracenum/1.0}: line=\{MOMLINE/1.0} PC=\{$}h"
endif
endif
tracenum := (tracenum+1)
endif
endm
else
trace macro
endm
endif
tracenum := 0
if zeroOffsetOptimization=0
; disable a space optimization in AS so we can build a bit-perfect ROM
; (the hard way, but it requires no modification of AS itself)
chkop function op,ref,(substr(lowstring(op),0,strlen(ref))<>ref)
; 1-arg instruction that's self-patching to remove 0-offset optimization
insn1op macro oper,x
if (chkop("x","0(") && chkop("x","id(") && chkop("x","slot_rout(") && chkop("x","soundqueue.music0("))
!oper x
else
!oper 1+x
!org *-1
!dc.b 0
endif
endm
; 2-arg instruction that's self-patching to remove 0-offset optimization
insn2op macro oper,x,y
if (chkop("x","0(") && chkop("x","id(") && chkop("x","slot_rout(") && chkop("x","soundqueue.music0("))
if (chkop("y","0(") && chkop("y","id(") && chkop("y","slot_rout(") && chkop("y","soundqueue.music0("))
!oper x,y
else
!oper x,1+y
!org *-1
!dc.b 0
endif
else
if chkop("y","d")
if (chkop("y","0(") && chkop("y","id(") && chkop("y","slot_rout(") && chkop("y","soundqueue.music0("))
start:
!oper 1+x,y
end:
!org start+3
!dc.b 0
!org end
else
!oper 1+x,1+y
!org *-3
!dc.b 0
!org *+1
!dc.b 0
endif
else
!oper 1+x,y
!org *-1
!dc.b 0
endif
endif
endm
; instructions that were used with 0(a#) syntax
; defined to assemble as they originally did
_move macro
insn2op move.ATTRIBUTE, ALLARGS
endm
_add macro
insn2op add.ATTRIBUTE, ALLARGS
endm
_addq macro
insn2op addq.ATTRIBUTE, ALLARGS
endm
_cmp macro
insn2op cmp.ATTRIBUTE, ALLARGS
endm
_cmpi macro
insn2op cmpi.ATTRIBUTE, ALLARGS
endm
_clr macro
insn1op clr.ATTRIBUTE, ALLARGS
endm
_tst macro
insn1op tst.ATTRIBUTE, ALLARGS
endm
else
; regular meaning to the assembler; better but unlike original
_move macro
!move.ATTRIBUTE ALLARGS
endm
_add macro
!add.ATTRIBUTE ALLARGS
endm
_addq macro
!addq.ATTRIBUTE ALLARGS
endm
_cmp macro
!cmp.ATTRIBUTE ALLARGS
endm
_cmpi macro
!cmpi.ATTRIBUTE ALLARGS
endm
_clr macro
!clr.ATTRIBUTE ALLARGS
endm
_tst macro
!tst.ATTRIBUTE ALLARGS
endm
endif
; in REV02, almost all possible add/sub optimizations were made.
; this toggle allows you to have them in any revision
if addsubOptimize
; if addsubOptimize, optimize these
addi_ macro
!addq.ATTRIBUTE ALLARGS
endm
subi_ macro
!subq.ATTRIBUTE ALLARGS
endm
adda_ macro
!addq.ATTRIBUTE ALLARGS
endm
else
; otherwise, leave them unoptimized
addi_ macro
!addi.ATTRIBUTE ALLARGS
endm
subi_ macro
!subi.ATTRIBUTE ALLARGS
endm
adda_ macro
!adda.ATTRIBUTE ALLARGS
endm
endif
; depending on if relativeLea is set or not, this will create a pc-relative lea or an absolute long lea.
lea_ macro address,reg
if relativeLea
!lea address(pc),reg
else
!lea (address).l,reg
endif
endm
; This 'even' will only exist in REV02. It is unnecessary, presumably being
; automatically generated by the assembler after 'dc.b' opcodes.
rev02even macro
if gameRevision=2
even
endif
endm
; Discard everything before the first underscore.
; This expects that every JmpTo label start with 'JmpTo_'.
extractJmpToName function name,val(substr(name, strstr(name, "_") + 1, strlen(name)))
; depending on if removeJmpTos is set or not, these macros will create a jump directly
; to the destination, or create a branch to a JmpTo
jsrto macro indirectaddr
if removeJmpTos
!jsr (extractJmpToName("indirectaddr")).l ; jump directly to address
else
!bsr.w indirectaddr ; otherwise, branch to an indirect JmpTo
endif
endm
jmpto macro indirectaddr
if removeJmpTos
!jmp (extractJmpToName("indirectaddr")).l ; jump directly to address
else
!bra.w indirectaddr ; otherwise, branch to an indirect JmpTo
endif
endm
jmpTosInternal2 macro
if ARGCOUNT>0
irp op,ALLARGS
op label *
jmp (extractJmpToName("op")).l
endm
endif
endm
jmpTosInternal macro UseNop
if ~~removeJmpTos
if (*)&2
; I wish I understood what really controls this.
if UseNop
nop
else
align 4
endif
endif
shift
jmpTosInternal2 ALLARGS
align 4
endif
endm
; Output list of JmpTos, pad start with a NOP instuction.
jmpTos macro
jmpTosInternal TRUE,ALLARGS
endm
; Output list of JmpTos, pad start with zeroes.
jmpTos0 macro
jmpTosInternal FALSE,ALLARGS
endm
bit function nBits,1<<(nBits-1)
signmask function val,nBits,-((-(val&bit(nBits)))&bit(nBits))
signextend function val,nBits,(val+signmask(val,nBits))!signmask(val,nBits)
signextendB function val,signextend(val,8)
roundFloatToInteger function float,INT(float+0.5)
min function a,b,b!((a!b)&(-(a<b)))
max function a,b,a!((a!b)&(-(a<b)))