drc: attempt to support little endian
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / linkage_x86_64.s
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  *   Mupen64plus - linkage_x86_64.s                                        *
3  *   Copyright (C) 2009-2010 Ari64                                         *
4  *                                                                         *
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.                                   *
9  *                                                                         *
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.                          *
14  *                                                                         *
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"
21         .bss
22         .align 4
23 //.globl rdram
24 //rdram = 0x80000000
25         .section        .rodata
26         .text
27 .globl dyna_linker
28         .type   dyna_linker, @function
29 dyna_linker:
30         /* eax = virtual target address */
31         /* ebx = instruction to patch */
32         mov     %eax, %edi
33         mov     %eax, %ecx
34         shr     $12, %edi
35         cmp     $0xC0000000, %eax
36         cmovge  tlb_LUT_r(,%edi,4), %ecx
37         test    %ecx, %ecx
38         cmovz   %eax, %ecx
39         xor     $0x80000000, %ecx
40         mov     $2047, %edx
41         shr     $12, %ecx
42         and     %ecx, %edx
43         or      $2048, %edx
44         cmp     %edx, %ecx
45         cmova   %edx, %ecx
46         /* jump_in lookup */
47         movq    jump_in(,%ecx,8), %r12
48 .A1:
49         test    %r12, %r12
50         je      .A3
51         mov     (%r12), %edi
52         xor     %eax, %edi
53         or      4(%r12), %edi
54         je      .A2
55         movq    16(%r12), %r12
56         jmp     .A1
57 .A2:
58         mov     (%ebx), %edi
59         mov     %esi, %ebp
60         lea     4(%ebx,%edi,1), %esi
61         mov     %eax, %edi
62         call    add_link
63         mov     8(%r12), %edi
64         mov     %ebp, %esi
65         lea     -4(%edi), %edx
66         subl    %ebx, %edx
67         movl    %edx, (%ebx)
68         jmp     *%rdi
69 .A3:
70         /* hash_table lookup */
71         mov     %eax, %edi
72         mov     %eax, %edx
73         shr     $16, %edi
74         shr     $12, %edx
75         xor     %eax, %edi
76         and     $2047, %edx
77         movzwl  %di, %edi
78         shl     $4, %edi
79         cmp     $2048, %ecx
80         cmovc   %edx, %ecx
81         cmp     hash_table(%edi), %eax
82         jne     .A5
83 .A4:
84         mov     hash_table+4(%edi), %edx
85         jmp     *%rdx
86 .A5:
87         cmp     hash_table+8(%edi), %eax
88         lea     8(%edi), %edi
89         je      .A4
90         /* jump_dirty lookup */
91         movq    jump_dirty(,%ecx,8), %r12
92 .A6:
93         test    %r12, %r12
94         je      .A8
95         mov     (%r12), %ecx
96         xor     %eax, %ecx
97         or      4(%r12), %ecx
98         je      .A7
99         movq    16(%r12), %r12
100         jmp     .A6
101 .A7:
102         movl    8(%r12), %edx
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)
110         jmp     *%rdx
111 .A8:
112         mov     %eax, %edi
113         mov     %eax, %ebp /* Note: assumes %rbx and %rbp are callee-saved */
114         mov     %esi, %r12d
115         call    new_recompile_block
116         test    %eax, %eax
117         mov     %ebp, %eax
118         mov     %r12d, %esi
119         je      dyna_linker
120         /* pagefault */
121         mov     %eax, %ebx
122         mov     $0x08, %ecx
123         .size   dyna_linker, .-dyna_linker
124
125 .globl exec_pagefault
126         .type   exec_pagefault, @function
127 exec_pagefault:
128         /* eax = instruction pointer */
129         /* ebx = fault address */
130         /* ecx = cause */
131         mov     reg_cop0+48, %edx
132         mov     reg_cop0+16, %edi
133         or      $2, %edx
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 */
139         mov     %ebx, %ecx
140         shr     $9, %ebx
141         and     $0xFFFFE000, %ecx
142         and     $0x007FFFF0, %ebx
143         mov     %ecx, reg_cop0+40 /* EntryHI */
144         or      %ebx, %edi
145         mov     %edi, reg_cop0+16 /* Context */
146         mov     %esi, %ebx
147         mov     $0x80000000, %edi
148         call    get_addr_ht
149         mov     %ebx, %esi
150         jmp     *%rax
151         .size   exec_pagefault, .-exec_pagefault
152
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
157 dyna_linker_ds:
158         mov     %eax, %edi
159         mov     %eax, %ecx
160         shr     $12, %edi
161         cmp     $0xC0000000, %eax
162         cmovge  tlb_LUT_r(,%edi,4), %ecx
163         test    %ecx, %ecx
164         cmovz   %eax, %ecx
165         xor     $0x80000000, %ecx
166         mov     $2047, %edx
167         shr     $12, %ecx
168         and     %ecx, %edx
169         or      $2048, %edx
170         cmp     %edx, %ecx
171         cmova   %edx, %ecx
172         /* jump_in lookup */
173         movq    jump_in(,%ecx,8), %r12
174 .B1:
175         test    %r12, %r12
176         je      .B3
177         mov     (%r12), %edi
178         xor     %eax, %edi
179         or      4(%r12), %edi
180         je      .B2
181         movq    16(%r12), %r12
182         jmp     .B1
183 .B2:
184         mov     (%ebx), %edi
185         mov     %esi, %r13d
186         lea     4(%ebx,%edi,1), %esi
187         mov     %eax, %edi
188         call    add_link
189         mov     8(%r12), %edi
190         mov     %r13d, %esi
191         lea     -4(%edi), %edx
192         subl    %ebx, %edx
193         movl    %edx, (%ebx)
194         jmp     *%rdi
195 .B3:
196         /* hash_table lookup */
197         mov     %eax, %edi
198         mov     %eax, %edx
199         shr     $16, %edi
200         shr     $12, %edx
201         xor     %eax, %edi
202         and     $2047, %edx
203         movzwl  %di, %edi
204         shl     $4, %edi
205         cmp     $2048, %ecx
206         cmovc   %edx, %ecx
207         cmp     hash_table(%edi), %eax
208         jne     .B5
209 .B4:
210         mov     hash_table+4(%edi), %edx
211         jmp     *%rdx
212 .B5:
213         cmp     hash_table+8(%edi), %eax
214         lea     8(%edi), %edi
215         je      .B4
216         /* jump_dirty lookup */
217         movq    jump_dirty(,%ecx,8), %r12
218 .B6:
219         test    %r12, %r12
220         je      .B8
221         mov     (%r12), %ecx
222         xor     %eax, %ecx
223         or      4(%r12), %ecx
224         je      .B7
225         movq    16(%r12), %r12
226         jmp     .B6
227 .B7:
228         movl    8(%r12), %edx
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)
236         jmp     *%rdx
237 .B8:
238         mov     %eax, %edi
239         mov     %eax, %r12d /* Note: assumes %rbx and %rbp are callee-saved */
240         and     $0xFFFFFFF8, %edi
241         mov     %esi, %r13d
242         inc     %edi
243         call    new_recompile_block
244         test    %eax, %eax
245         mov     %r12d, %eax
246         mov     %r13d, %esi
247         je      dyna_linker_ds
248         /* pagefault */
249         and     $0xFFFFFFF8, %eax
250         mov     $0x80000008, %ecx /* High bit set indicates pagefault in delay slot */
251         mov     %eax, %ebx
252         sub     $4, %eax
253         jmp     exec_pagefault
254         .size   dyna_linker_ds, .-dyna_linker_ds
255
256 .globl jump_vaddr_eax
257         .type   jump_vaddr_eax, @function
258 jump_vaddr_eax:
259         mov     %eax, %edi
260         jmp     jump_vaddr_edi
261         .size   jump_vaddr_eax, .-jump_vaddr_eax
262 .globl jump_vaddr_ecx
263         .type   jump_vaddr_ecx, @function
264 jump_vaddr_ecx:
265         mov     %ecx, %edi
266         jmp     jump_vaddr_edi
267         .size   jump_vaddr_ecx, .-jump_vaddr_ecx
268 .globl jump_vaddr_edx
269         .type   jump_vaddr_edx, @function
270 jump_vaddr_edx:
271         mov     %edx, %edi
272         jmp     jump_vaddr_edi
273         .size   jump_vaddr_edx, .-jump_vaddr_edx
274 .globl jump_vaddr_ebx
275         .type   jump_vaddr_ebx, @function
276 jump_vaddr_ebx:
277         mov     %ebx, %edi
278         jmp     jump_vaddr_edi
279         .size   jump_vaddr_ebx, .-jump_vaddr_ebx
280 .globl jump_vaddr_ebp
281         .type   jump_vaddr_ebp, @function
282 jump_vaddr_ebp:
283         mov     %ebp, %edi
284         .size   jump_vaddr_ebp, .-jump_vaddr_ebp
285 .globl jump_vaddr_edi
286         .type   jump_vaddr_edi, @function
287 jump_vaddr_edi:
288         mov     %edi, %eax
289         .size   jump_vaddr_edi, .-jump_vaddr_edi
290
291 .globl jump_vaddr
292         .type   jump_vaddr, @function
293 jump_vaddr:
294   /* Check hash table */
295         shr     $16, %eax
296         xor     %edi, %eax
297         movzwl  %ax, %eax
298         shl     $4, %eax
299         cmp     hash_table(%eax), %edi
300         jne     .C2
301 .C1:
302         mov     hash_table+4(%eax), %edi
303         jmp     *%rdi
304 .C2:
305         cmp     hash_table+8(%eax), %edi
306         lea     8(%eax), %eax
307         je      .C1
308   /* No hit on hash table, call compiler */
309         mov     %esi, cycle_count /* CCREG */
310         call    get_addr
311         mov     cycle_count, %esi
312         jmp     *%rax
313         .size   jump_vaddr, .-jump_vaddr
314
315 .globl verify_code_ds
316         .type   verify_code_ds, @function
317 verify_code_ds:
318         nop
319         .size   verify_code_ds, .-verify_code_ds
320
321 .globl verify_code_vm
322         .type   verify_code_vm, @function
323 verify_code_vm:
324         /* eax = source (virtual address) */
325         /* ebx = target */
326         /* ecx = length */
327         cmp     $0xC0000000, %eax
328         jl      verify_code
329         mov     %eax, %edx
330         lea     -1(%eax,%ecx,1), %r9d
331         shr     $12, %edx
332         shr     $12, %r9d
333         mov     memory_map(,%edx,4), %edi
334         test    %edi, %edi
335         js      .D4
336         lea     (%eax,%edi,4), %eax
337         mov     %edi, %r8d
338 .D1:
339         xor     memory_map(,%edx,4), %edi
340         shl     $2, %edi
341         jne     .D4
342         mov     %r8d, %edi
343         inc     %edx
344         cmp     %r9d, %edx
345         jbe     .D1
346         .size   verify_code_vm, .-verify_code_vm
347
348 .globl verify_code
349         .type   verify_code, @function
350 verify_code:
351         /* eax = source */
352         /* ebx = target */
353         /* ecx = length */
354         /* r12d = instruction pointer */
355         mov     -4(%eax,%ecx,1), %edi
356         xor     -4(%ebx,%ecx,1), %edi
357         jne     .D4
358         mov     %ecx, %edx
359         add     $-4, %ecx
360         je      .D3
361         test    $4, %edx
362         cmove   %edx, %ecx
363 .D2:
364         mov     -8(%eax,%ecx,1), %rdi
365         cmp     -8(%ebx,%ecx,1), %rdi
366         jne     .D4
367         add     $-8, %ecx
368         jne     .D2
369 .D3:
370         ret
371 .D4:
372         add     $8, %rsp /* pop return address, we're not returning */
373         mov     %r12d, %edi
374         mov     %esi, %ebx
375         call    get_addr
376         mov     %ebx, %esi
377         jmp     *%rax
378         .size   verify_code, .-verify_code
379
380 .globl cc_interrupt
381         .type   cc_interrupt, @function
382 cc_interrupt:
383         add     last_count, %esi
384         add     $-8, %rsp /* Align stack */
385         mov     %esi, reg_cop0+36 /* Count */
386         shr     $19, %esi
387         movl    $0, pending_exception
388         and     $0x7f, %esi
389         cmpl    $0, restore_candidate(,%esi,4)
390         jne     .E4
391 .E1:
392         call    gen_interupt
393         mov     reg_cop0+36, %esi
394         mov     next_interupt, %eax
395         mov     pending_exception, %ebx
396         mov     stop, %ecx
397         add     $8, %rsp
398         mov     %eax, last_count
399         sub     %eax, %esi
400         test    %ecx, %ecx
401         jne     .E3
402         test    %ebx, %ebx
403         jne     .E2
404         ret
405 .E2:
406         mov     pcaddr, %edi
407         mov     %esi, cycle_count /* CCREG */
408         call    get_addr_ht
409         mov     cycle_count, %esi
410         add     $8, %rsp /* pop return address */
411         jmp     *%rax
412 .E3:
413         pop     %rbp /* pop return address and discard it */
414         pop     %rbp /* pop junk */
415         pop     %r15 /* restore callee-save registers */
416         pop     %r14
417         pop     %r13
418         pop     %r12
419         pop     %rbx
420         pop     %rbp
421         ret          /* exit dynarec */
422 .E4:
423         /* Move 'dirty' blocks to the 'clean' list */
424         mov     restore_candidate(,%esi,4), %ebx
425         mov     %esi, %ebp
426         movl    $0, restore_candidate(,%esi,4)
427         shl     $5, %ebp
428 .E5:
429         shr     $1, %ebx
430         jnc     .E6
431         mov     %ebp, %edi
432         call    clean_blocks
433 .E6:
434         inc     %ebp
435         test    $31, %ebp
436         jne     .E5
437         jmp     .E1
438         .size   cc_interrupt, .-cc_interrupt
439
440 .globl do_interrupt
441         .type   do_interrupt, @function
442 do_interrupt:
443         mov     pcaddr, %edi
444         call    get_addr_ht
445         mov     reg_cop0+36, %esi
446         mov     next_interupt, %ebx
447         mov     %ebx, last_count
448         sub     %ebx, %esi
449         add     $2, %esi
450         jmp     *%rax
451         .size   do_interrupt, .-do_interrupt
452
453 .globl fp_exception
454         .type   fp_exception, @function
455 fp_exception:
456         mov     $0x1000002c, %edx
457 .E7:
458         mov     reg_cop0+48, %ebx
459         or      $2, %ebx
460         mov     %ebx, reg_cop0+48 /* Status */
461         mov     %edx, reg_cop0+52 /* Cause */
462         mov     %eax, reg_cop0+56 /* EPC */
463         mov     %esi, %ebx
464         mov     $0x80000180, %edi
465         call    get_addr_ht
466         mov     %ebx, %esi
467         jmp     *%rax
468         .size   fp_exception, .-fp_exception
469
470 .globl fp_exception_ds
471         .type   fp_exception_ds, @function
472 fp_exception_ds:
473         mov     $0x9000002c, %edx /* Set high bit if delay slot */
474         jmp     .E7
475         .size   fp_exception_ds, .-fp_exception_ds
476
477 .globl jump_syscall
478         .type   jump_syscall, @function
479 jump_syscall:
480         mov     $0x20, %edx
481         mov     reg_cop0+48, %ebx
482         or      $2, %ebx
483         mov     %ebx, reg_cop0+48 /* Status */
484         mov     %edx, reg_cop0+52 /* Cause */
485         mov     %eax, reg_cop0+56 /* EPC */
486         mov     %esi, %ebx
487         mov     $0x80000180, %edi
488         call    get_addr_ht
489         mov     %ebx, %esi
490         jmp     *%rax
491         .size   jump_syscall, .-jump_syscall
492
493 .globl jump_eret
494         .type   jump_eret, @function
495 jump_eret:
496         mov     reg_cop0+48, %ebx /* Status */
497         add     last_count, %esi
498         and     $0xFFFFFFFD, %ebx
499         mov     %esi, reg_cop0+36 /* Count */
500         mov     %ebx, reg_cop0+48 /* Status */
501         call    check_interupt
502         mov     next_interupt, %eax
503         mov     reg_cop0+36, %esi
504         mov     %eax, last_count
505         sub     %eax, %esi
506         mov     reg_cop0+56, %edi /* EPC */
507         jns     .E11
508 .E8:
509         mov     %esi, %r12d
510         mov     $248, %ebx
511         xor     %esi, %esi
512 .E9:
513         mov     reg(%ebx), %ecx
514         mov     reg+4(%ebx), %edx
515         sar     $31, %ecx
516         xor     %ecx, %edx
517         neg     %edx
518         adc     %esi, %esi
519         sub     $8, %ebx
520         jne     .E9
521         mov     hi(%ebx), %ecx
522         mov     hi+4(%ebx), %edx
523         sar     $31, %ecx
524         xor     %ecx, %edx
525         jne     .E10
526         mov     lo(%ebx), %ecx
527         mov     lo+4(%ebx), %edx
528         sar     $31, %ecx
529         xor     %ecx, %edx
530 .E10:
531         neg     %edx
532         adc     %esi, %esi
533         call    get_addr_32
534         mov     %r12d, %esi
535         jmp     *%rax
536 .E11:
537         mov     %edi, pcaddr
538         call    cc_interrupt
539         mov     pcaddr, %edi
540         jmp     .E8
541         .size   jump_eret, .-jump_eret
542
543 .globl new_dyna_start
544         .type   new_dyna_start, @function
545 new_dyna_start:
546         push    %rbp
547         push    %rbx
548         push    %r12
549         push    %r13
550         push    %r14
551         push    %r15
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
558         subl    %edi, %esi
559         jmp     0x70000000
560         .size   new_dyna_start, .-new_dyna_start
561
562 .globl write_rdram_new
563         .type   write_rdram_new, @function
564 write_rdram_new:
565         mov     address, %edi
566         mov     word, %ecx
567         and     $0x7FFFFFFF, %edi
568         mov     %ecx, rdram(%rdi)
569         jmp     .E12
570         .size   write_rdram_new, .-write_rdram_new
571
572 .globl write_rdramb_new
573         .type   write_rdramb_new, @function
574 write_rdramb_new:
575         mov     address, %edi
576         xor     $3, %edi
577         movb    byte, %cl
578         and     $0x7FFFFFFF, %edi
579         movb    %cl, rdram(%rdi)
580         jmp     .E12
581         .size   write_rdramb_new, .-write_rdramb_new
582
583 .globl write_rdramh_new
584         .type   write_rdramh_new, @function
585 write_rdramh_new:
586         mov     address, %edi
587         xor     $2, %edi
588         movw    hword, %cx
589         and     $0x7FFFFFFF, %edi
590         movw    %cx, rdram(%rdi)
591         jmp     .E12
592         .size   write_rdramh_new, .-write_rdramh_new
593
594 .globl write_rdramd_new
595         .type   write_rdramd_new, @function
596 write_rdramd_new:
597         mov     address, %edi
598         mov     dword+4, %ecx
599         mov     dword, %edx
600         and     $0x7FFFFFFF, %edi
601         mov     %ecx, rdram(%rdi)
602         mov     %edx, rdram+4(%rdi)
603         jmp     .E12
604         .size   write_rdramd_new, .-write_rdramd_new
605
606 .globl do_invalidate
607         .type   do_invalidate, @function
608 do_invalidate:
609         mov     address, %edi
610         mov     %edi, %ebx /* Return ebx to caller */
611 .E12:
612         shr     $12, %edi
613         mov     %edi, %r12d /* Return r12 to caller */
614         cmpb    $1, invalid_code(%edi)
615         je      .E13
616         call    invalidate_block
617 .E13:
618         ret
619         .size   do_invalidate, .-do_invalidate
620
621 .globl read_nomem_new
622         .type   read_nomem_new, @function
623 read_nomem_new:
624         mov     address, %edi
625         mov     %edi, %ebx
626         shr     $12, %edi
627         mov     memory_map(,%edi,4),%edi
628         mov     $0x8, %eax
629         test    %edi, %edi
630         js      tlb_exception
631         mov     (%ebx,%edi,4), %ecx
632         mov     %ecx, readmem_dword
633         ret
634         .size   read_nomem_new, .-read_nomem_new
635
636 .globl read_nomemb_new
637         .type   read_nomemb_new, @function
638 read_nomemb_new:
639         mov     address, %edi
640         mov     %edi, %ebx
641         shr     $12, %edi
642         mov     memory_map(,%edi,4),%edi
643         mov     $0x8, %eax
644         test    %edi, %edi
645         js      tlb_exception
646         xor     $3, %ebx
647         movzbl  (%ebx,%edi,4), %ecx
648         mov     %ecx, readmem_dword
649         ret
650         .size   read_nomemb_new, .-read_nomemb_new
651
652 .globl read_nomemh_new
653         .type   read_nomemh_new, @function
654 read_nomemh_new:
655         mov     address, %edi
656         mov     %edi, %ebx
657         shr     $12, %edi
658         mov     memory_map(,%edi,4),%edi
659         mov     $0x8, %eax
660         test    %edi, %edi
661         js      tlb_exception
662         xor     $2, %ebx
663         movzwl  (%ebx,%edi,4), %ecx
664         mov     %ecx, readmem_dword
665         ret
666         .size   read_nomemh_new, .-read_nomemh_new
667
668 .globl read_nomemd_new
669         .type   read_nomemd_new, @function
670 read_nomemd_new:
671         mov     address, %edi
672         mov     %edi, %ebx
673         shr     $12, %edi
674         mov     memory_map(,%edi,4),%edi
675         mov     $0x8, %eax
676         test    %edi, %edi
677         js      tlb_exception
678         mov     4(%ebx,%edi,4), %ecx
679         mov     (%ebx,%edi,4), %edx
680         mov     %ecx, readmem_dword
681         mov     %edx, readmem_dword+4
682         ret
683         .size   read_nomemd_new, .-read_nomemd_new
684
685 .globl write_nomem_new
686         .type   write_nomem_new, @function
687 write_nomem_new:
688         call    do_invalidate
689         mov     memory_map(,%r12d,4),%edi
690         mov     word, %ecx
691         mov     $0xc, %eax
692         shl     $2, %edi
693         jc      tlb_exception
694         mov     %ecx, (%ebx,%edi)
695         ret
696         .size   write_nomem_new, .-write_nomem_new
697
698 .globl write_nomemb_new
699         .type   write_nomemb_new, @function
700 write_nomemb_new:
701         call    do_invalidate
702         mov     memory_map(,%r12d,4),%edi
703         movb    byte, %cl
704         mov     $0xc, %eax
705         shl     $2, %edi
706         jc      tlb_exception
707         xor     $3, %ebx
708         movb    %cl, (%ebx,%edi)
709         ret
710         .size   write_nomemb_new, .-write_nomemb_new
711
712 .globl write_nomemh_new
713         .type   write_nomemh_new, @function
714 write_nomemh_new:
715         call    do_invalidate
716         mov     memory_map(,%r12d,4),%edi
717         movw    hword, %cx
718         mov     $0xc, %eax
719         shl     $2, %edi
720         jc      tlb_exception
721         xor     $2, %ebx
722         movw    %cx, (%ebx,%edi)
723         ret
724         .size   write_nomemh_new, .-write_nomemh_new
725
726 .globl write_nomemd_new
727         .type   write_nomemd_new, @function
728 write_nomemd_new:
729         call    do_invalidate
730         mov     memory_map(,%r12d,4),%edi
731         mov     dword+4, %edx
732         mov     dword, %ecx
733         mov     $0xc, %eax
734         shl     $2, %edi
735         jc      tlb_exception
736         mov     %edx, (%ebx,%edi)
737         mov     %ecx, 4(%ebx,%edi)
738         ret
739         .size   write_nomemd_new, .-write_nomemd_new
740
741 .globl tlb_exception
742         .type   tlb_exception, @function
743 tlb_exception:
744         /* eax = cause */
745         /* ebx = address */
746         /* ebp = instr addr + flags */
747         mov     8(%rsp), %ebp
748         mov     reg_cop0+48, %esi
749         mov     %ebp, %ecx
750         mov     %ebp, %edx
751         mov     %ebp, %edi
752         shl     $31, %ebp
753         shr     $12, %ecx
754         or      %ebp, %eax
755         sar     $29, %ebp
756         and     $0xFFFFFFFC, %edx
757         mov     memory_map(,%ecx,4), %ecx
758         or      $2, %esi
759         mov     (%edx, %ecx, 4), %ecx
760         add     %ebp, %edx
761         mov     %esi, reg_cop0+48 /* Status */
762         mov     %eax, reg_cop0+52 /* Cause */
763         mov     %edx, reg_cop0+56 /* EPC */
764         add     $0x48, %rsp
765         mov     $0x6000022, %edx
766         mov     %ecx, %ebp
767         movswl  %cx, %eax
768         shr     $26, %ecx
769         shr     $21, %ebp
770         sub     %eax, %ebx
771         and     $0x1f, %ebp
772         ror     %cl, %edx
773         mov     reg_cop0+16, %esi
774         cmovc   reg(,%ebp,8), %ebx
775         and     $0xFF80000F, %esi
776         mov     %ebx, reg(,%ebp,8)
777         add     %ebx, %eax
778         sar     $31, %ebx
779         mov     %eax, reg_cop0+32 /* BadVAddr */
780         shr     $9, %eax
781         test    $2, %edi
782         cmove   reg+4(,%ebp,8), %ebx
783         and     $0x007FFFF0, %eax
784         mov     $0x80000180, %edi
785         mov     %ebx, reg+4(,%ebp,8)
786         or      %eax, %esi
787         mov     %esi, reg_cop0+16 /* Context */
788         call    get_addr_ht
789         movl    next_interupt, %edi
790         movl    reg_cop0+36, %esi /* Count */
791         movl    %edi, last_count
792         subl    %edi, %esi
793         jmp     *%rax
794         .size   tlb_exception, .-tlb_exception