improved memhandlers
[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 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, 128
154psxRegs_end = intCycle + 128
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 /* FIXME: cycles already calculated, not needed? */
628 ldr r0, [fp, #pcaddr-dynarec_local]
629 bl get_addr_ht
630 ldr r1, [fp, #next_interupt-dynarec_local]
631 ldr r10, [fp, #cycle-dynarec_local]
632 str r1, [fp, #last_count-dynarec_local]
633 sub r10, r10, r1
634 add r10, r10, #2
635 mov pc, r0
636 .size do_interrupt, .-do_interrupt
637 .align 2
638 .global fp_exception
639 .type fp_exception, %function
640fp_exception:
641 mov r2, #0x10000000
642.E7:
643 ldr r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
644 mov r3, #0x80000000
645 str r0, [fp, #reg_cop0+56-dynarec_local] /* EPC */
646 orr r1, #2
647 add r2, r2, #0x2c
648 str r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
649 str r2, [fp, #reg_cop0+52-dynarec_local] /* Cause */
650 add r0, r3, #0x80
651 bl get_addr_ht
652 mov pc, r0
653 .size fp_exception, .-fp_exception
654 .align 2
655 .global fp_exception_ds
656 .type fp_exception_ds, %function
657fp_exception_ds:
658 mov r2, #0x90000000 /* Set high bit if delay slot */
659 b .E7
660 .size fp_exception_ds, .-fp_exception_ds
661
662 .align 2
663 .global jump_syscall
664 .type jump_syscall, %function
665jump_syscall:
666 ldr r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
667 mov r3, #0x80000000
668 str r0, [fp, #reg_cop0+56-dynarec_local] /* EPC */
669 orr r1, #2
670 mov r2, #0x20
671 str r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
672 str r2, [fp, #reg_cop0+52-dynarec_local] /* Cause */
673 add r0, r3, #0x80
674 bl get_addr_ht
675 mov pc, r0
676 .size jump_syscall, .-jump_syscall
677 .align 2
678
679 .align 2
680 .global jump_syscall_hle
681 .type jump_syscall_hle, %function
682jump_syscall_hle:
683 str r0, [fp, #pcaddr-dynarec_local] /* PC must be set to EPC for psxException */
684 ldr r2, [fp, #last_count-dynarec_local]
685 mov r1, #0 /* in delay slot */
686 add r2, r2, r10
687 mov r0, #0x20 /* cause */
688 str r2, [fp, #cycle-dynarec_local] /* PCSX cycle counter */
689 bl psxException
690
691 /* note: psxException might do recorsive recompiler call from it's HLE code,
692 * so be ready for this */
693pcsx_return:
694 ldr r1, [fp, #next_interupt-dynarec_local]
695 ldr r10, [fp, #cycle-dynarec_local]
696 ldr r0, [fp, #pcaddr-dynarec_local]
697 sub r10, r10, r1
698 str r1, [fp, #last_count-dynarec_local]
699 bl get_addr_ht
700 mov pc, r0
701 .size jump_syscall_hle, .-jump_syscall_hle
702
703 .align 2
704 .global jump_hlecall
705 .type jump_hlecall, %function
706jump_hlecall:
707 ldr r2, [fp, #last_count-dynarec_local]
708 str r0, [fp, #pcaddr-dynarec_local]
709 add r2, r2, r10
710 str r2, [fp, #cycle-dynarec_local] /* PCSX cycle counter */
711 adr lr, pcsx_return
712 bx r1
713 .size jump_hlecall, .-jump_hlecall
714
715new_dyna_leave:
716 .align 2
717 .global new_dyna_leave
718 .type new_dyna_leave, %function
719 ldr r0, [fp, #last_count-dynarec_local]
720 add r12, fp, #28
721 add r10, r0, r10
722 str r10, [fp, #cycle-dynarec_local]
723 ldmfd sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}
724 .size new_dyna_leave, .-new_dyna_leave
725
726 /* these are used to call memhandlers */
727 .align 2
728 .global indirect_jump_indexed
729 .type indirect_jump_indexed, %function
730indirect_jump_indexed:
731 ldr r0, [r0, r1, lsl #2]
732 .global indirect_jump
733 .type indirect_jump, %function
734indirect_jump:
735 ldr r12, [fp, #last_count-dynarec_local]
736 add r2, r2, r12
737 str r2, [fp, #cycle-dynarec_local]
738 mov pc, r0
739 .size indirect_jump, .-indirect_jump
740 .size indirect_jump_indexed, .-indirect_jump_indexed
741
742 .align 2
743 .global jump_eret
744 .type jump_eret, %function
745jump_eret:
746 ldr r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
747 ldr r0, [fp, #last_count-dynarec_local]
748 bic r1, r1, #2
749 add r10, r0, r10
750 str r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
751 str r10, [fp, #cycle-dynarec_local]
752 bl check_interupt
753 ldr r1, [fp, #next_interupt-dynarec_local]
754 ldr r0, [fp, #reg_cop0+56-dynarec_local] /* EPC */
755 str r1, [fp, #last_count-dynarec_local]
756 subs r10, r10, r1
757 bpl .E11
758.E8:
759 bl get_addr
760 mov pc, r0
761.E11:
762 str r0, [fp, #pcaddr-dynarec_local]
763 bl cc_interrupt
764 ldr r0, [fp, #pcaddr-dynarec_local]
765 b .E8
766 .size jump_eret, .-jump_eret
767
768 .align 2
769 .global new_dyna_start
770 .type new_dyna_start, %function
771new_dyna_start:
772 /* ip is stored to conform EABI alignment */
773 stmfd sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
774.if HAVE_ARMV7
775 movw fp, #:lower16:dynarec_local
776 movt fp, #:upper16:dynarec_local
777.else
778 ldr fp, .dlptr
779.endif
780 ldr r0, [fp, #pcaddr-dynarec_local]
781 bl get_addr_ht
782 ldr r1, [fp, #next_interupt-dynarec_local]
783 ldr r10, [fp, #cycle-dynarec_local]
784 str r1, [fp, #last_count-dynarec_local]
785 sub r10, r10, r1
786 mov pc, r0
787.dlptr:
788 .word dynarec_local
789 .size new_dyna_start, .-new_dyna_start
790
791/* --------------------------------------- */
792
793.align 2
794.global ari_read_ram8
795.global ari_read_ram16
796.global ari_read_ram32
797.global ari_read_ram_mirror8
798.global ari_read_ram_mirror16
799.global ari_read_ram_mirror32
800.global ari_write_ram8
801.global ari_write_ram16
802.global ari_write_ram32
803.global ari_write_ram_mirror8
804.global ari_write_ram_mirror16
805.global ari_write_ram_mirror32
806.global ari_read_io8
807.global ari_read_io16
808.global ari_read_io32
809.global ari_write_io8
810.global ari_write_io16
811.global ari_write_io32
812
813.macro ari_read_ram bic_const op
814 ldr r0, [fp, #address-dynarec_local]
815.if \bic_const
816 bic r0, r0, #\bic_const
817.endif
818 \op r0, [r0]
819 str r0, [fp, #readmem_dword-dynarec_local]
820 mov pc, lr
821.endm
822
823ari_read_ram8:
824 ari_read_ram 0, ldrb
825
826ari_read_ram16:
827 ari_read_ram 1, ldrh
828
829ari_read_ram32:
830 ari_read_ram 3, ldr
831
832.macro ari_read_ram_mirror mvn_const, op
833 ldr r0, [fp, #address-dynarec_local]
834 mvn r1, #\mvn_const
835 and r0, r1, lsr #11
836 orr r0, r0, #1<<31
837 \op r0, [r0]
838 str r0, [fp, #readmem_dword-dynarec_local]
839 mov pc, lr
840.endm
841
842ari_read_ram_mirror8:
843 ari_read_ram_mirror 0, ldrb
844
845ari_read_ram_mirror16:
846 ari_read_ram_mirror (1<<11), ldrh
847
848ari_read_ram_mirror32:
849 ari_read_ram_mirror (3<<11), ldr
850
851/* invalidation is already taken care of by the caller */
852.macro ari_write_ram bic_const var op
853 ldr r0, [fp, #address-dynarec_local]
854 ldr r1, [fp, #\var-dynarec_local]
855.if \bic_const
856 bic r0, r0, #\bic_const
857.endif
858 \op r1, [r0]
859 mov pc, lr
860.endm
861
862ari_write_ram8:
863 ari_write_ram 0, byte, strb
864
865ari_write_ram16:
866 ari_write_ram 1, hword, strh
867
868ari_write_ram32:
869 ari_write_ram 3, word, str
870
871.macro ari_write_ram_mirror mvn_const var op
872 ldr r0, [fp, #address-dynarec_local]
873 mvn r3, #\mvn_const
874 ldr r1, [fp, #\var-dynarec_local]
875 and r0, r3, lsr #11
876 ldr r2, [fp, #invc_ptr-dynarec_local]
877 orr r0, r0, #1<<31
878 ldrb r2, [r2, r0, lsr #12]
879 \op r1, [r0]
880 tst r2, r2
881 movne pc, lr
882 lsr r0, r0, #12
883 b invalidate_block
884.endm
885
886ari_write_ram_mirror8:
887 ari_write_ram_mirror 0, byte, strb
888
889ari_write_ram_mirror16:
890 ari_write_ram_mirror (1<<11), hword, strh
891
892ari_write_ram_mirror32:
893 ari_write_ram_mirror (3<<11), word, str
894
895
896@ for testing
897.macro ari_read_io_old tab_shift
898 str lr, [sp, #-8]! @ EABI alignment..
899.if \tab_shift == 0
900 bl psxHwRead32
901.endif
902.if \tab_shift == 1
903 bl psxHwRead16
904.endif
905.if \tab_shift == 2
906 bl psxHwRead8
907.endif
908 str r0, [fp, #readmem_dword-dynarec_local]
909 ldr pc, [sp], #8
910.endm
911
912.macro ari_read_io readop mem_tab tab_shift
913 ldr r0, [fp, #address-dynarec_local]
914 ldr r1, [fp, #psxH_ptr-dynarec_local]
915.if \tab_shift == 0
916 bic r0, r0, #3
917.endif
918.if \tab_shift == 1
919 bic r0, r0, #1
920.endif
921 bic r2, r0, #0x1f800000
922 ldr r12,[fp, #\mem_tab-dynarec_local]
923 subs r3, r2, #0x1000
924 blo 2f
925@ ari_read_io_old \tab_shift
926 cmp r3, #0x880
927 bhs 1f
928 ldr r12,[r12, r3, lsl #\tab_shift]
929 tst r12,r12
930 beq 2f
9310:
932 str lr, [sp, #-8]! @ EABI alignment..
933 blx r12
934 str r0, [fp, #readmem_dword-dynarec_local]
935 ldr pc, [sp], #8
936
9371:
938.if \tab_shift == 1 @ read16
939 cmp r2, #0x1c00
940 blo 2f
941 cmp r2, #0x1e00
942 bhs 2f
943 ldr r12,[fp, #spu_readf-dynarec_local]
944 b 0b
945.endif
9462:
947 @ no handler, just read psxH
948 \readop r0, [r1, r2]
949 str r0, [fp, #readmem_dword-dynarec_local]
950 mov pc, lr
951.endm
952
953ari_read_io8:
954 ari_read_io ldrb, tab_read8, 2
955
956ari_read_io16:
957 ari_read_io ldrh, tab_read16, 1
958
959ari_read_io32:
960 ari_read_io ldr, tab_read32, 0
961
962.macro ari_write_io_old tab_shift
963.if \tab_shift == 0
964 b psxHwWrite32
965.endif
966.if \tab_shift == 1
967 b psxHwWrite16
968.endif
969.if \tab_shift == 2
970 b psxHwWrite8
971.endif
972.endm
973
974.macro ari_write_io opvl opst var mem_tab tab_shift
975 ldr r0, [fp, #address-dynarec_local]
976 \opvl r1, [fp, #\var-dynarec_local]
977.if \tab_shift == 0
978 bic r0, r0, #3
979.endif
980.if \tab_shift == 1
981 bic r0, r0, #1
982.endif
983 bic r2, r0, #0x1f800000
984 ldr r12,[fp, #\mem_tab-dynarec_local]
985 subs r3, r2, #0x1000
986 blo 0f
987@ ari_write_io_old \tab_shift
988 cmp r3, #0x880
989 bhs 1f
990 ldr r12,[r12, r3, lsl #\tab_shift]
991 mov r0, r1
992 tst r12,r12
993 bxne r12
9940:
995 ldr r3, [fp, #psxH_ptr-dynarec_local]
996 \opst r1, [r2, r3]
997 mov pc, lr
9981:
999.if \tab_shift == 1 @ write16
1000 cmp r2, #0x1c00
1001 blo 0b
1002 cmp r2, #0x1e00
1003 ldrlo pc, [fp, #spu_writef-dynarec_local]
1004 nop
1005.endif
1006 b 0b
1007.endm
1008
1009ari_write_io8:
1010 ari_write_io ldrb, strb, byte, tab_write8, 2
1011
1012ari_write_io16:
1013 ari_write_io ldrh, strh, hword, tab_write16, 1
1014
1015ari_write_io32:
1016 ari_write_io ldr, str, word, tab_write32, 0
1017
1018@ vim:filetype=armasm