1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * linkage_arm.s for PCSX *
3 * Copyright (C) 2009-2011 Ari64 *
4 * Copyright (C) 2010-2011 GraÅžvydas "notaz" Ignotas *
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. *
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. *
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 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
22 /* .equiv HAVE_ARMV7, 1 */
38 .global pending_exception
52 .global restore_candidate
60 .global inv_code_start
65 .type dynarec_local, %object
66 .size dynarec_local, dynarec_local_end-dynarec_local
68 .space dynarec_local_end-dynarec_local /*0x400630*/
69 next_interupt = dynarec_local + 64
70 .type next_interupt, %object
71 .size next_interupt, 4
72 cycle_count = next_interupt + 4
73 .type cycle_count, %object
75 last_count = cycle_count + 4
76 .type last_count, %object
78 pending_exception = last_count + 4
79 .type pending_exception, %object
80 .size pending_exception, 4
81 stop = pending_exception + 4
85 .type invc_ptr, %object
87 address = invc_ptr + 4
88 .type address, %object
90 readmem_dword = address + 4
91 readmem_word = readmem_dword
92 .type readmem_dword, %object
93 .size readmem_dword, 8
94 dword = readmem_dword + 8
105 .size byte, 1 /* 1 byte free */
115 .type psxRegs, %object
116 .size psxRegs, psxRegs_end-psxRegs
127 .type reg_cop0, %object
129 reg_cop2d = reg_cop0 + 128
130 .type reg_cop2d, %object
132 reg_cop2c = reg_cop2d + 128
133 .type reg_cop2c, %object
145 interrupt = cycle + 4
146 .type interrupt, %object
148 intCycle = interrupt + 4
149 .type intCycle, %object
151 psxRegs_end = intCycle + 256
153 mem_rtab = psxRegs_end
154 .type mem_rtab, %object
156 mem_wtab = mem_rtab + 4
157 .type mem_wtab, %object
161 nd_pcsx_io = mem_wtab + 4
162 .type nd_pcsx_io, %object
163 .size nd_pcsx_io, nd_pcsx_io_end-nd_pcsx_io
164 tab_read8 = nd_pcsx_io
165 .type tab_read8, %object
167 tab_read16 = tab_read8 + 4
168 .type tab_read16, %object
170 tab_read32 = tab_read16 + 4
171 .type tab_read32, %object
173 tab_write8 = tab_read32 + 4
174 .type tab_write8, %object
176 tab_write16 = tab_write8 + 4
177 .type tab_write16, %object
179 tab_write32 = tab_write16 + 4
180 .type tab_write32, %object
182 spu_readf = tab_write32 + 4
183 .type spu_readf, %object
185 spu_writef = spu_readf + 4
186 .type spu_writef, %object
188 nd_pcsx_io_end = spu_writef + 4
190 psxH_ptr = nd_pcsx_io_end
191 .type psxH_ptr, %object
193 inv_code_start = psxH_ptr + 4
194 .type inv_code_start, %object
195 .size inv_code_start, 4
196 inv_code_end = inv_code_start + 4
197 .type inv_code_end, %object
198 .size inv_code_end, 4
199 align0 = inv_code_end + 4 /* just for alignment */
200 .type align0, %object
202 branch_target = align0 + 4
203 .type branch_target, %object
204 .size branch_target, 4
205 mini_ht = branch_target + 4
206 .type mini_ht, %object
208 restore_candidate = mini_ht + 256
209 .type restore_candidate, %object
210 .size restore_candidate, 512
211 memory_map = restore_candidate + 512
212 .type memory_map, %object
213 .size memory_map, 4194304
214 dynarec_local_end = memory_map + 4194304
216 .macro load_var_adr reg var
218 movw \reg, #:lower16:\var
219 movt \reg, #:upper16:\var
225 .macro dyna_linker_main
226 /* r0 = virtual target address */
227 /* r1 = instruction to patch */
241 ldr r5, [r3, r2, lsl #2]
243 add r6, r1, r12, asr #6
258 moveq pc, r4 /* Stale i-cache */
260 b 1b /* jump_in may have dupes, continue search */
263 beq 3f /* r0 not in jump_in */
269 and r1, r7, #0xff000000
272 add r1, r1, r2, lsr #8
276 /* hash_table lookup */
279 eor r4, r0, r0, lsl #16
285 ldr r5, [r3, r2, lsl #2]
292 /* jump_dirty lookup */
302 /* hash_table insert */
316 .type dyna_linker, %function
318 /* r0 = virtual target address */
319 /* r1 = instruction to patch */
324 bl new_recompile_block
332 .size dyna_linker, .-dyna_linker
333 .global exec_pagefault
334 .type exec_pagefault, %function
336 /* r0 = instruction pointer */
337 /* r1 = fault address */
339 ldr r3, [fp, #reg_cop0+48-dynarec_local] /* Status */
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 */
345 str r1, [fp, #reg_cop0+32-dynarec_local] /* BadVAddr */
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 */
353 str r4, [fp, #reg_cop0+16-dynarec_local] /* Context */
357 .size exec_pagefault, .-exec_pagefault
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
364 /* r0 = virtual target address */
365 /* r1 = instruction to patch */
372 bl new_recompile_block
379 mov r2, #0x80000008 /* High bit set indicates pagefault in delay slot */
382 .size dyna_linker_ds, .-dyna_linker_ds
391 .global jump_vaddr_r0
392 .type jump_vaddr_r0, %function
394 eor r2, r0, r0, lsl #16
396 .size jump_vaddr_r0, .-jump_vaddr_r0
397 .global jump_vaddr_r1
398 .type jump_vaddr_r1, %function
400 eor r2, r1, r1, lsl #16
403 .size jump_vaddr_r1, .-jump_vaddr_r1
404 .global jump_vaddr_r2
405 .type jump_vaddr_r2, %function
408 eor r2, r2, r2, lsl #16
410 .size jump_vaddr_r2, .-jump_vaddr_r2
411 .global jump_vaddr_r3
412 .type jump_vaddr_r3, %function
414 eor r2, r3, r3, lsl #16
417 .size jump_vaddr_r3, .-jump_vaddr_r3
418 .global jump_vaddr_r4
419 .type jump_vaddr_r4, %function
421 eor r2, r4, r4, lsl #16
424 .size jump_vaddr_r4, .-jump_vaddr_r4
425 .global jump_vaddr_r5
426 .type jump_vaddr_r5, %function
428 eor r2, r5, r5, lsl #16
431 .size jump_vaddr_r5, .-jump_vaddr_r5
432 .global jump_vaddr_r6
433 .type jump_vaddr_r6, %function
435 eor r2, r6, r6, lsl #16
438 .size jump_vaddr_r6, .-jump_vaddr_r6
439 .global jump_vaddr_r8
440 .type jump_vaddr_r8, %function
442 eor r2, r8, r8, lsl #16
445 .size jump_vaddr_r8, .-jump_vaddr_r8
446 .global jump_vaddr_r9
447 .type jump_vaddr_r9, %function
449 eor r2, r9, r9, lsl #16
452 .size jump_vaddr_r9, .-jump_vaddr_r9
453 .global jump_vaddr_r10
454 .type jump_vaddr_r10, %function
456 eor r2, r10, r10, lsl #16
459 .size jump_vaddr_r10, .-jump_vaddr_r10
460 .global jump_vaddr_r12
461 .type jump_vaddr_r12, %function
463 eor r2, r12, r12, lsl #16
466 .size jump_vaddr_r12, .-jump_vaddr_r12
467 .global jump_vaddr_r7
468 .type jump_vaddr_r7, %function
470 eor r2, r7, r7, lsl #16
472 .size jump_vaddr_r7, .-jump_vaddr_r7
474 .type jump_vaddr, %function
478 and r2, r3, r2, lsr #12
485 str r10, [fp, #cycle_count-dynarec_local]
487 ldr r10, [fp, #cycle_count-dynarec_local]
489 .size jump_vaddr, .-jump_vaddr
492 .global verify_code_ds
493 .type verify_code_ds, %function
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
501 .type verify_code, %function
530 ldr r8, [fp, #branch_target-dynarec_local]
535 .size verify_code, .-verify_code
536 .size verify_code_vm, .-verify_code_vm
540 .type cc_interrupt, %function
542 ldr r0, [fp, #last_count-dynarec_local]
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 */
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]
565 ldmnefd sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}
569 ldr r0, [fp, #pcaddr-dynarec_local]
573 /* Move 'dirty' blocks to the 'clean' list */
584 .size cc_interrupt, .-cc_interrupt
588 .type do_interrupt, %function
590 ldr r0, [fp, #pcaddr-dynarec_local]
594 .size do_interrupt, .-do_interrupt
598 .type fp_exception, %function
602 ldr r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
604 str r0, [fp, #reg_cop0+56-dynarec_local] /* EPC */
607 str r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
608 str r2, [fp, #reg_cop0+52-dynarec_local] /* Cause */
612 .size fp_exception, .-fp_exception
614 .global fp_exception_ds
615 .type fp_exception_ds, %function
617 mov r2, #0x90000000 /* Set high bit if delay slot */
619 .size fp_exception_ds, .-fp_exception_ds
623 .type jump_syscall, %function
625 ldr r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
627 str r0, [fp, #reg_cop0+56-dynarec_local] /* EPC */
630 str r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
631 str r2, [fp, #reg_cop0+52-dynarec_local] /* Cause */
635 .size jump_syscall, .-jump_syscall
639 .global jump_syscall_hle
640 .type jump_syscall_hle, %function
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 */
646 mov r0, #0x20 /* cause */
647 str r2, [fp, #cycle-dynarec_local] /* PCSX cycle counter */
650 /* note: psxException might do recorsive recompiler call from it's HLE code,
651 * so be ready for this */
653 ldr r1, [fp, #next_interupt-dynarec_local]
654 ldr r10, [fp, #cycle-dynarec_local]
655 ldr r0, [fp, #pcaddr-dynarec_local]
657 str r1, [fp, #last_count-dynarec_local]
660 .size jump_syscall_hle, .-jump_syscall_hle
664 .type jump_hlecall, %function
666 ldr r2, [fp, #last_count-dynarec_local]
667 str r0, [fp, #pcaddr-dynarec_local]
670 str r2, [fp, #cycle-dynarec_local] /* PCSX cycle counter */
672 .size jump_hlecall, .-jump_hlecall
676 .type jump_intcall, %function
678 ldr r2, [fp, #last_count-dynarec_local]
679 str r0, [fp, #pcaddr-dynarec_local]
682 str r2, [fp, #cycle-dynarec_local] /* PCSX cycle counter */
684 .size jump_hlecall, .-jump_hlecall
688 .global new_dyna_leave
689 .type new_dyna_leave, %function
690 ldr r0, [fp, #last_count-dynarec_local]
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
697 /* these are used to call memhandlers */
699 .global indirect_jump_indexed
700 .type indirect_jump_indexed, %function
701 indirect_jump_indexed:
702 ldr r0, [r0, r1, lsl #2]
703 .global indirect_jump
704 .type indirect_jump, %function
706 ldr r12, [fp, #last_count-dynarec_local]
708 str r2, [fp, #cycle-dynarec_local]
710 .size indirect_jump, .-indirect_jump
711 .size indirect_jump_indexed, .-indirect_jump_indexed
714 .global invalidate_addr_r0
715 .type invalidate_addr_r0, %function
717 stmia fp, {r0, r1, r2, r3, r12, lr}
718 b invalidate_addr_call
719 .size invalidate_addr_r0, .-invalidate_addr_r0
721 .global invalidate_addr_r1
722 .type invalidate_addr_r1, %function
724 stmia fp, {r0, r1, r2, r3, r12, lr}
726 b invalidate_addr_call
727 .size invalidate_addr_r1, .-invalidate_addr_r1
729 .global invalidate_addr_r2
730 .type invalidate_addr_r2, %function
732 stmia fp, {r0, r1, r2, r3, r12, lr}
734 b invalidate_addr_call
735 .size invalidate_addr_r2, .-invalidate_addr_r2
737 .global invalidate_addr_r3
738 .type invalidate_addr_r3, %function
740 stmia fp, {r0, r1, r2, r3, r12, lr}
742 b invalidate_addr_call
743 .size invalidate_addr_r3, .-invalidate_addr_r3
745 .global invalidate_addr_r4
746 .type invalidate_addr_r4, %function
748 stmia fp, {r0, r1, r2, r3, r12, lr}
750 b invalidate_addr_call
751 .size invalidate_addr_r4, .-invalidate_addr_r4
753 .global invalidate_addr_r5
754 .type invalidate_addr_r5, %function
756 stmia fp, {r0, r1, r2, r3, r12, lr}
758 b invalidate_addr_call
759 .size invalidate_addr_r5, .-invalidate_addr_r5
761 .global invalidate_addr_r6
762 .type invalidate_addr_r6, %function
764 stmia fp, {r0, r1, r2, r3, r12, lr}
766 b invalidate_addr_call
767 .size invalidate_addr_r6, .-invalidate_addr_r6
769 .global invalidate_addr_r7
770 .type invalidate_addr_r7, %function
772 stmia fp, {r0, r1, r2, r3, r12, lr}
774 b invalidate_addr_call
775 .size invalidate_addr_r7, .-invalidate_addr_r7
777 .global invalidate_addr_r8
778 .type invalidate_addr_r8, %function
780 stmia fp, {r0, r1, r2, r3, r12, lr}
782 b invalidate_addr_call
783 .size invalidate_addr_r8, .-invalidate_addr_r8
785 .global invalidate_addr_r9
786 .type invalidate_addr_r9, %function
788 stmia fp, {r0, r1, r2, r3, r12, lr}
790 b invalidate_addr_call
791 .size invalidate_addr_r9, .-invalidate_addr_r9
793 .global invalidate_addr_r10
794 .type invalidate_addr_r10, %function
796 stmia fp, {r0, r1, r2, r3, r12, lr}
798 b invalidate_addr_call
799 .size invalidate_addr_r10, .-invalidate_addr_r10
801 .global invalidate_addr_r12
802 .type invalidate_addr_r12, %function
804 stmia fp, {r0, r1, r2, r3, r12, lr}
806 .size invalidate_addr_r12, .-invalidate_addr_r12
808 .global invalidate_addr_call
809 .type invalidate_addr_call, %function
810 invalidate_addr_call:
811 ldr r12, [fp, #inv_code_start-dynarec_local]
812 ldr lr, [fp, #inv_code_end-dynarec_local]
816 ldmia fp, {r0, r1, r2, r3, r12, pc}
817 .size invalidate_addr_call, .-invalidate_addr_call
820 .global new_dyna_start
821 .type new_dyna_start, %function
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]
828 ldr r1, [fp, #next_interupt-dynarec_local]
829 ldr r10, [fp, #cycle-dynarec_local]
830 str r1, [fp, #last_count-dynarec_local]
833 .size new_dyna_start, .-new_dyna_start
835 /* --------------------------------------- */
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
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 .global jump_handler_write8
864 .global jump_handler_write16
865 .global jump_handler_write32
866 .global jump_handler_write_h
867 .global jump_handle_swl
868 .global jump_handle_swr
870 .macro ari_read_ram bic_const op
871 ldr r0, [fp, #address-dynarec_local]
873 bic r0, r0, #\bic_const
876 str r0, [fp, #readmem_dword-dynarec_local]
889 .macro ari_read_ram_mirror mvn_const, op
890 ldr r0, [fp, #address-dynarec_local]
895 str r0, [fp, #readmem_dword-dynarec_local]
899 ari_read_ram_mirror8:
900 ari_read_ram_mirror 0, ldrb
902 ari_read_ram_mirror16:
903 ari_read_ram_mirror (1<<11), ldrh
905 ari_read_ram_mirror32:
906 ari_read_ram_mirror (3<<11), ldr
908 /* invalidation is already taken care of by the caller */
909 .macro ari_write_ram bic_const var pf
910 ldr r0, [fp, #address-dynarec_local]
911 ldr\pf r1, [fp, #\var-dynarec_local]
913 bic r0, r0, #\bic_const
920 ari_write_ram 0, byte, b
923 ari_write_ram 1, hword, h
926 ari_write_ram 3, word,
928 .macro ari_write_ram_mirror mvn_const var pf
929 ldr r0, [fp, #address-dynarec_local]
931 ldr\pf r1, [fp, #\var-dynarec_local]
933 ldr r2, [fp, #invc_ptr-dynarec_local]
935 ldrb r2, [r2, r0, lsr #12]
939 ldr r1, [fp, #inv_code_start-dynarec_local]
940 ldr r2, [fp, #inv_code_end-dynarec_local]
948 ari_write_ram_mirror8:
949 ari_write_ram_mirror 0, byte, b
951 ari_write_ram_mirror16:
952 ari_write_ram_mirror (1<<11), hword, h
954 ari_write_ram_mirror32:
955 ari_write_ram_mirror (3<<11), word,
957 ari_write_ram_mirror_ro32:
958 load_var_adr r0, pcsx_ram_is_ro
963 b ari_write_ram_mirror32
966 .macro ari_read_bios_mirror bic_const op
967 ldr r0, [fp, #address-dynarec_local]
968 orr r0, r0, #0x80000000
969 bic r0, r0, #(0x20000000|\bic_const) @ map to 0x9fc...
971 str r0, [fp, #readmem_dword-dynarec_local]
976 ari_read_bios_mirror 0, ldrb
979 ari_read_bios_mirror 1, ldrh
982 ari_read_bios_mirror 3, ldr
986 .macro ari_read_io_old tab_shift
987 str lr, [sp, #-8]! @ EABI alignment..
997 str r0, [fp, #readmem_dword-dynarec_local]
1001 .macro ari_read_io readop mem_tab tab_shift
1002 ldr r0, [fp, #address-dynarec_local]
1003 ldr r1, [fp, #psxH_ptr-dynarec_local]
1010 bic r2, r0, #0x1f800000
1011 ldr r12,[fp, #\mem_tab-dynarec_local]
1012 subs r3, r2, #0x1000
1014 @ ari_read_io_old \tab_shift
1017 ldr r12,[r12, r3, lsl #\tab_shift]
1021 str lr, [sp, #-8]! @ EABI alignment..
1023 str r0, [fp, #readmem_dword-dynarec_local]
1027 .if \tab_shift == 1 @ read16
1032 ldr r12,[fp, #spu_readf-dynarec_local]
1036 @ no handler, just read psxH
1037 \readop r0, [r1, r2]
1038 str r0, [fp, #readmem_dword-dynarec_local]
1043 ari_read_io ldrb, tab_read8, 2
1046 ari_read_io ldrh, tab_read16, 1
1049 ari_read_io ldr, tab_read32, 0
1051 .macro ari_write_io_old tab_shift
1063 .macro ari_write_io pf var mem_tab tab_shift
1064 ldr r0, [fp, #address-dynarec_local]
1065 ldr\pf r1, [fp, #\var-dynarec_local]
1072 bic r2, r0, #0x1f800000
1073 ldr r12,[fp, #\mem_tab-dynarec_local]
1074 subs r3, r2, #0x1000
1076 @ ari_write_io_old \tab_shift
1079 ldr r12,[r12, r3, lsl #\tab_shift]
1084 ldr r3, [fp, #psxH_ptr-dynarec_local]
1092 ldrlo pc, [fp, #spu_writef-dynarec_local]
1094 @ write32 to SPU - very rare case (is this correct?)
1100 ldr pc, [fp, #spu_writef-dynarec_local]
1102 ldr pc, [fp, #spu_writef-dynarec_local]
1109 @ PCSX always writes to psxH, so do we for consistency
1110 ldr r0, [fp, #address-dynarec_local]
1111 ldr r3, [fp, #psxH_ptr-dynarec_local]
1112 ldrb r1, [fp, #byte-dynarec_local]
1113 bic r2, r0, #0x1f800000
1114 ldr r12,[fp, #tab_write8-dynarec_local]
1116 subs r3, r2, #0x1000
1118 @ ari_write_io_old 2
1121 ldr r12,[r12, r3, lsl #2]
1128 ari_write_io h, hword, tab_write16, 1
1131 ari_write_io , word, tab_write32, 0
1135 .macro pcsx_read_mem readop tab_shift
1136 /* r0 = address, r1 = handler_tab, r2 = cycles */
1138 lsr r3, #(20+\tab_shift)
1139 ldr r12, [fp, #last_count-dynarec_local]
1140 ldr r1, [r1, r3, lsl #2]
1145 \readop r0, [r1, r3]
1147 \readop r0, [r1, r3, lsl #\tab_shift]
1150 str r2, [fp, #cycle-dynarec_local]
1155 add r1, #0x1000/4*4 + 0x1000/2*4 @ shift to r8 part
1156 pcsx_read_mem ldrccb, 0
1158 jump_handler_read16:
1159 add r1, #0x1000/4*4 @ shift to r16 part
1160 pcsx_read_mem ldrcch, 1
1162 jump_handler_read32:
1163 pcsx_read_mem ldrcc, 2
1166 .macro pcsx_write_mem wrtop tab_shift
1167 /* r0 = address, r1 = data, r2 = cycles, r3 = handler_tab */
1169 lsr r12, #(20+\tab_shift)
1170 ldr r3, [r3, r12, lsl #2]
1171 str r0, [fp, #address-dynarec_local] @ some handlers still need it..
1173 mov r0, r2 @ cycle return in case of direct store
1176 \wrtop r1, [r3, r12]
1178 \wrtop r1, [r3, r12, lsl #\tab_shift]
1181 ldr r12, [fp, #last_count-dynarec_local]
1185 str r2, [fp, #cycle-dynarec_local]
1188 ldr r0, [fp, #next_interupt-dynarec_local]
1190 str r0, [fp, #last_count-dynarec_local]
1195 jump_handler_write8:
1196 add r3, #0x1000/4*4 + 0x1000/2*4 @ shift to r8 part
1197 pcsx_write_mem strccb, 0
1199 jump_handler_write16:
1200 add r3, #0x1000/4*4 @ shift to r16 part
1201 pcsx_write_mem strcch, 1
1203 jump_handler_write32:
1204 pcsx_write_mem strcc, 2
1206 jump_handler_write_h:
1207 /* r0 = address, r1 = data, r2 = cycles, r3 = handler */
1208 ldr r12, [fp, #last_count-dynarec_local]
1209 str r0, [fp, #address-dynarec_local] @ some handlers still need it..
1213 str r2, [fp, #cycle-dynarec_local]
1216 ldr r0, [fp, #next_interupt-dynarec_local]
1218 str r0, [fp, #last_count-dynarec_local]
1223 /* r0 = address, r1 = data, r2 = cycles */
1224 ldr r3, [fp, #mem_wtab-dynarec_local]
1226 ldr r3, [r3, r12, lsl #2]
1247 lsreq r12, r1, #24 @ 0
1248 strneh r1, [r3, #-1]
1258 /* r0 = address, r1 = data, r2 = cycles */
1259 ldr r3, [fp, #mem_wtab-dynarec_local]
1261 ldr r3, [r3, r12, lsl #2]
1283 @ vim:filetype=armasm