rewrite memhandlers (write)
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / linkage_arm.s
CommitLineData
57871462 1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7e605697 2 * linkage_arm.s for PCSX *
0bbd1454 3 * Copyright (C) 2009-2011 Ari64 *
576bbd8f 4 * Copyright (C) 2010-2011 GraÅžvydas "notaz" Ignotas *
57871462 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 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
b021ee75 21
a80ae4a0 22/* .equiv HAVE_ARMV7, 1 */
b021ee75 23
57871462 24 .global rdram
25rdram = 0x80000000
26 .global dynarec_local
27 .global reg
28 .global hi
29 .global lo
57871462 30 .global reg_cop0
b9b61529 31 .global reg_cop2d
32 .global reg_cop2c
57871462 33 .global FCR0
34 .global FCR31
57871462 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
f95a77f7 44 .global readmem_word
57871462 45 .global dword
46 .global word
47 .global hword
48 .global byte
49 .global branch_target
50 .global PC
57871462 51 .global mini_ht
52 .global restore_candidate
53 .global memory_map
f95a77f7 54 /* psx */
55 .global psxRegs
c6c3b1b3 56 .global mem_rtab
57 .global mem_wtab
7e605697 58 .global nd_pcsx_io
59 .global psxH_ptr
9be4ba64 60 .global inv_code_start
61 .global inv_code_end
f95a77f7 62
57871462 63 .bss
64 .align 4
65 .type dynarec_local, %object
f95a77f7 66 .size dynarec_local, dynarec_local_end-dynarec_local
57871462 67dynarec_local:
f95a77f7 68 .space dynarec_local_end-dynarec_local /*0x400630*/
57871462 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
7139f3c8 81stop = pending_exception + 4
57871462 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
f95a77f7 91readmem_word = readmem_dword
57871462 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
7e605697 112psxRegs = FCR31 + 4
f95a77f7 113
114/* psxRegs */
7e605697 115 .type psxRegs, %object
116 .size psxRegs, psxRegs_end-psxRegs
117reg = psxRegs
57871462 118 .type reg, %object
f95a77f7 119 .size reg, 128
7139f3c8 120lo = reg + 128
57871462 121 .type lo, %object
f95a77f7 122 .size lo, 4
7139f3c8 123hi = lo + 4
124 .type hi, %object
125 .size hi, 4
126reg_cop0 = hi + 4
57871462 127 .type reg_cop0, %object
128 .size reg_cop0, 128
f95a77f7 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
7139f3c8 136pcaddr = PC
57871462 137 .type PC, %object
138 .size PC, 4
f95a77f7 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
52082bc1 150 .size intCycle, 256
151psxRegs_end = intCycle + 256
f95a77f7 152
c6c3b1b3 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
7e605697 160/* nd_pcsx_io */
c6c3b1b3 161nd_pcsx_io = mem_wtab + 4
7e605697 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
9be4ba64 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 */
f95a77f7 200 .type align0, %object
c6c3b1b3 201 .size align0, 4
202branch_target = align0 + 4
f95a77f7 203 .type branch_target, %object
204 .size branch_target, 4
205mini_ht = branch_target + 4
57871462 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
f95a77f7 214dynarec_local_end = memory_map + 4194304
57871462 215
274c4243 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
76f71c27 225.macro dyna_linker_main
57871462 226 /* r0 = virtual target address */
227 /* r1 = instruction to patch */
57871462 228 ldr r3, .jiptr
f968d35d 229 /* get_page */
230 lsr r2, r0, #12
231 mov r6, #4096
232 bic r2, r2, #0xe0000
57871462 233 sub r6, r6, #1
f968d35d 234 cmp r2, #0x1000
57871462 235 ldr r7, [r1]
f968d35d 236 biclt r2, #0x0e00
237 and r6, r6, r2
57871462 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
76f71c27 243 add r6, r1, r12, asr #6
244 mov r8, #0
57871462 245 /* jump_in lookup */
76f71c27 2461:
57871462 247 movs r4, r5
76f71c27 248 beq 2f
57871462 249 ldr r3, [r5]
250 ldr r5, [r4, #12]
251 teq r3, r0
76f71c27 252 bne 1b
57871462 253 ldr r3, [r4, #4]
254 ldr r4, [r4, #8]
255 tst r3, r3
76f71c27 256 bne 1b
257 teq r4, r6
57871462 258 moveq pc, r4 /* Stale i-cache */
76f71c27 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
57871462 267 bl add_link
76f71c27 268 sub r2, r8, r5
57871462 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]
76f71c27 274 mov pc, r8
2753:
57871462 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 */
76f71c27 2936:
57871462 294 movs r4, r5
76f71c27 295 beq 8f
57871462 296 ldr r3, [r5]
297 ldr r5, [r4, #12]
298 teq r3, r0
76f71c27 299 bne 6b
3007:
57871462 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
76f71c27 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
57871462 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
7139f3c8 358
57871462 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 */
76f71c27 366 dyna_linker_main
367
57871462 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
57871462 387.htptr:
388 .word hash_table
7139f3c8 389
57871462 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
7139f3c8 490
57871462 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:
57871462 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
7139f3c8 536 .size verify_code_vm, .-verify_code_vm
537
57871462 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
822b27d1 549 str r10, [fp, #cycle-dynarec_local] /* PCSX cycles */
550@@ str r10, [fp, #reg_cop0+36-dynarec_local] /* Count */
57871462 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
822b27d1 558 ldr r10, [fp, #cycle-dynarec_local]
57871462 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
b021ee75 565 ldmnefd sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}
57871462 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
57871462 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
57871462 584 .size cc_interrupt, .-cc_interrupt
7139f3c8 585
57871462 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
57871462 592 add r10, r10, #2
593 mov pc, r0
594 .size do_interrupt, .-do_interrupt
fca1aef2 595
57871462 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 */
7139f3c8 609 add r0, r3, #0x80
57871462 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
7139f3c8 620
57871462 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 */
7139f3c8 632 add r0, r3, #0x80
57871462 633 bl get_addr_ht
634 mov pc, r0
635 .size jump_syscall, .-jump_syscall
7139f3c8 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 */
7139f3c8 648 bl psxException
649
650 /* note: psxException might do recorsive recompiler call from it's HLE code,
651 * so be ready for this */
822b27d1 652pcsx_return:
653 ldr r1, [fp, #next_interupt-dynarec_local]
654 ldr r10, [fp, #cycle-dynarec_local]
7139f3c8 655 ldr r0, [fp, #pcaddr-dynarec_local]
822b27d1 656 sub r10, r10, r1
657 str r1, [fp, #last_count-dynarec_local]
7139f3c8 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]
7139f3c8 668 add r2, r2, r10
822b27d1 669 adr lr, pcsx_return
0d16cda2 670 str r2, [fp, #cycle-dynarec_local] /* PCSX cycle counter */
67ba0fb4 671 bx r1
7139f3c8 672 .size jump_hlecall, .-jump_hlecall
673
0d16cda2 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
7139f3c8 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
822b27d1 693 str r10, [fp, #cycle-dynarec_local]
b021ee75 694 ldmfd sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}
7139f3c8 695 .size new_dyna_leave, .-new_dyna_leave
696
822b27d1 697 /* these are used to call memhandlers */
57871462 698 .align 2
699 .global indirect_jump_indexed
700 .type indirect_jump_indexed, %function
701indirect_jump_indexed:
702 ldr r0, [r0, r1, lsl #2]
57871462 703 .global indirect_jump
704 .type indirect_jump, %function
705indirect_jump:
706 ldr r12, [fp, #last_count-dynarec_local]
707 add r2, r2, r12
822b27d1 708 str r2, [fp, #cycle-dynarec_local]
57871462 709 mov pc, r0
710 .size indirect_jump, .-indirect_jump
7139f3c8 711 .size indirect_jump_indexed, .-indirect_jump_indexed
712
0bbd1454 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}
0bbd1454 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}
9be4ba64 725 mov r0, r1
0bbd1454 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}
9be4ba64 733 mov r0, r2
0bbd1454 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}
9be4ba64 741 mov r0, r3
0bbd1454 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}
9be4ba64 749 mov r0, r4
0bbd1454 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}
9be4ba64 757 mov r0, r5
0bbd1454 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}
9be4ba64 765 mov r0, r6
0bbd1454 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}
9be4ba64 773 mov r0, r7
0bbd1454 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}
9be4ba64 781 mov r0, r8
0bbd1454 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}
9be4ba64 789 mov r0, r9
0bbd1454 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}
9be4ba64 797 mov r0, r10
0bbd1454 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}
9be4ba64 805 mov r0, r12
0bbd1454 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:
9be4ba64 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
0bbd1454 816 ldmia fp, {r0, r1, r2, r3, r12, pc}
817 .size invalidate_addr_call, .-invalidate_addr_call
818
57871462 819 .align 2
820 .global new_dyna_start
821 .type new_dyna_start, %function
822new_dyna_start:
b021ee75 823 /* ip is stored to conform EABI alignment */
824 stmfd sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
274c4243 825 load_var_adr fp, dynarec_local
7139f3c8 826 ldr r0, [fp, #pcaddr-dynarec_local]
7139f3c8 827 bl get_addr_ht
828 ldr r1, [fp, #next_interupt-dynarec_local]
822b27d1 829 ldr r10, [fp, #cycle-dynarec_local]
7139f3c8 830 str r1, [fp, #last_count-dynarec_local]
831 sub r10, r10, r1
832 mov pc, r0
57871462 833 .size new_dyna_start, .-new_dyna_start
7139f3c8 834
7e605697 835/* --------------------------------------- */
7139f3c8 836
7e605697 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
274c4243 850.global ari_write_ram_mirror_ro32
a06c1d6e 851.global ari_read_bios8
852.global ari_read_bios16
853.global ari_read_bios32
7e605697 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
c6c3b1b3 860.global jump_handler_read8
861.global jump_handler_read16
862.global jump_handler_read32
b96d3df7 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
7139f3c8 869
7e605697 870.macro ari_read_ram bic_const op
871 ldr r0, [fp, #address-dynarec_local]
872.if \bic_const
873 bic r0, r0, #\bic_const
874.endif
875 \op r0, [r0]
57871462 876 str r0, [fp, #readmem_dword-dynarec_local]
877 mov pc, lr
7e605697 878.endm
879
880ari_read_ram8:
881 ari_read_ram 0, ldrb
882
883ari_read_ram16:
884 ari_read_ram 1, ldrh
885
886ari_read_ram32:
887 ari_read_ram 3, ldr
888
889.macro ari_read_ram_mirror mvn_const, op
890 ldr r0, [fp, #address-dynarec_local]
891 mvn r1, #\mvn_const
892 and r0, r1, lsr #11
893 orr r0, r0, #1<<31
894 \op r0, [r0]
895 str r0, [fp, #readmem_dword-dynarec_local]
57871462 896 mov pc, lr
7e605697 897.endm
7139f3c8 898
7e605697 899ari_read_ram_mirror8:
900 ari_read_ram_mirror 0, ldrb
901
902ari_read_ram_mirror16:
903 ari_read_ram_mirror (1<<11), ldrh
904
905ari_read_ram_mirror32:
906 ari_read_ram_mirror (3<<11), ldr
907
908/* invalidation is already taken care of by the caller */
0d16cda2 909.macro ari_write_ram bic_const var pf
7e605697 910 ldr r0, [fp, #address-dynarec_local]
0d16cda2 911 ldr\pf r1, [fp, #\var-dynarec_local]
7e605697 912.if \bic_const
913 bic r0, r0, #\bic_const
914.endif
0d16cda2 915 str\pf r1, [r0]
57871462 916 mov pc, lr
7e605697 917.endm
7139f3c8 918
7e605697 919ari_write_ram8:
0d16cda2 920 ari_write_ram 0, byte, b
7e605697 921
922ari_write_ram16:
0d16cda2 923 ari_write_ram 1, hword, h
7e605697 924
925ari_write_ram32:
0d16cda2 926 ari_write_ram 3, word,
7e605697 927
0d16cda2 928.macro ari_write_ram_mirror mvn_const var pf
7e605697 929 ldr r0, [fp, #address-dynarec_local]
930 mvn r3, #\mvn_const
0d16cda2 931 ldr\pf r1, [fp, #\var-dynarec_local]
7e605697 932 and r0, r3, lsr #11
933 ldr r2, [fp, #invc_ptr-dynarec_local]
934 orr r0, r0, #1<<31
935 ldrb r2, [r2, r0, lsr #12]
0d16cda2 936 str\pf r1, [r0]
7e605697 937 tst r2, r2
938 movne pc, lr
9be4ba64 939 ldr r1, [fp, #inv_code_start-dynarec_local]
940 ldr r2, [fp, #inv_code_end-dynarec_local]
941 cmp r0, r1
942 cmpcs r2, r0
943 movcs pc, lr
944 nop
945 b invalidate_addr
7e605697 946.endm
947
948ari_write_ram_mirror8:
0d16cda2 949 ari_write_ram_mirror 0, byte, b
7e605697 950
951ari_write_ram_mirror16:
0d16cda2 952 ari_write_ram_mirror (1<<11), hword, h
7e605697 953
954ari_write_ram_mirror32:
0d16cda2 955 ari_write_ram_mirror (3<<11), word,
7e605697 956
274c4243 957ari_write_ram_mirror_ro32:
958 load_var_adr r0, pcsx_ram_is_ro
959 ldr r0, [r0]
960 tst r0, r0
961 movne pc, lr
962 nop
963 b ari_write_ram_mirror32
964
7e605697 965
a06c1d6e 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...
970 \op r0, [r0]
971 str r0, [fp, #readmem_dword-dynarec_local]
972 mov pc, lr
973.endm
974
975ari_read_bios8:
976 ari_read_bios_mirror 0, ldrb
977
978ari_read_bios16:
979 ari_read_bios_mirror 1, ldrh
980
981ari_read_bios32:
982 ari_read_bios_mirror 3, ldr
983
984
7e605697 985@ for testing
986.macro ari_read_io_old tab_shift
987 str lr, [sp, #-8]! @ EABI alignment..
988.if \tab_shift == 0
989 bl psxHwRead32
990.endif
991.if \tab_shift == 1
992 bl psxHwRead16
993.endif
994.if \tab_shift == 2
995 bl psxHwRead8
996.endif
997 str r0, [fp, #readmem_dword-dynarec_local]
998 ldr pc, [sp], #8
999.endm
1000
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]
1004.if \tab_shift == 0
1005 bic r0, r0, #3
1006.endif
1007.if \tab_shift == 1
1008 bic r0, r0, #1
1009.endif
1010 bic r2, r0, #0x1f800000
1011 ldr r12,[fp, #\mem_tab-dynarec_local]
1012 subs r3, r2, #0x1000
1013 blo 2f
1014@ ari_read_io_old \tab_shift
1015 cmp r3, #0x880
1016 bhs 1f
1017 ldr r12,[r12, r3, lsl #\tab_shift]
1018 tst r12,r12
1019 beq 2f
10200:
1021 str lr, [sp, #-8]! @ EABI alignment..
1022 blx r12
1023 str r0, [fp, #readmem_dword-dynarec_local]
1024 ldr pc, [sp], #8
1025
10261:
1027.if \tab_shift == 1 @ read16
1028 cmp r2, #0x1c00
1029 blo 2f
1030 cmp r2, #0x1e00
1031 bhs 2f
1032 ldr r12,[fp, #spu_readf-dynarec_local]
1033 b 0b
1034.endif
10352:
1036 @ no handler, just read psxH
1037 \readop r0, [r1, r2]
1038 str r0, [fp, #readmem_dword-dynarec_local]
57871462 1039 mov pc, lr
7e605697 1040.endm
1041
1042ari_read_io8:
1043 ari_read_io ldrb, tab_read8, 2
1044
1045ari_read_io16:
1046 ari_read_io ldrh, tab_read16, 1
1047
1048ari_read_io32:
1049 ari_read_io ldr, tab_read32, 0
1050
1051.macro ari_write_io_old tab_shift
1052.if \tab_shift == 0
1053 b psxHwWrite32
1054.endif
1055.if \tab_shift == 1
1056 b psxHwWrite16
1057.endif
1058.if \tab_shift == 2
1059 b psxHwWrite8
1060.endif
1061.endm
1062
0d16cda2 1063.macro ari_write_io pf var mem_tab tab_shift
7e605697 1064 ldr r0, [fp, #address-dynarec_local]
0d16cda2 1065 ldr\pf r1, [fp, #\var-dynarec_local]
7e605697 1066.if \tab_shift == 0
1067 bic r0, r0, #3
1068.endif
1069.if \tab_shift == 1
1070 bic r0, r0, #1
1071.endif
1072 bic r2, r0, #0x1f800000
1073 ldr r12,[fp, #\mem_tab-dynarec_local]
1074 subs r3, r2, #0x1000
1075 blo 0f
1076@ ari_write_io_old \tab_shift
1077 cmp r3, #0x880
1078 bhs 1f
1079 ldr r12,[r12, r3, lsl #\tab_shift]
1080 mov r0, r1
1081 tst r12,r12
1082 bxne r12
10830:
1084 ldr r3, [fp, #psxH_ptr-dynarec_local]
0d16cda2 1085 str\pf r1, [r2, r3]
57871462 1086 mov pc, lr
7e605697 10871:
7e605697 1088 cmp r2, #0x1c00
1089 blo 0b
1090 cmp r2, #0x1e00
018f9fea 1091.if \tab_shift != 0
7e605697 1092 ldrlo pc, [fp, #spu_writef-dynarec_local]
018f9fea 1093.else
1094 @ write32 to SPU - very rare case (is this correct?)
1095 bhs 0b
1096 add r2, r0, #2
1097 mov r3, r1, lsr #16
1098 push {r2,r3,lr}
1099 mov lr, pc
1100 ldr pc, [fp, #spu_writef-dynarec_local]
1101 pop {r0,r1,lr}
1102 ldr pc, [fp, #spu_writef-dynarec_local]
7e605697 1103.endif
018f9fea 1104 nop
7e605697 1105 b 0b
1106.endm
1107
1108ari_write_io8:
80e38194 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]
1115 strb r1, [r2, r3]
1116 subs r3, r2, #0x1000
1117 movlo pc, lr
1118@ ari_write_io_old 2
1119 cmp r3, #0x880
1120 movhs pc, lr
1121 ldr r12,[r12, r3, lsl #2]
1122 mov r0, r1
1123 tst r12,r12
1124 bxne r12
1125 mov pc, lr
7e605697 1126
1127ari_write_io16:
0d16cda2 1128 ari_write_io h, hword, tab_write16, 1
7e605697 1129
1130ari_write_io32:
0d16cda2 1131 ari_write_io , word, tab_write32, 0
7e605697 1132
c6c3b1b3 1133/* */
1134
1135.macro pcsx_read_mem readop tab_shift
1136 /* r0 = address, r1 = handler_tab, r2 = cycles */
1137 lsl r3, r0, #20
1138 lsr r3, #(20+\tab_shift)
1139 ldr r12, [fp, #last_count-dynarec_local]
1140 ldr r1, [r1, r3, lsl #2]
1141 add r2, r2, r12
1142 lsls r1, #1
1143.if \tab_shift == 1
1144 lsl r3, #1
1145 \readop r0, [r1, r3]
1146.else
1147 \readop r0, [r1, r3, lsl #\tab_shift]
1148.endif
1149 movcc pc, lr
1150 str r2, [fp, #cycle-dynarec_local]
1151 bx r1
1152.endm
1153
1154jump_handler_read8:
1155 add r1, #0x1000/4*4 + 0x1000/2*4 @ shift to r8 part
1156 pcsx_read_mem ldrccb, 0
1157
1158jump_handler_read16:
1159 add r1, #0x1000/4*4 @ shift to r16 part
1160 pcsx_read_mem ldrcch, 1
1161
1162jump_handler_read32:
1163 pcsx_read_mem ldrcc, 2
1164
b96d3df7 1165
1166.macro pcsx_write_mem wrtop tab_shift
1167 /* r0 = address, r1 = data, r2 = cycles, r3 = handler_tab */
1168 lsl r12,r0, #20
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..
1172 lsls r3, #1
1173 mov r0, r2 @ cycle return in case of direct store
1174.if \tab_shift == 1
1175 lsl r12, #1
1176 \wrtop r1, [r3, r12]
1177.else
1178 \wrtop r1, [r3, r12, lsl #\tab_shift]
1179.endif
1180 movcc pc, lr
1181 ldr r12, [fp, #last_count-dynarec_local]
1182 mov r0, r1
1183 add r2, r2, r12
1184 push {r2, lr}
1185 str r2, [fp, #cycle-dynarec_local]
1186 blx r3
1187
1188 ldr r0, [fp, #next_interupt-dynarec_local]
1189 pop {r2, r3}
1190 str r0, [fp, #last_count-dynarec_local]
1191 sub r0, r2, r0
1192 bx r3
1193.endm
1194
1195jump_handler_write8:
1196 add r3, #0x1000/4*4 + 0x1000/2*4 @ shift to r8 part
1197 pcsx_write_mem strccb, 0
1198
1199jump_handler_write16:
1200 add r3, #0x1000/4*4 @ shift to r16 part
1201 pcsx_write_mem strcch, 1
1202
1203jump_handler_write32:
1204 pcsx_write_mem strcc, 2
1205
1206jump_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..
1210 add r2, r2, r12
1211 mov r0, r1
1212 push {r2, lr}
1213 str r2, [fp, #cycle-dynarec_local]
1214 blx r3
1215
1216 ldr r0, [fp, #next_interupt-dynarec_local]
1217 pop {r2, r3}
1218 str r0, [fp, #last_count-dynarec_local]
1219 sub r0, r2, r0
1220 bx r3
1221
1222jump_handle_swl:
1223 /* r0 = address, r1 = data, r2 = cycles */
1224 ldr r3, [fp, #mem_wtab-dynarec_local]
1225 mov r12,r0,lsr #12
1226 ldr r3, [r3, r12, lsl #2]
1227 lsls r3, #1
1228 bcs 4f
1229 add r3, r0, r3
1230 mov r0, r2
1231 tst r3, #2
1232 beq 101f
1233 tst r3, #1
1234 beq 2f
12353:
1236 str r1, [r3, #-3]
1237 bx lr
12382:
1239 lsr r2, r1, #8
1240 lsr r1, #24
1241 strh r2, [r3, #-2]
1242 strb r1, [r3]
1243 bx lr
1244101:
1245 tst r3, #1
1246 lsrne r1, #16 @ 1
1247 lsreq r12, r1, #24 @ 0
1248 strneh r1, [r3, #-1]
1249 streqb r12, [r3]
1250 bx lr
12514:
1252 mov r0, r2
1253 b abort
1254 bx lr @ TODO?
1255
1256
1257jump_handle_swr:
1258 /* r0 = address, r1 = data, r2 = cycles */
1259 ldr r3, [fp, #mem_wtab-dynarec_local]
1260 mov r12,r0,lsr #12
1261 ldr r3, [r3, r12, lsl #2]
1262 lsls r3, #1
1263 bcs 4f
1264 add r3, r0, r3
1265 and r12,r3, #3
1266 mov r0, r2
1267 cmp r12,#2
1268 strgtb r1, [r3] @ 3
1269 streqh r1, [r3] @ 2
1270 cmp r12,#1
1271 strlt r1, [r3] @ 0
1272 bxne lr
1273 lsr r2, r1, #8 @ 1
1274 strb r1, [r3]
1275 strh r2, [r3, #1]
1276 bx lr
12774:
1278 mov r0, r2
1279 b abort
1280 bx lr @ TODO?
1281
1282
7e605697 1283@ vim:filetype=armasm