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