main
zruntime.S
1z_inccycles_io:
2 cmp %edi, %ebp
3 jnb do_limit
4no_sync_io:
5 add $4, %ebp
6 ret
7do_limit_io:
8 cmp 112(%rsi), %ebp
9 jb no_sync_io
10 jmp sync_io
11
12z_inccycles:
13 cmp %edi, %ebp
14 jnb do_limit
15no_sync:
16 add $3, %ebp
17 ret
18do_limit:
19 cmp 112(%rsi), %ebp
20 jb no_sync
21sync_io:
22 movw $0, 164(%rsi)
23 call z80_save_context_scratch
24 pop %rax /*return address in read/write func*/
25 pop 104(%rsi) /*return address in native code*/
26 sub $5, %rax /* adjust return addres to point to the call instruction that got us here */
27 mov %rax, (%rsi)
28
29 pop %r15 /* restore callee saved regsiters */
30 pop %r14
31 pop %r13
32 pop %r12
33 pop %rbp
34 pop %rbx
35 ret /* return to caller of z80_run */
36
37forced_sync:
38 movw $0, 164(%rsi)
39 call z80_save_context_scratch
40 pop (%rsi) /*return address in read/write func*/
41 pop 104(%rsi) /*return address in native code*/
42
43 pop %r15 /* restore callee saved regsiters */
44 pop %r14
45 pop %r13
46 pop %r12
47 pop %rbp
48 pop %rbx
49 ret /* return to caller of z80_run */
50
51 .global z80_handle_cycle_limit_int
52z80_handle_cycle_limit_int:
53 cmp 116(%rsi), %ebp
54 jb zskip_int
55 mov 112(%rsi), %ebp /* set cycle limit to sync cycle */
56 /* not sure this is really necessary now that IFF1 and IFF2 are geting cleared */
57 movl $0xFFFFFFFF, 116(%rsi) /* make sure the interrupt doesn't fire more than once */
58 /* disable interrupts */
59 movb $0, 96(%rsi)
60 movb $0, 97(%rsi)
61 add $7, %ebp
62 sub $2, %r9w
63 mov %r9w, %r14w
64 call z_inccycles
65 push %r13
66 call z80_write_byte_noinc
67 pop %r13
68 mov %r9w, %r14w
69 add $1, %r14w
70 shr $8, %r13w
71 call z_inccycles
72 call z80_write_byte_noinc
73 pop %r14 /*dispose of return address */
74 /* TODO: Support interrupt mode 0 and 2 */
75 mov $0x38, %r13w
76 call z80_native_addr
77 jmp *%r13
78zskip_int:
79 cmp 112(%rsi), %ebp
80 jb zskip_sync
81mov %r13w, 164(%rsi)
82 .global z80_do_sync
83z80_do_sync:
84 call z80_save_context
85 pop (%rsi) /*return address in native code*/
86 pop %r15 /* restore callee saved regsiters */
87 pop %r14
88 pop %r13
89 pop %r12
90 pop %rbp
91 pop %rbx
92zskip_sync:
93 ret
94
95 .global z80_halt
96z80_halt:
97 mov %edi, %r14d
98 sub %ebp, %r14d
99 and $0xFFFFFFFC, %r14d
100 add %r14d, %ebp
101 cmp %edi, %ebp
102 jnb z80_handle_cycle_limit_int
103 add $4, %ebp
104 jmp z80_handle_cycle_limit_int
105
106 .global z80_read_byte
107z80_read_byte:
108 call z_inccycles
109z80_read_byte_noinc:
110 cmp $0x4000, %r13w
111 jb z80_read_ram
112 cmp $0x8000, %r13w
113 jae z80_read_bank
114 cmp $0x6000, %r13w
115 jb z80_read_ym2612
116 /* TODO: Bank reg, YM-2612, PSG/VDP */
117 mov $0xFF, %r13b
118 ret
119z80_read_ram:
120 and $0x1FFF, %r13
121 mov (%r11, %r13), %r13b
122 ret
123z80_read_bank:
124 /* approximation of wait states for normal 68K bus access */
125 add $3, %ebp
126 push %rsi
127 mov 144(%rsi), %rsi /* get system context pointer */
128 cmpb $0, 120(%rsi) /* check bus busy flag */
129 pop %rsi
130 jne bus_busy
131z80_read_bank_cont:
132 and $0x7FFF, %r13
133 cmp $0, %r12
134 je slow_bank_read
135 /* 68K memory is byte swapped */
136 xor $1, %r13
137 mov (%r12, %r13), %r13b
138 ret
139slow_bank_read:
140 /* TODO: Call into C to implement this */
141 ret
142bus_busy:
143 cmp %ebp, %edi
144 jbe no_adjust
145 mov %edi, %ebp
146no_adjust:
147 call forced_sync
148 jmp z80_read_bank_cont
149z80_read_ym2612:
150 call z80_save_context
151 mov %r13w, %di
152 push %rsi
153 test $8, %rsp
154 jnz 0f
155 call z80_read_ym
156 jmp 1f
1570:
158 sub $8, %rsp
159 call z80_read_ym
160 add $8, %rsp
1611:
162 pop %rsi
163 mov %al, %r13b
164 call z80_load_context
165 ret
166
167 .global z80_write_byte
168z80_write_byte:
169 call z_inccycles
170z80_write_byte_noinc:
171 cmp $0x4000, %r14w
172 jb z80_write_ram
173 cmp $0x8000, %r14w
174 jae z80_write_bank
175 cmp $0x6000, %r14w
176 jb z80_write_ym2612
177 cmp $0x6100, %r14w
178 jb z80_write_bank_reg
179 cmp $0x7F00, %r14w
180 jae z80_write_vdp
181 ret
182z80_write_ram:
183 and $0x1FFF, %r14
184 mov %r13b, (%r11, %r14)
185 mov %r14d, %r13d
186 shr $7, %r13d
187 bt %r13d, 152(%rsi)
188 jnc not_code
189 call z80_save_context
190 mov %r14d, %edi
191 call z80_handle_code_write
192 mov %rax, %rsi
193 call z80_load_context
194not_code:
195 ret
196z80_write_bank:
197slow_bank_write:
198 /* approximation of wait states for 68K bus access */
199 add $3, %ebp
200 /* TODO: Call into C to implement this */
201 ret
202z80_write_ym2612:
203 and $0x3, %r14w
204 call z80_save_context
205 mov %r14w, %di
206 mov %r13b, %dl
207 test $8, %rsp
208 jnz 0f
209 call z80_write_ym
210 jmp 1f
2110:
212 sub $8, %rsp
213 call z80_write_ym
214 add $8, %rsp
2151:
216 mov %rax, %rsi
217 jmp z80_load_context
218z80_write_bank_reg:
219 and $1, %r13w
220 shr %r15w
221 shl $8, %r13w
222 xor %r12, %r12
223 or %r13w, %r15w
224 and $0x1FF, %r15w
225 cmp $0x80, %r15w
226 jb update_bank_ptr
227 ret
228update_bank_ptr:
229 mov %r15w, %r12w
230 shl $15, %r12
231 add 80(%rsi), %r12
232 ret
233z80_write_vdp:
234 and $0xFF, %r14w
235 call z80_save_context
236 mov %r14w, %di
237 mov %r13b, %dl
238 test $8, %rsp
239 jnz 0f
240 call z80_vdp_port_write
241 jmp 1f
2420:
243 sub $8, %rsp
244 call z80_vdp_port_write
245 add $8, %rsp
2461:
247 mov %rax, %rsi
248 jmp z80_load_context
249
250 .global z80_read_word
251z80_read_word:
252 call z_inccycles
253 cmp $0x8000, %r13w
254 jae z80_read_bank_word
255 push %r13
256 call z80_read_byte_noinc
257 mov %r13b, %r14b
258 pop %r13
259 inc %r13
260 call z_inccycles
261 call z80_read_byte_noinc
262 shl $8, %r13w
263 mov %r14b, %r13b
264 ret
265
266z80_read_bank_word:
267 add $3, %ebp /* first read typically has 3 wait states */
268 push %rsi
269 mov 144(%rsi), %rsi /* get system context pointer */
270 cmpb $0, 120(%rsi) /* check bus busy flag */
271 pop %rsi
272 jne bus_busy_word
273z80_read_bank_word_cont:
274 push %r13
275 call z80_read_bank_cont
276 mov %r13b, %r14b
277 pop %r13
278 inc %r13
279 call z_inccycles
280 add $4, %ebp /* second read typically has 4 wait states */
281 push %rsi
282 mov 144(%rsi), %rsi /* get system context pointer */
283 cmpb $0, 120(%rsi) /* check bus busy flag */
284 pop %rsi
285 jne bus_busy_word2
286z80_read_bank_word_cont2:
287 call z80_read_bank_cont
288 shl $8, %r13w
289 mov %r14b, %r13b
290 ret
291
292bus_busy_word:
293 cmp %ebp, %edi
294 jb no_adjust_word
295 mov %edi, %ebp
296no_adjust_word:
297 call forced_sync
298 jmp z80_read_bank_word_cont
299
300foofoo:
301 jmp foofoo
302
303bus_busy_word2:
304 cmp %ebp, %edi
305 jb no_adjust_word2
306 mov %edi, %ebp
307no_adjust_word2:
308 call forced_sync
309 jmp z80_read_bank_word_cont2
310blahblah:
311 jmp blahblah
312
313 .global z80_write_word_highfirst
314z80_write_word_highfirst:
315 call z_inccycles
316 push %r14
317 push %r13
318 add $1, %r14w
319 shr $8, %r13w
320 call z80_write_byte_noinc
321 pop %r13
322 pop %r14
323 call z_inccycles
324 call z80_write_byte_noinc
325 ret
326
327 .global z80_write_word_lowfirst
328z80_write_word_lowfirst:
329 call z_inccycles
330 push %r14
331 push %r13
332 call z80_write_byte_noinc
333 pop %r13
334 pop %r14
335 add $1, %r14w
336 shr $8, %r13w
337 call z_inccycles
338 call z80_write_byte_noinc
339 ret
340
341 .global z80_io_read
342z80_io_read:
343 call z_inccycles_io
344 /* genesis Z80 has no IO port hardware and always returns FF */
345 mov $0xFF, %r13
346 ret
347
348 .global z80_io_write
349z80_io_write:
350 call z_inccycles_io
351 /* genesis Z80 has no IO port hardware and writes have no effect */
352 ret
353
354 .global z80_retrans_stub
355z80_retrans_stub:
356 pop %r14
357 call z80_save_context
358 /* adjust for mov and call instructions */
359 sub $11, %r14
360 mov %r13d, %edi
361 mov %r14, %rdx
362 push %rsi
363 call z80_retranslate_inst
364 pop %rsi
365 mov %rax, %r13
366 call z80_load_context
367 jmp *%r13
368
369 .global z80_native_addr
370z80_native_addr:
371 call z80_save_context
372 push %rsi
373 mov %rsi, %rdi
374 movzx %r13w, %esi
375 call z80_get_native_address_trans
376 mov %rax, %r13
377 pop %rsi
378 call z80_load_context
379 ret
380
381z80_save_context_scratch:
382 mov %r13w, 98(%rsi) /* scratch1 */
383 mov %r14w, 100(%rsi) /* scratch2 */
384
385 .global z80_save_context
386z80_save_context:
387 mov %r9w, 8(%rsi) /* SP */
388 mov %r15w, 16(%rsi) /* bank register */
389 mov %bx, 18(%rsi) /* BC */
390 mov %cx, 20(%rsi) /* DE */
391 mov %ax, 22(%rsi) /* HL */
392 mov %dx, 24(%rsi) /* IX */
393 mov %r8w, 26(%rsi) /* IY */
394 mov %r10b, 30(%rsi) /* A */
395 mov %edi, 48(%rsi) /* target_cycle */
396 mov %ebp, 52(%rsi) /* current_cycle */
397 mov %r12, 72(%rsi) /* cartridge bank pointer */
398 ret
399
400
401z80_load_context_scratch:
402 mov 98(%rsi), %r13w /* scratch1 */
403 mov 100(%rsi), %r14w /* scratch2 */
404
405 .global z80_load_context
406z80_load_context:
407 mov 8(%rsi), %r9w /* SP */
408 mov 16(%rsi), %r15w /* bank register */
409 mov 18(%rsi), %bx /* BC */
410 mov 20(%rsi), %cx /* DE */
411 mov 22(%rsi), %ax /* HL */
412 mov 24(%rsi), %dx /* IX */
413 mov 26(%rsi), %r8w /* IY */
414 mov 30(%rsi), %r10b /* A */
415 mov 48(%rsi), %edi /* target_cycle */
416 mov 52(%rsi), %ebp /* current_cycle */
417 mov 64(%rsi), %r11 /* z80 RAM */
418 mov 72(%rsi), %r12 /* cartridge bank pointer */
419 ret
420
421 .global z80_run
422z80_run:
423 push %rbx
424 push %rbp
425 push %r12
426 push %r13
427 push %r14
428 push %r15
429 mov %rdi, %rsi
430 call z80_load_context_scratch
431 cmpq $0, 104(%rsi)
432 je no_extra
433 push 104(%rsi)
434 movq $0, 104(%rsi)
435no_extra:
436 jmp *(%rsi)
437