drc: make sure dyna_linker is really called from stub
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / linkage_arm.s
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  *   linkage_arm.s for PCSX                                                *
3  *   Copyright (C) 2009-2011 Ari64                                         *
4  *   Copyright (C) 2010-2011 GraÅžvydas "notaz" Ignotas                     *
5  *                                                                         *
6  *   This program is free software; you can redistribute it and/or modify  *
7  *   it under the terms of the GNU General Public License as published by  *
8  *   the Free Software Foundation; either version 2 of the License, or     *
9  *   (at your option) any later version.                                   *
10  *                                                                         *
11  *   This program is distributed in the hope that it will be useful,       *
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14  *   GNU General Public License for more details.                          *
15  *                                                                         *
16  *   You should have received a copy of the GNU General Public License     *
17  *   along with this program; if not, write to the                         *
18  *   Free Software Foundation, Inc.,                                       *
19  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
20  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
21
22 .equiv HAVE_ARMV7, 1
23
24 .if HAVE_ARMV7
25         .cpu cortex-a8
26         .fpu vfp
27 .else
28         .cpu arm9tdmi
29         .fpu softvfp
30 .endif 
31         .global rdram
32 rdram = 0x80000000
33         .global dynarec_local
34         .global reg
35         .global hi
36         .global lo
37         .global reg_cop0
38         .global reg_cop2d
39         .global reg_cop2c
40         .global FCR0
41         .global FCR31
42         .global next_interupt
43         .global cycle_count
44         .global last_count
45         .global pending_exception
46         .global pcaddr
47         .global stop
48         .global invc_ptr
49         .global address
50         .global readmem_dword
51         .global readmem_word
52         .global dword
53         .global word
54         .global hword
55         .global byte
56         .global branch_target
57         .global PC
58         .global mini_ht
59         .global restore_candidate
60         .global memory_map
61         /* psx */
62         .global psxRegs
63         .global nd_pcsx_io
64         .global psxH_ptr
65
66         .bss
67         .align  4
68         .type   dynarec_local, %object
69         .size   dynarec_local, dynarec_local_end-dynarec_local
70 dynarec_local:
71         .space  dynarec_local_end-dynarec_local /*0x400630*/
72 next_interupt = dynarec_local + 64
73         .type   next_interupt, %object
74         .size   next_interupt, 4
75 cycle_count = next_interupt + 4
76         .type   cycle_count, %object
77         .size   cycle_count, 4
78 last_count = cycle_count + 4
79         .type   last_count, %object
80         .size   last_count, 4
81 pending_exception = last_count + 4
82         .type   pending_exception, %object
83         .size   pending_exception, 4
84 stop = pending_exception + 4
85         .type   stop, %object
86         .size   stop, 4
87 invc_ptr = stop + 4
88         .type   invc_ptr, %object
89         .size   invc_ptr, 4
90 address = invc_ptr + 4
91         .type   address, %object
92         .size   address, 4
93 readmem_dword = address + 4
94 readmem_word = readmem_dword
95         .type   readmem_dword, %object
96         .size   readmem_dword, 8
97 dword = readmem_dword + 8
98         .type   dword, %object
99         .size   dword, 8
100 word = dword + 8
101         .type   word, %object
102         .size   word, 4
103 hword = word + 4
104         .type   hword, %object
105         .size   hword, 2
106 byte = hword + 2
107         .type   byte, %object
108         .size   byte, 1 /* 1 byte free */
109 FCR0 = hword + 4
110         .type   FCR0, %object
111         .size   FCR0, 4
112 FCR31 = FCR0 + 4
113         .type   FCR31, %object
114         .size   FCR31, 4
115 psxRegs = FCR31 + 4
116
117 /* psxRegs */
118         .type   psxRegs, %object
119         .size   psxRegs, psxRegs_end-psxRegs
120 reg = psxRegs
121         .type   reg, %object
122         .size   reg, 128
123 lo = reg + 128
124         .type   lo, %object
125         .size   lo, 4
126 hi = lo + 4
127         .type   hi, %object
128         .size   hi, 4
129 reg_cop0 = hi + 4
130         .type   reg_cop0, %object
131         .size   reg_cop0, 128
132 reg_cop2d = reg_cop0 + 128
133         .type   reg_cop2d, %object
134         .size   reg_cop2d, 128
135 reg_cop2c = reg_cop2d + 128
136         .type   reg_cop2c, %object
137         .size   reg_cop2c, 128
138 PC = reg_cop2c + 128
139 pcaddr = PC
140         .type   PC, %object
141         .size   PC, 4
142 code = PC + 4
143         .type   code, %object
144         .size   code, 4
145 cycle = code + 4
146         .type   cycle, %object
147         .size   cycle, 4
148 interrupt = cycle + 4
149         .type   interrupt, %object
150         .size   interrupt, 4
151 intCycle = interrupt + 4
152         .type   intCycle, %object
153         .size   intCycle, 256
154 psxRegs_end = intCycle + 256
155
156 /* nd_pcsx_io */
157 nd_pcsx_io = psxRegs_end
158         .type   nd_pcsx_io, %object
159         .size   nd_pcsx_io, nd_pcsx_io_end-nd_pcsx_io
160 tab_read8 = nd_pcsx_io
161         .type   tab_read8, %object
162         .size   tab_read8, 4
163 tab_read16 = tab_read8 + 4
164         .type   tab_read16, %object
165         .size   tab_read16, 4
166 tab_read32 = tab_read16 + 4
167         .type   tab_read32, %object
168         .size   tab_read32, 4
169 tab_write8 = tab_read32 + 4
170         .type   tab_write8, %object
171         .size   tab_write8, 4
172 tab_write16 = tab_write8 + 4
173         .type   tab_write16, %object
174         .size   tab_write16, 4
175 tab_write32 = tab_write16 + 4
176         .type   tab_write32, %object
177         .size   tab_write32, 4
178 spu_readf = tab_write32 + 4
179         .type   spu_readf, %object
180         .size   spu_readf, 4
181 spu_writef = spu_readf + 4
182         .type   spu_writef, %object
183         .size   spu_writef, 4
184 nd_pcsx_io_end = spu_writef + 4
185
186 psxH_ptr = nd_pcsx_io_end
187         .type   psxH_ptr, %object
188         .size   psxH_ptr, 4
189 align0 = psxH_ptr + 4 /* just for alignment */
190         .type   align0, %object
191         .size   align0, 4
192 branch_target = align0 + 4
193         .type   branch_target, %object
194         .size   branch_target, 4
195 mini_ht = branch_target + 4
196         .type   mini_ht, %object
197         .size   mini_ht, 256
198 restore_candidate = mini_ht + 256
199         .type   restore_candidate, %object
200         .size   restore_candidate, 512
201 memory_map = restore_candidate + 512
202         .type   memory_map, %object
203         .size   memory_map, 4194304
204 dynarec_local_end = memory_map + 4194304
205
206 .macro load_var_adr reg var
207 .if HAVE_ARMV7
208         movw    \reg, #:lower16:\var
209         movt    \reg, #:upper16:\var
210 .else
211         ldr     \reg, =\var
212 .endif
213 .endm
214
215 .macro dyna_linker_main
216         /* r0 = virtual target address */
217         /* r1 = instruction to patch */
218         ldr     r3, .jiptr
219         /* get_page */
220         lsr     r2, r0, #12
221         mov     r6, #4096
222         bic     r2, r2, #0xe0000
223         sub     r6, r6, #1
224         cmp     r2, #0x1000
225         ldr     r7, [r1]
226         biclt   r2, #0x0e00
227         and     r6, r6, r2
228         cmp     r2, #2048
229         add     r12, r7, #2
230         orrcs   r2, r6, #2048
231         ldr     r5, [r3, r2, lsl #2]
232         lsl     r12, r12, #8
233         add     r6, r1, r12, asr #6
234         mov     r8, #0
235         /* jump_in lookup */
236 1:
237         movs    r4, r5
238         beq     2f
239         ldr     r3, [r5]
240         ldr     r5, [r4, #12]
241         teq     r3, r0
242         bne     1b
243         ldr     r3, [r4, #4]
244         ldr     r4, [r4, #8]
245         tst     r3, r3
246         bne     1b
247         teq     r4, r6
248         moveq   pc, r4 /* Stale i-cache */
249         mov     r8, r4
250         b       1b     /* jump_in may have dupes, continue search */
251 2:
252         tst     r8, r8
253         beq     3f     /* r0 not in jump_in */
254
255         mov     r5, r1
256         mov     r1, r6
257         bl      add_link
258         sub     r2, r8, r5
259         and     r1, r7, #0xff000000
260         lsl     r2, r2, #6
261         sub     r1, r1, #2
262         add     r1, r1, r2, lsr #8
263         str     r1, [r5]
264         mov     pc, r8
265 3:
266         /* hash_table lookup */
267         cmp     r2, #2048
268         ldr     r3, .jdptr
269         eor     r4, r0, r0, lsl #16
270         lslcc   r2, r0, #9
271         ldr     r6, .htptr
272         lsr     r4, r4, #12
273         lsrcc   r2, r2, #21
274         bic     r4, r4, #15
275         ldr     r5, [r3, r2, lsl #2]
276         ldr     r7, [r6, r4]!
277         teq     r7, r0
278         ldreq   pc, [r6, #4]
279         ldr     r7, [r6, #8]
280         teq     r7, r0
281         ldreq   pc, [r6, #12]
282         /* jump_dirty lookup */
283 6:
284         movs    r4, r5
285         beq     8f
286         ldr     r3, [r5]
287         ldr     r5, [r4, #12]
288         teq     r3, r0
289         bne     6b
290 7:
291         ldr     r1, [r4, #8]
292         /* hash_table insert */
293         ldr     r2, [r6]
294         ldr     r3, [r6, #4]
295         str     r0, [r6]
296         str     r1, [r6, #4]
297         str     r2, [r6, #8]
298         str     r3, [r6, #12]
299         mov     pc, r1
300 8:
301 .endm
302
303         .text
304         .align  2
305         .global dyna_linker
306         .type   dyna_linker, %function
307 dyna_linker:
308         /* r0 = virtual target address */
309         /* r1 = instruction to patch */
310         dyna_linker_main
311
312         mov     r4, r0
313         mov     r5, r1
314         bl      new_recompile_block
315         tst     r0, r0
316         mov     r0, r4
317         mov     r1, r5
318         beq     dyna_linker
319         /* pagefault */
320         mov     r1, r0
321         mov     r2, #8
322         .size   dyna_linker, .-dyna_linker
323         .global exec_pagefault
324         .type   exec_pagefault, %function
325 exec_pagefault:
326         /* r0 = instruction pointer */
327         /* r1 = fault address */
328         /* r2 = cause */
329         ldr     r3, [fp, #reg_cop0+48-dynarec_local] /* Status */
330         mvn     r6, #0xF000000F
331         ldr     r4, [fp, #reg_cop0+16-dynarec_local] /* Context */
332         bic     r6, r6, #0x0F800000
333         str     r0, [fp, #reg_cop0+56-dynarec_local] /* EPC */
334         orr     r3, r3, #2
335         str     r1, [fp, #reg_cop0+32-dynarec_local] /* BadVAddr */
336         bic     r4, r4, r6
337         str     r3, [fp, #reg_cop0+48-dynarec_local] /* Status */
338         and     r5, r6, r1, lsr #9
339         str     r2, [fp, #reg_cop0+52-dynarec_local] /* Cause */
340         and     r1, r1, r6, lsl #9
341         str     r1, [fp, #reg_cop0+40-dynarec_local] /* EntryHi */
342         orr     r4, r4, r5
343         str     r4, [fp, #reg_cop0+16-dynarec_local] /* Context */
344         mov     r0, #0x80000000
345         bl      get_addr_ht
346         mov     pc, r0
347         .size   exec_pagefault, .-exec_pagefault
348
349 /* Special dynamic linker for the case where a page fault
350    may occur in a branch delay slot */
351         .global dyna_linker_ds
352         .type   dyna_linker_ds, %function
353 dyna_linker_ds:
354         /* r0 = virtual target address */
355         /* r1 = instruction to patch */
356         dyna_linker_main
357
358         mov     r4, r0
359         bic     r0, r0, #7
360         mov     r5, r1
361         orr     r0, r0, #1
362         bl      new_recompile_block
363         tst     r0, r0
364         mov     r0, r4
365         mov     r1, r5
366         beq     dyna_linker_ds
367         /* pagefault */
368         bic     r1, r0, #7
369         mov     r2, #0x80000008 /* High bit set indicates pagefault in delay slot */
370         sub     r0, r1, #4
371         b       exec_pagefault
372         .size   dyna_linker_ds, .-dyna_linker_ds
373 .jiptr:
374         .word   jump_in
375 .jdptr:
376         .word   jump_dirty
377 .htptr:
378         .word   hash_table
379
380         .align  2
381         .global jump_vaddr_r0
382         .type   jump_vaddr_r0, %function
383 jump_vaddr_r0:
384         eor     r2, r0, r0, lsl #16
385         b       jump_vaddr
386         .size   jump_vaddr_r0, .-jump_vaddr_r0
387         .global jump_vaddr_r1
388         .type   jump_vaddr_r1, %function
389 jump_vaddr_r1:
390         eor     r2, r1, r1, lsl #16
391         mov     r0, r1
392         b       jump_vaddr
393         .size   jump_vaddr_r1, .-jump_vaddr_r1
394         .global jump_vaddr_r2
395         .type   jump_vaddr_r2, %function
396 jump_vaddr_r2:
397         mov     r0, r2
398         eor     r2, r2, r2, lsl #16
399         b       jump_vaddr
400         .size   jump_vaddr_r2, .-jump_vaddr_r2
401         .global jump_vaddr_r3
402         .type   jump_vaddr_r3, %function
403 jump_vaddr_r3:
404         eor     r2, r3, r3, lsl #16
405         mov     r0, r3
406         b       jump_vaddr
407         .size   jump_vaddr_r3, .-jump_vaddr_r3
408         .global jump_vaddr_r4
409         .type   jump_vaddr_r4, %function
410 jump_vaddr_r4:
411         eor     r2, r4, r4, lsl #16
412         mov     r0, r4
413         b       jump_vaddr
414         .size   jump_vaddr_r4, .-jump_vaddr_r4
415         .global jump_vaddr_r5
416         .type   jump_vaddr_r5, %function
417 jump_vaddr_r5:
418         eor     r2, r5, r5, lsl #16
419         mov     r0, r5
420         b       jump_vaddr
421         .size   jump_vaddr_r5, .-jump_vaddr_r5
422         .global jump_vaddr_r6
423         .type   jump_vaddr_r6, %function
424 jump_vaddr_r6:
425         eor     r2, r6, r6, lsl #16
426         mov     r0, r6
427         b       jump_vaddr
428         .size   jump_vaddr_r6, .-jump_vaddr_r6
429         .global jump_vaddr_r8
430         .type   jump_vaddr_r8, %function
431 jump_vaddr_r8:
432         eor     r2, r8, r8, lsl #16
433         mov     r0, r8
434         b       jump_vaddr
435         .size   jump_vaddr_r8, .-jump_vaddr_r8
436         .global jump_vaddr_r9
437         .type   jump_vaddr_r9, %function
438 jump_vaddr_r9:
439         eor     r2, r9, r9, lsl #16
440         mov     r0, r9
441         b       jump_vaddr
442         .size   jump_vaddr_r9, .-jump_vaddr_r9
443         .global jump_vaddr_r10
444         .type   jump_vaddr_r10, %function
445 jump_vaddr_r10:
446         eor     r2, r10, r10, lsl #16
447         mov     r0, r10
448         b       jump_vaddr
449         .size   jump_vaddr_r10, .-jump_vaddr_r10
450         .global jump_vaddr_r12
451         .type   jump_vaddr_r12, %function
452 jump_vaddr_r12:
453         eor     r2, r12, r12, lsl #16
454         mov     r0, r12
455         b       jump_vaddr
456         .size   jump_vaddr_r12, .-jump_vaddr_r12
457         .global jump_vaddr_r7
458         .type   jump_vaddr_r7, %function
459 jump_vaddr_r7:
460         eor     r2, r7, r7, lsl #16
461         add     r0, r7, #0
462         .size   jump_vaddr_r7, .-jump_vaddr_r7
463         .global jump_vaddr
464         .type   jump_vaddr, %function
465 jump_vaddr:
466         ldr     r1, .htptr
467         mvn     r3, #15
468         and     r2, r3, r2, lsr #12
469         ldr     r2, [r1, r2]!
470         teq     r2, r0
471         ldreq   pc, [r1, #4]
472         ldr     r2, [r1, #8]
473         teq     r2, r0
474         ldreq   pc, [r1, #12]
475         str     r10, [fp, #cycle_count-dynarec_local]
476         bl      get_addr
477         ldr     r10, [fp, #cycle_count-dynarec_local]
478         mov     pc, r0
479         .size   jump_vaddr, .-jump_vaddr
480
481         .align  2
482         .global verify_code_ds
483         .type   verify_code_ds, %function
484 verify_code_ds:
485         str     r8, [fp, #branch_target-dynarec_local]
486         .size   verify_code_ds, .-verify_code_ds
487         .global verify_code_vm
488         .type   verify_code_vm, %function
489 verify_code_vm:
490         .global verify_code
491         .type   verify_code, %function
492 verify_code:
493         /* r1 = source */
494         /* r2 = target */
495         /* r3 = length */
496         tst     r3, #4
497         mov     r4, #0
498         add     r3, r1, r3
499         mov     r5, #0
500         ldrne   r4, [r1], #4
501         mov     r12, #0
502         ldrne   r5, [r2], #4
503         teq     r1, r3
504         beq     .D3
505 .D2:
506         ldr     r7, [r1], #4
507         eor     r9, r4, r5
508         ldr     r8, [r2], #4
509         orrs    r9, r9, r12
510         bne     .D4
511         ldr     r4, [r1], #4
512         eor     r12, r7, r8
513         ldr     r5, [r2], #4
514         cmp     r1, r3
515         bcc     .D2
516         teq     r7, r8
517 .D3:
518         teqeq   r4, r5
519 .D4:
520         ldr     r8, [fp, #branch_target-dynarec_local]
521         moveq   pc, lr
522 .D5:
523         bl      get_addr
524         mov     pc, r0
525         .size   verify_code, .-verify_code
526         .size   verify_code_vm, .-verify_code_vm
527
528         .align  2
529         .global cc_interrupt
530         .type   cc_interrupt, %function
531 cc_interrupt:
532         ldr     r0, [fp, #last_count-dynarec_local]
533         mov     r1, #0
534         mov     r2, #0x1fc
535         add     r10, r0, r10
536         str     r1, [fp, #pending_exception-dynarec_local]
537         and     r2, r2, r10, lsr #17
538         add     r3, fp, #restore_candidate-dynarec_local
539         str     r10, [fp, #cycle-dynarec_local] /* PCSX cycles */
540 @@      str     r10, [fp, #reg_cop0+36-dynarec_local] /* Count */
541         ldr     r4, [r2, r3]
542         mov     r10, lr
543         tst     r4, r4
544         bne     .E4
545 .E1:
546         bl      gen_interupt
547         mov     lr, r10
548         ldr     r10, [fp, #cycle-dynarec_local]
549         ldr     r0, [fp, #next_interupt-dynarec_local]
550         ldr     r1, [fp, #pending_exception-dynarec_local]
551         ldr     r2, [fp, #stop-dynarec_local]
552         str     r0, [fp, #last_count-dynarec_local]
553         sub     r10, r10, r0
554         tst     r2, r2
555         ldmnefd sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}
556         tst     r1, r1
557         moveq   pc, lr
558 .E2:
559         ldr     r0, [fp, #pcaddr-dynarec_local]
560         bl      get_addr_ht
561         mov     pc, r0
562 .E4:
563         /* Move 'dirty' blocks to the 'clean' list */
564         lsl     r5, r2, #3
565         str     r1, [r2, r3]
566 .E5:
567         lsrs    r4, r4, #1
568         mov     r0, r5
569         add     r5, r5, #1
570         blcs    clean_blocks
571         tst     r5, #31
572         bne     .E5
573         b       .E1
574         .size   cc_interrupt, .-cc_interrupt
575
576         .align  2
577         .global do_interrupt
578         .type   do_interrupt, %function
579 do_interrupt:
580         ldr     r0, [fp, #pcaddr-dynarec_local]
581         bl      get_addr_ht
582         add     r10, r10, #2
583         mov     pc, r0
584         .size   do_interrupt, .-do_interrupt
585
586         .align  2
587         .global fp_exception
588         .type   fp_exception, %function
589 fp_exception:
590         mov     r2, #0x10000000
591 .E7:
592         ldr     r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
593         mov     r3, #0x80000000
594         str     r0, [fp, #reg_cop0+56-dynarec_local] /* EPC */
595         orr     r1, #2
596         add     r2, r2, #0x2c
597         str     r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
598         str     r2, [fp, #reg_cop0+52-dynarec_local] /* Cause */
599         add     r0, r3, #0x80
600         bl      get_addr_ht
601         mov     pc, r0
602         .size   fp_exception, .-fp_exception
603         .align  2
604         .global fp_exception_ds
605         .type   fp_exception_ds, %function
606 fp_exception_ds:
607         mov     r2, #0x90000000 /* Set high bit if delay slot */
608         b       .E7
609         .size   fp_exception_ds, .-fp_exception_ds
610
611         .align  2
612         .global jump_syscall
613         .type   jump_syscall, %function
614 jump_syscall:
615         ldr     r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
616         mov     r3, #0x80000000
617         str     r0, [fp, #reg_cop0+56-dynarec_local] /* EPC */
618         orr     r1, #2
619         mov     r2, #0x20
620         str     r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
621         str     r2, [fp, #reg_cop0+52-dynarec_local] /* Cause */
622         add     r0, r3, #0x80
623         bl      get_addr_ht
624         mov     pc, r0
625         .size   jump_syscall, .-jump_syscall
626         .align  2
627
628         .align  2
629         .global jump_syscall_hle
630         .type   jump_syscall_hle, %function
631 jump_syscall_hle:
632         str     r0, [fp, #pcaddr-dynarec_local] /* PC must be set to EPC for psxException */
633         ldr     r2, [fp, #last_count-dynarec_local]
634         mov     r1, #0    /* in delay slot */
635         add     r2, r2, r10
636         mov     r0, #0x20 /* cause */
637         str     r2, [fp, #cycle-dynarec_local] /* PCSX cycle counter */
638         bl      psxException
639
640         /* note: psxException might do recorsive recompiler call from it's HLE code,
641          * so be ready for this */
642 pcsx_return:
643         ldr     r1, [fp, #next_interupt-dynarec_local]
644         ldr     r10, [fp, #cycle-dynarec_local]
645         ldr     r0, [fp, #pcaddr-dynarec_local]
646         sub     r10, r10, r1
647         str     r1, [fp, #last_count-dynarec_local]
648         bl      get_addr_ht
649         mov     pc, r0
650         .size   jump_syscall_hle, .-jump_syscall_hle
651
652         .align  2
653         .global jump_hlecall
654         .type   jump_hlecall, %function
655 jump_hlecall:
656         ldr     r2, [fp, #last_count-dynarec_local]
657         str     r0, [fp, #pcaddr-dynarec_local]
658         add     r2, r2, r10
659         adr     lr, pcsx_return
660         str     r2, [fp, #cycle-dynarec_local] /* PCSX cycle counter */
661         bx      r1
662         .size   jump_hlecall, .-jump_hlecall
663
664         .align  2
665         .global jump_intcall
666         .type   jump_intcall, %function
667 jump_intcall:
668         ldr     r2, [fp, #last_count-dynarec_local]
669         str     r0, [fp, #pcaddr-dynarec_local]
670         add     r2, r2, r10
671         adr     lr, pcsx_return
672         str     r2, [fp, #cycle-dynarec_local] /* PCSX cycle counter */
673         b       execI
674         .size   jump_hlecall, .-jump_hlecall
675
676 new_dyna_leave:
677         .align  2
678         .global new_dyna_leave
679         .type   new_dyna_leave, %function
680         ldr     r0, [fp, #last_count-dynarec_local]
681         add     r12, fp, #28
682         add     r10, r0, r10
683         str     r10, [fp, #cycle-dynarec_local]
684         ldmfd   sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}
685         .size   new_dyna_leave, .-new_dyna_leave
686
687         /* these are used to call memhandlers */
688         .align  2
689         .global indirect_jump_indexed
690         .type   indirect_jump_indexed, %function
691 indirect_jump_indexed:
692         ldr     r0, [r0, r1, lsl #2]
693         .global indirect_jump
694         .type   indirect_jump, %function
695 indirect_jump:
696         ldr     r12, [fp, #last_count-dynarec_local]
697         add     r2, r2, r12 
698         str     r2, [fp, #cycle-dynarec_local]
699         mov     pc, r0
700         .size   indirect_jump, .-indirect_jump
701         .size   indirect_jump_indexed, .-indirect_jump_indexed
702
703         .align  2
704         .global invalidate_addr_r0
705         .type   invalidate_addr_r0, %function
706 invalidate_addr_r0:
707         stmia   fp, {r0, r1, r2, r3, r12, lr}
708         lsr     r0, r0, #12     
709         b       invalidate_addr_call
710         .size   invalidate_addr_r0, .-invalidate_addr_r0
711         .align  2
712         .global invalidate_addr_r1
713         .type   invalidate_addr_r1, %function
714 invalidate_addr_r1:
715         stmia   fp, {r0, r1, r2, r3, r12, lr}
716         lsr     r0, r1, #12     
717         b       invalidate_addr_call
718         .size   invalidate_addr_r1, .-invalidate_addr_r1
719         .align  2
720         .global invalidate_addr_r2
721         .type   invalidate_addr_r2, %function
722 invalidate_addr_r2:
723         stmia   fp, {r0, r1, r2, r3, r12, lr}
724         lsr     r0, r2, #12     
725         b       invalidate_addr_call
726         .size   invalidate_addr_r2, .-invalidate_addr_r2
727         .align  2
728         .global invalidate_addr_r3
729         .type   invalidate_addr_r3, %function
730 invalidate_addr_r3:
731         stmia   fp, {r0, r1, r2, r3, r12, lr}
732         lsr     r0, r3, #12     
733         b       invalidate_addr_call
734         .size   invalidate_addr_r3, .-invalidate_addr_r3
735         .align  2
736         .global invalidate_addr_r4
737         .type   invalidate_addr_r4, %function
738 invalidate_addr_r4:
739         stmia   fp, {r0, r1, r2, r3, r12, lr}
740         lsr     r0, r4, #12     
741         b       invalidate_addr_call
742         .size   invalidate_addr_r4, .-invalidate_addr_r4
743         .align  2
744         .global invalidate_addr_r5
745         .type   invalidate_addr_r5, %function
746 invalidate_addr_r5:
747         stmia   fp, {r0, r1, r2, r3, r12, lr}
748         lsr     r0, r5, #12     
749         b       invalidate_addr_call
750         .size   invalidate_addr_r5, .-invalidate_addr_r5
751         .align  2
752         .global invalidate_addr_r6
753         .type   invalidate_addr_r6, %function
754 invalidate_addr_r6:
755         stmia   fp, {r0, r1, r2, r3, r12, lr}
756         lsr     r0, r6, #12     
757         b       invalidate_addr_call
758         .size   invalidate_addr_r6, .-invalidate_addr_r6
759         .align  2
760         .global invalidate_addr_r7
761         .type   invalidate_addr_r7, %function
762 invalidate_addr_r7:
763         stmia   fp, {r0, r1, r2, r3, r12, lr}
764         lsr     r0, r7, #12     
765         b       invalidate_addr_call
766         .size   invalidate_addr_r7, .-invalidate_addr_r7
767         .align  2
768         .global invalidate_addr_r8
769         .type   invalidate_addr_r8, %function
770 invalidate_addr_r8:
771         stmia   fp, {r0, r1, r2, r3, r12, lr}
772         lsr     r0, r8, #12     
773         b       invalidate_addr_call
774         .size   invalidate_addr_r8, .-invalidate_addr_r8
775         .align  2
776         .global invalidate_addr_r9
777         .type   invalidate_addr_r9, %function
778 invalidate_addr_r9:
779         stmia   fp, {r0, r1, r2, r3, r12, lr}
780         lsr     r0, r9, #12     
781         b       invalidate_addr_call
782         .size   invalidate_addr_r9, .-invalidate_addr_r9
783         .align  2
784         .global invalidate_addr_r10
785         .type   invalidate_addr_r10, %function
786 invalidate_addr_r10:
787         stmia   fp, {r0, r1, r2, r3, r12, lr}
788         lsr     r0, r10, #12    
789         b       invalidate_addr_call
790         .size   invalidate_addr_r10, .-invalidate_addr_r10
791         .align  2
792         .global invalidate_addr_r12
793         .type   invalidate_addr_r12, %function
794 invalidate_addr_r12:
795         stmia   fp, {r0, r1, r2, r3, r12, lr}
796         lsr     r0, r12, #12    
797         .size   invalidate_addr_r12, .-invalidate_addr_r12
798         .align  2
799         .global invalidate_addr_call
800         .type   invalidate_addr_call, %function
801 invalidate_addr_call:
802         bl      invalidate_block
803         ldmia   fp, {r0, r1, r2, r3, r12, pc}
804         .size   invalidate_addr_call, .-invalidate_addr_call
805
806         .align  2
807         .global new_dyna_start
808         .type   new_dyna_start, %function
809 new_dyna_start:
810         /* ip is stored to conform EABI alignment */
811         stmfd   sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
812         load_var_adr fp, dynarec_local
813         ldr     r0, [fp, #pcaddr-dynarec_local]
814         bl      get_addr_ht
815         ldr     r1, [fp, #next_interupt-dynarec_local]
816         ldr     r10, [fp, #cycle-dynarec_local]
817         str     r1, [fp, #last_count-dynarec_local]
818         sub     r10, r10, r1
819         mov     pc, r0
820         .size   new_dyna_start, .-new_dyna_start
821
822 /* --------------------------------------- */
823
824 .align  2
825 .global ari_read_ram8
826 .global ari_read_ram16
827 .global ari_read_ram32
828 .global ari_read_ram_mirror8
829 .global ari_read_ram_mirror16
830 .global ari_read_ram_mirror32
831 .global ari_write_ram8
832 .global ari_write_ram16
833 .global ari_write_ram32
834 .global ari_write_ram_mirror8
835 .global ari_write_ram_mirror16
836 .global ari_write_ram_mirror32
837 .global ari_write_ram_mirror_ro32
838 .global ari_read_bios8
839 .global ari_read_bios16
840 .global ari_read_bios32
841 .global ari_read_io8
842 .global ari_read_io16
843 .global ari_read_io32
844 .global ari_write_io8
845 .global ari_write_io16
846 .global ari_write_io32
847
848 .macro ari_read_ram bic_const op
849         ldr     r0, [fp, #address-dynarec_local]
850 .if \bic_const
851         bic     r0, r0, #\bic_const
852 .endif
853         \op     r0, [r0]
854         str     r0, [fp, #readmem_dword-dynarec_local]
855         mov     pc, lr
856 .endm
857
858 ari_read_ram8:
859         ari_read_ram 0, ldrb
860
861 ari_read_ram16:
862         ari_read_ram 1, ldrh
863
864 ari_read_ram32:
865         ari_read_ram 3, ldr
866
867 .macro ari_read_ram_mirror mvn_const, op
868         ldr     r0, [fp, #address-dynarec_local]
869         mvn     r1, #\mvn_const
870         and     r0, r1, lsr #11
871         orr     r0, r0, #1<<31
872         \op     r0, [r0]
873         str     r0, [fp, #readmem_dword-dynarec_local]
874         mov     pc, lr
875 .endm
876
877 ari_read_ram_mirror8:
878         ari_read_ram_mirror 0, ldrb
879
880 ari_read_ram_mirror16:
881         ari_read_ram_mirror (1<<11), ldrh
882
883 ari_read_ram_mirror32:
884         ari_read_ram_mirror (3<<11), ldr
885
886 /* invalidation is already taken care of by the caller */
887 .macro ari_write_ram bic_const var pf
888         ldr     r0, [fp, #address-dynarec_local]
889         ldr\pf  r1, [fp, #\var-dynarec_local]
890 .if \bic_const
891         bic     r0, r0, #\bic_const
892 .endif
893         str\pf  r1, [r0]
894         mov     pc, lr
895 .endm
896
897 ari_write_ram8:
898         ari_write_ram 0, byte, b
899
900 ari_write_ram16:
901         ari_write_ram 1, hword, h
902
903 ari_write_ram32:
904         ari_write_ram 3, word,
905
906 .macro ari_write_ram_mirror mvn_const var pf
907         ldr     r0, [fp, #address-dynarec_local]
908         mvn     r3, #\mvn_const
909         ldr\pf  r1, [fp, #\var-dynarec_local]
910         and     r0, r3, lsr #11
911         ldr     r2, [fp, #invc_ptr-dynarec_local]
912         orr     r0, r0, #1<<31
913         ldrb    r2, [r2, r0, lsr #12]
914         str\pf  r1, [r0]
915         tst     r2, r2
916         movne   pc, lr
917         lsr     r0, r0, #12
918         b       invalidate_block
919 .endm
920
921 ari_write_ram_mirror8:
922         ari_write_ram_mirror 0, byte, b
923
924 ari_write_ram_mirror16:
925         ari_write_ram_mirror (1<<11), hword, h
926
927 ari_write_ram_mirror32:
928         ari_write_ram_mirror (3<<11), word,
929
930 ari_write_ram_mirror_ro32:
931         load_var_adr r0, pcsx_ram_is_ro
932         ldr     r0, [r0]
933         tst     r0, r0
934         movne   pc, lr
935         nop
936         b       ari_write_ram_mirror32
937
938
939 .macro ari_read_bios_mirror bic_const op
940         ldr     r0, [fp, #address-dynarec_local]
941         orr     r0, r0, #0x80000000
942         bic     r0, r0, #(0x20000000|\bic_const)        @ map to 0x9fc...
943         \op     r0, [r0]
944         str     r0, [fp, #readmem_dword-dynarec_local]
945         mov     pc, lr
946 .endm
947
948 ari_read_bios8:
949         ari_read_bios_mirror 0, ldrb
950
951 ari_read_bios16:
952         ari_read_bios_mirror 1, ldrh
953
954 ari_read_bios32:
955         ari_read_bios_mirror 3, ldr
956
957
958 @ for testing
959 .macro ari_read_io_old tab_shift
960         str     lr, [sp, #-8]! @ EABI alignment..
961 .if \tab_shift == 0
962         bl      psxHwRead32
963 .endif
964 .if \tab_shift == 1
965         bl      psxHwRead16
966 .endif
967 .if \tab_shift == 2
968         bl      psxHwRead8
969 .endif
970         str     r0, [fp, #readmem_dword-dynarec_local]
971         ldr     pc, [sp], #8
972 .endm
973
974 .macro ari_read_io readop mem_tab tab_shift
975         ldr     r0, [fp, #address-dynarec_local]
976         ldr     r1, [fp, #psxH_ptr-dynarec_local]
977 .if \tab_shift == 0
978         bic     r0, r0, #3
979 .endif
980 .if \tab_shift == 1
981         bic     r0, r0, #1
982 .endif
983         bic     r2, r0, #0x1f800000
984         ldr     r12,[fp, #\mem_tab-dynarec_local]
985         subs    r3, r2, #0x1000
986         blo     2f
987 @       ari_read_io_old \tab_shift
988         cmp     r3, #0x880
989         bhs     1f
990         ldr     r12,[r12, r3, lsl #\tab_shift]
991         tst     r12,r12
992         beq     2f
993 0:
994         str     lr, [sp, #-8]! @ EABI alignment..
995         blx     r12
996         str     r0, [fp, #readmem_dword-dynarec_local]
997         ldr     pc, [sp], #8
998
999 1:
1000 .if \tab_shift == 1 @ read16
1001         cmp     r2, #0x1c00
1002         blo     2f
1003         cmp     r2, #0x1e00
1004         bhs     2f
1005         ldr     r12,[fp, #spu_readf-dynarec_local]
1006         b       0b
1007 .endif
1008 2:
1009         @ no handler, just read psxH
1010         \readop r0, [r1, r2]
1011         str     r0, [fp, #readmem_dword-dynarec_local]
1012         mov     pc, lr
1013 .endm
1014
1015 ari_read_io8:
1016         ari_read_io ldrb, tab_read8, 2
1017
1018 ari_read_io16:
1019         ari_read_io ldrh, tab_read16, 1
1020
1021 ari_read_io32:
1022         ari_read_io ldr, tab_read32, 0
1023
1024 .macro ari_write_io_old tab_shift
1025 .if \tab_shift == 0
1026         b       psxHwWrite32
1027 .endif
1028 .if \tab_shift == 1
1029         b       psxHwWrite16
1030 .endif
1031 .if \tab_shift == 2
1032         b       psxHwWrite8
1033 .endif
1034 .endm
1035
1036 .macro ari_write_io pf var mem_tab tab_shift
1037         ldr     r0, [fp, #address-dynarec_local]
1038         ldr\pf  r1, [fp, #\var-dynarec_local]
1039 .if \tab_shift == 0
1040         bic     r0, r0, #3
1041 .endif
1042 .if \tab_shift == 1
1043         bic     r0, r0, #1
1044 .endif
1045         bic     r2, r0, #0x1f800000
1046         ldr     r12,[fp, #\mem_tab-dynarec_local]
1047         subs    r3, r2, #0x1000
1048         blo     0f
1049 @       ari_write_io_old \tab_shift
1050         cmp     r3, #0x880
1051         bhs     1f
1052         ldr     r12,[r12, r3, lsl #\tab_shift]
1053         mov     r0, r1
1054         tst     r12,r12
1055         bxne    r12
1056 0:
1057         ldr     r3, [fp, #psxH_ptr-dynarec_local]
1058         str\pf  r1, [r2, r3]
1059         mov     pc, lr
1060 1:
1061         cmp     r2, #0x1c00
1062         blo     0b
1063         cmp     r2, #0x1e00
1064 .if \tab_shift != 0
1065         ldrlo   pc, [fp, #spu_writef-dynarec_local]
1066 .else
1067         @ write32 to SPU - very rare case (is this correct?)
1068         bhs     0b
1069         add     r2, r0, #2
1070         mov     r3, r1, lsr #16
1071         push    {r2,r3,lr}
1072         mov     lr, pc
1073         ldr     pc, [fp, #spu_writef-dynarec_local]
1074         pop     {r0,r1,lr}
1075         ldr     pc, [fp, #spu_writef-dynarec_local]
1076 .endif
1077         nop
1078         b       0b
1079 .endm
1080
1081 ari_write_io8:
1082         @ PCSX always writes to psxH, so do we for consistency
1083         ldr     r0, [fp, #address-dynarec_local]
1084         ldr     r3, [fp, #psxH_ptr-dynarec_local]
1085         ldrb    r1, [fp, #byte-dynarec_local]
1086         bic     r2, r0, #0x1f800000
1087         ldr     r12,[fp, #tab_write8-dynarec_local]
1088         strb    r1, [r2, r3]
1089         subs    r3, r2, #0x1000
1090         movlo   pc, lr
1091 @       ari_write_io_old 2
1092         cmp     r3, #0x880
1093         movhs   pc, lr
1094         ldr     r12,[r12, r3, lsl #2]
1095         mov     r0, r1
1096         tst     r12,r12
1097         bxne    r12
1098         mov     pc, lr
1099
1100 ari_write_io16:
1101         ari_write_io h, hword, tab_write16, 1
1102
1103 ari_write_io32:
1104         ari_write_io , word, tab_write32, 0
1105
1106 @ vim:filetype=armasm