Core commit. Compile and run on the OpenPandora
[mupen64plus-pandora.git] / source / mupen64plus-core / src / r4300 / new_dynarec / linkage_arm.S
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
97 extra_memory:
98         .space  33554432+64+16+16+8+8+8+8+256+8+8+128+128+128+16+8+132+4+256+512+4194304
99 dynarec_local = extra_memory + 33554432
100         .type   dynarec_local, %object
101         .size   dynarec_local, 64
102 next_interupt = dynarec_local + 64
103         .type   next_interupt, %object
104         .size   next_interupt, 4
105 cycle_count = next_interupt + 4
106         .type   cycle_count, %object
107         .size   cycle_count, 4
108 last_count = cycle_count + 4
109         .type   last_count, %object
110         .size   last_count, 4
111 pending_exception = last_count + 4
112         .type   pending_exception, %object
113         .size   pending_exception, 4
114 pcaddr = pending_exception + 4
115         .type   pcaddr, %object
116         .size   pcaddr, 4
117 stop = pcaddr + 4
118         .type   stop, %object
119         .size   stop, 4
120 invc_ptr = stop + 4
121         .type   invc_ptr, %object
122         .size   invc_ptr, 4
123 address = invc_ptr + 4
124         .type   address, %object
125         .size   address, 4
126 readmem_dword = address + 4
127         .type   readmem_dword, %object
128         .size   readmem_dword, 8
129 dword = readmem_dword + 8
130         .type   dword, %object
131         .size   dword, 8
132 word = dword + 8
133         .type   word, %object
134         .size   word, 4
135 hword = word + 4
136         .type   hword, %object
137         .size   hword, 2
138 cpu_byte = hword + 2
139         .type   cpu_byte, %object
140         .size   cpu_byte, 1 /* 1 byte free */
141 FCR0 = hword + 4
142         .type   FCR0, %object
143         .size   FCR0, 4
144 FCR31 = FCR0 + 4
145         .type   FCR31, %object
146         .size   FCR31, 4
147 reg = FCR31 + 4
148         .type   reg, %object
149         .size   reg, 256
150 hi = reg + 256
151         .type   hi, %object
152         .size   hi, 8
153 lo = hi + 8
154         .type   lo, %object
155         .size   lo, 8
156 reg_cop0 = lo + 8
157         .type   reg_cop0, %object
158         .size   reg_cop0, 128
159 reg_cop1_simple = reg_cop0 + 128
160         .type   reg_cop1_simple, %object
161         .size   reg_cop1_simple, 128
162 reg_cop1_double = reg_cop1_simple + 128
163         .type   reg_cop1_double, %object
164         .size   reg_cop1_double, 128
165 rounding_modes = reg_cop1_double + 128
166         .type   rounding_modes, %object
167         .size   rounding_modes, 16
168 branch_target = rounding_modes + 16
169         .type   branch_target, %object
170         .size   branch_target, 4
171 PC = branch_target + 4
172         .type   PC, %object
173         .size   PC, 4
174 fake_pc = PC + 4
175         .type   fake_pc, %object
176         .size   fake_pc, 132
177 ram_offset = fake_pc + 132
178         .type   ram_offset, %object
179         .size   ram_offset, 4
180 mini_ht = ram_offset + 4
181         .type   mini_ht, %object
182         .size   mini_ht, 256
183 restore_candidate = mini_ht + 256
184         .type   restore_candidate, %object
185         .size   restore_candidate, 512
186 memory_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
195 dyna_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
290 exec_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
318 dyna_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
428 jump_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
435 jump_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
443 jump_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
451 jump_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
459 jump_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
467 jump_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
475 jump_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
483 jump_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
491 jump_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
499 jump_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
507 jump_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
515 jump_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
522 jump_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
541 verify_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
547 verify_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
575 verify_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
613 cc_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
664 do_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
678 fp_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
696 fp_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
704 jump_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
720 indirect_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
727 indirect_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
737 jump_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
782 new_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
805 invalidate_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
814 invalidate_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
823 invalidate_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
832 invalidate_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
841 invalidate_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
850 invalidate_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
859 invalidate_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
868 invalidate_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
877 invalidate_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
886 invalidate_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
895 invalidate_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
904 invalidate_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
910 invalidate_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
918 write_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
929 write_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
941 write_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
954 write_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
967 do_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
981 read_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
997 read_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
1014 read_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
1032 read_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
1053 write_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
1074 write_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
1096 write_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
1118 write_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
1141 tlb_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
1194 breakpoint:
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