drc: add some hack options
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / linkage_arm.s
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  *   linkage_arm.s for PCSX                                                *
3  *   Copyright (C) 2009-2011 Ari64                                         *
4  *   Copyright (C) 2010-2011 GraÅžvydas "notaz" Ignotas                     *
5  *                                                                         *
6  *   This program is free software; you can redistribute it and/or modify  *
7  *   it under the terms of the GNU General Public License as published by  *
8  *   the Free Software Foundation; either version 2 of the License, or     *
9  *   (at your option) any later version.                                   *
10  *                                                                         *
11  *   This program is distributed in the hope that it will be useful,       *
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14  *   GNU General Public License for more details.                          *
15  *                                                                         *
16  *   You should have received a copy of the GNU General Public License     *
17  *   along with this program; if not, write to the                         *
18  *   Free Software Foundation, Inc.,                                       *
19  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
20  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
21
22 /* .equiv HAVE_ARMV7, 1 */
23
24         .global rdram
25 rdram = 0x80000000
26         .global dynarec_local
27         .global reg
28         .global hi
29         .global lo
30         .global reg_cop0
31         .global reg_cop2d
32         .global reg_cop2c
33         .global FCR0
34         .global FCR31
35         .global next_interupt
36         .global cycle_count
37         .global last_count
38         .global pending_exception
39         .global pcaddr
40         .global stop
41         .global invc_ptr
42         .global address
43         .global branch_target
44         .global PC
45         .global mini_ht
46         .global restore_candidate
47         /* psx */
48         .global psxRegs
49         .global mem_rtab
50         .global mem_wtab
51         .global psxH_ptr
52         .global zeromem_ptr
53         .global inv_code_start
54         .global inv_code_end
55         .global rcnts
56
57         .bss
58         .align  4
59         .type   dynarec_local, %object
60         .size   dynarec_local, dynarec_local_end-dynarec_local
61 dynarec_local:
62         .space  dynarec_local_end-dynarec_local
63 next_interupt = dynarec_local + 64
64         .type   next_interupt, %object
65         .size   next_interupt, 4
66 cycle_count = next_interupt + 4
67         .type   cycle_count, %object
68         .size   cycle_count, 4
69 last_count = cycle_count + 4
70         .type   last_count, %object
71         .size   last_count, 4
72 pending_exception = last_count + 4
73         .type   pending_exception, %object
74         .size   pending_exception, 4
75 stop = pending_exception + 4
76         .type   stop, %object
77         .size   stop, 4
78 invc_ptr = stop + 4
79         .type   invc_ptr, %object
80         .size   invc_ptr, 4
81 address = invc_ptr + 4
82         .type   address, %object
83         .size   address, 4
84 psxRegs = address + 4
85
86 /* psxRegs */
87         .type   psxRegs, %object
88         .size   psxRegs, psxRegs_end-psxRegs
89 reg = psxRegs
90         .type   reg, %object
91         .size   reg, 128
92 lo = reg + 128
93         .type   lo, %object
94         .size   lo, 4
95 hi = lo + 4
96         .type   hi, %object
97         .size   hi, 4
98 reg_cop0 = hi + 4
99         .type   reg_cop0, %object
100         .size   reg_cop0, 128
101 reg_cop2d = reg_cop0 + 128
102         .type   reg_cop2d, %object
103         .size   reg_cop2d, 128
104 reg_cop2c = reg_cop2d + 128
105         .type   reg_cop2c, %object
106         .size   reg_cop2c, 128
107 PC = reg_cop2c + 128
108 pcaddr = PC
109         .type   PC, %object
110         .size   PC, 4
111 code = PC + 4
112         .type   code, %object
113         .size   code, 4
114 cycle = code + 4
115         .type   cycle, %object
116         .size   cycle, 4
117 interrupt = cycle + 4
118         .type   interrupt, %object
119         .size   interrupt, 4
120 intCycle = interrupt + 4
121         .type   intCycle, %object
122         .size   intCycle, 256
123 psxRegs_end = intCycle + 256
124
125 rcnts = psxRegs_end
126         .type   rcnts, %object
127         .size   rcnts, 7*4*4
128 rcnts_end = rcnts + 7*4*4
129
130 mem_rtab = rcnts_end
131         .type   mem_rtab, %object
132         .size   mem_rtab, 4
133 mem_wtab = mem_rtab + 4
134         .type   mem_wtab, %object
135         .size   mem_wtab, 4
136 psxH_ptr = mem_wtab + 4
137         .type   psxH_ptr, %object
138         .size   psxH_ptr, 4
139 zeromem_ptr = psxH_ptr + 4
140         .type   zeromem_ptr, %object
141         .size   zeromem_ptr, 4
142 inv_code_start = zeromem_ptr + 4
143         .type   inv_code_start, %object
144         .size   inv_code_start, 4
145 inv_code_end = inv_code_start + 4
146         .type   inv_code_end, %object
147         .size   inv_code_end, 4
148 branch_target = inv_code_end + 4
149         .type   branch_target, %object
150         .size   branch_target, 4
151 align0 = branch_target + 4 /* unused/alignment */
152         .type   align0, %object
153         .size   align0, 16
154 mini_ht = align0 + 16
155         .type   mini_ht, %object
156         .size   mini_ht, 256
157 restore_candidate = mini_ht + 256
158         .type   restore_candidate, %object
159         .size   restore_candidate, 512
160 dynarec_local_end = restore_candidate + 512
161
162 /* unused */
163 FCR0 = align0
164         .type   FCR0, %object
165         .size   FCR0, 4
166 FCR31 = align0
167         .type   FCR31, %object
168         .size   FCR31, 4
169
170 .macro load_var_adr reg var
171 .if HAVE_ARMV7
172         movw    \reg, #:lower16:\var
173         movt    \reg, #:upper16:\var
174 .else
175         ldr     \reg, =\var
176 .endif
177 .endm
178
179 .macro mov_16 reg imm
180 .if HAVE_ARMV7
181         movw    \reg, #\imm
182 .else
183         mov     \reg, #(\imm & 0x00ff)
184         orr     \reg, #(\imm & 0xff00)
185 .endif
186 .endm
187
188 .macro mov_24 reg imm
189 .if HAVE_ARMV7
190         movw    \reg, #(\imm & 0xffff)
191         movt    \reg, #(\imm >> 16)
192 .else
193         mov     \reg, #(\imm & 0x0000ff)
194         orr     \reg, #(\imm & 0x00ff00)
195         orr     \reg, #(\imm & 0xff0000)
196 .endif
197 .endm
198
199 .macro dyna_linker_main
200         /* r0 = virtual target address */
201         /* r1 = instruction to patch */
202         ldr     r3, .jiptr
203         /* get_page */
204         lsr     r2, r0, #12
205         mov     r6, #4096
206         bic     r2, r2, #0xe0000
207         sub     r6, r6, #1
208         cmp     r2, #0x1000
209         ldr     r7, [r1]
210         biclt   r2, #0x0e00
211         and     r6, r6, r2
212         cmp     r2, #2048
213         add     r12, r7, #2
214         orrcs   r2, r6, #2048
215         ldr     r5, [r3, r2, lsl #2]
216         lsl     r12, r12, #8
217         add     r6, r1, r12, asr #6
218         mov     r8, #0
219         /* jump_in lookup */
220 1:
221         movs    r4, r5
222         beq     2f
223         ldr     r3, [r5]
224         ldr     r5, [r4, #12]
225         teq     r3, r0
226         bne     1b
227         ldr     r3, [r4, #4]
228         ldr     r4, [r4, #8]
229         tst     r3, r3
230         bne     1b
231         teq     r4, r6
232         moveq   pc, r4 /* Stale i-cache */
233         mov     r8, r4
234         b       1b     /* jump_in may have dupes, continue search */
235 2:
236         tst     r8, r8
237         beq     3f     /* r0 not in jump_in */
238
239         mov     r5, r1
240         mov     r1, r6
241         bl      add_link
242         sub     r2, r8, r5
243         and     r1, r7, #0xff000000
244         lsl     r2, r2, #6
245         sub     r1, r1, #2
246         add     r1, r1, r2, lsr #8
247         str     r1, [r5]
248         mov     pc, r8
249 3:
250         /* hash_table lookup */
251         cmp     r2, #2048
252         ldr     r3, .jdptr
253         eor     r4, r0, r0, lsl #16
254         lslcc   r2, r0, #9
255         ldr     r6, .htptr
256         lsr     r4, r4, #12
257         lsrcc   r2, r2, #21
258         bic     r4, r4, #15
259         ldr     r5, [r3, r2, lsl #2]
260         ldr     r7, [r6, r4]!
261         teq     r7, r0
262         ldreq   pc, [r6, #4]
263         ldr     r7, [r6, #8]
264         teq     r7, r0
265         ldreq   pc, [r6, #12]
266         /* jump_dirty lookup */
267 6:
268         movs    r4, r5
269         beq     8f
270         ldr     r3, [r5]
271         ldr     r5, [r4, #12]
272         teq     r3, r0
273         bne     6b
274 7:
275         ldr     r1, [r4, #8]
276         /* hash_table insert */
277         ldr     r2, [r6]
278         ldr     r3, [r6, #4]
279         str     r0, [r6]
280         str     r1, [r6, #4]
281         str     r2, [r6, #8]
282         str     r3, [r6, #12]
283         mov     pc, r1
284 8:
285 .endm
286
287         .text
288         .align  2
289         .global dyna_linker
290         .type   dyna_linker, %function
291 dyna_linker:
292         /* r0 = virtual target address */
293         /* r1 = instruction to patch */
294         dyna_linker_main
295
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         dyna_linker_main
341
342         mov     r4, r0
343         bic     r0, r0, #7
344         mov     r5, r1
345         orr     r0, r0, #1
346         bl      new_recompile_block
347         tst     r0, r0
348         mov     r0, r4
349         mov     r1, r5
350         beq     dyna_linker_ds
351         /* pagefault */
352         bic     r1, r0, #7
353         mov     r2, #0x80000008 /* High bit set indicates pagefault in delay slot */
354         sub     r0, r1, #4
355         b       exec_pagefault
356         .size   dyna_linker_ds, .-dyna_linker_ds
357 .jiptr:
358         .word   jump_in
359 .jdptr:
360         .word   jump_dirty
361 .htptr:
362         .word   hash_table
363
364         .align  2
365         .global jump_vaddr_r0
366         .type   jump_vaddr_r0, %function
367 jump_vaddr_r0:
368         eor     r2, r0, r0, lsl #16
369         b       jump_vaddr
370         .size   jump_vaddr_r0, .-jump_vaddr_r0
371         .global jump_vaddr_r1
372         .type   jump_vaddr_r1, %function
373 jump_vaddr_r1:
374         eor     r2, r1, r1, lsl #16
375         mov     r0, r1
376         b       jump_vaddr
377         .size   jump_vaddr_r1, .-jump_vaddr_r1
378         .global jump_vaddr_r2
379         .type   jump_vaddr_r2, %function
380 jump_vaddr_r2:
381         mov     r0, r2
382         eor     r2, r2, r2, lsl #16
383         b       jump_vaddr
384         .size   jump_vaddr_r2, .-jump_vaddr_r2
385         .global jump_vaddr_r3
386         .type   jump_vaddr_r3, %function
387 jump_vaddr_r3:
388         eor     r2, r3, r3, lsl #16
389         mov     r0, r3
390         b       jump_vaddr
391         .size   jump_vaddr_r3, .-jump_vaddr_r3
392         .global jump_vaddr_r4
393         .type   jump_vaddr_r4, %function
394 jump_vaddr_r4:
395         eor     r2, r4, r4, lsl #16
396         mov     r0, r4
397         b       jump_vaddr
398         .size   jump_vaddr_r4, .-jump_vaddr_r4
399         .global jump_vaddr_r5
400         .type   jump_vaddr_r5, %function
401 jump_vaddr_r5:
402         eor     r2, r5, r5, lsl #16
403         mov     r0, r5
404         b       jump_vaddr
405         .size   jump_vaddr_r5, .-jump_vaddr_r5
406         .global jump_vaddr_r6
407         .type   jump_vaddr_r6, %function
408 jump_vaddr_r6:
409         eor     r2, r6, r6, lsl #16
410         mov     r0, r6
411         b       jump_vaddr
412         .size   jump_vaddr_r6, .-jump_vaddr_r6
413         .global jump_vaddr_r8
414         .type   jump_vaddr_r8, %function
415 jump_vaddr_r8:
416         eor     r2, r8, r8, lsl #16
417         mov     r0, r8
418         b       jump_vaddr
419         .size   jump_vaddr_r8, .-jump_vaddr_r8
420         .global jump_vaddr_r9
421         .type   jump_vaddr_r9, %function
422 jump_vaddr_r9:
423         eor     r2, r9, r9, lsl #16
424         mov     r0, r9
425         b       jump_vaddr
426         .size   jump_vaddr_r9, .-jump_vaddr_r9
427         .global jump_vaddr_r10
428         .type   jump_vaddr_r10, %function
429 jump_vaddr_r10:
430         eor     r2, r10, r10, lsl #16
431         mov     r0, r10
432         b       jump_vaddr
433         .size   jump_vaddr_r10, .-jump_vaddr_r10
434         .global jump_vaddr_r12
435         .type   jump_vaddr_r12, %function
436 jump_vaddr_r12:
437         eor     r2, r12, r12, lsl #16
438         mov     r0, r12
439         b       jump_vaddr
440         .size   jump_vaddr_r12, .-jump_vaddr_r12
441         .global jump_vaddr_r7
442         .type   jump_vaddr_r7, %function
443 jump_vaddr_r7:
444         eor     r2, r7, r7, lsl #16
445         add     r0, r7, #0
446         .size   jump_vaddr_r7, .-jump_vaddr_r7
447         .global jump_vaddr
448         .type   jump_vaddr, %function
449 jump_vaddr:
450         ldr     r1, .htptr
451         mvn     r3, #15
452         and     r2, r3, r2, lsr #12
453         ldr     r2, [r1, r2]!
454         teq     r2, r0
455         ldreq   pc, [r1, #4]
456         ldr     r2, [r1, #8]
457         teq     r2, r0
458         ldreq   pc, [r1, #12]
459         str     r10, [fp, #cycle_count-dynarec_local]
460         bl      get_addr
461         ldr     r10, [fp, #cycle_count-dynarec_local]
462         mov     pc, r0
463         .size   jump_vaddr, .-jump_vaddr
464
465         .align  2
466         .global verify_code_ds
467         .type   verify_code_ds, %function
468 verify_code_ds:
469         str     r8, [fp, #branch_target-dynarec_local]
470         .size   verify_code_ds, .-verify_code_ds
471         .global verify_code_vm
472         .type   verify_code_vm, %function
473 verify_code_vm:
474         .global verify_code
475         .type   verify_code, %function
476 verify_code:
477         /* r1 = source */
478         /* r2 = target */
479         /* r3 = length */
480         tst     r3, #4
481         mov     r4, #0
482         add     r3, r1, r3
483         mov     r5, #0
484         ldrne   r4, [r1], #4
485         mov     r12, #0
486         ldrne   r5, [r2], #4
487         teq     r1, r3
488         beq     .D3
489 .D2:
490         ldr     r7, [r1], #4
491         eor     r9, r4, r5
492         ldr     r8, [r2], #4
493         orrs    r9, r9, r12
494         bne     .D4
495         ldr     r4, [r1], #4
496         eor     r12, r7, r8
497         ldr     r5, [r2], #4
498         cmp     r1, r3
499         bcc     .D2
500         teq     r7, r8
501 .D3:
502         teqeq   r4, r5
503 .D4:
504         ldr     r8, [fp, #branch_target-dynarec_local]
505         moveq   pc, lr
506 .D5:
507         bl      get_addr
508         mov     pc, r0
509         .size   verify_code, .-verify_code
510         .size   verify_code_vm, .-verify_code_vm
511
512         .align  2
513         .global cc_interrupt
514         .type   cc_interrupt, %function
515 cc_interrupt:
516         ldr     r0, [fp, #last_count-dynarec_local]
517         mov     r1, #0
518         mov     r2, #0x1fc
519         add     r10, r0, r10
520         str     r1, [fp, #pending_exception-dynarec_local]
521         and     r2, r2, r10, lsr #17
522         add     r3, fp, #restore_candidate-dynarec_local
523         str     r10, [fp, #cycle-dynarec_local] /* PCSX cycles */
524 @@      str     r10, [fp, #reg_cop0+36-dynarec_local] /* Count */
525         ldr     r4, [r2, r3]
526         mov     r10, lr
527         tst     r4, r4
528         bne     .E4
529 .E1:
530         bl      gen_interupt
531         mov     lr, r10
532         ldr     r10, [fp, #cycle-dynarec_local]
533         ldr     r0, [fp, #next_interupt-dynarec_local]
534         ldr     r1, [fp, #pending_exception-dynarec_local]
535         ldr     r2, [fp, #stop-dynarec_local]
536         str     r0, [fp, #last_count-dynarec_local]
537         sub     r10, r10, r0
538         tst     r2, r2
539         ldmnefd sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}
540         tst     r1, r1
541         moveq   pc, lr
542 .E2:
543         ldr     r0, [fp, #pcaddr-dynarec_local]
544         bl      get_addr_ht
545         mov     pc, r0
546 .E4:
547         /* Move 'dirty' blocks to the 'clean' list */
548         lsl     r5, r2, #3
549         str     r1, [r2, r3]
550 .E5:
551         lsrs    r4, r4, #1
552         mov     r0, r5
553         add     r5, r5, #1
554         blcs    clean_blocks
555         tst     r5, #31
556         bne     .E5
557         b       .E1
558         .size   cc_interrupt, .-cc_interrupt
559
560         .align  2
561         .global do_interrupt
562         .type   do_interrupt, %function
563 do_interrupt:
564         ldr     r0, [fp, #pcaddr-dynarec_local]
565         bl      get_addr_ht
566         add     r10, r10, #2
567         mov     pc, r0
568         .size   do_interrupt, .-do_interrupt
569
570         .align  2
571         .global fp_exception
572         .type   fp_exception, %function
573 fp_exception:
574         mov     r2, #0x10000000
575 .E7:
576         ldr     r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
577         mov     r3, #0x80000000
578         str     r0, [fp, #reg_cop0+56-dynarec_local] /* EPC */
579         orr     r1, #2
580         add     r2, r2, #0x2c
581         str     r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
582         str     r2, [fp, #reg_cop0+52-dynarec_local] /* Cause */
583         add     r0, r3, #0x80
584         bl      get_addr_ht
585         mov     pc, r0
586         .size   fp_exception, .-fp_exception
587         .align  2
588         .global fp_exception_ds
589         .type   fp_exception_ds, %function
590 fp_exception_ds:
591         mov     r2, #0x90000000 /* Set high bit if delay slot */
592         b       .E7
593         .size   fp_exception_ds, .-fp_exception_ds
594
595         .align  2
596         .global jump_syscall
597         .type   jump_syscall, %function
598 jump_syscall:
599         ldr     r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
600         mov     r3, #0x80000000
601         str     r0, [fp, #reg_cop0+56-dynarec_local] /* EPC */
602         orr     r1, #2
603         mov     r2, #0x20
604         str     r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
605         str     r2, [fp, #reg_cop0+52-dynarec_local] /* Cause */
606         add     r0, r3, #0x80
607         bl      get_addr_ht
608         mov     pc, r0
609         .size   jump_syscall, .-jump_syscall
610         .align  2
611
612         .align  2
613         .global jump_syscall_hle
614         .type   jump_syscall_hle, %function
615 jump_syscall_hle:
616         str     r0, [fp, #pcaddr-dynarec_local] /* PC must be set to EPC for psxException */
617         ldr     r2, [fp, #last_count-dynarec_local]
618         mov     r1, #0    /* in delay slot */
619         add     r2, r2, r10
620         mov     r0, #0x20 /* cause */
621         str     r2, [fp, #cycle-dynarec_local] /* PCSX cycle counter */
622         bl      psxException
623
624         /* note: psxException might do recorsive recompiler call from it's HLE code,
625          * so be ready for this */
626 pcsx_return:
627         ldr     r1, [fp, #next_interupt-dynarec_local]
628         ldr     r10, [fp, #cycle-dynarec_local]
629         ldr     r0, [fp, #pcaddr-dynarec_local]
630         sub     r10, r10, r1
631         str     r1, [fp, #last_count-dynarec_local]
632         bl      get_addr_ht
633         mov     pc, r0
634         .size   jump_syscall_hle, .-jump_syscall_hle
635
636         .align  2
637         .global jump_hlecall
638         .type   jump_hlecall, %function
639 jump_hlecall:
640         ldr     r2, [fp, #last_count-dynarec_local]
641         str     r0, [fp, #pcaddr-dynarec_local]
642         add     r2, r2, r10
643         adr     lr, pcsx_return
644         str     r2, [fp, #cycle-dynarec_local] /* PCSX cycle counter */
645         bx      r1
646         .size   jump_hlecall, .-jump_hlecall
647
648         .align  2
649         .global jump_intcall
650         .type   jump_intcall, %function
651 jump_intcall:
652         ldr     r2, [fp, #last_count-dynarec_local]
653         str     r0, [fp, #pcaddr-dynarec_local]
654         add     r2, r2, r10
655         adr     lr, pcsx_return
656         str     r2, [fp, #cycle-dynarec_local] /* PCSX cycle counter */
657         b       execI
658         .size   jump_hlecall, .-jump_hlecall
659
660 new_dyna_leave:
661         .align  2
662         .global new_dyna_leave
663         .type   new_dyna_leave, %function
664         ldr     r0, [fp, #last_count-dynarec_local]
665         add     r12, fp, #28
666         add     r10, r0, r10
667         str     r10, [fp, #cycle-dynarec_local]
668         ldmfd   sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}
669         .size   new_dyna_leave, .-new_dyna_leave
670
671         .align  2
672         .global invalidate_addr_r0
673         .type   invalidate_addr_r0, %function
674 invalidate_addr_r0:
675         stmia   fp, {r0, r1, r2, r3, r12, lr}
676         b       invalidate_addr_call
677         .size   invalidate_addr_r0, .-invalidate_addr_r0
678         .align  2
679         .global invalidate_addr_r1
680         .type   invalidate_addr_r1, %function
681 invalidate_addr_r1:
682         stmia   fp, {r0, r1, r2, r3, r12, lr}
683         mov     r0, r1
684         b       invalidate_addr_call
685         .size   invalidate_addr_r1, .-invalidate_addr_r1
686         .align  2
687         .global invalidate_addr_r2
688         .type   invalidate_addr_r2, %function
689 invalidate_addr_r2:
690         stmia   fp, {r0, r1, r2, r3, r12, lr}
691         mov     r0, r2
692         b       invalidate_addr_call
693         .size   invalidate_addr_r2, .-invalidate_addr_r2
694         .align  2
695         .global invalidate_addr_r3
696         .type   invalidate_addr_r3, %function
697 invalidate_addr_r3:
698         stmia   fp, {r0, r1, r2, r3, r12, lr}
699         mov     r0, r3
700         b       invalidate_addr_call
701         .size   invalidate_addr_r3, .-invalidate_addr_r3
702         .align  2
703         .global invalidate_addr_r4
704         .type   invalidate_addr_r4, %function
705 invalidate_addr_r4:
706         stmia   fp, {r0, r1, r2, r3, r12, lr}
707         mov     r0, r4
708         b       invalidate_addr_call
709         .size   invalidate_addr_r4, .-invalidate_addr_r4
710         .align  2
711         .global invalidate_addr_r5
712         .type   invalidate_addr_r5, %function
713 invalidate_addr_r5:
714         stmia   fp, {r0, r1, r2, r3, r12, lr}
715         mov     r0, r5
716         b       invalidate_addr_call
717         .size   invalidate_addr_r5, .-invalidate_addr_r5
718         .align  2
719         .global invalidate_addr_r6
720         .type   invalidate_addr_r6, %function
721 invalidate_addr_r6:
722         stmia   fp, {r0, r1, r2, r3, r12, lr}
723         mov     r0, r6
724         b       invalidate_addr_call
725         .size   invalidate_addr_r6, .-invalidate_addr_r6
726         .align  2
727         .global invalidate_addr_r7
728         .type   invalidate_addr_r7, %function
729 invalidate_addr_r7:
730         stmia   fp, {r0, r1, r2, r3, r12, lr}
731         mov     r0, r7
732         b       invalidate_addr_call
733         .size   invalidate_addr_r7, .-invalidate_addr_r7
734         .align  2
735         .global invalidate_addr_r8
736         .type   invalidate_addr_r8, %function
737 invalidate_addr_r8:
738         stmia   fp, {r0, r1, r2, r3, r12, lr}
739         mov     r0, r8
740         b       invalidate_addr_call
741         .size   invalidate_addr_r8, .-invalidate_addr_r8
742         .align  2
743         .global invalidate_addr_r9
744         .type   invalidate_addr_r9, %function
745 invalidate_addr_r9:
746         stmia   fp, {r0, r1, r2, r3, r12, lr}
747         mov     r0, r9
748         b       invalidate_addr_call
749         .size   invalidate_addr_r9, .-invalidate_addr_r9
750         .align  2
751         .global invalidate_addr_r10
752         .type   invalidate_addr_r10, %function
753 invalidate_addr_r10:
754         stmia   fp, {r0, r1, r2, r3, r12, lr}
755         mov     r0, r10
756         b       invalidate_addr_call
757         .size   invalidate_addr_r10, .-invalidate_addr_r10
758         .align  2
759         .global invalidate_addr_r12
760         .type   invalidate_addr_r12, %function
761 invalidate_addr_r12:
762         stmia   fp, {r0, r1, r2, r3, r12, lr}
763         mov     r0, r12
764         .size   invalidate_addr_r12, .-invalidate_addr_r12
765         .align  2
766         .global invalidate_addr_call
767         .type   invalidate_addr_call, %function
768 invalidate_addr_call:
769         ldr     r12, [fp, #inv_code_start-dynarec_local]
770         ldr     lr, [fp, #inv_code_end-dynarec_local]
771         cmp     r0, r12
772         cmpcs   lr, r0
773         blcc    invalidate_addr
774         ldmia   fp, {r0, r1, r2, r3, r12, pc}
775         .size   invalidate_addr_call, .-invalidate_addr_call
776
777         .align  2
778         .global new_dyna_start
779         .type   new_dyna_start, %function
780 new_dyna_start:
781         /* ip is stored to conform EABI alignment */
782         stmfd   sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
783         load_var_adr fp, dynarec_local
784         ldr     r0, [fp, #pcaddr-dynarec_local]
785         bl      get_addr_ht
786         ldr     r1, [fp, #next_interupt-dynarec_local]
787         ldr     r10, [fp, #cycle-dynarec_local]
788         str     r1, [fp, #last_count-dynarec_local]
789         sub     r10, r10, r1
790         mov     pc, r0
791         .size   new_dyna_start, .-new_dyna_start
792
793 /* --------------------------------------- */
794
795 .align  2
796 .global jump_handler_read8
797 .global jump_handler_read16
798 .global jump_handler_read32
799 .global jump_handler_write8
800 .global jump_handler_write16
801 .global jump_handler_write32
802 .global jump_handler_write_h
803 .global jump_handle_swl
804 .global jump_handle_swr
805 .global rcnt0_read_count_m0
806 .global rcnt0_read_count_m1
807 .global rcnt1_read_count_m0
808 .global rcnt1_read_count_m1
809 .global rcnt2_read_count_m0
810 .global rcnt2_read_count_m1
811
812
813 .macro pcsx_read_mem readop tab_shift
814         /* r0 = address, r1 = handler_tab, r2 = cycles */
815         lsl     r3, r0, #20
816         lsr     r3, #(20+\tab_shift)
817         ldr     r12, [fp, #last_count-dynarec_local]
818         ldr     r1, [r1, r3, lsl #2]
819         add     r2, r2, r12
820         lsls    r1, #1
821 .if \tab_shift == 1
822         lsl     r3, #1
823         \readop r0, [r1, r3]
824 .else
825         \readop r0, [r1, r3, lsl #\tab_shift]
826 .endif
827         movcc   pc, lr
828         str     r2, [fp, #cycle-dynarec_local]
829         bx      r1
830 .endm
831
832 jump_handler_read8:
833         add     r1, #0x1000/4*4 + 0x1000/2*4 @ shift to r8 part
834         pcsx_read_mem ldrccb, 0
835
836 jump_handler_read16:
837         add     r1, #0x1000/4*4              @ shift to r16 part
838         pcsx_read_mem ldrcch, 1
839
840 jump_handler_read32:
841         pcsx_read_mem ldrcc, 2
842
843
844 .macro pcsx_write_mem wrtop tab_shift
845         /* r0 = address, r1 = data, r2 = cycles, r3 = handler_tab */
846         lsl     r12,r0, #20
847         lsr     r12, #(20+\tab_shift)
848         ldr     r3, [r3, r12, lsl #2]
849         str     r0, [fp, #address-dynarec_local]      @ some handlers still need it..
850         lsls    r3, #1
851         mov     r0, r2                                @ cycle return in case of direct store
852 .if \tab_shift == 1
853         lsl     r12, #1
854         \wrtop  r1, [r3, r12]
855 .else
856         \wrtop  r1, [r3, r12, lsl #\tab_shift]
857 .endif
858         movcc   pc, lr
859         ldr     r12, [fp, #last_count-dynarec_local]
860         mov     r0, r1
861         add     r2, r2, r12
862         push    {r2, lr}
863         str     r2, [fp, #cycle-dynarec_local]
864         blx     r3
865
866         ldr     r0, [fp, #next_interupt-dynarec_local]
867         pop     {r2, r3}
868         str     r0, [fp, #last_count-dynarec_local]
869         sub     r0, r2, r0
870         bx      r3
871 .endm
872
873 jump_handler_write8:
874         add     r3, #0x1000/4*4 + 0x1000/2*4 @ shift to r8 part
875         pcsx_write_mem strccb, 0
876
877 jump_handler_write16:
878         add     r3, #0x1000/4*4              @ shift to r16 part
879         pcsx_write_mem strcch, 1
880
881 jump_handler_write32:
882         pcsx_write_mem strcc, 2
883
884 jump_handler_write_h:
885         /* r0 = address, r1 = data, r2 = cycles, r3 = handler */
886         ldr     r12, [fp, #last_count-dynarec_local]
887         str     r0, [fp, #address-dynarec_local]      @ some handlers still need it..
888         add     r2, r2, r12
889         mov     r0, r1
890         push    {r2, lr}
891         str     r2, [fp, #cycle-dynarec_local]
892         blx     r3
893
894         ldr     r0, [fp, #next_interupt-dynarec_local]
895         pop     {r2, r3}
896         str     r0, [fp, #last_count-dynarec_local]
897         sub     r0, r2, r0
898         bx      r3
899
900 jump_handle_swl:
901         /* r0 = address, r1 = data, r2 = cycles */
902         ldr     r3, [fp, #mem_wtab-dynarec_local]
903         mov     r12,r0,lsr #12
904         ldr     r3, [r3, r12, lsl #2]
905         lsls    r3, #1
906         bcs     4f
907         add     r3, r0, r3
908         mov     r0, r2
909         tst     r3, #2
910         beq     101f
911         tst     r3, #1
912         beq     2f
913 3:
914         str     r1, [r3, #-3]
915         bx      lr
916 2:
917         lsr     r2, r1, #8
918         lsr     r1, #24
919         strh    r2, [r3, #-2]
920         strb    r1, [r3]
921         bx      lr
922 101:
923         tst     r3, #1
924         lsrne   r1, #16         @ 1
925         lsreq   r12, r1, #24    @ 0
926         strneh  r1, [r3, #-1]
927         streqb  r12, [r3]
928         bx      lr
929 4:
930         mov     r0, r2
931 @       b       abort
932         bx      lr              @ TODO?
933
934
935 jump_handle_swr:
936         /* r0 = address, r1 = data, r2 = cycles */
937         ldr     r3, [fp, #mem_wtab-dynarec_local]
938         mov     r12,r0,lsr #12
939         ldr     r3, [r3, r12, lsl #2]
940         lsls    r3, #1
941         bcs     4f
942         add     r3, r0, r3
943         and     r12,r3, #3
944         mov     r0, r2
945         cmp     r12,#2
946         strgtb  r1, [r3]        @ 3
947         streqh  r1, [r3]        @ 2
948         cmp     r12,#1
949         strlt   r1, [r3]        @ 0
950         bxne    lr
951         lsr     r2, r1, #8      @ 1
952         strb    r1, [r3]
953         strh    r2, [r3, #1]
954         bx      lr
955 4:
956         mov     r0, r2
957 @       b       abort
958         bx      lr              @ TODO?
959
960
961 .macro rcntx_read_mode0 num
962         /* r0 = address, r2 = cycles */
963         ldr     r3, [fp, #rcnts-dynarec_local+6*4+7*4*\num] @ cycleStart
964         mov     r0, r2, lsl #16
965         sub     r0, r3, lsl #16
966         lsr     r0, #16
967         bx      lr
968 .endm
969
970 rcnt0_read_count_m0:
971         rcntx_read_mode0 0
972
973 rcnt1_read_count_m0:
974         rcntx_read_mode0 1
975
976 rcnt2_read_count_m0:
977         rcntx_read_mode0 2
978
979 rcnt0_read_count_m1:
980         /* r0 = address, r2 = cycles */
981         ldr     r3, [fp, #rcnts-dynarec_local+6*4+7*4*0] @ cycleStart
982         mov_16  r1, 0x3334
983         sub     r2, r2, r3
984         mul     r0, r1, r2              @ /= 5
985         lsr     r0, #16
986         bx      lr
987
988 rcnt1_read_count_m1:
989         /* r0 = address, r2 = cycles */
990         ldr     r3, [fp, #rcnts-dynarec_local+6*4+7*4*1]
991         mov_24  r1, 0x1e6cde
992         sub     r2, r2, r3
993         umull   r3, r0, r1, r2          @ ~ /= hsync_cycles, max ~0x1e6cdd
994         bx      lr
995
996 rcnt2_read_count_m1:
997         /* r0 = address, r2 = cycles */
998         ldr     r3, [fp, #rcnts-dynarec_local+6*4+7*4*2]
999         mov     r0, r2, lsl #16-3
1000         sub     r0, r3, lsl #16-3
1001         lsr     r0, #16                 @ /= 8
1002         bx      lr
1003
1004 @ vim:filetype=armasm