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