451ab91e |
1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | * Mupen64plus - linkage_x86.s * |
3 | * Copyright (C) 2009-2011 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.s" |
21 | .bss |
22 | .align 4 |
23 | |
24 | .section .rodata |
25 | .text |
26 | .globl dyna_linker |
27 | .hidden 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 | mov jump_in(,%ecx,4), %edx |
48 | .A1: |
49 | test %edx, %edx |
50 | je .A3 |
51 | mov (%edx), %edi |
52 | xor %eax, %edi |
53 | or 4(%edx), %edi |
54 | je .A2 |
55 | movl 12(%edx), %edx |
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 | pusha |
63 | call add_link |
64 | popa |
65 | mov 8(%edx), %edi |
66 | mov %ebp, %esi |
67 | lea -4(%edi), %edx |
68 | subl %ebx, %edx |
69 | movl %edx, (%ebx) |
70 | jmp *%edi |
71 | .A3: |
72 | /* hash_table lookup */ |
73 | mov %eax, %edi |
74 | mov %eax, %edx |
75 | shr $16, %edi |
76 | shr $12, %edx |
77 | xor %eax, %edi |
78 | and $2047, %edx |
79 | movzwl %di, %edi |
80 | shl $4, %edi |
81 | cmp $2048, %ecx |
82 | cmovc %edx, %ecx |
83 | cmp hash_table(%edi), %eax |
84 | jne .A5 |
85 | .A4: |
86 | mov hash_table+4(%edi), %edx |
87 | jmp *%edx |
88 | .A5: |
89 | cmp hash_table+8(%edi), %eax |
90 | lea 8(%edi), %edi |
91 | je .A4 |
92 | /* jump_dirty lookup */ |
93 | mov jump_dirty(,%ecx,4), %edx |
94 | .A6: |
95 | testl %edx, %edx |
96 | je .A8 |
97 | mov (%edx), %ecx |
98 | xor %eax, %ecx |
99 | or 4(%edx), %ecx |
100 | je .A7 |
101 | movl 12(%edx), %edx |
102 | jmp .A6 |
103 | .A7: |
104 | mov 8(%edx), %edx |
105 | /* hash_table insert */ |
106 | mov hash_table-8(%edi), %ebx |
107 | mov hash_table-4(%edi), %ecx |
108 | mov %eax, hash_table-8(%edi) |
109 | mov %edx, hash_table-4(%edi) |
110 | mov %ebx, hash_table(%edi) |
111 | mov %ecx, hash_table+4(%edi) |
112 | jmp *%edx |
113 | .A8: |
114 | mov %eax, %edi |
115 | pusha |
116 | call new_recompile_block |
117 | test %eax, %eax |
118 | popa |
119 | je dyna_linker |
120 | /* pagefault */ |
121 | mov %eax, %ebx |
122 | mov $0x08, %ecx |
123 | .size dyna_linker, .-dyna_linker |
124 | |
125 | .type exec_pagefault, @function |
126 | exec_pagefault: |
127 | /* eax = instruction pointer */ |
128 | /* ebx = fault address */ |
129 | /* ecx = cause */ |
130 | mov reg_cop0+48, %edx |
131 | add $-12, %esp |
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 | push $0x80000000 |
147 | call get_addr_ht |
148 | add $16, %esp |
149 | jmp *%eax |
150 | .size exec_pagefault, .-exec_pagefault |
151 | |
152 | /* Special dynamic linker for the case where a page fault |
153 | may occur in a branch delay slot */ |
154 | .globl dyna_linker_ds |
155 | .hidden 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 | mov jump_in(,%ecx,4), %edx |
174 | .B1: |
175 | test %edx, %edx |
176 | je .B3 |
177 | mov (%edx), %edi |
178 | xor %eax, %edi |
179 | or 4(%edx), %edi |
180 | je .B2 |
181 | movl 12(%edx), %edx |
182 | jmp .B1 |
183 | .B2: |
184 | mov (%ebx), %edi |
185 | mov %esi, %ecx |
186 | lea 4(%ebx,%edi,1), %esi |
187 | mov %eax, %edi |
188 | pusha |
189 | call add_link |
190 | popa |
191 | mov 8(%edx), %edi |
192 | mov %ecx, %esi |
193 | lea -4(%edi), %edx |
194 | subl %ebx, %edx |
195 | movl %edx, (%ebx) |
196 | jmp *%edi |
197 | .B3: |
198 | /* hash_table lookup */ |
199 | mov %eax, %edi |
200 | mov %eax, %edx |
201 | shr $16, %edi |
202 | shr $12, %edx |
203 | xor %eax, %edi |
204 | and $2047, %edx |
205 | movzwl %di, %edi |
206 | shl $4, %edi |
207 | cmp $2048, %ecx |
208 | cmovc %edx, %ecx |
209 | cmp hash_table(%edi), %eax |
210 | jne .B5 |
211 | .B4: |
212 | mov hash_table+4(%edi), %edx |
213 | jmp *%edx |
214 | .B5: |
215 | cmp hash_table+8(%edi), %eax |
216 | lea 8(%edi), %edi |
217 | je .B4 |
218 | /* jump_dirty lookup */ |
219 | mov jump_dirty(,%ecx,4), %edx |
220 | .B6: |
221 | testl %edx, %edx |
222 | je .B8 |
223 | mov (%edx), %ecx |
224 | xor %eax, %ecx |
225 | or 4(%edx), %ecx |
226 | je .B7 |
227 | movl 12(%edx), %edx |
228 | jmp .B6 |
229 | .B7: |
230 | mov 8(%edx), %edx |
231 | /* hash_table insert */ |
232 | mov hash_table-8(%edi), %ebx |
233 | mov hash_table-4(%edi), %ecx |
234 | mov %eax, hash_table-8(%edi) |
235 | mov %edx, hash_table-4(%edi) |
236 | mov %ebx, hash_table(%edi) |
237 | mov %ecx, hash_table+4(%edi) |
238 | jmp *%edx |
239 | .B8: |
240 | mov %eax, %edi |
241 | and $0xFFFFFFF8, %edi |
242 | inc %edi |
243 | pusha |
244 | call new_recompile_block |
245 | test %eax, %eax |
246 | popa |
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 | .hidden jump_vaddr_eax |
258 | .type jump_vaddr_eax, @function |
259 | jump_vaddr_eax: |
260 | mov %eax, %edi |
261 | jmp jump_vaddr_edi |
262 | .size jump_vaddr_eax, .-jump_vaddr_eax |
263 | .globl jump_vaddr_ecx |
264 | .hidden jump_vaddr_ecx |
265 | .type jump_vaddr_ecx, @function |
266 | jump_vaddr_ecx: |
267 | mov %ecx, %edi |
268 | jmp jump_vaddr_edi |
269 | .size jump_vaddr_ecx, .-jump_vaddr_ecx |
270 | .globl jump_vaddr_edx |
271 | .hidden jump_vaddr_edx |
272 | .type jump_vaddr_edx, @function |
273 | jump_vaddr_edx: |
274 | mov %edx, %edi |
275 | jmp jump_vaddr_edi |
276 | .size jump_vaddr_edx, .-jump_vaddr_edx |
277 | .globl jump_vaddr_ebx |
278 | .hidden jump_vaddr_ebx |
279 | .type jump_vaddr_ebx, @function |
280 | jump_vaddr_ebx: |
281 | mov %ebx, %edi |
282 | jmp jump_vaddr_edi |
283 | .size jump_vaddr_ebx, .-jump_vaddr_ebx |
284 | .globl jump_vaddr_ebp |
285 | .hidden jump_vaddr_ebp |
286 | .type jump_vaddr_ebp, @function |
287 | jump_vaddr_ebp: |
288 | mov %ebp, %edi |
289 | .size jump_vaddr_ebp, .-jump_vaddr_ebp |
290 | .globl jump_vaddr_edi |
291 | .hidden jump_vaddr_edi |
292 | .type jump_vaddr_edi, @function |
293 | jump_vaddr_edi: |
294 | mov %edi, %eax |
295 | .size jump_vaddr_edi, .-jump_vaddr_edi |
296 | |
297 | .type jump_vaddr, @function |
298 | jump_vaddr: |
299 | /* Check hash table */ |
300 | shr $16, %eax |
301 | xor %edi, %eax |
302 | movzwl %ax, %eax |
303 | shl $4, %eax |
304 | cmp hash_table(%eax), %edi |
305 | jne .C2 |
306 | .C1: |
307 | mov hash_table+4(%eax), %edi |
308 | jmp *%edi |
309 | .C2: |
310 | cmp hash_table+8(%eax), %edi |
311 | lea 8(%eax), %eax |
312 | je .C1 |
313 | /* No hit on hash table, call compiler */ |
314 | add $-12, %esp |
315 | push %edi |
316 | mov %esi, cycle_count /* CCREG */ |
317 | call get_addr |
318 | mov cycle_count, %esi |
319 | add $16, %esp |
320 | jmp *%eax |
321 | .size jump_vaddr, .-jump_vaddr |
322 | |
323 | .globl verify_code_ds |
324 | .hidden verify_code_ds |
325 | .type verify_code_ds, @function |
326 | verify_code_ds: |
327 | mov %ebp, branch_target |
328 | .size verify_code_ds, .-verify_code_ds |
329 | |
330 | .globl verify_code_vm |
331 | .hidden verify_code_vm |
332 | .type verify_code_vm, @function |
333 | verify_code_vm: |
334 | /* eax = source (virtual address) */ |
335 | /* ebx = target */ |
336 | /* ecx = length */ |
337 | cmp $0xC0000000, %eax |
338 | jl verify_code |
339 | mov %eax, %edx |
340 | lea -1(%eax,%ecx,1), %ebp |
341 | shr $12, %edx |
342 | shr $12, %ebp |
343 | mov memory_map(,%edx,4), %edi |
344 | test %edi, %edi |
345 | js .D5 |
346 | lea (%eax,%edi,4), %eax |
347 | .D1: |
348 | xor memory_map(,%edx,4), %edi |
349 | shl $2, %edi |
350 | jne .D5 |
351 | mov memory_map(,%edx,4), %edi |
352 | inc %edx |
353 | cmp %ebp, %edx |
354 | jbe .D1 |
355 | .size verify_code_vm, .-verify_code_vm |
356 | |
357 | .globl verify_code |
358 | .hidden verify_code |
359 | .type verify_code, @function |
360 | verify_code: |
361 | /* eax = source */ |
362 | /* ebx = target */ |
363 | /* ecx = length */ |
364 | mov -4(%eax,%ecx,1), %edi |
365 | xor -4(%ebx,%ecx,1), %edi |
366 | jne .D5 |
367 | mov %ecx, %edx |
368 | add $-4, %ecx |
369 | je .D3 |
370 | test $4, %edx |
371 | cmove %edx, %ecx |
372 | mov %esi, cycle_count |
373 | .D2: |
374 | mov -4(%eax,%ecx,1), %edx |
375 | mov -4(%ebx,%ecx,1), %ebp |
376 | mov -8(%eax,%ecx,1), %esi |
377 | xor %edx, %ebp |
378 | mov -8(%ebx,%ecx,1), %edi |
379 | jne .D4 |
380 | xor %esi, %edi |
381 | jne .D4 |
382 | add $-8, %ecx |
383 | jne .D2 |
384 | mov cycle_count, %esi |
385 | mov branch_target, %ebp |
386 | .D3: |
387 | ret |
388 | .D4: |
389 | mov cycle_count, %esi |
390 | .D5: |
391 | mov branch_target, %ebp |
392 | push %esi /* for stack alignment, unused */ |
393 | push 8(%esp) |
394 | call get_addr |
395 | add $16, %esp /* pop stack */ |
396 | jmp *%eax |
397 | .size verify_code, .-verify_code |
398 | |
399 | .globl cc_interrupt |
400 | .hidden cc_interrupt |
401 | .type cc_interrupt, @function |
402 | cc_interrupt: |
403 | add last_count, %esi |
404 | add $-28, %esp /* Align stack */ |
405 | mov %esi, reg_cop0+36 /* Count */ |
406 | shr $19, %esi |
407 | movl $0, pending_exception |
408 | and $0x7f, %esi |
409 | cmpl $0, restore_candidate(,%esi,4) |
410 | jne .E4 |
411 | .E1: |
412 | call gen_interupt |
413 | mov reg_cop0+36, %esi |
414 | mov next_interupt, %eax |
415 | mov pending_exception, %ebx |
416 | mov stop, %ecx |
417 | add $28, %esp |
418 | mov %eax, last_count |
419 | sub %eax, %esi |
420 | test %ecx, %ecx |
421 | jne .E3 |
422 | test %ebx, %ebx |
423 | jne .E2 |
424 | ret |
425 | .E2: |
426 | add $-8, %esp |
427 | mov pcaddr, %edi |
428 | mov %esi, cycle_count /* CCREG */ |
429 | push %edi |
430 | call get_addr_ht |
431 | mov cycle_count, %esi |
432 | add $16, %esp |
433 | jmp *%eax |
434 | .E3: |
435 | add $16, %esp /* pop stack */ |
436 | pop %edi /* restore edi */ |
437 | pop %esi /* restore esi */ |
438 | pop %ebx /* restore ebx */ |
439 | pop %ebp /* restore ebp */ |
440 | ret /* exit dynarec */ |
441 | .E4: |
442 | /* Move 'dirty' blocks to the 'clean' list */ |
443 | mov restore_candidate(,%esi,4), %ebx |
444 | mov %esi, %ebp |
445 | movl $0, restore_candidate(,%esi,4) |
446 | shl $5, %ebp |
447 | .E5: |
448 | shr $1, %ebx |
449 | jnc .E6 |
450 | mov %ebp, (%esp) |
451 | call clean_blocks |
452 | .E6: |
453 | inc %ebp |
454 | test $31, %ebp |
455 | jne .E5 |
456 | jmp .E1 |
457 | .size cc_interrupt, .-cc_interrupt |
458 | |
459 | .globl do_interrupt |
460 | .hidden do_interrupt |
461 | .type do_interrupt, @function |
462 | do_interrupt: |
463 | mov pcaddr, %edi |
464 | add $-12, %esp |
465 | push %edi |
466 | call get_addr_ht |
467 | add $16, %esp |
468 | mov reg_cop0+36, %esi |
469 | mov next_interupt, %ebx |
470 | mov %ebx, last_count |
471 | sub %ebx, %esi |
472 | add $2, %esi |
473 | jmp *%eax |
474 | .size do_interrupt, .-do_interrupt |
475 | |
476 | .globl fp_exception |
477 | .hidden fp_exception |
478 | .type fp_exception, @function |
479 | fp_exception: |
480 | mov $0x1000002c, %edx |
481 | .E7: |
482 | mov reg_cop0+48, %ebx |
483 | add $-12, %esp |
484 | or $2, %ebx |
485 | mov %ebx, reg_cop0+48 /* Status */ |
486 | mov %edx, reg_cop0+52 /* Cause */ |
487 | mov %eax, reg_cop0+56 /* EPC */ |
488 | push $0x80000180 |
489 | call get_addr_ht |
490 | add $16, %esp |
491 | jmp *%eax |
492 | .size fp_exception, .-fp_exception |
493 | |
494 | .globl fp_exception_ds |
495 | .hidden fp_exception_ds |
496 | .type fp_exception_ds, @function |
497 | fp_exception_ds: |
498 | mov $0x9000002c, %edx /* Set high bit if delay slot */ |
499 | jmp .E7 |
500 | .size fp_exception_ds, .-fp_exception_ds |
501 | |
502 | .globl jump_syscall |
503 | .hidden jump_syscall |
504 | .type jump_syscall, @function |
505 | jump_syscall: |
506 | mov $0x20, %edx |
507 | mov reg_cop0+48, %ebx |
508 | add $-12, %esp |
509 | or $2, %ebx |
510 | mov %ebx, reg_cop0+48 /* Status */ |
511 | mov %edx, reg_cop0+52 /* Cause */ |
512 | mov %eax, reg_cop0+56 /* EPC */ |
513 | push $0x80000180 |
514 | call get_addr_ht |
515 | mov $16, %esp |
516 | jmp *%eax |
517 | .size jump_syscall, .-jump_syscall |
518 | |
519 | .globl jump_eret |
520 | .hidden jump_eret |
521 | .type jump_eret, @function |
522 | jump_eret: |
523 | mov reg_cop0+48, %ebx /* Status */ |
524 | add last_count, %esi |
525 | and $0xFFFFFFFD, %ebx |
526 | mov %esi, reg_cop0+36 /* Count */ |
527 | mov %ebx, reg_cop0+48 /* Status */ |
528 | call check_interupt |
529 | mov next_interupt, %eax |
530 | mov reg_cop0+36, %esi |
531 | mov %eax, last_count |
532 | sub %eax, %esi |
533 | mov reg_cop0+56, %eax /* EPC */ |
534 | jns .E11 |
535 | .E8: |
536 | mov $248, %ebx |
537 | xor %edi, %edi |
538 | .E9: |
539 | mov reg(%ebx), %ecx |
540 | mov reg+4(%ebx), %edx |
541 | sar $31, %ecx |
542 | xor %ecx, %edx |
543 | neg %edx |
544 | adc %edi, %edi |
545 | sub $8, %ebx |
546 | jne .E9 |
547 | mov hi(%ebx), %ecx |
548 | mov hi+4(%ebx), %edx |
549 | sar $31, %ecx |
550 | xor %ecx, %edx |
551 | jne .E10 |
552 | mov lo(%ebx), %ecx |
553 | mov lo+4(%ebx), %edx |
554 | sar $31, %ecx |
555 | xor %ecx, %edx |
556 | .E10: |
557 | neg %edx |
558 | adc %edi, %edi |
559 | add $-8, %esp |
560 | push %edi |
561 | push %eax |
562 | mov %esi, cycle_count |
563 | call get_addr_32 |
564 | mov cycle_count, %esi |
565 | add $16, %esp |
566 | jmp *%eax |
567 | .E11: |
568 | mov %eax, pcaddr |
569 | call cc_interrupt |
570 | mov pcaddr, %eax |
571 | jmp .E8 |
572 | .size jump_eret, .-jump_eret |
573 | |
574 | .globl new_dyna_start |
575 | .hidden new_dyna_start |
576 | .type new_dyna_start, @function |
577 | new_dyna_start: |
578 | push %ebp |
579 | push %ebx |
580 | push %esi |
581 | push %edi |
582 | add $-8, %esp /* align stack */ |
583 | push $0xa4000040 |
584 | call new_recompile_block |
585 | movl next_interupt, %edi |
586 | movl reg_cop0+36, %esi |
587 | movl %edi, last_count |
588 | subl %edi, %esi |
589 | jmp *base_addr |
590 | .size new_dyna_start, .-new_dyna_start |
591 | |
592 | /* Note: Assumes %ebx, %ebp, %esi, %edi are callee-saved */ |
593 | .globl invalidate_block_eax |
594 | .hidden invalidate_block_eax |
595 | .type invalidate_block_eax, @function |
596 | invalidate_block_eax: |
597 | push %eax |
598 | push %ecx |
599 | push %edx |
600 | push %eax |
601 | jmp invalidate_block_call |
602 | .size invalidate_block_eax, .-invalidate_block_eax |
603 | .globl invalidate_block_ecx |
604 | .hidden invalidate_block_ecx |
605 | .type invalidate_block_ecx, @function |
606 | invalidate_block_ecx: |
607 | push %eax |
608 | push %ecx |
609 | push %edx |
610 | push %ecx |
611 | jmp invalidate_block_call |
612 | .size invalidate_block_ecx, .-invalidate_block_ecx |
613 | .globl invalidate_block_edx |
614 | .hidden invalidate_block_edx |
615 | .type invalidate_block_edx, @function |
616 | invalidate_block_edx: |
617 | push %eax |
618 | push %ecx |
619 | push %edx |
620 | push %edx |
621 | jmp invalidate_block_call |
622 | .size invalidate_block_edx, .-invalidate_block_edx |
623 | .globl invalidate_block_ebx |
624 | .hidden invalidate_block_ebx |
625 | .type invalidate_block_ebx, @function |
626 | invalidate_block_ebx: |
627 | push %eax |
628 | push %ecx |
629 | push %edx |
630 | push %ebx |
631 | jmp invalidate_block_call |
632 | .size invalidate_block_ebx, .-invalidate_block_ebx |
633 | .globl invalidate_block_ebp |
634 | .hidden invalidate_block_ebp |
635 | .type invalidate_block_ebp, @function |
636 | invalidate_block_ebp: |
637 | push %eax |
638 | push %ecx |
639 | push %edx |
640 | push %ebp |
641 | jmp invalidate_block_call |
642 | .size invalidate_block_ebp, .-invalidate_block_ebp |
643 | .globl invalidate_block_esi |
644 | .hidden invalidate_block_esi |
645 | .type invalidate_block_esi, @function |
646 | invalidate_block_esi: |
647 | push %eax |
648 | push %ecx |
649 | push %edx |
650 | push %esi |
651 | jmp invalidate_block_call |
652 | .size invalidate_block_esi, .-invalidate_block_esi |
653 | .globl invalidate_block_edi |
654 | .hidden invalidate_block_edi |
655 | .type invalidate_block_edi, @function |
656 | invalidate_block_edi: |
657 | push %eax |
658 | push %ecx |
659 | push %edx |
660 | push %edi |
661 | .size invalidate_block_edi, .-invalidate_block_edi |
662 | |
663 | .type invalidate_block_call, @function |
664 | invalidate_block_call: |
665 | call invalidate_block |
666 | pop %eax /* Throw away */ |
667 | pop %edx |
668 | pop %ecx |
669 | pop %eax |
670 | ret |
671 | .size invalidate_block_call, .-invalidate_block_call |
672 | |
673 | .globl write_rdram_new |
674 | .hidden write_rdram_new |
675 | .type write_rdram_new, @function |
676 | write_rdram_new: |
677 | mov address, %edi |
678 | mov word, %ecx |
679 | mov %ecx, rdram-0x80000000(%edi) |
680 | jmp .E12 |
681 | .size write_rdram_new, .-write_rdram_new |
682 | |
683 | .globl write_rdramb_new |
684 | .hidden write_rdramb_new |
685 | .type write_rdramb_new, @function |
686 | write_rdramb_new: |
687 | mov address, %edi |
688 | xor $3, %edi |
689 | movb cpu_byte, %cl |
690 | movb %cl, rdram-0x80000000(%edi) |
691 | jmp .E12 |
692 | .size write_rdramb_new, .-write_rdramb_new |
693 | |
694 | .globl write_rdramh_new |
695 | .hidden write_rdramh_new |
696 | .type write_rdramh_new, @function |
697 | write_rdramh_new: |
698 | mov address, %edi |
699 | xor $2, %edi |
700 | movw hword, %cx |
701 | movw %cx, rdram-0x80000000(%edi) |
702 | jmp .E12 |
703 | .size write_rdramh_new, .-write_rdramh_new |
704 | |
705 | .globl write_rdramd_new |
706 | .hidden write_rdramd_new |
707 | .type write_rdramd_new, @function |
708 | write_rdramd_new: |
709 | mov address, %edi |
710 | mov dword+4, %ecx |
711 | mov dword, %edx |
712 | mov %ecx, rdram-0x80000000(%edi) |
713 | mov %edx, rdram-0x80000000+4(%edi) |
714 | jmp .E12 |
715 | .size write_rdramd_new, .-write_rdramd_new |
716 | |
717 | .type do_invalidate, @function |
718 | do_invalidate: |
719 | mov address, %edi |
720 | mov %edi, %ebx /* Return ebx to caller */ |
721 | .E12: |
722 | shr $12, %edi |
723 | cmpb $1, invalid_code(%edi) |
724 | je .E13 |
725 | push %edi |
726 | call invalidate_block |
727 | pop %edi |
728 | .E13: |
729 | ret |
730 | .size do_invalidate, .-do_invalidate |
731 | |
732 | .globl read_nomem_new |
733 | .hidden read_nomem_new |
734 | .type read_nomem_new, @function |
735 | read_nomem_new: |
736 | mov address, %edi |
737 | mov %edi, %ebx |
738 | shr $12, %edi |
739 | mov memory_map(,%edi,4),%edi |
740 | mov $0x8, %eax |
741 | test %edi, %edi |
742 | js tlb_exception |
743 | mov (%ebx,%edi,4), %ecx |
744 | mov %ecx, readmem_dword |
745 | ret |
746 | .size read_nomem_new, .-read_nomem_new |
747 | |
748 | .globl read_nomemb_new |
749 | .hidden read_nomemb_new |
750 | .type read_nomemb_new, @function |
751 | read_nomemb_new: |
752 | mov address, %edi |
753 | mov %edi, %ebx |
754 | shr $12, %edi |
755 | mov memory_map(,%edi,4),%edi |
756 | mov $0x8, %eax |
757 | test %edi, %edi |
758 | js tlb_exception |
759 | xor $3, %ebx |
760 | movzbl (%ebx,%edi,4), %ecx |
761 | mov %ecx, readmem_dword |
762 | ret |
763 | .size read_nomemb_new, .-read_nomemb_new |
764 | |
765 | .globl read_nomemh_new |
766 | .hidden read_nomemh_new |
767 | .type read_nomemh_new, @function |
768 | read_nomemh_new: |
769 | mov address, %edi |
770 | mov %edi, %ebx |
771 | shr $12, %edi |
772 | mov memory_map(,%edi,4),%edi |
773 | mov $0x8, %eax |
774 | test %edi, %edi |
775 | js tlb_exception |
776 | xor $2, %ebx |
777 | movzwl (%ebx,%edi,4), %ecx |
778 | mov %ecx, readmem_dword |
779 | ret |
780 | .size read_nomemh_new, .-read_nomemh_new |
781 | |
782 | .globl read_nomemd_new |
783 | .hidden read_nomemd_new |
784 | .type read_nomemd_new, @function |
785 | read_nomemd_new: |
786 | mov address, %edi |
787 | mov %edi, %ebx |
788 | shr $12, %edi |
789 | mov memory_map(,%edi,4),%edi |
790 | mov $0x8, %eax |
791 | test %edi, %edi |
792 | js tlb_exception |
793 | mov 4(%ebx,%edi,4), %ecx |
794 | mov (%ebx,%edi,4), %edx |
795 | mov %ecx, readmem_dword |
796 | mov %edx, readmem_dword+4 |
797 | ret |
798 | .size read_nomemd_new, .-read_nomemd_new |
799 | |
800 | .globl write_nomem_new |
801 | .hidden write_nomem_new |
802 | .type write_nomem_new, @function |
803 | write_nomem_new: |
804 | call do_invalidate |
805 | mov memory_map(,%edi,4),%edi |
806 | mov word, %ecx |
807 | mov $0xc, %eax |
808 | shl $2, %edi |
809 | jc tlb_exception |
810 | mov %ecx, (%ebx,%edi) |
811 | ret |
812 | .size write_nomem_new, .-write_nomem_new |
813 | |
814 | .globl write_nomemb_new |
815 | .hidden write_nomemb_new |
816 | .type write_nomemb_new, @function |
817 | write_nomemb_new: |
818 | call do_invalidate |
819 | mov memory_map(,%edi,4),%edi |
820 | movb cpu_byte, %cl |
821 | mov $0xc, %eax |
822 | shl $2, %edi |
823 | jc tlb_exception |
824 | xor $3, %ebx |
825 | movb %cl, (%ebx,%edi) |
826 | ret |
827 | .size write_nomemb_new, .-write_nomemb_new |
828 | |
829 | .globl write_nomemh_new |
830 | .hidden write_nomemh_new |
831 | .type write_nomemh_new, @function |
832 | write_nomemh_new: |
833 | call do_invalidate |
834 | mov memory_map(,%edi,4),%edi |
835 | movw hword, %cx |
836 | mov $0xc, %eax |
837 | shl $2, %edi |
838 | jc tlb_exception |
839 | xor $2, %ebx |
840 | movw %cx, (%ebx,%edi) |
841 | ret |
842 | .size write_nomemh_new, .-write_nomemh_new |
843 | |
844 | .globl write_nomemd_new |
845 | .hidden write_nomemd_new |
846 | .type write_nomemd_new, @function |
847 | write_nomemd_new: |
848 | call do_invalidate |
849 | mov memory_map(,%edi,4),%edi |
850 | mov dword+4, %edx |
851 | mov dword, %ecx |
852 | mov $0xc, %eax |
853 | shl $2, %edi |
854 | jc tlb_exception |
855 | mov %edx, (%ebx,%edi) |
856 | mov %ecx, 4(%ebx,%edi) |
857 | ret |
858 | .size write_nomemd_new, .-write_nomemd_new |
859 | |
860 | .type tlb_exception, @function |
861 | tlb_exception: |
862 | /* eax = cause */ |
863 | /* ebx = address */ |
864 | /* ebp = instr addr + flags */ |
865 | mov 0x24(%esp), %ebp |
866 | /* Debug: |
867 | push %ebp |
868 | push %ebx |
869 | push %eax |
870 | call tlb_debug |
871 | pop %eax |
872 | pop %ebx |
873 | pop %ebp |
874 | /* end debug */ |
875 | mov reg_cop0+48, %esi |
876 | mov %ebp, %ecx |
877 | mov %ebp, %edx |
878 | mov %ebp, %edi |
879 | shl $31, %ebp |
880 | shr $12, %ecx |
881 | or %ebp, %eax |
882 | sar $29, %ebp |
883 | and $0xFFFFFFFC, %edx |
884 | mov memory_map(,%ecx,4), %ecx |
885 | or $2, %esi |
886 | mov (%edx, %ecx, 4), %ecx |
887 | add %ebp, %edx |
888 | mov %esi, reg_cop0+48 /* Status */ |
889 | mov %eax, reg_cop0+52 /* Cause */ |
890 | mov %edx, reg_cop0+56 /* EPC */ |
891 | add $0x24, %esp |
892 | mov $0x6000022, %edx |
893 | mov %ecx, %ebp |
894 | movswl %cx, %eax |
895 | shr $26, %ecx |
896 | shr $21, %ebp |
897 | sub %eax, %ebx |
898 | and $0x1f, %ebp |
899 | ror %cl, %edx |
900 | mov reg_cop0+16, %esi |
901 | cmovc reg(,%ebp,8), %ebx |
902 | and $0xFF80000F, %esi |
903 | mov %ebx, reg(,%ebp,8) |
904 | add %ebx, %eax |
905 | sar $31, %ebx |
906 | mov %eax, reg_cop0+32 /* BadVAddr */ |
907 | shr $9, %eax |
908 | test $2, %edi |
909 | cmove reg+4(,%ebp,8), %ebx |
910 | add $-12, %esp |
911 | and $0x007FFFF0, %eax |
912 | mov %ebx, reg+4(,%ebp,8) |
913 | push $0x80000180 |
914 | or %eax, %esi |
915 | mov %esi, reg_cop0+16 /* Context */ |
916 | call get_addr_ht |
917 | add $16, %esp |
918 | movl next_interupt, %edi |
919 | movl reg_cop0+36, %esi /* Count */ |
920 | movl %edi, last_count |
921 | subl %edi, %esi |
922 | jmp *%eax |
923 | .size tlb_exception, .-tlb_exception |
924 | |
925 | .globl breakpoint |
926 | .hidden breakpoint |
927 | .type breakpoint, @function |
928 | breakpoint: |
929 | .size breakpoint, .-breakpoint |