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