spu: split out mixing, use NEON for that on ARM
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / linkage_arm.s
... / ...
CommitLineData
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * linkage_arm.s for PCSX *
3 * Copyright (C) 2009-2011 Ari64 *
4 * Copyright (C) 2010-2011 GraÅžvydas "notaz" Ignotas *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
20 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
21
22.equiv HAVE_ARMV7, 1
23
24.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.macro load_var_adr reg var
207.if HAVE_ARMV7
208 movw \reg, #:lower16:\var
209 movt \reg, #:upper16:\var
210.else
211 ldr \reg, =\var
212.endif
213.endm
214
215 .text
216 .align 2
217 .global dyna_linker
218 .type dyna_linker, %function
219dyna_linker:
220 /* r0 = virtual target address */
221 /* r1 = instruction to patch */
222 mov r12, r0
223 mov r6, #4096
224 mov r2, #0x80000
225 ldr r3, .jiptr
226 sub r6, r6, #1
227 ldr r7, [r1]
228 eor r2, r2, r12, lsr #12
229 and r6, r6, r12, lsr #12
230 cmp r2, #2048
231 add r12, r7, #2
232 orrcs r2, r6, #2048
233 ldr r5, [r3, r2, lsl #2]
234 lsl r12, r12, #8
235 /* jump_in lookup */
236.A1:
237 movs r4, r5
238 beq .A3
239 ldr r3, [r5]
240 ldr r5, [r4, #12]
241 teq r3, r0
242 bne .A1
243 ldr r3, [r4, #4]
244 ldr r4, [r4, #8]
245 tst r3, r3
246 bne .A1
247.A2:
248 mov r5, r1
249 add r1, r1, r12, asr #6
250 teq r1, r4
251 moveq pc, r4 /* Stale i-cache */
252 bl add_link
253 sub r2, r4, r5
254 and r1, r7, #0xff000000
255 lsl r2, r2, #6
256 sub r1, r1, #2
257 add r1, r1, r2, lsr #8
258 str r1, [r5]
259 mov pc, r4
260.A3:
261 /* hash_table lookup */
262 cmp r2, #2048
263 ldr r3, .jdptr
264 eor r4, r0, r0, lsl #16
265 lslcc r2, r0, #9
266 ldr r6, .htptr
267 lsr r4, r4, #12
268 lsrcc r2, r2, #21
269 bic r4, r4, #15
270 ldr r5, [r3, r2, lsl #2]
271 ldr r7, [r6, r4]!
272 teq r7, r0
273 ldreq pc, [r6, #4]
274 ldr r7, [r6, #8]
275 teq r7, r0
276 ldreq pc, [r6, #12]
277 /* jump_dirty lookup */
278.A6:
279 movs r4, r5
280 beq .A8
281 ldr r3, [r5]
282 ldr r5, [r4, #12]
283 teq r3, r0
284 bne .A6
285.A7:
286 ldr r1, [r4, #8]
287 /* hash_table insert */
288 ldr r2, [r6]
289 ldr r3, [r6, #4]
290 str r0, [r6]
291 str r1, [r6, #4]
292 str r2, [r6, #8]
293 str r3, [r6, #12]
294 mov pc, r1
295.A8:
296 mov r4, r0
297 mov r5, r1
298 bl new_recompile_block
299 tst r0, r0
300 mov r0, r4
301 mov r1, r5
302 beq dyna_linker
303 /* pagefault */
304 mov r1, r0
305 mov r2, #8
306 .size dyna_linker, .-dyna_linker
307 .global exec_pagefault
308 .type exec_pagefault, %function
309exec_pagefault:
310 /* r0 = instruction pointer */
311 /* r1 = fault address */
312 /* r2 = cause */
313 ldr r3, [fp, #reg_cop0+48-dynarec_local] /* Status */
314 mvn r6, #0xF000000F
315 ldr r4, [fp, #reg_cop0+16-dynarec_local] /* Context */
316 bic r6, r6, #0x0F800000
317 str r0, [fp, #reg_cop0+56-dynarec_local] /* EPC */
318 orr r3, r3, #2
319 str r1, [fp, #reg_cop0+32-dynarec_local] /* BadVAddr */
320 bic r4, r4, r6
321 str r3, [fp, #reg_cop0+48-dynarec_local] /* Status */
322 and r5, r6, r1, lsr #9
323 str r2, [fp, #reg_cop0+52-dynarec_local] /* Cause */
324 and r1, r1, r6, lsl #9
325 str r1, [fp, #reg_cop0+40-dynarec_local] /* EntryHi */
326 orr r4, r4, r5
327 str r4, [fp, #reg_cop0+16-dynarec_local] /* Context */
328 mov r0, #0x80000000
329 bl get_addr_ht
330 mov pc, r0
331 .size exec_pagefault, .-exec_pagefault
332
333/* Special dynamic linker for the case where a page fault
334 may occur in a branch delay slot */
335 .global dyna_linker_ds
336 .type dyna_linker_ds, %function
337dyna_linker_ds:
338 /* r0 = virtual target address */
339 /* r1 = instruction to patch */
340 mov r12, r0
341 mov r6, #4096
342 mov r2, #0x80000
343 ldr r3, .jiptr
344 sub r6, r6, #1
345 ldr r7, [r1]
346 eor r2, r2, r12, lsr #12
347 and r6, r6, r12, lsr #12
348 cmp r2, #2048
349 add r12, r7, #2
350 orrcs r2, r6, #2048
351 ldr r5, [r3, r2, lsl #2]
352 lsl r12, r12, #8
353 /* jump_in lookup */
354.B1:
355 movs r4, r5
356 beq .B3
357 ldr r3, [r5]
358 ldr r5, [r4, #12]
359 teq r3, r0
360 bne .B1
361 ldr r3, [r4, #4]
362 ldr r4, [r4, #8]
363 tst r3, r3
364 bne .B1
365.B2:
366 mov r5, r1
367 add r1, r1, r12, asr #6
368 teq r1, r4
369 moveq pc, r4 /* Stale i-cache */
370 bl add_link
371 sub r2, r4, r5
372 and r1, r7, #0xff000000
373 lsl r2, r2, #6
374 sub r1, r1, #2
375 add r1, r1, r2, lsr #8
376 str r1, [r5]
377 mov pc, r4
378.B3:
379 /* hash_table lookup */
380 cmp r2, #2048
381 ldr r3, .jdptr
382 eor r4, r0, r0, lsl #16
383 lslcc r2, r0, #9
384 ldr r6, .htptr
385 lsr r4, r4, #12
386 lsrcc r2, r2, #21
387 bic r4, r4, #15
388 ldr r5, [r3, r2, lsl #2]
389 ldr r7, [r6, r4]!
390 teq r7, r0
391 ldreq pc, [r6, #4]
392 ldr r7, [r6, #8]
393 teq r7, r0
394 ldreq pc, [r6, #12]
395 /* jump_dirty lookup */
396.B6:
397 movs r4, r5
398 beq .B8
399 ldr r3, [r5]
400 ldr r5, [r4, #12]
401 teq r3, r0
402 bne .B6
403.B7:
404 ldr r1, [r4, #8]
405 /* hash_table insert */
406 ldr r2, [r6]
407 ldr r3, [r6, #4]
408 str r0, [r6]
409 str r1, [r6, #4]
410 str r2, [r6, #8]
411 str r3, [r6, #12]
412 mov pc, r1
413.B8:
414 mov r4, r0
415 bic r0, r0, #7
416 mov r5, r1
417 orr r0, r0, #1
418 bl new_recompile_block
419 tst r0, r0
420 mov r0, r4
421 mov r1, r5
422 beq dyna_linker_ds
423 /* pagefault */
424 bic r1, r0, #7
425 mov r2, #0x80000008 /* High bit set indicates pagefault in delay slot */
426 sub r0, r1, #4
427 b exec_pagefault
428 .size dyna_linker_ds, .-dyna_linker_ds
429.jiptr:
430 .word jump_in
431.jdptr:
432 .word jump_dirty
433.htptr:
434 .word hash_table
435
436 .align 2
437 .global jump_vaddr_r0
438 .type jump_vaddr_r0, %function
439jump_vaddr_r0:
440 eor r2, r0, r0, lsl #16
441 b jump_vaddr
442 .size jump_vaddr_r0, .-jump_vaddr_r0
443 .global jump_vaddr_r1
444 .type jump_vaddr_r1, %function
445jump_vaddr_r1:
446 eor r2, r1, r1, lsl #16
447 mov r0, r1
448 b jump_vaddr
449 .size jump_vaddr_r1, .-jump_vaddr_r1
450 .global jump_vaddr_r2
451 .type jump_vaddr_r2, %function
452jump_vaddr_r2:
453 mov r0, r2
454 eor r2, r2, r2, lsl #16
455 b jump_vaddr
456 .size jump_vaddr_r2, .-jump_vaddr_r2
457 .global jump_vaddr_r3
458 .type jump_vaddr_r3, %function
459jump_vaddr_r3:
460 eor r2, r3, r3, lsl #16
461 mov r0, r3
462 b jump_vaddr
463 .size jump_vaddr_r3, .-jump_vaddr_r3
464 .global jump_vaddr_r4
465 .type jump_vaddr_r4, %function
466jump_vaddr_r4:
467 eor r2, r4, r4, lsl #16
468 mov r0, r4
469 b jump_vaddr
470 .size jump_vaddr_r4, .-jump_vaddr_r4
471 .global jump_vaddr_r5
472 .type jump_vaddr_r5, %function
473jump_vaddr_r5:
474 eor r2, r5, r5, lsl #16
475 mov r0, r5
476 b jump_vaddr
477 .size jump_vaddr_r5, .-jump_vaddr_r5
478 .global jump_vaddr_r6
479 .type jump_vaddr_r6, %function
480jump_vaddr_r6:
481 eor r2, r6, r6, lsl #16
482 mov r0, r6
483 b jump_vaddr
484 .size jump_vaddr_r6, .-jump_vaddr_r6
485 .global jump_vaddr_r8
486 .type jump_vaddr_r8, %function
487jump_vaddr_r8:
488 eor r2, r8, r8, lsl #16
489 mov r0, r8
490 b jump_vaddr
491 .size jump_vaddr_r8, .-jump_vaddr_r8
492 .global jump_vaddr_r9
493 .type jump_vaddr_r9, %function
494jump_vaddr_r9:
495 eor r2, r9, r9, lsl #16
496 mov r0, r9
497 b jump_vaddr
498 .size jump_vaddr_r9, .-jump_vaddr_r9
499 .global jump_vaddr_r10
500 .type jump_vaddr_r10, %function
501jump_vaddr_r10:
502 eor r2, r10, r10, lsl #16
503 mov r0, r10
504 b jump_vaddr
505 .size jump_vaddr_r10, .-jump_vaddr_r10
506 .global jump_vaddr_r12
507 .type jump_vaddr_r12, %function
508jump_vaddr_r12:
509 eor r2, r12, r12, lsl #16
510 mov r0, r12
511 b jump_vaddr
512 .size jump_vaddr_r12, .-jump_vaddr_r12
513 .global jump_vaddr_r7
514 .type jump_vaddr_r7, %function
515jump_vaddr_r7:
516 eor r2, r7, r7, lsl #16
517 add r0, r7, #0
518 .size jump_vaddr_r7, .-jump_vaddr_r7
519 .global jump_vaddr
520 .type jump_vaddr, %function
521jump_vaddr:
522 ldr r1, .htptr
523 mvn r3, #15
524 and r2, r3, r2, lsr #12
525 ldr r2, [r1, r2]!
526 teq r2, r0
527 ldreq pc, [r1, #4]
528 ldr r2, [r1, #8]
529 teq r2, r0
530 ldreq pc, [r1, #12]
531 str r10, [fp, #cycle_count-dynarec_local]
532 bl get_addr
533 ldr r10, [fp, #cycle_count-dynarec_local]
534 mov pc, r0
535 .size jump_vaddr, .-jump_vaddr
536
537 .align 2
538 .global verify_code_ds
539 .type verify_code_ds, %function
540verify_code_ds:
541 str r8, [fp, #branch_target-dynarec_local]
542 .size verify_code_ds, .-verify_code_ds
543 .global verify_code_vm
544 .type verify_code_vm, %function
545verify_code_vm:
546 .global verify_code
547 .type verify_code, %function
548verify_code:
549 /* r1 = source */
550 /* r2 = target */
551 /* r3 = length */
552 tst r3, #4
553 mov r4, #0
554 add r3, r1, r3
555 mov r5, #0
556 ldrne r4, [r1], #4
557 mov r12, #0
558 ldrne r5, [r2], #4
559 teq r1, r3
560 beq .D3
561.D2:
562 ldr r7, [r1], #4
563 eor r9, r4, r5
564 ldr r8, [r2], #4
565 orrs r9, r9, r12
566 bne .D4
567 ldr r4, [r1], #4
568 eor r12, r7, r8
569 ldr r5, [r2], #4
570 cmp r1, r3
571 bcc .D2
572 teq r7, r8
573.D3:
574 teqeq r4, r5
575.D4:
576 ldr r8, [fp, #branch_target-dynarec_local]
577 moveq pc, lr
578.D5:
579 bl get_addr
580 mov pc, r0
581 .size verify_code, .-verify_code
582 .size verify_code_vm, .-verify_code_vm
583
584 .align 2
585 .global cc_interrupt
586 .type cc_interrupt, %function
587cc_interrupt:
588 ldr r0, [fp, #last_count-dynarec_local]
589 mov r1, #0
590 mov r2, #0x1fc
591 add r10, r0, r10
592 str r1, [fp, #pending_exception-dynarec_local]
593 and r2, r2, r10, lsr #17
594 add r3, fp, #restore_candidate-dynarec_local
595 str r10, [fp, #cycle-dynarec_local] /* PCSX cycles */
596@@ str r10, [fp, #reg_cop0+36-dynarec_local] /* Count */
597 ldr r4, [r2, r3]
598 mov r10, lr
599 tst r4, r4
600 bne .E4
601.E1:
602 bl gen_interupt
603 mov lr, r10
604 ldr r10, [fp, #cycle-dynarec_local]
605 ldr r0, [fp, #next_interupt-dynarec_local]
606 ldr r1, [fp, #pending_exception-dynarec_local]
607 ldr r2, [fp, #stop-dynarec_local]
608 str r0, [fp, #last_count-dynarec_local]
609 sub r10, r10, r0
610 tst r2, r2
611 ldmnefd sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}
612 tst r1, r1
613 moveq pc, lr
614.E2:
615 ldr r0, [fp, #pcaddr-dynarec_local]
616 bl get_addr_ht
617 mov pc, r0
618.E4:
619 /* Move 'dirty' blocks to the 'clean' list */
620 lsl r5, r2, #3
621 str r1, [r2, r3]
622.E5:
623 lsrs r4, r4, #1
624 mov r0, r5
625 add r5, r5, #1
626 blcs clean_blocks
627 tst r5, #31
628 bne .E5
629 b .E1
630 .size cc_interrupt, .-cc_interrupt
631
632 .align 2
633 .global do_interrupt
634 .type do_interrupt, %function
635do_interrupt:
636 ldr r0, [fp, #pcaddr-dynarec_local]
637 bl get_addr_ht
638 add r10, r10, #2
639 mov pc, r0
640 .size do_interrupt, .-do_interrupt
641
642 .align 2
643 .global fp_exception
644 .type fp_exception, %function
645fp_exception:
646 mov r2, #0x10000000
647.E7:
648 ldr r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
649 mov r3, #0x80000000
650 str r0, [fp, #reg_cop0+56-dynarec_local] /* EPC */
651 orr r1, #2
652 add r2, r2, #0x2c
653 str r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
654 str r2, [fp, #reg_cop0+52-dynarec_local] /* Cause */
655 add r0, r3, #0x80
656 bl get_addr_ht
657 mov pc, r0
658 .size fp_exception, .-fp_exception
659 .align 2
660 .global fp_exception_ds
661 .type fp_exception_ds, %function
662fp_exception_ds:
663 mov r2, #0x90000000 /* Set high bit if delay slot */
664 b .E7
665 .size fp_exception_ds, .-fp_exception_ds
666
667 .align 2
668 .global jump_syscall
669 .type jump_syscall, %function
670jump_syscall:
671 ldr r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
672 mov r3, #0x80000000
673 str r0, [fp, #reg_cop0+56-dynarec_local] /* EPC */
674 orr r1, #2
675 mov r2, #0x20
676 str r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
677 str r2, [fp, #reg_cop0+52-dynarec_local] /* Cause */
678 add r0, r3, #0x80
679 bl get_addr_ht
680 mov pc, r0
681 .size jump_syscall, .-jump_syscall
682 .align 2
683
684 .align 2
685 .global jump_syscall_hle
686 .type jump_syscall_hle, %function
687jump_syscall_hle:
688 str r0, [fp, #pcaddr-dynarec_local] /* PC must be set to EPC for psxException */
689 ldr r2, [fp, #last_count-dynarec_local]
690 mov r1, #0 /* in delay slot */
691 add r2, r2, r10
692 mov r0, #0x20 /* cause */
693 str r2, [fp, #cycle-dynarec_local] /* PCSX cycle counter */
694 bl psxException
695
696 /* note: psxException might do recorsive recompiler call from it's HLE code,
697 * so be ready for this */
698pcsx_return:
699 ldr r1, [fp, #next_interupt-dynarec_local]
700 ldr r10, [fp, #cycle-dynarec_local]
701 ldr r0, [fp, #pcaddr-dynarec_local]
702 sub r10, r10, r1
703 str r1, [fp, #last_count-dynarec_local]
704 bl get_addr_ht
705 mov pc, r0
706 .size jump_syscall_hle, .-jump_syscall_hle
707
708 .align 2
709 .global jump_hlecall
710 .type jump_hlecall, %function
711jump_hlecall:
712 ldr r2, [fp, #last_count-dynarec_local]
713 str r0, [fp, #pcaddr-dynarec_local]
714 add r2, r2, r10
715 adr lr, pcsx_return
716 str r2, [fp, #cycle-dynarec_local] /* PCSX cycle counter */
717 bx r1
718 .size jump_hlecall, .-jump_hlecall
719
720 .align 2
721 .global jump_intcall
722 .type jump_intcall, %function
723jump_intcall:
724 ldr r2, [fp, #last_count-dynarec_local]
725 str r0, [fp, #pcaddr-dynarec_local]
726 add r2, r2, r10
727 adr lr, pcsx_return
728 str r2, [fp, #cycle-dynarec_local] /* PCSX cycle counter */
729 b execI
730 .size jump_hlecall, .-jump_hlecall
731
732new_dyna_leave:
733 .align 2
734 .global new_dyna_leave
735 .type new_dyna_leave, %function
736 ldr r0, [fp, #last_count-dynarec_local]
737 add r12, fp, #28
738 add r10, r0, r10
739 str r10, [fp, #cycle-dynarec_local]
740 ldmfd sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}
741 .size new_dyna_leave, .-new_dyna_leave
742
743 /* these are used to call memhandlers */
744 .align 2
745 .global indirect_jump_indexed
746 .type indirect_jump_indexed, %function
747indirect_jump_indexed:
748 ldr r0, [r0, r1, lsl #2]
749 .global indirect_jump
750 .type indirect_jump, %function
751indirect_jump:
752 ldr r12, [fp, #last_count-dynarec_local]
753 add r2, r2, r12
754 str r2, [fp, #cycle-dynarec_local]
755 mov pc, r0
756 .size indirect_jump, .-indirect_jump
757 .size indirect_jump_indexed, .-indirect_jump_indexed
758
759 .align 2
760 .global invalidate_addr_r0
761 .type invalidate_addr_r0, %function
762invalidate_addr_r0:
763 stmia fp, {r0, r1, r2, r3, r12, lr}
764 lsr r0, r0, #12
765 b invalidate_addr_call
766 .size invalidate_addr_r0, .-invalidate_addr_r0
767 .align 2
768 .global invalidate_addr_r1
769 .type invalidate_addr_r1, %function
770invalidate_addr_r1:
771 stmia fp, {r0, r1, r2, r3, r12, lr}
772 lsr r0, r1, #12
773 b invalidate_addr_call
774 .size invalidate_addr_r1, .-invalidate_addr_r1
775 .align 2
776 .global invalidate_addr_r2
777 .type invalidate_addr_r2, %function
778invalidate_addr_r2:
779 stmia fp, {r0, r1, r2, r3, r12, lr}
780 lsr r0, r2, #12
781 b invalidate_addr_call
782 .size invalidate_addr_r2, .-invalidate_addr_r2
783 .align 2
784 .global invalidate_addr_r3
785 .type invalidate_addr_r3, %function
786invalidate_addr_r3:
787 stmia fp, {r0, r1, r2, r3, r12, lr}
788 lsr r0, r3, #12
789 b invalidate_addr_call
790 .size invalidate_addr_r3, .-invalidate_addr_r3
791 .align 2
792 .global invalidate_addr_r4
793 .type invalidate_addr_r4, %function
794invalidate_addr_r4:
795 stmia fp, {r0, r1, r2, r3, r12, lr}
796 lsr r0, r4, #12
797 b invalidate_addr_call
798 .size invalidate_addr_r4, .-invalidate_addr_r4
799 .align 2
800 .global invalidate_addr_r5
801 .type invalidate_addr_r5, %function
802invalidate_addr_r5:
803 stmia fp, {r0, r1, r2, r3, r12, lr}
804 lsr r0, r5, #12
805 b invalidate_addr_call
806 .size invalidate_addr_r5, .-invalidate_addr_r5
807 .align 2
808 .global invalidate_addr_r6
809 .type invalidate_addr_r6, %function
810invalidate_addr_r6:
811 stmia fp, {r0, r1, r2, r3, r12, lr}
812 lsr r0, r6, #12
813 b invalidate_addr_call
814 .size invalidate_addr_r6, .-invalidate_addr_r6
815 .align 2
816 .global invalidate_addr_r7
817 .type invalidate_addr_r7, %function
818invalidate_addr_r7:
819 stmia fp, {r0, r1, r2, r3, r12, lr}
820 lsr r0, r7, #12
821 b invalidate_addr_call
822 .size invalidate_addr_r7, .-invalidate_addr_r7
823 .align 2
824 .global invalidate_addr_r8
825 .type invalidate_addr_r8, %function
826invalidate_addr_r8:
827 stmia fp, {r0, r1, r2, r3, r12, lr}
828 lsr r0, r8, #12
829 b invalidate_addr_call
830 .size invalidate_addr_r8, .-invalidate_addr_r8
831 .align 2
832 .global invalidate_addr_r9
833 .type invalidate_addr_r9, %function
834invalidate_addr_r9:
835 stmia fp, {r0, r1, r2, r3, r12, lr}
836 lsr r0, r9, #12
837 b invalidate_addr_call
838 .size invalidate_addr_r9, .-invalidate_addr_r9
839 .align 2
840 .global invalidate_addr_r10
841 .type invalidate_addr_r10, %function
842invalidate_addr_r10:
843 stmia fp, {r0, r1, r2, r3, r12, lr}
844 lsr r0, r10, #12
845 b invalidate_addr_call
846 .size invalidate_addr_r10, .-invalidate_addr_r10
847 .align 2
848 .global invalidate_addr_r12
849 .type invalidate_addr_r12, %function
850invalidate_addr_r12:
851 stmia fp, {r0, r1, r2, r3, r12, lr}
852 lsr r0, r12, #12
853 .size invalidate_addr_r12, .-invalidate_addr_r12
854 .align 2
855 .global invalidate_addr_call
856 .type invalidate_addr_call, %function
857invalidate_addr_call:
858 bl invalidate_block
859 ldmia fp, {r0, r1, r2, r3, r12, pc}
860 .size invalidate_addr_call, .-invalidate_addr_call
861
862 .align 2
863 .global new_dyna_start
864 .type new_dyna_start, %function
865new_dyna_start:
866 /* ip is stored to conform EABI alignment */
867 stmfd sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
868 load_var_adr fp, dynarec_local
869 ldr r0, [fp, #pcaddr-dynarec_local]
870 bl get_addr_ht
871 ldr r1, [fp, #next_interupt-dynarec_local]
872 ldr r10, [fp, #cycle-dynarec_local]
873 str r1, [fp, #last_count-dynarec_local]
874 sub r10, r10, r1
875 mov pc, r0
876 .size new_dyna_start, .-new_dyna_start
877
878/* --------------------------------------- */
879
880.align 2
881.global ari_read_ram8
882.global ari_read_ram16
883.global ari_read_ram32
884.global ari_read_ram_mirror8
885.global ari_read_ram_mirror16
886.global ari_read_ram_mirror32
887.global ari_write_ram8
888.global ari_write_ram16
889.global ari_write_ram32
890.global ari_write_ram_mirror8
891.global ari_write_ram_mirror16
892.global ari_write_ram_mirror32
893.global ari_write_ram_mirror_ro32
894.global ari_read_bios8
895.global ari_read_bios16
896.global ari_read_bios32
897.global ari_read_io8
898.global ari_read_io16
899.global ari_read_io32
900.global ari_write_io8
901.global ari_write_io16
902.global ari_write_io32
903
904.macro ari_read_ram bic_const op
905 ldr r0, [fp, #address-dynarec_local]
906.if \bic_const
907 bic r0, r0, #\bic_const
908.endif
909 \op r0, [r0]
910 str r0, [fp, #readmem_dword-dynarec_local]
911 mov pc, lr
912.endm
913
914ari_read_ram8:
915 ari_read_ram 0, ldrb
916
917ari_read_ram16:
918 ari_read_ram 1, ldrh
919
920ari_read_ram32:
921 ari_read_ram 3, ldr
922
923.macro ari_read_ram_mirror mvn_const, op
924 ldr r0, [fp, #address-dynarec_local]
925 mvn r1, #\mvn_const
926 and r0, r1, lsr #11
927 orr r0, r0, #1<<31
928 \op r0, [r0]
929 str r0, [fp, #readmem_dword-dynarec_local]
930 mov pc, lr
931.endm
932
933ari_read_ram_mirror8:
934 ari_read_ram_mirror 0, ldrb
935
936ari_read_ram_mirror16:
937 ari_read_ram_mirror (1<<11), ldrh
938
939ari_read_ram_mirror32:
940 ari_read_ram_mirror (3<<11), ldr
941
942/* invalidation is already taken care of by the caller */
943.macro ari_write_ram bic_const var pf
944 ldr r0, [fp, #address-dynarec_local]
945 ldr\pf r1, [fp, #\var-dynarec_local]
946.if \bic_const
947 bic r0, r0, #\bic_const
948.endif
949 str\pf r1, [r0]
950 mov pc, lr
951.endm
952
953ari_write_ram8:
954 ari_write_ram 0, byte, b
955
956ari_write_ram16:
957 ari_write_ram 1, hword, h
958
959ari_write_ram32:
960 ari_write_ram 3, word,
961
962.macro ari_write_ram_mirror mvn_const var pf
963 ldr r0, [fp, #address-dynarec_local]
964 mvn r3, #\mvn_const
965 ldr\pf r1, [fp, #\var-dynarec_local]
966 and r0, r3, lsr #11
967 ldr r2, [fp, #invc_ptr-dynarec_local]
968 orr r0, r0, #1<<31
969 ldrb r2, [r2, r0, lsr #12]
970 str\pf r1, [r0]
971 tst r2, r2
972 movne pc, lr
973 lsr r0, r0, #12
974 b invalidate_block
975.endm
976
977ari_write_ram_mirror8:
978 ari_write_ram_mirror 0, byte, b
979
980ari_write_ram_mirror16:
981 ari_write_ram_mirror (1<<11), hword, h
982
983ari_write_ram_mirror32:
984 ari_write_ram_mirror (3<<11), word,
985
986ari_write_ram_mirror_ro32:
987 load_var_adr r0, pcsx_ram_is_ro
988 ldr r0, [r0]
989 tst r0, r0
990 movne pc, lr
991 nop
992 b ari_write_ram_mirror32
993
994
995.macro ari_read_bios_mirror bic_const op
996 ldr r0, [fp, #address-dynarec_local]
997 orr r0, r0, #0x80000000
998 bic r0, r0, #(0x20000000|\bic_const) @ map to 0x9fc...
999 \op r0, [r0]
1000 str r0, [fp, #readmem_dword-dynarec_local]
1001 mov pc, lr
1002.endm
1003
1004ari_read_bios8:
1005 ari_read_bios_mirror 0, ldrb
1006
1007ari_read_bios16:
1008 ari_read_bios_mirror 1, ldrh
1009
1010ari_read_bios32:
1011 ari_read_bios_mirror 3, ldr
1012
1013
1014@ for testing
1015.macro ari_read_io_old tab_shift
1016 str lr, [sp, #-8]! @ EABI alignment..
1017.if \tab_shift == 0
1018 bl psxHwRead32
1019.endif
1020.if \tab_shift == 1
1021 bl psxHwRead16
1022.endif
1023.if \tab_shift == 2
1024 bl psxHwRead8
1025.endif
1026 str r0, [fp, #readmem_dword-dynarec_local]
1027 ldr pc, [sp], #8
1028.endm
1029
1030.macro ari_read_io readop mem_tab tab_shift
1031 ldr r0, [fp, #address-dynarec_local]
1032 ldr r1, [fp, #psxH_ptr-dynarec_local]
1033.if \tab_shift == 0
1034 bic r0, r0, #3
1035.endif
1036.if \tab_shift == 1
1037 bic r0, r0, #1
1038.endif
1039 bic r2, r0, #0x1f800000
1040 ldr r12,[fp, #\mem_tab-dynarec_local]
1041 subs r3, r2, #0x1000
1042 blo 2f
1043@ ari_read_io_old \tab_shift
1044 cmp r3, #0x880
1045 bhs 1f
1046 ldr r12,[r12, r3, lsl #\tab_shift]
1047 tst r12,r12
1048 beq 2f
10490:
1050 str lr, [sp, #-8]! @ EABI alignment..
1051 blx r12
1052 str r0, [fp, #readmem_dword-dynarec_local]
1053 ldr pc, [sp], #8
1054
10551:
1056.if \tab_shift == 1 @ read16
1057 cmp r2, #0x1c00
1058 blo 2f
1059 cmp r2, #0x1e00
1060 bhs 2f
1061 ldr r12,[fp, #spu_readf-dynarec_local]
1062 b 0b
1063.endif
10642:
1065 @ no handler, just read psxH
1066 \readop r0, [r1, r2]
1067 str r0, [fp, #readmem_dword-dynarec_local]
1068 mov pc, lr
1069.endm
1070
1071ari_read_io8:
1072 ari_read_io ldrb, tab_read8, 2
1073
1074ari_read_io16:
1075 ari_read_io ldrh, tab_read16, 1
1076
1077ari_read_io32:
1078 ari_read_io ldr, tab_read32, 0
1079
1080.macro ari_write_io_old tab_shift
1081.if \tab_shift == 0
1082 b psxHwWrite32
1083.endif
1084.if \tab_shift == 1
1085 b psxHwWrite16
1086.endif
1087.if \tab_shift == 2
1088 b psxHwWrite8
1089.endif
1090.endm
1091
1092.macro ari_write_io pf var mem_tab tab_shift
1093 ldr r0, [fp, #address-dynarec_local]
1094 ldr\pf r1, [fp, #\var-dynarec_local]
1095.if \tab_shift == 0
1096 bic r0, r0, #3
1097.endif
1098.if \tab_shift == 1
1099 bic r0, r0, #1
1100.endif
1101 bic r2, r0, #0x1f800000
1102 ldr r12,[fp, #\mem_tab-dynarec_local]
1103 subs r3, r2, #0x1000
1104 blo 0f
1105@ ari_write_io_old \tab_shift
1106 cmp r3, #0x880
1107 bhs 1f
1108 ldr r12,[r12, r3, lsl #\tab_shift]
1109 mov r0, r1
1110 tst r12,r12
1111 bxne r12
11120:
1113 ldr r3, [fp, #psxH_ptr-dynarec_local]
1114 str\pf r1, [r2, r3]
1115 mov pc, lr
11161:
1117 cmp r2, #0x1c00
1118 blo 0b
1119 cmp r2, #0x1e00
1120.if \tab_shift != 0
1121 ldrlo pc, [fp, #spu_writef-dynarec_local]
1122.else
1123 @ write32 to SPU - very rare case (is this correct?)
1124 bhs 0b
1125 add r2, r0, #2
1126 mov r3, r1, lsr #16
1127 push {r2,r3,lr}
1128 mov lr, pc
1129 ldr pc, [fp, #spu_writef-dynarec_local]
1130 pop {r0,r1,lr}
1131 ldr pc, [fp, #spu_writef-dynarec_local]
1132.endif
1133 nop
1134 b 0b
1135.endm
1136
1137ari_write_io8:
1138 @ PCSX always writes to psxH, so do we for consistency
1139 ldr r0, [fp, #address-dynarec_local]
1140 ldr r3, [fp, #psxH_ptr-dynarec_local]
1141 ldrb r1, [fp, #byte-dynarec_local]
1142 bic r2, r0, #0x1f800000
1143 ldr r12,[fp, #tab_write8-dynarec_local]
1144 strb r1, [r2, r3]
1145 subs r3, r2, #0x1000
1146 movlo pc, lr
1147@ ari_write_io_old 2
1148 cmp r3, #0x880
1149 movhs pc, lr
1150 ldr r12,[r12, r3, lsl #2]
1151 mov r0, r1
1152 tst r12,r12
1153 bxne r12
1154 mov pc, lr
1155
1156ari_write_io16:
1157 ari_write_io h, hword, tab_write16, 1
1158
1159ari_write_io32:
1160 ari_write_io , word, tab_write32, 0
1161
1162@ vim:filetype=armasm