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