1;Mupen64plus - linkage_x86.asm
2;Copyright (C) 2009-2011 Ari64
3;
4;This program is free software; you can redistribute it and/or modify
5;it under the terms of the GNU General Public License as published by
6;the Free Software Foundation; either version 2 of the License, or
7;(at your option) any later version.
8;
9;This program is distributed in the hope that it will be useful,
10;but WITHOUT ANY WARRANTY; without even the implied warranty of
11;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12;GNU General Public License for more details.
13;
14;You should have received a copy of the GNU General Public License
15;along with this program; if not, write to the
16;Free Software Foundation, Inc.,
17;51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
19%ifdef ELF_TYPE
20    %macro  cglobal 1
21      global  %1
22    %endmacro
23
24    %macro  cextern 1
25      extern  %1
26    %endmacro
27%else
28    %macro  cglobal 1
29      global  _%1
30      %define %1 _%1
31    %endmacro
32
33    %macro  cextern 1
34      extern  _%1
35      %define %1 _%1
36    %endmacro
37%endif
38
39cglobal dyna_linker
40cglobal dyna_linker_ds
41cglobal jump_vaddr_eax
42cglobal jump_vaddr_ecx
43cglobal jump_vaddr_edx
44cglobal jump_vaddr_ebx
45cglobal jump_vaddr_ebp
46cglobal jump_vaddr_edi
47cglobal verify_code_ds
48cglobal verify_code_vm
49cglobal verify_code
50cglobal cc_interrupt
51cglobal do_interrupt
52cglobal fp_exception
53cglobal fp_exception_ds
54cglobal jump_syscall
55cglobal jump_eret
56cglobal new_dyna_start
57cglobal invalidate_block_eax
58cglobal invalidate_block_ecx
59cglobal invalidate_block_edx
60cglobal invalidate_block_ebx
61cglobal invalidate_block_ebp
62cglobal invalidate_block_esi
63cglobal invalidate_block_edi
64cglobal write_rdram_new
65cglobal write_rdramb_new
66cglobal write_rdramh_new
67cglobal write_rdramd_new
68cglobal read_nomem_new
69cglobal read_nomemb_new
70cglobal read_nomemh_new
71cglobal read_nomemd_new
72cglobal write_nomem_new
73cglobal write_nomemb_new
74cglobal write_nomemh_new
75cglobal write_nomemd_new
76cglobal write_mi_new
77cglobal write_mib_new
78cglobal write_mih_new
79cglobal write_mid_new
80cglobal breakpoint
81
82cextern base_addr
83cextern tlb_LUT_r
84cextern jump_in
85cextern add_link
86cextern hash_table
87cextern jump_dirty
88cextern new_recompile_block
89cextern g_cp0_regs
90cextern get_addr_ht
91cextern cycle_count
92cextern get_addr
93cextern branch_target
94cextern memory_map
95cextern pending_exception
96cextern restore_candidate
97cextern gen_interrupt
98cextern next_interrupt
99cextern stop
100cextern last_count
101cextern pcaddr
102cextern clean_blocks
103cextern reg
104cextern hi
105cextern lo
106cextern invalidate_block
107cextern address
108cextern g_rdram
109cextern cpu_byte
110cextern cpu_hword
111cextern cpu_word
112cextern cpu_dword
113cextern invalid_code
114cextern readmem_dword
115cextern check_interrupt
116cextern get_addr_32
117cextern write_mi
118cextern write_mib
119cextern write_mih
120cextern write_mid
121cextern TLB_refill_exception_new
122
123section .bss
124align 4
125
126section .rodata
127section .text
128
129dyna_linker:
130    ;eax = virtual target address
131    ;ebx = instruction to patch
132    mov     edi,    eax
133    mov     ecx,    eax
134    shr     edi,    12
135    cmp     eax,    0C0000000h
136    cmovge  ecx,    [tlb_LUT_r+edi*4]
137    test    ecx,    ecx
138    cmovz   ecx,    eax
139    xor     ecx,    080000000h
140    mov     edx,    2047
141    shr     ecx,    12
142    and     edx,    ecx
143    or      edx,    2048
144    cmp     ecx,    edx
145    cmova   ecx,    edx
146    ;jump_in lookup
147    mov     edx,    [jump_in+ecx*4]
148_A1:
149    test    edx,    edx
150    je      _A3
151    mov     edi,    [edx]
152    xor     edi,    eax
153    or      edi,    [4+edx]
154    je      _A2
155    mov     edx,    DWORD [12+edx]
156    jmp     _A1
157_A2:
158    mov     edi,    [ebx]
159    mov     ebp,    esi
160    lea     esi,    [4+ebx+edi*1]
161    mov     edi,    eax
162    pusha
163    call    add_link
164    popa
165    mov     edi,    [8+edx]
166    mov     esi,    ebp
167    lea     edx,    [-4+edi]
168    sub     edx,    ebx
169    mov     DWORD [ebx],    edx
170    jmp     edi
171_A3:
172    ;hash_table lookup
173    mov     edi,    eax
174    mov     edx,    eax
175    shr     edi,    16
176    shr     edx,    12
177    xor     edi,    eax
178    and     edx,    2047
179    movzx   edi,    di
180    shl     edi,    4
181    cmp     ecx,    2048
182    cmovc   ecx,    edx
183    cmp     eax,    [hash_table+edi]
184    jne     _A5
185_A4:
186    mov     edx,    [hash_table+4+edi]
187    jmp     edx
188_A5:
189    cmp     eax,    [hash_table+8+edi]
190    lea     edi,    [8+edi]
191    je      _A4
192    ;jump_dirty lookup
193    mov     edx,    [jump_dirty+ecx*4]
194_A6:
195    test    edx,    edx
196    je      _A8
197    mov     ecx,    [edx]
198    xor     ecx,    eax
199    or      ecx,    [4+edx]
200    je      _A7
201    mov     edx,    DWORD [12+edx]
202    jmp     _A6
203_A7:
204    mov     edx,    [8+edx]
205    ;hash_table insert
206    mov     ebx,    [hash_table-8+edi]
207    mov     ecx,    [hash_table-4+edi]
208    mov     [hash_table-8+edi],    eax
209    mov     [hash_table-4+edi],    edx
210    mov     [hash_table+edi],      ebx
211    mov     [hash_table+4+edi],    ecx
212    jmp     edx
213_A8:
214    mov     edi,    eax
215    pusha
216    call    new_recompile_block
217    test    eax,    eax
218    popa
219    je      dyna_linker
220    ;pagefault
221    mov     ebx,    eax
222    mov     ecx,    008h
223
224exec_pagefault:
225    ;eax = instruction pointer
226    ;ebx = fault address
227    ;ecx = cause
228    mov     edx,    [g_cp0_regs+48]
229    add     esp,    -12
230    mov     edi,    [g_cp0_regs+16]
231    or      edx,    2
232    mov     [g_cp0_regs+32],    ebx        ;BadVAddr
233    and     edi,    0FF80000Fh
234    mov     [g_cp0_regs+48],    edx        ;Status
235    mov     [g_cp0_regs+52],    ecx        ;Cause
236    mov     [g_cp0_regs+56],    eax        ;EPC
237    mov     ecx,    ebx
238    shr     ebx,    9
239    and     ecx,    0FFFFE000h
240    and     ebx,    0007FFFF0h
241    mov     [g_cp0_regs+40],    ecx        ;EntryHI
242    or      edi,    ebx
243    mov     [g_cp0_regs+16],    edi        ;Context
244    push     080000000h
245    call    get_addr_ht
246    add     esp,    16
247    jmp     eax
248
249;Special dynamic linker for the case where a page fault
250;may occur in a branch delay slot
251dyna_linker_ds:
252    mov     edi,    eax
253    mov     ecx,    eax
254    shr     edi,    12
255    cmp     eax,    0C0000000h
256    cmovge  ecx,    [tlb_LUT_r+edi*4]
257    test    ecx,    ecx
258    cmovz   ecx,    eax
259    xor     ecx,    080000000h
260    mov     edx,    2047
261    shr     ecx,    12
262    and     edx,    ecx
263    or      edx,    2048
264    cmp     ecx,    edx
265    cmova   ecx,    edx
266    ;jump_in lookup
267    mov     edx,    [jump_in+ecx*4]
268_B1:
269    test    edx,    edx
270    je      _B3
271    mov     edi,    [edx]
272    xor     edi,    eax
273    or      edi,    [4+edx]
274    je      _B2
275    mov     edx,    DWORD [12+edx]
276    jmp     _B1
277_B2:
278    mov     edi,    [ebx]
279    mov     ecx,    esi
280    lea     esi,    [4+ebx+edi*1]
281    mov     edi,    eax
282    pusha
283    call    add_link
284    popa
285    mov     edi,    [8+edx]
286    mov     esi,    ecx
287    lea     edx,    [-4+edi]
288    sub     edx,    ebx
289    mov     DWORD [ebx],    edx
290    jmp     edi
291_B3:
292    ;hash_table lookup
293    mov     edi,    eax
294    mov     edx,    eax
295    shr     edi,    16
296    shr     edx,    12
297    xor     edi,    eax
298    and     edx,    2047
299    movzx   edi,    di
300    shl     edi,    4
301    cmp     ecx,    2048
302    cmovc   ecx,    edx
303    cmp     eax,    [hash_table+edi]
304    jne     _B5
305_B4:
306    mov     edx,    [hash_table+4+edi]
307    jmp     edx
308_B5:
309    cmp     eax,    [hash_table+8+edi]
310    lea     edi,    [8+edi]
311    je      _B4
312    ;jump_dirty lookup
313    mov     edx,    [jump_dirty+ecx*4]
314_B6:
315    test    edx,    edx
316    je      _B8
317    mov     ecx,    [edx]
318    xor     ecx,    eax
319    or      ecx,    [4+edx]
320    je      _B7
321    mov     edx,    DWORD [12+edx]
322    jmp     _B6
323_B7:
324    mov     edx,    [8+edx]
325    ;hash_table insert
326    mov     ebx,    [hash_table-8+edi]
327    mov     ecx,    [hash_table-4+edi]
328    mov     [hash_table-8+edi],    eax
329    mov     [hash_table-4+edi],    edx
330    mov     [hash_table+edi],      ebx
331    mov     [hash_table+4+edi],    ecx
332    jmp     edx
333_B8:
334    mov     edi,    eax
335    and     edi,    0FFFFFFF8h
336    inc     edi
337    pusha
338    call    new_recompile_block
339    test    eax,    eax
340    popa
341    je      dyna_linker_ds
342    ;pagefault
343    and     eax,    0FFFFFFF8h
344    mov     ecx,    080000008h    ;High bit set indicates pagefault in delay slot
345    mov     ebx,    eax
346    sub     eax,    4
347    jmp     exec_pagefault
348
349jump_vaddr_eax:
350    mov     edi,    eax
351    jmp     jump_vaddr_edi
352
353jump_vaddr_ecx:
354    mov     edi,    ecx
355    jmp     jump_vaddr_edi
356
357jump_vaddr_edx:
358    mov     edi,    edx
359    jmp     jump_vaddr_edi
360
361jump_vaddr_ebx:
362    mov     edi,    ebx
363    jmp     jump_vaddr_edi
364
365jump_vaddr_ebp:
366    mov     edi,    ebp
367
368jump_vaddr_edi:
369    mov     eax,    edi
370
371jump_vaddr:
372    ;Check hash table
373    shr     eax,    16
374    xor     eax,    edi
375    movzx   eax,    ax
376    shl     eax,    4
377    cmp     edi,    [hash_table+eax]
378    jne     _C2
379_C1:
380    mov     edi,    [hash_table+4+eax]
381    jmp     edi
382_C2:
383    cmp     edi,    [hash_table+8+eax]
384    lea     eax,    [8+eax]
385    je      _C1
386    ;No hit on hash table, call compiler
387    add     esp,    -12
388    push    edi
389    mov     [cycle_count],    esi    ;CCREG
390    call    get_addr
391    mov     esi,    [cycle_count]
392    add     esp,    16
393    jmp     eax
394
395verify_code_ds:
396    mov     [branch_target],    ebp
397
398verify_code_vm:
399    ;eax = source (virtual address)
400    ;ebx = target
401    ;ecx = length
402    cmp     eax,    0C0000000h
403    jl      verify_code
404    mov     edx,    eax
405    lea     ebp,    [-1+eax+ecx*1]
406    shr     edx,    12
407    shr     ebp,    12
408    mov     edi,    [memory_map+edx*4]
409    test    edi,    edi
410    js      _D5
411    lea     eax,    [eax+edi*4]
412_D1:
413    xor     edi,    [memory_map+edx*4]
414    shl     edi,    2
415    jne     _D5
416    mov     edi,    [memory_map+edx*4]
417    inc     edx
418    cmp     edx,    ebp
419    jbe     _D1
420
421verify_code:
422    ;eax = source
423    ;ebx = target
424    ;ecx = length
425    mov     edi,    [-4+eax+ecx*1]
426    xor     edi,    [-4+ebx+ecx*1]
427    jne     _D5
428    mov     edx,    ecx
429    add     ecx,    -4
430    je      _D3
431    test    edx,    4
432    cmove   ecx,    edx
433    mov     [cycle_count],    esi
434_D2:
435    mov     edx,    [-4+eax+ecx*1]
436    mov     ebp,    [-4+ebx+ecx*1]
437    mov     esi,    [-8+eax+ecx*1]
438    xor     ebp,    edx
439    mov     edi,    [-8+ebx+ecx*1]
440    jne     _D4
441    xor     edi,    esi
442    jne     _D4
443    add     ecx,    -8
444    jne     _D2
445    mov     esi,    [cycle_count]
446    mov     ebp,    [branch_target]
447_D3:
448    ret
449_D4:
450    mov     esi,    [cycle_count]
451_D5:
452    mov     ebp,    [branch_target]
453    push    esi           ;for stack alignment, unused
454    push    DWORD [8+esp]
455    call    get_addr
456    add     esp,    16    ;pop stack
457    jmp     eax
458
459cc_interrupt:
460    add     esi,    [last_count]
461    add     esp,    -28                 ;Align stack
462    mov     [g_cp0_regs+36],    esi    ;Count
463    shr     esi,    19
464    mov     DWORD [pending_exception],    0
465    and     esi,    01fch
466    cmp     DWORD [restore_candidate+esi],    0
467    jne     _E4
468_E1:
469    call    gen_interrupt
470    mov     esi,    [g_cp0_regs+36]
471    mov     eax,    [next_interrupt]
472    mov     ebx,    [pending_exception]
473    mov     ecx,    [stop]
474    add     esp,    28
475    mov     [last_count],    eax
476    sub     esi,    eax
477    test    ecx,    ecx
478    jne     _E3
479    test    ebx,    ebx
480    jne     _E2
481    ret
482_E2:
483    add     esp,    -8
484    mov     edi,    [pcaddr]
485    mov     [cycle_count],    esi    ;CCREG
486    push    edi
487    call    get_addr_ht
488    mov     esi,    [cycle_count]
489    add     esp,    16
490    jmp     eax
491_E3:
492    add     esp,    16     ;pop stack
493    pop     edi            ;restore edi
494    pop     esi            ;restore esi
495    pop     ebx            ;restore ebx
496    pop     ebp            ;restore ebp
497    ret                    ;exit dynarec
498_E4:
499    ;Move 'dirty' blocks to the 'clean' list
500    mov     ebx,    DWORD [restore_candidate+esi]
501    mov     DWORD [restore_candidate+esi],    0
502    shl     esi,    3
503    mov     ebp,    0
504_E5:
505    shr     ebx,    1
506    jnc     _E6
507    mov     ecx,    esi
508    add     ecx,    ebp
509    push    ecx
510    call    clean_blocks
511    pop     ecx
512_E6:
513    inc     ebp
514    test    ebp,    31
515    jne     _E5
516    jmp     _E1
517
518do_interrupt:
519    mov     edi,    [pcaddr]
520    add     esp,    -12
521    push    edi
522    call    get_addr_ht
523    add     esp,    16
524    mov     esi,    [g_cp0_regs+36]
525    mov     ebx,    [next_interrupt]
526    mov     [last_count],    ebx
527    sub     esi,    ebx
528    add     esi,    2
529    jmp     eax
530
531fp_exception:
532    mov     edx,    01000002ch
533_E7:
534    mov     ebx,    [g_cp0_regs+48]
535    add     esp,    -12
536    or      ebx,    2
537    mov     [g_cp0_regs+48],    ebx     ;Status
538    mov     [g_cp0_regs+52],    edx     ;Cause
539    mov     [g_cp0_regs+56],    eax     ;EPC
540    push    080000180h
541    call    get_addr_ht
542    add     esp,    16
543    jmp     eax
544
545fp_exception_ds:
546    mov     edx,    09000002ch    ;Set high bit if delay slot
547    jmp     _E7
548
549jump_syscall:
550    mov     edx,    020h
551    mov     ebx,    [g_cp0_regs+48]
552    add     esp,    -12
553    or      ebx,    2
554    mov     [g_cp0_regs+48],    ebx     ;Status
555    mov     [g_cp0_regs+52],    edx     ;Cause
556    mov     [g_cp0_regs+56],    eax     ;EPC
557    push    080000180h
558    call    get_addr_ht
559    add     esp,    16
560    jmp     eax
561
562jump_eret:
563    mov     ebx,    [g_cp0_regs+48]        ;Status
564    add     esi,    [last_count]
565    and     ebx,    0FFFFFFFDh
566    mov     [g_cp0_regs+36],    esi        ;Count
567    mov     [g_cp0_regs+48],    ebx        ;Status
568    call    check_interrupt
569    mov     eax,    [next_interrupt]
570    mov     esi,    [g_cp0_regs+36]
571    mov     [last_count],    eax
572    sub     esi,    eax
573    mov     eax,    [g_cp0_regs+56]        ;EPC
574    jns     _E11
575_E8:
576    mov     ebx,    248
577    xor     edi,    edi
578_E9:
579    mov     ecx,    [reg+ebx]
580    mov     edx,    [reg+4+ebx]
581    sar     ecx,    31
582    xor     edx,    ecx
583    neg     edx
584    adc     edi,    edi
585    sub     ebx,    8
586    jne     _E9
587    mov     ecx,    [hi+ebx]
588    mov     edx,    [hi+4+ebx]
589    sar     ecx,    31
590    xor     edx,    ecx
591    jne     _E10
592    mov     ecx,    [lo+ebx]
593    mov     edx,    [lo+4+ebx]
594    sar     ecx,    31
595    xor     edx,    ecx
596_E10:
597    neg     edx
598    adc     edi,    edi
599    add     esp,    -8
600    push    edi
601    push    eax
602    mov     [cycle_count],    esi
603    call    get_addr_32
604    mov     esi,    [cycle_count]
605    add     esp,    16
606    jmp     eax
607_E11:
608    mov     [pcaddr],    eax
609    call    cc_interrupt
610    mov     eax,    [pcaddr]
611    jmp     _E8
612
613new_dyna_start:
614    push    ebp
615    push    ebx
616    push    esi
617    push    edi
618    add     esp,    -8    ;align stack
619    push    0a4000040h
620    call    new_recompile_block
621    mov     edi,    DWORD [next_interrupt]
622    mov     esi,    DWORD [g_cp0_regs+36]
623    mov     DWORD [last_count],    edi
624    sub     esi,    edi
625    jmp     DWORD [base_addr]
626
627invalidate_block_eax:
628    push    eax
629    push    ecx
630    push    edx
631    push    eax
632    jmp     invalidate_block_call
633
634invalidate_block_ecx:
635    push    eax
636    push    ecx
637    push    edx
638    push    ecx
639    jmp     invalidate_block_call
640
641invalidate_block_edx:
642    push    eax
643    push    ecx
644    push    edx
645    push    edx
646    jmp     invalidate_block_call
647
648invalidate_block_ebx:
649    push    eax
650    push    ecx
651    push    edx
652    push    ebx
653    jmp     invalidate_block_call
654
655invalidate_block_ebp:
656    push    eax
657    push    ecx
658    push    edx
659    push    ebp
660    jmp     invalidate_block_call
661
662invalidate_block_esi:
663    push    eax
664    push    ecx
665    push    edx
666    push    esi
667    jmp     invalidate_block_call
668
669invalidate_block_edi:
670    push    eax
671    push    ecx
672    push    edx
673    push    edi
674
675invalidate_block_call:
676    call    invalidate_block
677    pop     eax ;Throw away
678    pop     edx
679    pop     ecx
680    pop     eax
681    ret
682
683write_rdram_new:
684    mov     edi,    [address]
685    mov     ecx,    [cpu_word]
686    mov     [g_rdram-0x80000000+edi],    ecx
687    jmp     _E12
688
689write_rdramb_new:
690    mov     edi,    [address]
691    xor     edi,    3
692    mov     cl,     BYTE [cpu_byte]
693    mov     BYTE [g_rdram-0x80000000+edi],    cl
694    jmp     _E12
695
696write_rdramh_new:
697    mov     edi,    [address]
698    xor     edi,    2
699    mov     cx,     WORD [cpu_hword]
700    mov     WORD [g_rdram-0x80000000+edi],    cx
701    jmp     _E12
702
703write_rdramd_new:
704    mov     edi,    [address]
705    mov     ecx,    [cpu_dword+4]
706    mov     edx,    [cpu_dword+0]
707    mov     [g_rdram-0x80000000+edi],      ecx
708    mov     [g_rdram-0x80000000+4+edi],    edx
709    jmp     _E12
710
711
712do_invalidate:
713    mov     edi,    [address]
714    mov     ebx,    edi    ;Return ebx to caller
715_E12:
716    shr     edi,    12
717    cmp     BYTE [invalid_code+edi],    1
718    je      _E13
719    push    edi
720    call    invalidate_block
721    pop     edi
722_E13:
723    ret
724
725read_nomem_new:
726    mov     edi,    [address]
727    mov     ebx,    edi
728    shr     edi,    12
729    mov     edi,    [memory_map+edi*4]
730    mov     eax,    00h
731    test    edi,    edi
732    js      tlb_exception
733    mov     ecx,    [ebx+edi*4]
734    mov     [readmem_dword],    ecx
735    ret
736
737read_nomemb_new:
738    mov     edi,    [address]
739    mov     ebx,    edi
740    shr     edi,    12
741    mov     edi,    [memory_map+edi*4]
742    mov     eax,    00h
743    test    edi,    edi
744    js      tlb_exception
745    xor     ebx,    3
746    movzx   ecx,    BYTE [ebx+edi*4]
747    mov     [readmem_dword],    ecx
748    ret
749
750read_nomemh_new:
751    mov     edi,    [address]
752    mov     ebx,    edi
753    shr     edi,    12
754    mov     edi,    [memory_map+edi*4]
755    mov     eax,    00h
756    test    edi,    edi
757    js      tlb_exception
758    xor     ebx,    2
759    movzx   ecx,    WORD [ebx+edi*4]
760    mov     [readmem_dword],    ecx
761    ret
762
763read_nomemd_new:
764    mov     edi,    [address]
765    mov     ebx,    edi
766    shr     edi,    12
767    mov     edi,    [memory_map+edi*4]
768    mov     eax,    00h
769    test    edi,    edi
770    js      tlb_exception
771    mov     ecx,    [4+ebx+edi*4]
772    mov     edx,    [ebx+edi*4]
773    mov     [readmem_dword],      ecx
774    mov     [readmem_dword+4],    edx
775    ret
776
777write_nomem_new:
778    call    do_invalidate
779    mov     edi,    [memory_map+edi*4]
780    mov     ecx,    [cpu_word]
781    mov     eax,    01h
782    shl     edi,    2
783    jc      tlb_exception
784    mov     [ebx+edi],    ecx
785    ret
786
787write_nomemb_new:
788    call    do_invalidate
789    mov     edi,    [memory_map+edi*4]
790    mov     cl,     BYTE [cpu_byte]
791    mov     eax,    01h
792    shl     edi,    2
793    jc      tlb_exception
794    xor     ebx,    3
795    mov     BYTE [ebx+edi],    cl
796    ret
797
798write_nomemh_new:
799    call    do_invalidate
800    mov     edi,    [memory_map+edi*4]
801    mov     cx,     WORD [cpu_hword]
802    mov     eax,    01h
803    shl     edi,    2
804    jc      tlb_exception
805    xor     ebx,    2
806    mov     WORD [ebx+edi],    cx
807    ret
808
809write_nomemd_new:
810    call    do_invalidate
811    mov     edi,    [memory_map+edi*4]
812    mov     edx,    [cpu_dword+4]
813    mov     ecx,    [cpu_dword+0]
814    mov     eax,    01h
815    shl     edi,    2
816    jc      tlb_exception
817    mov     [ebx+edi],    edx
818    mov     [4+ebx+edi],    ecx
819    ret
820
821write_mi_new:
822    mov     ebx,    [024h+esp]
823    add     ebx,    4
824    mov     [pcaddr],    ebx
825    mov     DWORD [pending_exception],    0
826    call    write_mi
827    mov     ebx,    [pending_exception]
828    test    ebx,    ebx
829    jne     mi_exception
830    ret
831
832write_mib_new:
833    mov     ebx,    [024h+esp]
834    add     ebx,    4
835    mov     [pcaddr],    ebx
836    mov     DWORD [pending_exception],    0
837    call    write_mib
838    mov     ebx,    [pending_exception]
839    test    ebx,    ebx
840    jne     mi_exception
841    ret
842
843write_mih_new:
844    mov     ebx,    [024h+esp]
845    add     ebx,    4
846    mov     [pcaddr],    ebx
847    mov     DWORD [pending_exception],    0
848    call    write_mih
849    mov     ebx,    [pending_exception]
850    test    ebx,    ebx
851    jne     mi_exception
852    ret
853
854write_mid_new:
855    mov     ebx,    [024h+esp]
856    add     ebx,    4
857    mov     [pcaddr],    ebx
858    mov     DWORD [pending_exception],    0
859    call    write_mid
860    mov     ebx,    [pending_exception]
861    test    ebx,    ebx
862    jne     mi_exception
863    ret
864
865mi_exception:
866    ;ebx = mem addr
867    ;ebp = instr addr + flags
868    mov     ebp,    [024h+esp]
869    mov     ebx,    [address]
870    add     esp,    024h
871    call    wb_base_reg
872    jmp     do_interrupt
873
874tlb_exception:
875    ;eax = r/w
876    ;ebx = mem addr
877    ;ebp = instr addr + flags
878    mov     ebp,    [024h+esp]
879    add     esp,    024h
880    call    wb_base_reg
881    add     esp,    -4
882    push    eax
883    push    ebx
884    push    ebp
885    call    TLB_refill_exception_new
886    add     esp,    16
887    mov     edi,    DWORD [next_interrupt]
888    mov     esi,    DWORD [g_cp0_regs+36]    ;Count
889    mov     DWORD [last_count],    edi
890    sub     esi,    edi
891    jmp     eax
892
893wb_base_reg:
894    ;ebx = address
895    ;ebp = instr addr + flags
896    mov     ecx,    ebp
897    mov     edx,    ebp
898    shr     ecx,    12
899    and     edx,    0FFFFFFFCh
900    mov     ecx,    [memory_map+ecx*4]
901    mov     ecx,    [edx+ecx*4]
902    mov     edx,    06000022h
903    mov     edi,    ecx
904    movsx   esi,    cx
905    shr     ecx,    26
906    shr     edi,    21
907    sub     ebx,    esi
908    add     esi,    ebx
909    and     edi,    01fh
910    rcr     edx,    cl
911    cmovc   ebx,    [reg+edi*8]
912    mov     [reg+edi*8],    ebx
913    sar     ebx,    31
914    test    ebp,    2
915    cmove   ebx,    [reg+4+edi*8]
916    mov     [reg+4+edi*8],    ebx
917    mov     ebx,    esi
918    ret
919
920breakpoint:
921    int    3
922    ret
923