1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Mupen64plus - linkage_x86_64.s *
3 * Copyright (C) 2009-2010 Ari64 *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
20 .file "linkage_x86_64.s"
28 .type dyna_linker, @function
30 /* eax = virtual target address */
31 /* ebx = instruction to patch */
36 cmovge tlb_LUT_r(,%edi,4), %ecx
47 movq jump_in(,%ecx,8), %r12
60 lea 4(%ebx,%edi,1), %esi
70 /* hash_table lookup */
81 cmp hash_table(%edi), %eax
84 mov hash_table+4(%edi), %edx
87 cmp hash_table+8(%edi), %eax
90 /* jump_dirty lookup */
91 movq jump_dirty(,%ecx,8), %r12
103 /* hash_table insert */
104 mov hash_table-8(%edi), %ebx
105 mov hash_table-4(%edi), %ecx
106 mov %eax, hash_table-8(%edi)
107 mov %edx, hash_table-4(%edi)
108 mov %ebx, hash_table(%edi)
109 mov %ecx, hash_table+4(%edi)
113 mov %eax, %ebp /* Note: assumes %rbx and %rbp are callee-saved */
115 call new_recompile_block
123 .size dyna_linker, .-dyna_linker
125 .globl exec_pagefault
126 .type exec_pagefault, @function
128 /* eax = instruction pointer */
129 /* ebx = fault address */
131 mov reg_cop0+48, %edx
132 mov reg_cop0+16, %edi
134 mov %ebx, reg_cop0+32 /* BadVAddr */
135 and $0xFF80000F, %edi
136 mov %edx, reg_cop0+48 /* Status */
137 mov %ecx, reg_cop0+52 /* Cause */
138 mov %eax, reg_cop0+56 /* EPC */
141 and $0xFFFFE000, %ecx
142 and $0x007FFFF0, %ebx
143 mov %ecx, reg_cop0+40 /* EntryHI */
145 mov %edi, reg_cop0+16 /* Context */
147 mov $0x80000000, %edi
151 .size exec_pagefault, .-exec_pagefault
153 /* Special dynamic linker for the case where a page fault
154 may occur in a branch delay slot */
155 .globl dyna_linker_ds
156 .type dyna_linker_ds, @function
161 cmp $0xC0000000, %eax
162 cmovge tlb_LUT_r(,%edi,4), %ecx
165 xor $0x80000000, %ecx
173 movq jump_in(,%ecx,8), %r12
186 lea 4(%ebx,%edi,1), %esi
196 /* hash_table lookup */
207 cmp hash_table(%edi), %eax
210 mov hash_table+4(%edi), %edx
213 cmp hash_table+8(%edi), %eax
216 /* jump_dirty lookup */
217 movq jump_dirty(,%ecx,8), %r12
229 /* hash_table insert */
230 mov hash_table-8(%edi), %ebx
231 mov hash_table-4(%edi), %ecx
232 mov %eax, hash_table-8(%edi)
233 mov %edx, hash_table-4(%edi)
234 mov %ebx, hash_table(%edi)
235 mov %ecx, hash_table+4(%edi)
239 mov %eax, %r12d /* Note: assumes %rbx and %rbp are callee-saved */
240 and $0xFFFFFFF8, %edi
243 call new_recompile_block
249 and $0xFFFFFFF8, %eax
250 mov $0x80000008, %ecx /* High bit set indicates pagefault in delay slot */
254 .size dyna_linker_ds, .-dyna_linker_ds
256 .globl jump_vaddr_eax
257 .type jump_vaddr_eax, @function
261 .size jump_vaddr_eax, .-jump_vaddr_eax
262 .globl jump_vaddr_ecx
263 .type jump_vaddr_ecx, @function
267 .size jump_vaddr_ecx, .-jump_vaddr_ecx
268 .globl jump_vaddr_edx
269 .type jump_vaddr_edx, @function
273 .size jump_vaddr_edx, .-jump_vaddr_edx
274 .globl jump_vaddr_ebx
275 .type jump_vaddr_ebx, @function
279 .size jump_vaddr_ebx, .-jump_vaddr_ebx
280 .globl jump_vaddr_ebp
281 .type jump_vaddr_ebp, @function
284 .size jump_vaddr_ebp, .-jump_vaddr_ebp
285 .globl jump_vaddr_edi
286 .type jump_vaddr_edi, @function
289 .size jump_vaddr_edi, .-jump_vaddr_edi
292 .type jump_vaddr, @function
294 /* Check hash table */
299 cmp hash_table(%eax), %edi
302 mov hash_table+4(%eax), %edi
305 cmp hash_table+8(%eax), %edi
308 /* No hit on hash table, call compiler */
309 mov %esi, cycle_count /* CCREG */
311 mov cycle_count, %esi
313 .size jump_vaddr, .-jump_vaddr
315 .globl verify_code_ds
316 .type verify_code_ds, @function
319 .size verify_code_ds, .-verify_code_ds
321 .globl verify_code_vm
322 .type verify_code_vm, @function
324 /* eax = source (virtual address) */
327 cmp $0xC0000000, %eax
330 lea -1(%eax,%ecx,1), %r9d
333 mov memory_map(,%edx,4), %edi
336 lea (%eax,%edi,4), %eax
339 xor memory_map(,%edx,4), %edi
346 .size verify_code_vm, .-verify_code_vm
349 .type verify_code, @function
354 /* r12d = instruction pointer */
355 mov -4(%eax,%ecx,1), %edi
356 xor -4(%ebx,%ecx,1), %edi
364 mov -8(%eax,%ecx,1), %rdi
365 cmp -8(%ebx,%ecx,1), %rdi
372 add $8, %rsp /* pop return address, we're not returning */
378 .size verify_code, .-verify_code
381 .type cc_interrupt, @function
384 add $-8, %rsp /* Align stack */
385 mov %esi, reg_cop0+36 /* Count */
387 movl $0, pending_exception
389 cmpl $0, restore_candidate(,%esi,4)
393 mov reg_cop0+36, %esi
394 mov next_interupt, %eax
395 mov pending_exception, %ebx
407 mov %esi, cycle_count /* CCREG */
409 mov cycle_count, %esi
410 add $8, %rsp /* pop return address */
413 pop %rbp /* pop return address and discard it */
414 pop %rbp /* pop junk */
415 pop %r15 /* restore callee-save registers */
421 ret /* exit dynarec */
423 /* Move 'dirty' blocks to the 'clean' list */
424 mov restore_candidate(,%esi,4), %ebx
426 movl $0, restore_candidate(,%esi,4)
438 .size cc_interrupt, .-cc_interrupt
441 .type do_interrupt, @function
445 mov reg_cop0+36, %esi
446 mov next_interupt, %ebx
451 .size do_interrupt, .-do_interrupt
454 .type fp_exception, @function
456 mov $0x1000002c, %edx
458 mov reg_cop0+48, %ebx
460 mov %ebx, reg_cop0+48 /* Status */
461 mov %edx, reg_cop0+52 /* Cause */
462 mov %eax, reg_cop0+56 /* EPC */
464 mov $0x80000180, %edi
468 .size fp_exception, .-fp_exception
470 .globl fp_exception_ds
471 .type fp_exception_ds, @function
473 mov $0x9000002c, %edx /* Set high bit if delay slot */
475 .size fp_exception_ds, .-fp_exception_ds
478 .type jump_syscall, @function
481 mov reg_cop0+48, %ebx
483 mov %ebx, reg_cop0+48 /* Status */
484 mov %edx, reg_cop0+52 /* Cause */
485 mov %eax, reg_cop0+56 /* EPC */
487 mov $0x80000180, %edi
491 .size jump_syscall, .-jump_syscall
494 .type jump_eret, @function
496 mov reg_cop0+48, %ebx /* Status */
498 and $0xFFFFFFFD, %ebx
499 mov %esi, reg_cop0+36 /* Count */
500 mov %ebx, reg_cop0+48 /* Status */
502 mov next_interupt, %eax
503 mov reg_cop0+36, %esi
506 mov reg_cop0+56, %edi /* EPC */
514 mov reg+4(%ebx), %edx
541 .size jump_eret, .-jump_eret
543 .globl new_dyna_start
544 .type new_dyna_start, @function
552 mov $0xa4000040, %edi
553 call new_recompile_block
554 add $-8, %rsp /* align stack */
555 movl next_interupt, %edi
556 movl reg_cop0+36, %esi
557 movl %edi, last_count
560 .size new_dyna_start, .-new_dyna_start
562 .globl write_rdram_new
563 .type write_rdram_new, @function
567 and $0x7FFFFFFF, %edi
568 mov %ecx, rdram(%rdi)
570 .size write_rdram_new, .-write_rdram_new
572 .globl write_rdramb_new
573 .type write_rdramb_new, @function
578 and $0x7FFFFFFF, %edi
579 movb %cl, rdram(%rdi)
581 .size write_rdramb_new, .-write_rdramb_new
583 .globl write_rdramh_new
584 .type write_rdramh_new, @function
589 and $0x7FFFFFFF, %edi
590 movw %cx, rdram(%rdi)
592 .size write_rdramh_new, .-write_rdramh_new
594 .globl write_rdramd_new
595 .type write_rdramd_new, @function
600 and $0x7FFFFFFF, %edi
601 mov %ecx, rdram(%rdi)
602 mov %edx, rdram+4(%rdi)
604 .size write_rdramd_new, .-write_rdramd_new
607 .type do_invalidate, @function
610 mov %edi, %ebx /* Return ebx to caller */
613 mov %edi, %r12d /* Return r12 to caller */
614 cmpb $1, invalid_code(%edi)
616 call invalidate_block
619 .size do_invalidate, .-do_invalidate
621 .globl read_nomem_new
622 .type read_nomem_new, @function
627 mov memory_map(,%edi,4),%edi
631 mov (%ebx,%edi,4), %ecx
632 mov %ecx, readmem_dword
634 .size read_nomem_new, .-read_nomem_new
636 .globl read_nomemb_new
637 .type read_nomemb_new, @function
642 mov memory_map(,%edi,4),%edi
647 movzbl (%ebx,%edi,4), %ecx
648 mov %ecx, readmem_dword
650 .size read_nomemb_new, .-read_nomemb_new
652 .globl read_nomemh_new
653 .type read_nomemh_new, @function
658 mov memory_map(,%edi,4),%edi
663 movzwl (%ebx,%edi,4), %ecx
664 mov %ecx, readmem_dword
666 .size read_nomemh_new, .-read_nomemh_new
668 .globl read_nomemd_new
669 .type read_nomemd_new, @function
674 mov memory_map(,%edi,4),%edi
678 mov 4(%ebx,%edi,4), %ecx
679 mov (%ebx,%edi,4), %edx
680 mov %ecx, readmem_dword
681 mov %edx, readmem_dword+4
683 .size read_nomemd_new, .-read_nomemd_new
685 .globl write_nomem_new
686 .type write_nomem_new, @function
689 mov memory_map(,%r12d,4),%edi
694 mov %ecx, (%ebx,%edi)
696 .size write_nomem_new, .-write_nomem_new
698 .globl write_nomemb_new
699 .type write_nomemb_new, @function
702 mov memory_map(,%r12d,4),%edi
708 movb %cl, (%ebx,%edi)
710 .size write_nomemb_new, .-write_nomemb_new
712 .globl write_nomemh_new
713 .type write_nomemh_new, @function
716 mov memory_map(,%r12d,4),%edi
722 movw %cx, (%ebx,%edi)
724 .size write_nomemh_new, .-write_nomemh_new
726 .globl write_nomemd_new
727 .type write_nomemd_new, @function
730 mov memory_map(,%r12d,4),%edi
736 mov %edx, (%ebx,%edi)
737 mov %ecx, 4(%ebx,%edi)
739 .size write_nomemd_new, .-write_nomemd_new
742 .type tlb_exception, @function
746 /* ebp = instr addr + flags */
748 mov reg_cop0+48, %esi
756 and $0xFFFFFFFC, %edx
757 mov memory_map(,%ecx,4), %ecx
759 mov (%edx, %ecx, 4), %ecx
761 mov %esi, reg_cop0+48 /* Status */
762 mov %eax, reg_cop0+52 /* Cause */
763 mov %edx, reg_cop0+56 /* EPC */
773 mov reg_cop0+16, %esi
774 cmovc reg(,%ebp,8), %ebx
775 and $0xFF80000F, %esi
776 mov %ebx, reg(,%ebp,8)
779 mov %eax, reg_cop0+32 /* BadVAddr */
782 cmove reg+4(,%ebp,8), %ebx
783 and $0x007FFFF0, %eax
784 mov $0x80000180, %edi
785 mov %ebx, reg+4(,%ebp,8)
787 mov %esi, reg_cop0+16 /* Context */
789 movl next_interupt, %edi
790 movl reg_cop0+36, %esi /* Count */
791 movl %edi, last_count
794 .size tlb_exception, .-tlb_exception