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