DYNAREC: More work on DIV, no effect
[mupen64plus-pandora.git] / source / mupen64plus-core / src / r4300 / new_dynarec / linkage_arm.S
CommitLineData
451ab91e 1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Mupen64plus - linkage_arm.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 .cpu arm9tdmi
21 .fpu softvfp
22 .eabi_attribute 20, 1
23 .eabi_attribute 21, 1
24 .eabi_attribute 23, 3
25 .eabi_attribute 24, 1
26 .eabi_attribute 25, 1
27 .eabi_attribute 26, 2
28 .eabi_attribute 30, 6
29 .eabi_attribute 18, 4
30 .file "linkage_arm.S"
31 .global extra_memory
32 .hidden extra_memory
33 .global dynarec_local
34 .hidden dynarec_local
35 .global reg
36 .hidden reg
37 .global hi
38 .hidden hi
39 .global lo
40 .hidden lo
41 .global reg_cop1_simple
42 .hidden reg_cop1_simple
43 .global reg_cop1_double
44 .hidden reg_cop1_double
45 .global reg_cop0
46 .hidden reg_cop0
47 .global FCR0
48 .hidden FCR0
49 .global FCR31
50 .hidden FCR31
51 .global rounding_modes
52 .hidden rounding_modes
53 .global next_interupt
54 .hidden next_interupt
55 .global cycle_count
56 .hidden cycle_count
57 .global last_count
58 .hidden last_count
59 .global pending_exception
60 .hidden pending_exception
61 .global pcaddr
62 .hidden pcaddr
63 .global stop
64 .hidden stop
65 .global invc_ptr
66 .hidden invc_ptr
67 .global address
68 .hidden address
69 .global readmem_dword
70 .hidden readmem_dword
71 .global dword
72 .hidden dword
73 .global word
74 .hidden word
75 .global hword
76 .hidden hword
77 .global cpu_byte
78 .hidden cpu_byte
79 .global branch_target
80 .hidden branch_target
81 .global PC
82 .hidden PC
83 .global fake_pc
84 .hidden fake_pc
85 .global mini_ht
86 .hidden mini_ht
87 .global restore_candidate
88 .hidden restore_candidate
89 .global ram_offset
90 .hidden ram_offset
91 .global memory_map
92 .hidden memory_map
93 .bss
94 .align 12
95 .type extra_memory, %object
96 .size extra_memory, 33554432
97extra_memory:
98 .space 33554432+64+16+16+8+8+8+8+256+8+8+128+128+128+16+8+132+4+256+512+4194304
99dynarec_local = extra_memory + 33554432
100 .type dynarec_local, %object
101 .size dynarec_local, 64
102next_interupt = dynarec_local + 64
103 .type next_interupt, %object
104 .size next_interupt, 4
105cycle_count = next_interupt + 4
106 .type cycle_count, %object
107 .size cycle_count, 4
108last_count = cycle_count + 4
109 .type last_count, %object
110 .size last_count, 4
111pending_exception = last_count + 4
112 .type pending_exception, %object
113 .size pending_exception, 4
114pcaddr = pending_exception + 4
115 .type pcaddr, %object
116 .size pcaddr, 4
117stop = pcaddr + 4
118 .type stop, %object
119 .size stop, 4
120invc_ptr = stop + 4
121 .type invc_ptr, %object
122 .size invc_ptr, 4
123address = invc_ptr + 4
124 .type address, %object
125 .size address, 4
126readmem_dword = address + 4
127 .type readmem_dword, %object
128 .size readmem_dword, 8
129dword = readmem_dword + 8
130 .type dword, %object
131 .size dword, 8
132word = dword + 8
133 .type word, %object
134 .size word, 4
135hword = word + 4
136 .type hword, %object
137 .size hword, 2
138cpu_byte = hword + 2
139 .type cpu_byte, %object
140 .size cpu_byte, 1 /* 1 byte free */
141FCR0 = hword + 4
142 .type FCR0, %object
143 .size FCR0, 4
144FCR31 = FCR0 + 4
145 .type FCR31, %object
146 .size FCR31, 4
147reg = FCR31 + 4
148 .type reg, %object
149 .size reg, 256
150hi = reg + 256
151 .type hi, %object
152 .size hi, 8
153lo = hi + 8
154 .type lo, %object
155 .size lo, 8
156reg_cop0 = lo + 8
157 .type reg_cop0, %object
158 .size reg_cop0, 128
159reg_cop1_simple = reg_cop0 + 128
160 .type reg_cop1_simple, %object
161 .size reg_cop1_simple, 128
162reg_cop1_double = reg_cop1_simple + 128
163 .type reg_cop1_double, %object
164 .size reg_cop1_double, 128
165rounding_modes = reg_cop1_double + 128
166 .type rounding_modes, %object
167 .size rounding_modes, 16
168branch_target = rounding_modes + 16
169 .type branch_target, %object
170 .size branch_target, 4
171PC = branch_target + 4
172 .type PC, %object
173 .size PC, 4
174fake_pc = PC + 4
175 .type fake_pc, %object
176 .size fake_pc, 132
177ram_offset = fake_pc + 132
178 .type ram_offset, %object
179 .size ram_offset, 4
180mini_ht = ram_offset + 4
181 .type mini_ht, %object
182 .size mini_ht, 256
183restore_candidate = mini_ht + 256
184 .type restore_candidate, %object
185 .size restore_candidate, 512
186memory_map = restore_candidate + 512
187 .type memory_map, %object
188 .size memory_map, 4194304
189
190 .text
191 .align 2
192 .global dyna_linker
193 .hidden dyna_linker
194 .type dyna_linker, %function
195dyna_linker:
196 /* r0 = virtual target address */
197 /* r1 = instruction to patch */
198 ldr r4, .tlbptr
199 lsr r5, r0, #12
200 mov r12, r0
201 cmp r0, #0xC0000000
202 mov r6, #4096
203 ldrge r12, [r4, r5, lsl #2]
204 mov r2, #0x80000
205 ldr r3, .jiptr
206 tst r12, r12
207 sub r6, r6, #1
208 moveq r12, r0
209 ldr r7, [r1]
210 eor r2, r2, r12, lsr #12
211 and r6, r6, r12, lsr #12
212 cmp r2, #2048
213 add r12, r7, #2
214 orrcs r2, r6, #2048
215 ldr r5, [r3, r2, lsl #2]
216 lsl r12, r12, #8
217 /* jump_in lookup */
218.A1:
219 movs r4, r5
220 beq .A3
221 ldr r3, [r5]
222 ldr r5, [r4, #12]
223 teq r3, r0
224 bne .A1
225 ldr r3, [r4, #4]
226 ldr r4, [r4, #8]
227 tst r3, r3
228 bne .A1
229.A2:
230 mov r5, r1
231 add r1, r1, r12, asr #6
232 teq r1, r4
233 moveq pc, r4 /* Stale i-cache */
234 bl add_link
235 sub r2, r4, r5
236 and r1, r7, #0xff000000
237 lsl r2, r2, #6
238 sub r1, r1, #2
239 add r1, r1, r2, lsr #8
240 str r1, [r5]
241 mov pc, r4
242.A3:
243 /* hash_table lookup */
244 cmp r2, #2048
245 ldr r3, .jdptr
246 eor r4, r0, r0, lsl #16
247 lslcc r2, r0, #9
248 ldr r6, .htptr
249 lsr r4, r4, #12
250 lsrcc r2, r2, #21
251 bic r4, r4, #15
252 ldr r5, [r3, r2, lsl #2]
253 ldr r7, [r6, r4]!
254 teq r7, r0
255 ldreq pc, [r6, #4]
256 ldr r7, [r6, #8]
257 teq r7, r0
258 ldreq pc, [r6, #12]
259 /* jump_dirty lookup */
260.A6:
261 movs r4, r5
262 beq .A8
263 ldr r3, [r5]
264 ldr r5, [r4, #12]
265 teq r3, r0
266 bne .A6
267.A7:
268 ldr r1, [r4, #8]
269 /* hash_table insert */
270 ldr r2, [r6]
271 ldr r3, [r6, #4]
272 str r0, [r6]
273 str r1, [r6, #4]
274 str r2, [r6, #8]
275 str r3, [r6, #12]
276 mov pc, r1
277.A8:
278 mov r4, r0
279 mov r5, r1
280 bl new_recompile_block
281 tst r0, r0
282 mov r0, r4
283 mov r1, r5
284 beq dyna_linker
285 /* pagefault */
286 mov r1, r0
287 mov r2, #8
288 .size dyna_linker, .-dyna_linker
289 .type exec_pagefault, %function
290exec_pagefault:
291 /* r0 = instruction pointer */
292 /* r1 = fault address */
293 /* r2 = cause */
294 ldr r3, [fp, #reg_cop0+48-dynarec_local] /* Status */
295 mvn r6, #0xF000000F
296 ldr r4, [fp, #reg_cop0+16-dynarec_local] /* Context */
297 bic r6, r6, #0x0F800000
298 str r0, [fp, #reg_cop0+56-dynarec_local] /* EPC */
299 orr r3, r3, #2
300 str r1, [fp, #reg_cop0+32-dynarec_local] /* BadVAddr */
301 bic r4, r4, r6
302 str r3, [fp, #reg_cop0+48-dynarec_local] /* Status */
303 and r5, r6, r1, lsr #9
304 str r2, [fp, #reg_cop0+52-dynarec_local] /* Cause */
305 and r1, r1, r6, lsl #9
306 str r1, [fp, #reg_cop0+40-dynarec_local] /* EntryHi */
307 orr r4, r4, r5
308 str r4, [fp, #reg_cop0+16-dynarec_local] /* Context */
309 mov r0, #0x80000000
310 bl get_addr_ht
311 mov pc, r0
312 .size exec_pagefault, .-exec_pagefault
313/* Special dynamic linker for the case where a page fault
314 may occur in a branch delay slot */
315 .global dyna_linker_ds
316 .hidden dyna_linker_ds
317 .type dyna_linker_ds, %function
318dyna_linker_ds:
319 /* r0 = virtual target address */
320 /* r1 = instruction to patch */
321 ldr r4, .tlbptr
322 lsr r5, r0, #12
323 mov r12, r0
324 cmp r0, #0xC0000000
325 mov r6, #4096
326 ldrge r12, [r4, r5, lsl #2]
327 mov r2, #0x80000
328 ldr r3, .jiptr
329 tst r12, r12
330 sub r6, r6, #1
331 moveq r12, r0
332 ldr r7, [r1]
333 eor r2, r2, r12, lsr #12
334 and r6, r6, r12, lsr #12
335 cmp r2, #2048
336 add r12, r7, #2
337 orrcs r2, r6, #2048
338 ldr r5, [r3, r2, lsl #2]
339 lsl r12, r12, #8
340 /* jump_in lookup */
341.B1:
342 movs r4, r5
343 beq .B3
344 ldr r3, [r5]
345 ldr r5, [r4, #12]
346 teq r3, r0
347 bne .B1
348 ldr r3, [r4, #4]
349 ldr r4, [r4, #8]
350 tst r3, r3
351 bne .B1
352.B2:
353 mov r5, r1
354 add r1, r1, r12, asr #6
355 teq r1, r4
356 moveq pc, r4 /* Stale i-cache */
357 bl add_link
358 sub r2, r4, r5
359 and r1, r7, #0xff000000
360 lsl r2, r2, #6
361 sub r1, r1, #2
362 add r1, r1, r2, lsr #8
363 str r1, [r5]
364 mov pc, r4
365.B3:
366 /* hash_table lookup */
367 cmp r2, #2048
368 ldr r3, .jdptr
369 eor r4, r0, r0, lsl #16
370 lslcc r2, r0, #9
371 ldr r6, .htptr
372 lsr r4, r4, #12
373 lsrcc r2, r2, #21
374 bic r4, r4, #15
375 ldr r5, [r3, r2, lsl #2]
376 ldr r7, [r6, r4]!
377 teq r7, r0
378 ldreq pc, [r6, #4]
379 ldr r7, [r6, #8]
380 teq r7, r0
381 ldreq pc, [r6, #12]
382 /* jump_dirty lookup */
383.B6:
384 movs r4, r5
385 beq .B8
386 ldr r3, [r5]
387 ldr r5, [r4, #12]
388 teq r3, r0
389 bne .B6
390.B7:
391 ldr r1, [r4, #8]
392 /* hash_table insert */
393 ldr r2, [r6]
394 ldr r3, [r6, #4]
395 str r0, [r6]
396 str r1, [r6, #4]
397 str r2, [r6, #8]
398 str r3, [r6, #12]
399 mov pc, r1
400.B8:
401 mov r4, r0
402 bic r0, r0, #7
403 mov r5, r1
404 orr r0, r0, #1
405 bl new_recompile_block
406 tst r0, r0
407 mov r0, r4
408 mov r1, r5
409 beq dyna_linker_ds
410 /* pagefault */
411 bic r1, r0, #7
412 mov r2, #0x80000008 /* High bit set indicates pagefault in delay slot */
413 sub r0, r1, #4
414 b exec_pagefault
415 .size dyna_linker_ds, .-dyna_linker_ds
416.jiptr:
417 .word jump_in
418.jdptr:
419 .word jump_dirty
420.tlbptr:
421 .word tlb_LUT_r
422.htptr:
423 .word hash_table
424 .align 2
425 .global jump_vaddr_r0
426 .hidden jump_vaddr_r0
427 .type jump_vaddr_r0, %function
428jump_vaddr_r0:
429 eor r2, r0, r0, lsl #16
430 b jump_vaddr
431 .size jump_vaddr_r0, .-jump_vaddr_r0
432 .global jump_vaddr_r1
433 .hidden jump_vaddr_r1
434 .type jump_vaddr_r1, %function
435jump_vaddr_r1:
436 eor r2, r1, r1, lsl #16
437 mov r0, r1
438 b jump_vaddr
439 .size jump_vaddr_r1, .-jump_vaddr_r1
440 .global jump_vaddr_r2
441 .hidden jump_vaddr_r2
442 .type jump_vaddr_r2, %function
443jump_vaddr_r2:
444 mov r0, r2
445 eor r2, r2, r2, lsl #16
446 b jump_vaddr
447 .size jump_vaddr_r2, .-jump_vaddr_r2
448 .global jump_vaddr_r3
449 .hidden jump_vaddr_r3
450 .type jump_vaddr_r3, %function
451jump_vaddr_r3:
452 eor r2, r3, r3, lsl #16
453 mov r0, r3
454 b jump_vaddr
455 .size jump_vaddr_r3, .-jump_vaddr_r3
456 .global jump_vaddr_r4
457 .hidden jump_vaddr_r4
458 .type jump_vaddr_r4, %function
459jump_vaddr_r4:
460 eor r2, r4, r4, lsl #16
461 mov r0, r4
462 b jump_vaddr
463 .size jump_vaddr_r4, .-jump_vaddr_r4
464 .global jump_vaddr_r5
465 .hidden jump_vaddr_r5
466 .type jump_vaddr_r5, %function
467jump_vaddr_r5:
468 eor r2, r5, r5, lsl #16
469 mov r0, r5
470 b jump_vaddr
471 .size jump_vaddr_r5, .-jump_vaddr_r5
472 .global jump_vaddr_r6
473 .hidden jump_vaddr_r6
474 .type jump_vaddr_r6, %function
475jump_vaddr_r6:
476 eor r2, r6, r6, lsl #16
477 mov r0, r6
478 b jump_vaddr
479 .size jump_vaddr_r6, .-jump_vaddr_r6
480 .global jump_vaddr_r8
481 .hidden jump_vaddr_r8
482 .type jump_vaddr_r8, %function
483jump_vaddr_r8:
484 eor r2, r8, r8, lsl #16
485 mov r0, r8
486 b jump_vaddr
487 .size jump_vaddr_r8, .-jump_vaddr_r8
488 .global jump_vaddr_r9
489 .hidden jump_vaddr_r9
490 .type jump_vaddr_r9, %function
491jump_vaddr_r9:
492 eor r2, r9, r9, lsl #16
493 mov r0, r9
494 b jump_vaddr
495 .size jump_vaddr_r9, .-jump_vaddr_r9
496 .global jump_vaddr_r10
497 .hidden jump_vaddr_r10
498 .type jump_vaddr_r10, %function
499jump_vaddr_r10:
500 eor r2, r10, r10, lsl #16
501 mov r0, r10
502 b jump_vaddr
503 .size jump_vaddr_r10, .-jump_vaddr_r10
504 .global jump_vaddr_r12
505 .hidden jump_vaddr_r12
506 .type jump_vaddr_r12, %function
507jump_vaddr_r12:
508 eor r2, r12, r12, lsl #16
509 mov r0, r12
510 b jump_vaddr
511 .size jump_vaddr_r12, .-jump_vaddr_r12
512 .global jump_vaddr_r7
513 .hidden jump_vaddr_r7
514 .type jump_vaddr_r7, %function
515jump_vaddr_r7:
516 eor r2, r7, r7, lsl #16
517 add r0, r7, #0
518 .size jump_vaddr_r7, .-jump_vaddr_r7
519 .global jump_vaddr
520 .hidden jump_vaddr
521 .type jump_vaddr, %function
522jump_vaddr:
523 ldr r1, .htptr
524 mvn r3, #15
525 and r2, r3, r2, lsr #12
526 ldr r2, [r1, r2]!
527 teq r2, r0
528 ldreq pc, [r1, #4]
529 ldr r2, [r1, #8]
530 teq r2, r0
531 ldreq pc, [r1, #12]
532 str r10, [fp, #cycle_count-dynarec_local]
533 bl get_addr
534 ldr r10, [fp, #cycle_count-dynarec_local]
535 mov pc, r0
536 .size jump_vaddr, .-jump_vaddr
537 .align 2
538 .global verify_code_ds
539 .hidden verify_code_ds
540 .type verify_code_ds, %function
541verify_code_ds:
542 str r8, [fp, #branch_target-dynarec_local]
543 .size verify_code_ds, .-verify_code_ds
544 .global verify_code_vm
545 .hidden verify_code_vm
546 .type verify_code_vm, %function
547verify_code_vm:
548 /* r0 = instruction pointer (virtual address) */
549 /* r1 = source (virtual address) */
550 /* r2 = target */
551 /* r3 = length */
552 cmp r1, #0xC0000000
553 blt verify_code
554 add r12, fp, #memory_map-dynarec_local
555 lsr r4, r1, #12
556 add r5, r1, r3
557 sub r5, #1
558 ldr r6, [r12, r4, lsl #2]
559 lsr r5, r5, #12
560 movs r7, r6
561 bmi .D5
562 add r1, r1, r6, lsl #2
563 lsl r6, r6, #2
564.D1:
565 add r4, r4, #1
566 teq r6, r7, lsl #2
567 bne .D5
568 ldr r7, [r12, r4, lsl #2]
569 cmp r4, r5
570 bls .D1
571 .size verify_code_vm, .-verify_code_vm
572 .global verify_code
573 .hidden verify_code
574 .type verify_code, %function
575verify_code:
576 /* r1 = source */
577 /* r2 = target */
578 /* r3 = length */
579 tst r3, #4
580 mov r4, #0
581 add r3, r1, r3
582 mov r5, #0
583 ldrne r4, [r1], #4
584 mov r12, #0
585 ldrne r5, [r2], #4
586 teq r1, r3
587 beq .D3
588.D2:
589 ldr r7, [r1], #4
590 eor r9, r4, r5
591 ldr r8, [r2], #4
592 orrs r9, r9, r12
593 bne .D4
594 ldr r4, [r1], #4
595 eor r12, r7, r8
596 ldr r5, [r2], #4
597 cmp r1, r3
598 bcc .D2
599 teq r7, r8
600.D3:
601 teqeq r4, r5
602.D4:
603 ldr r8, [fp, #branch_target-dynarec_local]
604 moveq pc, lr
605.D5:
606 bl get_addr
607 mov pc, r0
608 .size verify_code, .-verify_code
609 .align 2
610 .global cc_interrupt
611 .hidden cc_interrupt
612 .type cc_interrupt, %function
613cc_interrupt:
614 ldr r0, [fp, #last_count-dynarec_local]
615 mov r1, #0
616 mov r2, #0x1fc
617 add r10, r0, r10
618 str r1, [fp, #pending_exception-dynarec_local]
619 and r2, r2, r10, lsr #17
620 add r3, fp, #restore_candidate-dynarec_local
621 str r10, [fp, #reg_cop0+36-dynarec_local] /* Count */
622 ldr r4, [r2, r3]
623 mov r10, lr
624 tst r4, r4
625 bne .E4
626.E1:
627 bl gen_interupt
628 mov lr, r10
629 ldr r10, [fp, #reg_cop0+36-dynarec_local] /* Count */
630 ldr r0, [fp, #next_interupt-dynarec_local]
631 ldr r1, [fp, #pending_exception-dynarec_local]
632 ldr r2, [fp, #stop-dynarec_local]
633 str r0, [fp, #last_count-dynarec_local]
634 sub r10, r10, r0
635 tst r2, r2
636 bne .E3
637 tst r1, r1
638 moveq pc, lr
639.E2:
640 ldr r0, [fp, #pcaddr-dynarec_local]
641 bl get_addr_ht
642 mov pc, r0
643.E3:
644 add r12, fp, #28
645 ldmia r12, {r4, r5, r6, r7, r8, r9, sl, fp, pc}
646.E4:
647 /* Move 'dirty' blocks to the 'clean' list */
648 lsl r5, r2, #3
649 str r1, [r2, r3]
650.E5:
651 lsrs r4, r4, #1
652 mov r0, r5
653 add r5, r5, #1
654 blcs clean_blocks
655 tst r5, #31
656 bne .E5
657 b .E1
658
659 .size cc_interrupt, .-cc_interrupt
660 .align 2
661 .global do_interrupt
662 .hidden do_interrupt
663 .type do_interrupt, %function
664do_interrupt:
665 ldr r0, [fp, #pcaddr-dynarec_local]
666 bl get_addr_ht
667 ldr r1, [fp, #next_interupt-dynarec_local]
668 ldr r10, [fp, #reg_cop0+36-dynarec_local] /* Count */
669 str r1, [fp, #last_count-dynarec_local]
670 sub r10, r10, r1
671 add r10, r10, #2
672 mov pc, r0
673 .size do_interrupt, .-do_interrupt
674 .align 2
675 .global fp_exception
676 .hidden fp_exception
677 .type fp_exception, %function
678fp_exception:
679 mov r2, #0x10000000
680.E7:
681 ldr r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
682 mov r3, #0x80000000
683 str r0, [fp, #reg_cop0+56-dynarec_local] /* EPC */
684 orr r1, #2
685 add r2, r2, #0x2c
686 str r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
687 str r2, [fp, #reg_cop0+52-dynarec_local] /* Cause */
688 add r0, r3, #0x180
689 bl get_addr_ht
690 mov pc, r0
691 .size fp_exception, .-fp_exception
692 .align 2
693 .global fp_exception_ds
694 .hidden fp_exception_ds
695 .type fp_exception_ds, %function
696fp_exception_ds:
697 mov r2, #0x90000000 /* Set high bit if delay slot */
698 b .E7
699 .size fp_exception_ds, .-fp_exception_ds
700 .align 2
701 .global jump_syscall
702 .hidden jump_syscall
703 .type jump_syscall, %function
704jump_syscall:
705 ldr r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
706 mov r3, #0x80000000
707 str r0, [fp, #reg_cop0+56-dynarec_local] /* EPC */
708 orr r1, #2
709 mov r2, #0x20
710 str r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
711 str r2, [fp, #reg_cop0+52-dynarec_local] /* Cause */
712 add r0, r3, #0x180
713 bl get_addr_ht
714 mov pc, r0
715 .size jump_syscall, .-jump_syscall
716 .align 2
717 .global indirect_jump_indexed
718 .hidden indirect_jump_indexed
719 .type indirect_jump_indexed, %function
720indirect_jump_indexed:
721 ldr r0, [r0, r1, lsl #2]
722 .size indirect_jump_indexed, .-indirect_jump_indexed
723 .align 2
724 .global indirect_jump
725 .hidden indirect_jump
726 .type indirect_jump, %function
727indirect_jump:
728 ldr r12, [fp, #last_count-dynarec_local]
729 add r2, r2, r12
730 str r2, [fp, #reg_cop0+36-dynarec_local] /* Count */
731 mov pc, r0
732 .size indirect_jump, .-indirect_jump
733 .align 2
734 .global jump_eret
735 .hidden jump_eret
736 .type jump_eret, %function
737jump_eret:
738 ldr r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
739 ldr r0, [fp, #last_count-dynarec_local]
740 bic r1, r1, #2
741 add r10, r0, r10
742 str r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
743 str r10, [fp, #reg_cop0+36-dynarec_local] /* Count */
744 bl check_interupt
745 ldr r1, [fp, #next_interupt-dynarec_local]
746 ldr r0, [fp, #reg_cop0+56-dynarec_local] /* EPC */
747 str r1, [fp, #last_count-dynarec_local]
748 subs r10, r10, r1
749 bpl .E11
750.E8:
751 add r6, fp, #reg+256-dynarec_local
752 mov r5, #248
753 mov r1, #0
754.E9:
755 ldr r2, [r6, #-8]!
756 ldr r3, [r6, #4]
757 eor r3, r3, r2, asr #31
758 subs r3, r3, #1
759 adc r1, r1, r1
760 subs r5, r5, #8
761 bne .E9
762 ldr r2, [fp, #hi-dynarec_local]
763 ldr r3, [fp, #hi+4-dynarec_local]
764 eors r3, r3, r2, asr #31
765 ldr r2, [fp, #lo-dynarec_local]
766 ldreq r3, [fp, #lo+4-dynarec_local]
767 eoreq r3, r3, r2, asr #31
768 subs r3, r3, #1
769 adc r1, r1, r1
770 bl get_addr_32
771 mov pc, r0
772.E11:
773 str r0, [fp, #pcaddr-dynarec_local]
774 bl cc_interrupt
775 ldr r0, [fp, #pcaddr-dynarec_local]
776 b .E8
777 .size jump_eret, .-jump_eret
778 .align 2
779 .global new_dyna_start
780 .hidden new_dyna_start
781 .type new_dyna_start, %function
782new_dyna_start:
783 ldr r12, .dlptr
784 ldr r1, .tgtptr
785 mov r0, #0xa4000000
786 stmia r12, {r4, r5, r6, r7, r8, r9, sl, fp, lr}
787 sub fp, r12, #28
788 ldr r4, [r1]
789 add r0, r0, #0x40
790 bl new_recompile_block
791 ldr r0, [fp, #next_interupt-dynarec_local]
792 ldr r10, [fp, #reg_cop0+36-dynarec_local] /* Count */
793 str r0, [fp, #last_count-dynarec_local]
794 sub r10, r10, r0
795 mov pc, r4
796.dlptr:
797 .word dynarec_local+28
798.tgtptr:
799 .word out
800 .size new_dyna_start, .-new_dyna_start
801 .align 2
802 .global invalidate_addr_r0
803 .hidden invalidate_addr_r0
804 .type invalidate_addr_r0, %function
805invalidate_addr_r0:
806 stmia fp, {r0, r1, r2, r3, r12, lr}
807 lsr r0, r0, #12
808 b invalidate_addr_call
809 .size invalidate_addr_r0, .-invalidate_addr_r0
810 .align 2
811 .global invalidate_addr_r1
812 .hidden invalidate_addr_r1
813 .type invalidate_addr_r1, %function
814invalidate_addr_r1:
815 stmia fp, {r0, r1, r2, r3, r12, lr}
816 lsr r0, r1, #12
817 b invalidate_addr_call
818 .size invalidate_addr_r1, .-invalidate_addr_r1
819 .align 2
820 .global invalidate_addr_r2
821 .hidden invalidate_addr_r2
822 .type invalidate_addr_r2, %function
823invalidate_addr_r2:
824 stmia fp, {r0, r1, r2, r3, r12, lr}
825 lsr r0, r2, #12
826 b invalidate_addr_call
827 .size invalidate_addr_r2, .-invalidate_addr_r2
828 .align 2
829 .global invalidate_addr_r3
830 .hidden invalidate_addr_r3
831 .type invalidate_addr_r3, %function
832invalidate_addr_r3:
833 stmia fp, {r0, r1, r2, r3, r12, lr}
834 lsr r0, r3, #12
835 b invalidate_addr_call
836 .size invalidate_addr_r3, .-invalidate_addr_r3
837 .align 2
838 .global invalidate_addr_r4
839 .hidden invalidate_addr_r4
840 .type invalidate_addr_r4, %function
841invalidate_addr_r4:
842 stmia fp, {r0, r1, r2, r3, r12, lr}
843 lsr r0, r4, #12
844 b invalidate_addr_call
845 .size invalidate_addr_r4, .-invalidate_addr_r4
846 .align 2
847 .global invalidate_addr_r5
848 .hidden invalidate_addr_r5
849 .type invalidate_addr_r5, %function
850invalidate_addr_r5:
851 stmia fp, {r0, r1, r2, r3, r12, lr}
852 lsr r0, r5, #12
853 b invalidate_addr_call
854 .size invalidate_addr_r5, .-invalidate_addr_r5
855 .align 2
856 .global invalidate_addr_r6
857 .hidden invalidate_addr_r6
858 .type invalidate_addr_r6, %function
859invalidate_addr_r6:
860 stmia fp, {r0, r1, r2, r3, r12, lr}
861 lsr r0, r6, #12
862 b invalidate_addr_call
863 .size invalidate_addr_r6, .-invalidate_addr_r6
864 .align 2
865 .global invalidate_addr_r7
866 .hidden invalidate_addr_r7
867 .type invalidate_addr_r7, %function
868invalidate_addr_r7:
869 stmia fp, {r0, r1, r2, r3, r12, lr}
870 lsr r0, r7, #12
871 b invalidate_addr_call
872 .size invalidate_addr_r7, .-invalidate_addr_r7
873 .align 2
874 .global invalidate_addr_r8
875 .hidden invalidate_addr_r8
876 .type invalidate_addr_r8, %function
877invalidate_addr_r8:
878 stmia fp, {r0, r1, r2, r3, r12, lr}
879 lsr r0, r8, #12
880 b invalidate_addr_call
881 .size invalidate_addr_r8, .-invalidate_addr_r8
882 .align 2
883 .global invalidate_addr_r9
884 .hidden invalidate_addr_r9
885 .type invalidate_addr_r9, %function
886invalidate_addr_r9:
887 stmia fp, {r0, r1, r2, r3, r12, lr}
888 lsr r0, r9, #12
889 b invalidate_addr_call
890 .size invalidate_addr_r9, .-invalidate_addr_r9
891 .align 2
892 .global invalidate_addr_r10
893 .hidden invalidate_addr_r10
894 .type invalidate_addr_r10, %function
895invalidate_addr_r10:
896 stmia fp, {r0, r1, r2, r3, r12, lr}
897 lsr r0, r10, #12
898 b invalidate_addr_call
899 .size invalidate_addr_r10, .-invalidate_addr_r10
900 .align 2
901 .global invalidate_addr_r12
902 .hidden invalidate_addr_r12
903 .type invalidate_addr_r12, %function
904invalidate_addr_r12:
905 stmia fp, {r0, r1, r2, r3, r12, lr}
906 lsr r0, r12, #12
907 .size invalidate_addr_r12, .-invalidate_addr_r12
908 .align 2
909 .type invalidate_addr_call, %function
910invalidate_addr_call:
911 bl invalidate_block
912 ldmia fp, {r0, r1, r2, r3, r12, pc}
913 .size invalidate_addr_call, .-invalidate_addr_call
914 .align 2
915 .global write_rdram_new
916 .hidden write_rdram_new
917 .type write_rdram_new, %function
918write_rdram_new:
919 ldr r3, [fp, #ram_offset-dynarec_local]
920 ldr r2, [fp, #address-dynarec_local]
921 ldr r0, [fp, #word-dynarec_local]
922 str r0, [r2, r3, lsl #2]
923 b .E12
924 .size write_rdram_new, .-write_rdram_new
925 .align 2
926 .global write_rdramb_new
927 .hidden write_rdramb_new
928 .type write_rdramb_new, %function
929write_rdramb_new:
930 ldr r3, [fp, #ram_offset-dynarec_local]
931 ldr r2, [fp, #address-dynarec_local]
932 ldrb r0, [fp, #cpu_byte-dynarec_local]
933 eor r2, r2, #3
934 strb r0, [r2, r3, lsl #2]
935 b .E12
936 .size write_rdramb_new, .-write_rdramb_new
937 .align 2
938 .global write_rdramh_new
939 .hidden write_rdramh_new
940 .type write_rdramh_new, %function
941write_rdramh_new:
942 ldr r3, [fp, #ram_offset-dynarec_local]
943 ldr r2, [fp, #address-dynarec_local]
944 ldrh r0, [fp, #hword-dynarec_local]
945 eor r2, r2, #2
946 lsl r3, r3, #2
947 strh r0, [r2, r3]
948 b .E12
949 .size write_rdramh_new, .-write_rdramh_new
950 .align 2
951 .global write_rdramd_new
952 .hidden write_rdramd_new
953 .type write_rdramd_new, %function
954write_rdramd_new:
955 ldr r3, [fp, #ram_offset-dynarec_local]
956 ldr r2, [fp, #address-dynarec_local]
957/* ldrd r0, [fp, #dword-dynarec_local]*/
958 ldr r0, [fp, #dword-dynarec_local]
959 ldr r1, [fp, #dword+4-dynarec_local]
960 add r3, r2, r3, lsl #2
961 str r0, [r3, #4]
962 str r1, [r3]
963 b .E12
964 .size write_rdramd_new, .-write_rdramd_new
965 .align 2
966 .type do_invalidate, %function
967do_invalidate:
968 ldr r2, [fp, #address-dynarec_local]
969.E12:
970 ldr r1, [fp, #invc_ptr-dynarec_local]
971 lsr r0, r2, #12
972 ldrb r2, [r1, r0]
973 tst r2, r2
974 beq invalidate_block
975 mov pc, lr
976 .size do_invalidate, .-do_invalidate
977 .align 2
978 .global read_nomem_new
979 .hidden read_nomem_new
980 .type read_nomem_new, %function
981read_nomem_new:
982 ldr r2, [fp, #address-dynarec_local]
983 add r12, fp, #memory_map-dynarec_local
984 lsr r0, r2, #12
985 ldr r12, [r12, r0, lsl #2]
986 mov r1, #8
987 tst r12, r12
988 bmi tlb_exception
989 ldr r0, [r2, r12, lsl #2]
990 str r0, [fp, #readmem_dword-dynarec_local]
991 mov pc, lr
992 .size read_nomem_new, .-read_nomem_new
993 .align 2
994 .global read_nomemb_new
995 .hidden read_nomemb_new
996 .type read_nomemb_new, %function
997read_nomemb_new:
998 ldr r2, [fp, #address-dynarec_local]
999 add r12, fp, #memory_map-dynarec_local
1000 lsr r0, r2, #12
1001 ldr r12, [r12, r0, lsl #2]
1002 mov r1, #8
1003 tst r12, r12
1004 bmi tlb_exception
1005 eor r2, r2, #3
1006 ldrb r0, [r2, r12, lsl #2]
1007 str r0, [fp, #readmem_dword-dynarec_local]
1008 mov pc, lr
1009 .size read_nomemb_new, .-read_nomemb_new
1010 .align 2
1011 .global read_nomemh_new
1012 .hidden read_nomemh_new
1013 .type read_nomemh_new, %function
1014read_nomemh_new:
1015 ldr r2, [fp, #address-dynarec_local]
1016 add r12, fp, #memory_map-dynarec_local
1017 lsr r0, r2, #12
1018 ldr r12, [r12, r0, lsl #2]
1019 mov r1, #8
1020 tst r12, r12
1021 bmi tlb_exception
1022 lsl r12, r12, #2
1023 eor r2, r2, #2
1024 ldrh r0, [r2, r12]
1025 str r0, [fp, #readmem_dword-dynarec_local]
1026 mov pc, lr
1027 .size read_nomemh_new, .-read_nomemh_new
1028 .align 2
1029 .global read_nomemd_new
1030 .hidden read_nomemd_new
1031 .type read_nomemd_new, %function
1032read_nomemd_new:
1033 ldr r2, [fp, #address-dynarec_local]
1034 add r12, fp, #memory_map-dynarec_local
1035 lsr r0, r2, #12
1036 ldr r12, [r12, r0, lsl #2]
1037 mov r1, #8
1038 tst r12, r12
1039 bmi tlb_exception
1040 lsl r12, r12, #2
1041/* ldrd r0, [r2, r12]*/
1042 add r3, r2, #4
1043 ldr r0, [r2, r12]
1044 ldr r1, [r3, r12]
1045 str r0, [fp, #readmem_dword+4-dynarec_local]
1046 str r1, [fp, #readmem_dword-dynarec_local]
1047 mov pc, lr
1048 .size read_nomemd_new, .-read_nomemd_new
1049 .align 2
1050 .global write_nomem_new
1051 .hidden write_nomem_new
1052 .type write_nomem_new, %function
1053write_nomem_new:
1054 str r3, [fp, #24]
1055 str lr, [fp, #28]
1056 bl do_invalidate
1057 ldr r2, [fp, #address-dynarec_local]
1058 add r12, fp, #memory_map-dynarec_local
1059 ldr lr, [fp, #28]
1060 lsr r0, r2, #12
1061 ldr r3, [fp, #24]
1062 ldr r12, [r12, r0, lsl #2]
1063 mov r1, #0xc
1064 tst r12, #0x40000000
1065 bne tlb_exception
1066 ldr r0, [fp, #word-dynarec_local]
1067 str r0, [r2, r12, lsl #2]
1068 mov pc, lr
1069 .size write_nomem_new, .-write_nomem_new
1070 .align 2
1071 .global write_nomemb_new
1072 .hidden write_nomemb_new
1073 .type write_nomemb_new, %function
1074write_nomemb_new:
1075 str r3, [fp, #24]
1076 str lr, [fp, #28]
1077 bl do_invalidate
1078 ldr r2, [fp, #address-dynarec_local]
1079 add r12, fp, #memory_map-dynarec_local
1080 ldr lr, [fp, #28]
1081 lsr r0, r2, #12
1082 ldr r3, [fp, #24]
1083 ldr r12, [r12, r0, lsl #2]
1084 mov r1, #0xc
1085 tst r12, #0x40000000
1086 bne tlb_exception
1087 eor r2, r2, #3
1088 ldrb r0, [fp, #cpu_byte-dynarec_local]
1089 strb r0, [r2, r12, lsl #2]
1090 mov pc, lr
1091 .size write_nomemb_new, .-write_nomemb_new
1092 .align 2
1093 .global write_nomemh_new
1094 .hidden write_nomemh_new
1095 .type write_nomemh_new, %function
1096write_nomemh_new:
1097 str r3, [fp, #24]
1098 str lr, [fp, #28]
1099 bl do_invalidate
1100 ldr r2, [fp, #address-dynarec_local]
1101 add r12, fp, #memory_map-dynarec_local
1102 ldr lr, [fp, #28]
1103 lsr r0, r2, #12
1104 ldr r3, [fp, #24]
1105 ldr r12, [r12, r0, lsl #2]
1106 mov r1, #0xc
1107 lsls r12, #2
1108 bcs tlb_exception
1109 eor r2, r2, #2
1110 ldrh r0, [fp, #hword-dynarec_local]
1111 strh r0, [r2, r12]
1112 mov pc, lr
1113 .size write_nomemh_new, .-write_nomemh_new
1114 .align 2
1115 .global write_nomemd_new
1116 .hidden write_nomemd_new
1117 .type write_nomemd_new, %function
1118write_nomemd_new:
1119 str r3, [fp, #24]
1120 str lr, [fp, #28]
1121 bl do_invalidate
1122 ldr r2, [fp, #address-dynarec_local]
1123 add r12, fp, #memory_map-dynarec_local
1124 ldr lr, [fp, #28]
1125 lsr r0, r2, #12
1126 ldr r3, [fp, #24]
1127 ldr r12, [r12, r0, lsl #2]
1128 mov r1, #0xc
1129 lsls r12, #2
1130 bcs tlb_exception
1131 add r3, r2, #4
1132 ldr r0, [fp, #dword+4-dynarec_local]
1133 ldr r1, [fp, #dword-dynarec_local]
1134/* strd r0, [r2, r12]*/
1135 str r0, [r2, r12]
1136 str r1, [r3, r12]
1137 mov pc, lr
1138 .size write_nomemd_new, .-write_nomemd_new
1139 .align 2
1140 .type tlb_exception, %function
1141tlb_exception:
1142 /* r1 = cause */
1143 /* r2 = address */
1144 /* r3 = instr addr/flags */
1145 ldr r4, [fp, #reg_cop0+48-dynarec_local] /* Status */
1146 add r5, fp, #memory_map-dynarec_local
1147 lsr r6, r3, #12
1148 orr r1, r1, r3, lsl #31
1149 orr r4, r4, #2
1150 ldr r7, [r5, r6, lsl #2]
1151 bic r8, r3, #3
1152 str r4, [fp, #reg_cop0+48-dynarec_local] /* Status */
1153 mov r6, #0x6000000
1154 str r1, [fp, #reg_cop0+52-dynarec_local] /* Cause */
1155 orr r6, r6, #0x22
1156 ldr r0, [r8, r7, lsl #2]
1157 add r4, r8, r1, asr #29
1158 add r5, fp, #reg-dynarec_local
1159 str r4, [fp, #reg_cop0+56-dynarec_local] /* EPC */
1160 mov r7, #0xf8
1161 ldr r8, [fp, #reg_cop0+16-dynarec_local] /* Context */
1162 lsl r1, r0, #16
1163 lsr r4, r0, #26
1164 and r7, r7, r0, lsr #18
1165 mvn r9, #0xF000000F
1166 sub r2, r2, r1, asr #16
1167 bic r9, r9, #0x0F800000
1168 rors r6, r6, r4
1169 mov r0, #0x80000000
1170 ldrcs r2, [r5, r7]
1171 bic r8, r8, r9
1172 tst r3, #2
1173 str r2, [r5, r7]
1174 add r4, r2, r1, asr #16
1175 add r6, fp, #reg+4-dynarec_local
1176 asr r3, r2, #31
1177 str r4, [fp, #reg_cop0+32-dynarec_local] /* BadVAddr */
1178 add r0, r0, #0x180
1179 and r4, r9, r4, lsr #9
1180 strne r3, [r6, r7]
1181 orr r8, r8, r4
1182 str r8, [fp, #reg_cop0+16-dynarec_local] /* Context */
1183 bl get_addr_ht
1184 ldr r1, [fp, #next_interupt-dynarec_local]
1185 ldr r10, [fp, #reg_cop0+36-dynarec_local] /* Count */
1186 str r1, [fp, #last_count-dynarec_local]
1187 sub r10, r10, r1
1188 mov pc, r0
1189 .size tlb_exception, .-tlb_exception
1190 .align 2
1191 .global breakpoint
1192 .hidden breakpoint
1193 .type breakpoint, %function
1194breakpoint:
1195 /* Set breakpoint here for debugging */
1196 mov pc, lr
1197 .size breakpoint, .-breakpoint
1198/* The following bug-fix implements __clear_cache (missing in Android) */
1199 .align 2
1200 .global __clear_cache_bugfix
1201 .hidden __clear_cache_bugfix
1202 .type __clear_cache_bugfix, %function
1203__clear_cache_bugfix:
1204 push {r7, lr}
1205 mov r2, #0
1206 mov r7, #0x2
1207 add r7, r7, #0xf0000
1208 svc 0x00000000
1209 pop {r7, pc}
1210 .size __clear_cache_bugfix, .-__clear_cache_bugfix
1211/* End of bug-fix */
1212 .section .note.GNU-stack,"",%progbits