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