57fb3d22c4892b8704cc80fbf7d2712554bc472a
[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         .text
207         .align  2
208         .global dyna_linker
209         .type   dyna_linker, %function
210 dyna_linker:
211         /* r0 = virtual target address */
212         /* r1 = instruction to patch */
213         mov     r12, r0
214         mov     r6, #4096
215         mov     r2, #0x80000
216         ldr     r3, .jiptr
217         sub     r6, r6, #1
218         ldr     r7, [r1]
219         eor     r2, r2, r12, lsr #12
220         and     r6, r6, r12, lsr #12
221         cmp     r2, #2048
222         add     r12, r7, #2
223         orrcs   r2, r6, #2048
224         ldr     r5, [r3, r2, lsl #2]
225         lsl     r12, r12, #8
226         /* jump_in lookup */
227 .A1:
228         movs    r4, r5
229         beq     .A3
230         ldr     r3, [r5]
231         ldr     r5, [r4, #12]
232         teq     r3, r0
233         bne     .A1
234         ldr     r3, [r4, #4]
235         ldr     r4, [r4, #8]
236         tst     r3, r3
237         bne     .A1
238 .A2:
239         mov     r5, r1
240         add     r1, r1, r12, asr #6
241         teq     r1, r4
242         moveq   pc, r4 /* Stale i-cache */
243         bl      add_link
244         sub     r2, r4, r5
245         and     r1, r7, #0xff000000
246         lsl     r2, r2, #6
247         sub     r1, r1, #2
248         add     r1, r1, r2, lsr #8
249         str     r1, [r5]
250         mov     pc, r4
251 .A3:
252         /* hash_table lookup */
253         cmp     r2, #2048
254         ldr     r3, .jdptr
255         eor     r4, r0, r0, lsl #16
256         lslcc   r2, r0, #9
257         ldr     r6, .htptr
258         lsr     r4, r4, #12
259         lsrcc   r2, r2, #21
260         bic     r4, r4, #15
261         ldr     r5, [r3, r2, lsl #2]
262         ldr     r7, [r6, r4]!
263         teq     r7, r0
264         ldreq   pc, [r6, #4]
265         ldr     r7, [r6, #8]
266         teq     r7, r0
267         ldreq   pc, [r6, #12]
268         /* jump_dirty lookup */
269 .A6:
270         movs    r4, r5
271         beq     .A8
272         ldr     r3, [r5]
273         ldr     r5, [r4, #12]
274         teq     r3, r0
275         bne     .A6
276 .A7:
277         ldr     r1, [r4, #8]
278         /* hash_table insert */
279         ldr     r2, [r6]
280         ldr     r3, [r6, #4]
281         str     r0, [r6]
282         str     r1, [r6, #4]
283         str     r2, [r6, #8]
284         str     r3, [r6, #12]
285         mov     pc, r1
286 .A8:
287         mov     r4, r0
288         mov     r5, r1
289         bl      new_recompile_block
290         tst     r0, r0
291         mov     r0, r4
292         mov     r1, r5
293         beq     dyna_linker
294         /* pagefault */
295         mov     r1, r0
296         mov     r2, #8
297         .size   dyna_linker, .-dyna_linker
298         .global exec_pagefault
299         .type   exec_pagefault, %function
300 exec_pagefault:
301         /* r0 = instruction pointer */
302         /* r1 = fault address */
303         /* r2 = cause */
304         ldr     r3, [fp, #reg_cop0+48-dynarec_local] /* Status */
305         mvn     r6, #0xF000000F
306         ldr     r4, [fp, #reg_cop0+16-dynarec_local] /* Context */
307         bic     r6, r6, #0x0F800000
308         str     r0, [fp, #reg_cop0+56-dynarec_local] /* EPC */
309         orr     r3, r3, #2
310         str     r1, [fp, #reg_cop0+32-dynarec_local] /* BadVAddr */
311         bic     r4, r4, r6
312         str     r3, [fp, #reg_cop0+48-dynarec_local] /* Status */
313         and     r5, r6, r1, lsr #9
314         str     r2, [fp, #reg_cop0+52-dynarec_local] /* Cause */
315         and     r1, r1, r6, lsl #9
316         str     r1, [fp, #reg_cop0+40-dynarec_local] /* EntryHi */
317         orr     r4, r4, r5
318         str     r4, [fp, #reg_cop0+16-dynarec_local] /* Context */
319         mov     r0, #0x80000000
320         bl      get_addr_ht
321         mov     pc, r0
322         .size   exec_pagefault, .-exec_pagefault
323
324 /* Special dynamic linker for the case where a page fault
325    may occur in a branch delay slot */
326         .global dyna_linker_ds
327         .type   dyna_linker_ds, %function
328 dyna_linker_ds:
329         /* r0 = virtual target address */
330         /* r1 = instruction to patch */
331         mov     r12, r0
332         mov     r6, #4096
333         mov     r2, #0x80000
334         ldr     r3, .jiptr
335         sub     r6, r6, #1
336         ldr     r7, [r1]
337         eor     r2, r2, r12, lsr #12
338         and     r6, r6, r12, lsr #12
339         cmp     r2, #2048
340         add     r12, r7, #2
341         orrcs   r2, r6, #2048
342         ldr     r5, [r3, r2, lsl #2]
343         lsl     r12, r12, #8
344         /* jump_in lookup */
345 .B1:
346         movs    r4, r5
347         beq     .B3
348         ldr     r3, [r5]
349         ldr     r5, [r4, #12]
350         teq     r3, r0
351         bne     .B1
352         ldr     r3, [r4, #4]
353         ldr     r4, [r4, #8]
354         tst     r3, r3
355         bne     .B1
356 .B2:
357         mov     r5, r1
358         add     r1, r1, r12, asr #6
359         teq     r1, r4
360         moveq   pc, r4 /* Stale i-cache */
361         bl      add_link
362         sub     r2, r4, r5
363         and     r1, r7, #0xff000000
364         lsl     r2, r2, #6
365         sub     r1, r1, #2
366         add     r1, r1, r2, lsr #8
367         str     r1, [r5]
368         mov     pc, r4
369 .B3:
370         /* hash_table lookup */
371         cmp     r2, #2048
372         ldr     r3, .jdptr
373         eor     r4, r0, r0, lsl #16
374         lslcc   r2, r0, #9
375         ldr     r6, .htptr
376         lsr     r4, r4, #12
377         lsrcc   r2, r2, #21
378         bic     r4, r4, #15
379         ldr     r5, [r3, r2, lsl #2]
380         ldr     r7, [r6, r4]!
381         teq     r7, r0
382         ldreq   pc, [r6, #4]
383         ldr     r7, [r6, #8]
384         teq     r7, r0
385         ldreq   pc, [r6, #12]
386         /* jump_dirty lookup */
387 .B6:
388         movs    r4, r5
389         beq     .B8
390         ldr     r3, [r5]
391         ldr     r5, [r4, #12]
392         teq     r3, r0
393         bne     .B6
394 .B7:
395         ldr     r1, [r4, #8]
396         /* hash_table insert */
397         ldr     r2, [r6]
398         ldr     r3, [r6, #4]
399         str     r0, [r6]
400         str     r1, [r6, #4]
401         str     r2, [r6, #8]
402         str     r3, [r6, #12]
403         mov     pc, r1
404 .B8:
405         mov     r4, r0
406         bic     r0, r0, #7
407         mov     r5, r1
408         orr     r0, r0, #1
409         bl      new_recompile_block
410         tst     r0, r0
411         mov     r0, r4
412         mov     r1, r5
413         beq     dyna_linker_ds
414         /* pagefault */
415         bic     r1, r0, #7
416         mov     r2, #0x80000008 /* High bit set indicates pagefault in delay slot */
417         sub     r0, r1, #4
418         b       exec_pagefault
419         .size   dyna_linker_ds, .-dyna_linker_ds
420 .jiptr:
421         .word   jump_in
422 .jdptr:
423         .word   jump_dirty
424 .htptr:
425         .word   hash_table
426
427         .align  2
428         .global jump_vaddr_r0
429         .type   jump_vaddr_r0, %function
430 jump_vaddr_r0:
431         eor     r2, r0, r0, lsl #16
432         b       jump_vaddr
433         .size   jump_vaddr_r0, .-jump_vaddr_r0
434         .global jump_vaddr_r1
435         .type   jump_vaddr_r1, %function
436 jump_vaddr_r1:
437         eor     r2, r1, r1, lsl #16
438         mov     r0, r1
439         b       jump_vaddr
440         .size   jump_vaddr_r1, .-jump_vaddr_r1
441         .global 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         .type   jump_vaddr_r3, %function
450 jump_vaddr_r3:
451         eor     r2, r3, r3, lsl #16
452         mov     r0, r3
453         b       jump_vaddr
454         .size   jump_vaddr_r3, .-jump_vaddr_r3
455         .global jump_vaddr_r4
456         .type   jump_vaddr_r4, %function
457 jump_vaddr_r4:
458         eor     r2, r4, r4, lsl #16
459         mov     r0, r4
460         b       jump_vaddr
461         .size   jump_vaddr_r4, .-jump_vaddr_r4
462         .global jump_vaddr_r5
463         .type   jump_vaddr_r5, %function
464 jump_vaddr_r5:
465         eor     r2, r5, r5, lsl #16
466         mov     r0, r5
467         b       jump_vaddr
468         .size   jump_vaddr_r5, .-jump_vaddr_r5
469         .global jump_vaddr_r6
470         .type   jump_vaddr_r6, %function
471 jump_vaddr_r6:
472         eor     r2, r6, r6, lsl #16
473         mov     r0, r6
474         b       jump_vaddr
475         .size   jump_vaddr_r6, .-jump_vaddr_r6
476         .global jump_vaddr_r8
477         .type   jump_vaddr_r8, %function
478 jump_vaddr_r8:
479         eor     r2, r8, r8, lsl #16
480         mov     r0, r8
481         b       jump_vaddr
482         .size   jump_vaddr_r8, .-jump_vaddr_r8
483         .global jump_vaddr_r9
484         .type   jump_vaddr_r9, %function
485 jump_vaddr_r9:
486         eor     r2, r9, r9, lsl #16
487         mov     r0, r9
488         b       jump_vaddr
489         .size   jump_vaddr_r9, .-jump_vaddr_r9
490         .global jump_vaddr_r10
491         .type   jump_vaddr_r10, %function
492 jump_vaddr_r10:
493         eor     r2, r10, r10, lsl #16
494         mov     r0, r10
495         b       jump_vaddr
496         .size   jump_vaddr_r10, .-jump_vaddr_r10
497         .global jump_vaddr_r12
498         .type   jump_vaddr_r12, %function
499 jump_vaddr_r12:
500         eor     r2, r12, r12, lsl #16
501         mov     r0, r12
502         b       jump_vaddr
503         .size   jump_vaddr_r12, .-jump_vaddr_r12
504         .global jump_vaddr_r7
505         .type   jump_vaddr_r7, %function
506 jump_vaddr_r7:
507         eor     r2, r7, r7, lsl #16
508         add     r0, r7, #0
509         .size   jump_vaddr_r7, .-jump_vaddr_r7
510         .global jump_vaddr
511         .type   jump_vaddr, %function
512 jump_vaddr:
513         ldr     r1, .htptr
514         mvn     r3, #15
515         and     r2, r3, r2, lsr #12
516         ldr     r2, [r1, r2]!
517         teq     r2, r0
518         ldreq   pc, [r1, #4]
519         ldr     r2, [r1, #8]
520         teq     r2, r0
521         ldreq   pc, [r1, #12]
522         str     r10, [fp, #cycle_count-dynarec_local]
523         bl      get_addr
524         ldr     r10, [fp, #cycle_count-dynarec_local]
525         mov     pc, r0
526         .size   jump_vaddr, .-jump_vaddr
527
528         .align  2
529         .global verify_code_ds
530         .type   verify_code_ds, %function
531 verify_code_ds:
532         str     r8, [fp, #branch_target-dynarec_local]
533         .size   verify_code_ds, .-verify_code_ds
534         .global verify_code_vm
535         .type   verify_code_vm, %function
536 verify_code_vm:
537         .global verify_code
538         .type   verify_code, %function
539 verify_code:
540         /* r1 = source */
541         /* r2 = target */
542         /* r3 = length */
543         tst     r3, #4
544         mov     r4, #0
545         add     r3, r1, r3
546         mov     r5, #0
547         ldrne   r4, [r1], #4
548         mov     r12, #0
549         ldrne   r5, [r2], #4
550         teq     r1, r3
551         beq     .D3
552 .D2:
553         ldr     r7, [r1], #4
554         eor     r9, r4, r5
555         ldr     r8, [r2], #4
556         orrs    r9, r9, r12
557         bne     .D4
558         ldr     r4, [r1], #4
559         eor     r12, r7, r8
560         ldr     r5, [r2], #4
561         cmp     r1, r3
562         bcc     .D2
563         teq     r7, r8
564 .D3:
565         teqeq   r4, r5
566 .D4:
567         ldr     r8, [fp, #branch_target-dynarec_local]
568         moveq   pc, lr
569 .D5:
570         bl      get_addr
571         mov     pc, r0
572         .size   verify_code, .-verify_code
573         .size   verify_code_vm, .-verify_code_vm
574
575         .align  2
576         .global cc_interrupt
577         .type   cc_interrupt, %function
578 cc_interrupt:
579         ldr     r0, [fp, #last_count-dynarec_local]
580         mov     r1, #0
581         mov     r2, #0x1fc
582         add     r10, r0, r10
583         str     r1, [fp, #pending_exception-dynarec_local]
584         and     r2, r2, r10, lsr #17
585         add     r3, fp, #restore_candidate-dynarec_local
586         str     r10, [fp, #cycle-dynarec_local] /* PCSX cycles */
587 @@      str     r10, [fp, #reg_cop0+36-dynarec_local] /* Count */
588         ldr     r4, [r2, r3]
589         mov     r10, lr
590         tst     r4, r4
591         bne     .E4
592 .E1:
593         bl      gen_interupt
594         mov     lr, r10
595         ldr     r10, [fp, #cycle-dynarec_local]
596         ldr     r0, [fp, #next_interupt-dynarec_local]
597         ldr     r1, [fp, #pending_exception-dynarec_local]
598         ldr     r2, [fp, #stop-dynarec_local]
599         str     r0, [fp, #last_count-dynarec_local]
600         sub     r10, r10, r0
601         tst     r2, r2
602         ldmnefd sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}
603         tst     r1, r1
604         moveq   pc, lr
605 .E2:
606         ldr     r0, [fp, #pcaddr-dynarec_local]
607         bl      get_addr_ht
608         mov     pc, r0
609 .E4:
610         /* Move 'dirty' blocks to the 'clean' list */
611         lsl     r5, r2, #3
612         str     r1, [r2, r3]
613 .E5:
614         lsrs    r4, r4, #1
615         mov     r0, r5
616         add     r5, r5, #1
617         blcs    clean_blocks
618         tst     r5, #31
619         bne     .E5
620         b       .E1
621         .size   cc_interrupt, .-cc_interrupt
622
623         .align  2
624         .global do_interrupt
625         .type   do_interrupt, %function
626 do_interrupt:
627         ldr     r0, [fp, #pcaddr-dynarec_local]
628         bl      get_addr_ht
629         add     r10, r10, #2
630         mov     pc, r0
631         .size   do_interrupt, .-do_interrupt
632
633         .align  2
634         .global fp_exception
635         .type   fp_exception, %function
636 fp_exception:
637         mov     r2, #0x10000000
638 .E7:
639         ldr     r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
640         mov     r3, #0x80000000
641         str     r0, [fp, #reg_cop0+56-dynarec_local] /* EPC */
642         orr     r1, #2
643         add     r2, r2, #0x2c
644         str     r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
645         str     r2, [fp, #reg_cop0+52-dynarec_local] /* Cause */
646         add     r0, r3, #0x80
647         bl      get_addr_ht
648         mov     pc, r0
649         .size   fp_exception, .-fp_exception
650         .align  2
651         .global fp_exception_ds
652         .type   fp_exception_ds, %function
653 fp_exception_ds:
654         mov     r2, #0x90000000 /* Set high bit if delay slot */
655         b       .E7
656         .size   fp_exception_ds, .-fp_exception_ds
657
658         .align  2
659         .global jump_syscall
660         .type   jump_syscall, %function
661 jump_syscall:
662         ldr     r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
663         mov     r3, #0x80000000
664         str     r0, [fp, #reg_cop0+56-dynarec_local] /* EPC */
665         orr     r1, #2
666         mov     r2, #0x20
667         str     r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
668         str     r2, [fp, #reg_cop0+52-dynarec_local] /* Cause */
669         add     r0, r3, #0x80
670         bl      get_addr_ht
671         mov     pc, r0
672         .size   jump_syscall, .-jump_syscall
673         .align  2
674
675         .align  2
676         .global jump_syscall_hle
677         .type   jump_syscall_hle, %function
678 jump_syscall_hle:
679         str     r0, [fp, #pcaddr-dynarec_local] /* PC must be set to EPC for psxException */
680         ldr     r2, [fp, #last_count-dynarec_local]
681         mov     r1, #0    /* in delay slot */
682         add     r2, r2, r10
683         mov     r0, #0x20 /* cause */
684         str     r2, [fp, #cycle-dynarec_local] /* PCSX cycle counter */
685         bl      psxException
686
687         /* note: psxException might do recorsive recompiler call from it's HLE code,
688          * so be ready for this */
689 pcsx_return:
690         ldr     r1, [fp, #next_interupt-dynarec_local]
691         ldr     r10, [fp, #cycle-dynarec_local]
692         ldr     r0, [fp, #pcaddr-dynarec_local]
693         sub     r10, r10, r1
694         str     r1, [fp, #last_count-dynarec_local]
695         bl      get_addr_ht
696         mov     pc, r0
697         .size   jump_syscall_hle, .-jump_syscall_hle
698
699         .align  2
700         .global jump_hlecall
701         .type   jump_hlecall, %function
702 jump_hlecall:
703         ldr     r2, [fp, #last_count-dynarec_local]
704         str     r0, [fp, #pcaddr-dynarec_local]
705         add     r2, r2, r10
706         adr     lr, pcsx_return
707         str     r2, [fp, #cycle-dynarec_local] /* PCSX cycle counter */
708         bx      r1
709         .size   jump_hlecall, .-jump_hlecall
710
711         .align  2
712         .global jump_intcall
713         .type   jump_intcall, %function
714 jump_intcall:
715         ldr     r2, [fp, #last_count-dynarec_local]
716         str     r0, [fp, #pcaddr-dynarec_local]
717         add     r2, r2, r10
718         adr     lr, pcsx_return
719         str     r2, [fp, #cycle-dynarec_local] /* PCSX cycle counter */
720         b       execI
721         .size   jump_hlecall, .-jump_hlecall
722
723 new_dyna_leave:
724         .align  2
725         .global new_dyna_leave
726         .type   new_dyna_leave, %function
727         ldr     r0, [fp, #last_count-dynarec_local]
728         add     r12, fp, #28
729         add     r10, r0, r10
730         str     r10, [fp, #cycle-dynarec_local]
731         ldmfd   sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}
732         .size   new_dyna_leave, .-new_dyna_leave
733
734         /* these are used to call memhandlers */
735         .align  2
736         .global indirect_jump_indexed
737         .type   indirect_jump_indexed, %function
738 indirect_jump_indexed:
739         ldr     r0, [r0, r1, lsl #2]
740         .global indirect_jump
741         .type   indirect_jump, %function
742 indirect_jump:
743         ldr     r12, [fp, #last_count-dynarec_local]
744         add     r2, r2, r12 
745         str     r2, [fp, #cycle-dynarec_local]
746         mov     pc, r0
747         .size   indirect_jump, .-indirect_jump
748         .size   indirect_jump_indexed, .-indirect_jump_indexed
749
750         .align  2
751         .global invalidate_addr_r0
752         .type   invalidate_addr_r0, %function
753 invalidate_addr_r0:
754         stmia   fp, {r0, r1, r2, r3, r12, lr}
755         lsr     r0, r0, #12     
756         b       invalidate_addr_call
757         .size   invalidate_addr_r0, .-invalidate_addr_r0
758         .align  2
759         .global invalidate_addr_r1
760         .type   invalidate_addr_r1, %function
761 invalidate_addr_r1:
762         stmia   fp, {r0, r1, r2, r3, r12, lr}
763         lsr     r0, r1, #12     
764         b       invalidate_addr_call
765         .size   invalidate_addr_r1, .-invalidate_addr_r1
766         .align  2
767         .global invalidate_addr_r2
768         .type   invalidate_addr_r2, %function
769 invalidate_addr_r2:
770         stmia   fp, {r0, r1, r2, r3, r12, lr}
771         lsr     r0, r2, #12     
772         b       invalidate_addr_call
773         .size   invalidate_addr_r2, .-invalidate_addr_r2
774         .align  2
775         .global invalidate_addr_r3
776         .type   invalidate_addr_r3, %function
777 invalidate_addr_r3:
778         stmia   fp, {r0, r1, r2, r3, r12, lr}
779         lsr     r0, r3, #12     
780         b       invalidate_addr_call
781         .size   invalidate_addr_r3, .-invalidate_addr_r3
782         .align  2
783         .global invalidate_addr_r4
784         .type   invalidate_addr_r4, %function
785 invalidate_addr_r4:
786         stmia   fp, {r0, r1, r2, r3, r12, lr}
787         lsr     r0, r4, #12     
788         b       invalidate_addr_call
789         .size   invalidate_addr_r4, .-invalidate_addr_r4
790         .align  2
791         .global invalidate_addr_r5
792         .type   invalidate_addr_r5, %function
793 invalidate_addr_r5:
794         stmia   fp, {r0, r1, r2, r3, r12, lr}
795         lsr     r0, r5, #12     
796         b       invalidate_addr_call
797         .size   invalidate_addr_r5, .-invalidate_addr_r5
798         .align  2
799         .global invalidate_addr_r6
800         .type   invalidate_addr_r6, %function
801 invalidate_addr_r6:
802         stmia   fp, {r0, r1, r2, r3, r12, lr}
803         lsr     r0, r6, #12     
804         b       invalidate_addr_call
805         .size   invalidate_addr_r6, .-invalidate_addr_r6
806         .align  2
807         .global invalidate_addr_r7
808         .type   invalidate_addr_r7, %function
809 invalidate_addr_r7:
810         stmia   fp, {r0, r1, r2, r3, r12, lr}
811         lsr     r0, r7, #12     
812         b       invalidate_addr_call
813         .size   invalidate_addr_r7, .-invalidate_addr_r7
814         .align  2
815         .global invalidate_addr_r8
816         .type   invalidate_addr_r8, %function
817 invalidate_addr_r8:
818         stmia   fp, {r0, r1, r2, r3, r12, lr}
819         lsr     r0, r8, #12     
820         b       invalidate_addr_call
821         .size   invalidate_addr_r8, .-invalidate_addr_r8
822         .align  2
823         .global invalidate_addr_r9
824         .type   invalidate_addr_r9, %function
825 invalidate_addr_r9:
826         stmia   fp, {r0, r1, r2, r3, r12, lr}
827         lsr     r0, r9, #12     
828         b       invalidate_addr_call
829         .size   invalidate_addr_r9, .-invalidate_addr_r9
830         .align  2
831         .global invalidate_addr_r10
832         .type   invalidate_addr_r10, %function
833 invalidate_addr_r10:
834         stmia   fp, {r0, r1, r2, r3, r12, lr}
835         lsr     r0, r10, #12    
836         b       invalidate_addr_call
837         .size   invalidate_addr_r10, .-invalidate_addr_r10
838         .align  2
839         .global invalidate_addr_r12
840         .type   invalidate_addr_r12, %function
841 invalidate_addr_r12:
842         stmia   fp, {r0, r1, r2, r3, r12, lr}
843         lsr     r0, r12, #12    
844         .size   invalidate_addr_r12, .-invalidate_addr_r12
845         .align  2
846         .global invalidate_addr_call
847         .type   invalidate_addr_call, %function
848 invalidate_addr_call:
849         bl      invalidate_block
850         ldmia   fp, {r0, r1, r2, r3, r12, pc}
851         .size   invalidate_addr_call, .-invalidate_addr_call
852
853         .align  2
854         .global new_dyna_start
855         .type   new_dyna_start, %function
856 new_dyna_start:
857         /* ip is stored to conform EABI alignment */
858         stmfd   sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
859 .if HAVE_ARMV7
860         movw    fp, #:lower16:dynarec_local
861         movt    fp, #:upper16:dynarec_local
862 .else
863         ldr     fp, .dlptr
864 .endif
865         ldr     r0, [fp, #pcaddr-dynarec_local]
866         bl      get_addr_ht
867         ldr     r1, [fp, #next_interupt-dynarec_local]
868         ldr     r10, [fp, #cycle-dynarec_local]
869         str     r1, [fp, #last_count-dynarec_local]
870         sub     r10, r10, r1
871         mov     pc, r0
872 .dlptr:
873         .word   dynarec_local
874         .size   new_dyna_start, .-new_dyna_start
875
876 /* --------------------------------------- */
877
878 .align  2
879 .global ari_read_ram8
880 .global ari_read_ram16
881 .global ari_read_ram32
882 .global ari_read_ram_mirror8
883 .global ari_read_ram_mirror16
884 .global ari_read_ram_mirror32
885 .global ari_write_ram8
886 .global ari_write_ram16
887 .global ari_write_ram32
888 .global ari_write_ram_mirror8
889 .global ari_write_ram_mirror16
890 .global ari_write_ram_mirror32
891 .global ari_read_bios8
892 .global ari_read_bios16
893 .global ari_read_bios32
894 .global ari_read_io8
895 .global ari_read_io16
896 .global ari_read_io32
897 .global ari_write_io8
898 .global ari_write_io16
899 .global ari_write_io32
900
901 .macro ari_read_ram bic_const op
902         ldr     r0, [fp, #address-dynarec_local]
903 .if \bic_const
904         bic     r0, r0, #\bic_const
905 .endif
906         \op     r0, [r0]
907         str     r0, [fp, #readmem_dword-dynarec_local]
908         mov     pc, lr
909 .endm
910
911 ari_read_ram8:
912         ari_read_ram 0, ldrb
913
914 ari_read_ram16:
915         ari_read_ram 1, ldrh
916
917 ari_read_ram32:
918         ari_read_ram 3, ldr
919
920 .macro ari_read_ram_mirror mvn_const, op
921         ldr     r0, [fp, #address-dynarec_local]
922         mvn     r1, #\mvn_const
923         and     r0, r1, lsr #11
924         orr     r0, r0, #1<<31
925         \op     r0, [r0]
926         str     r0, [fp, #readmem_dword-dynarec_local]
927         mov     pc, lr
928 .endm
929
930 ari_read_ram_mirror8:
931         ari_read_ram_mirror 0, ldrb
932
933 ari_read_ram_mirror16:
934         ari_read_ram_mirror (1<<11), ldrh
935
936 ari_read_ram_mirror32:
937         ari_read_ram_mirror (3<<11), ldr
938
939 /* invalidation is already taken care of by the caller */
940 .macro ari_write_ram bic_const var pf
941         ldr     r0, [fp, #address-dynarec_local]
942         ldr\pf  r1, [fp, #\var-dynarec_local]
943 .if \bic_const
944         bic     r0, r0, #\bic_const
945 .endif
946         str\pf  r1, [r0]
947         mov     pc, lr
948 .endm
949
950 ari_write_ram8:
951         ari_write_ram 0, byte, b
952
953 ari_write_ram16:
954         ari_write_ram 1, hword, h
955
956 ari_write_ram32:
957         ari_write_ram 3, word,
958
959 .macro ari_write_ram_mirror mvn_const var pf
960         ldr     r0, [fp, #address-dynarec_local]
961         mvn     r3, #\mvn_const
962         ldr\pf  r1, [fp, #\var-dynarec_local]
963         and     r0, r3, lsr #11
964         ldr     r2, [fp, #invc_ptr-dynarec_local]
965         orr     r0, r0, #1<<31
966         ldrb    r2, [r2, r0, lsr #12]
967         str\pf  r1, [r0]
968         tst     r2, r2
969         movne   pc, lr
970         lsr     r0, r0, #12
971         b       invalidate_block
972 .endm
973
974 ari_write_ram_mirror8:
975         ari_write_ram_mirror 0, byte, b
976
977 ari_write_ram_mirror16:
978         ari_write_ram_mirror (1<<11), hword, h
979
980 ari_write_ram_mirror32:
981         ari_write_ram_mirror (3<<11), word,
982
983
984 .macro ari_read_bios_mirror bic_const op
985         ldr     r0, [fp, #address-dynarec_local]
986         orr     r0, r0, #0x80000000
987         bic     r0, r0, #(0x20000000|\bic_const)        @ map to 0x9fc...
988         \op     r0, [r0]
989         str     r0, [fp, #readmem_dword-dynarec_local]
990         mov     pc, lr
991 .endm
992
993 ari_read_bios8:
994         ari_read_bios_mirror 0, ldrb
995
996 ari_read_bios16:
997         ari_read_bios_mirror 1, ldrh
998
999 ari_read_bios32:
1000         ari_read_bios_mirror 3, ldr
1001
1002
1003 @ for testing
1004 .macro ari_read_io_old tab_shift
1005         str     lr, [sp, #-8]! @ EABI alignment..
1006 .if \tab_shift == 0
1007         bl      psxHwRead32
1008 .endif
1009 .if \tab_shift == 1
1010         bl      psxHwRead16
1011 .endif
1012 .if \tab_shift == 2
1013         bl      psxHwRead8
1014 .endif
1015         str     r0, [fp, #readmem_dword-dynarec_local]
1016         ldr     pc, [sp], #8
1017 .endm
1018
1019 .macro ari_read_io readop mem_tab tab_shift
1020         ldr     r0, [fp, #address-dynarec_local]
1021         ldr     r1, [fp, #psxH_ptr-dynarec_local]
1022 .if \tab_shift == 0
1023         bic     r0, r0, #3
1024 .endif
1025 .if \tab_shift == 1
1026         bic     r0, r0, #1
1027 .endif
1028         bic     r2, r0, #0x1f800000
1029         ldr     r12,[fp, #\mem_tab-dynarec_local]
1030         subs    r3, r2, #0x1000
1031         blo     2f
1032 @       ari_read_io_old \tab_shift
1033         cmp     r3, #0x880
1034         bhs     1f
1035         ldr     r12,[r12, r3, lsl #\tab_shift]
1036         tst     r12,r12
1037         beq     2f
1038 0:
1039         str     lr, [sp, #-8]! @ EABI alignment..
1040         blx     r12
1041         str     r0, [fp, #readmem_dword-dynarec_local]
1042         ldr     pc, [sp], #8
1043
1044 1:
1045 .if \tab_shift == 1 @ read16
1046         cmp     r2, #0x1c00
1047         blo     2f
1048         cmp     r2, #0x1e00
1049         bhs     2f
1050         ldr     r12,[fp, #spu_readf-dynarec_local]
1051         b       0b
1052 .endif
1053 2:
1054         @ no handler, just read psxH
1055         \readop r0, [r1, r2]
1056         str     r0, [fp, #readmem_dword-dynarec_local]
1057         mov     pc, lr
1058 .endm
1059
1060 ari_read_io8:
1061         ari_read_io ldrb, tab_read8, 2
1062
1063 ari_read_io16:
1064         ari_read_io ldrh, tab_read16, 1
1065
1066 ari_read_io32:
1067         ari_read_io ldr, tab_read32, 0
1068
1069 .macro ari_write_io_old tab_shift
1070 .if \tab_shift == 0
1071         b       psxHwWrite32
1072 .endif
1073 .if \tab_shift == 1
1074         b       psxHwWrite16
1075 .endif
1076 .if \tab_shift == 2
1077         b       psxHwWrite8
1078 .endif
1079 .endm
1080
1081 .macro ari_write_io pf var mem_tab tab_shift
1082         ldr     r0, [fp, #address-dynarec_local]
1083         ldr\pf  r1, [fp, #\var-dynarec_local]
1084 .if \tab_shift == 0
1085         bic     r0, r0, #3
1086 .endif
1087 .if \tab_shift == 1
1088         bic     r0, r0, #1
1089 .endif
1090         bic     r2, r0, #0x1f800000
1091         ldr     r12,[fp, #\mem_tab-dynarec_local]
1092         subs    r3, r2, #0x1000
1093         blo     0f
1094 @       ari_write_io_old \tab_shift
1095         cmp     r3, #0x880
1096         bhs     1f
1097         ldr     r12,[r12, r3, lsl #\tab_shift]
1098         mov     r0, r1
1099         tst     r12,r12
1100         bxne    r12
1101 0:
1102         ldr     r3, [fp, #psxH_ptr-dynarec_local]
1103         str\pf  r1, [r2, r3]
1104         mov     pc, lr
1105 1:
1106         cmp     r2, #0x1c00
1107         blo     0b
1108         cmp     r2, #0x1e00
1109 .if \tab_shift != 0
1110         ldrlo   pc, [fp, #spu_writef-dynarec_local]
1111 .else
1112         @ write32 to SPU - very rare case (is this correct?)
1113         bhs     0b
1114         add     r2, r0, #2
1115         mov     r3, r1, lsr #16
1116         push    {r2,r3,lr}
1117         mov     lr, pc
1118         ldr     pc, [fp, #spu_writef-dynarec_local]
1119         pop     {r0,r1,lr}
1120         ldr     pc, [fp, #spu_writef-dynarec_local]
1121 .endif
1122         nop
1123         b       0b
1124 .endm
1125
1126 ari_write_io8:
1127         @ PCSX always writes to psxH, so do we for consistency
1128         ldr     r0, [fp, #address-dynarec_local]
1129         ldr     r3, [fp, #psxH_ptr-dynarec_local]
1130         ldrb    r1, [fp, #byte-dynarec_local]
1131         bic     r2, r0, #0x1f800000
1132         ldr     r12,[fp, #tab_write8-dynarec_local]
1133         strb    r1, [r2, r3]
1134         subs    r3, r2, #0x1000
1135         movlo   pc, lr
1136 @       ari_write_io_old 2
1137         cmp     r3, #0x880
1138         movhs   pc, lr
1139         ldr     r12,[r12, r3, lsl #2]
1140         mov     r0, r1
1141         tst     r12,r12
1142         bxne    r12
1143         mov     pc, lr
1144
1145 ari_write_io16:
1146         ari_write_io h, hword, tab_write16, 1
1147
1148 ari_write_io32:
1149         ari_write_io , word, tab_write32, 0
1150
1151 @ vim:filetype=armasm