drc: merge Ari64's patch: 11_reduce_invstub_memory_usage
[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 .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 adr lr, pcsx_return
707 str r2, [fp, #cycle-dynarec_local] /* PCSX cycle counter */
708 bx r1
709 .size jump_hlecall, .-jump_hlecall
710
711 .align 2
712 .global jump_intcall
713 .type jump_intcall, %function
714jump_intcall:
715 ldr r2, [fp, #last_count-dynarec_local]
716 str r0, [fp, #pcaddr-dynarec_local]
717 add r2, r2, r10
718 adr lr, pcsx_return
719 str r2, [fp, #cycle-dynarec_local] /* PCSX cycle counter */
720 b execI
721 .size jump_hlecall, .-jump_hlecall
722
723new_dyna_leave:
724 .align 2
725 .global new_dyna_leave
726 .type new_dyna_leave, %function
727 ldr r0, [fp, #last_count-dynarec_local]
728 add r12, fp, #28
729 add r10, r0, r10
730 str r10, [fp, #cycle-dynarec_local]
731 ldmfd sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}
732 .size new_dyna_leave, .-new_dyna_leave
733
734 /* these are used to call memhandlers */
735 .align 2
736 .global indirect_jump_indexed
737 .type indirect_jump_indexed, %function
738indirect_jump_indexed:
739 ldr r0, [r0, r1, lsl #2]
740 .global indirect_jump
741 .type indirect_jump, %function
742indirect_jump:
743 ldr r12, [fp, #last_count-dynarec_local]
744 add r2, r2, r12
745 str r2, [fp, #cycle-dynarec_local]
746 mov pc, r0
747 .size indirect_jump, .-indirect_jump
748 .size indirect_jump_indexed, .-indirect_jump_indexed
749
750 .align 2
751 .global invalidate_addr_r0
752 .type invalidate_addr_r0, %function
753invalidate_addr_r0:
754 stmia fp, {r0, r1, r2, r3, r12, lr}
755 lsr r0, r0, #12
756 b invalidate_addr_call
757 .size invalidate_addr_r0, .-invalidate_addr_r0
758 .align 2
759 .global invalidate_addr_r1
760 .type invalidate_addr_r1, %function
761invalidate_addr_r1:
762 stmia fp, {r0, r1, r2, r3, r12, lr}
763 lsr r0, r1, #12
764 b invalidate_addr_call
765 .size invalidate_addr_r1, .-invalidate_addr_r1
766 .align 2
767 .global invalidate_addr_r2
768 .type invalidate_addr_r2, %function
769invalidate_addr_r2:
770 stmia fp, {r0, r1, r2, r3, r12, lr}
771 lsr r0, r2, #12
772 b invalidate_addr_call
773 .size invalidate_addr_r2, .-invalidate_addr_r2
774 .align 2
775 .global invalidate_addr_r3
776 .type invalidate_addr_r3, %function
777invalidate_addr_r3:
778 stmia fp, {r0, r1, r2, r3, r12, lr}
779 lsr r0, r3, #12
780 b invalidate_addr_call
781 .size invalidate_addr_r3, .-invalidate_addr_r3
782 .align 2
783 .global invalidate_addr_r4
784 .type invalidate_addr_r4, %function
785invalidate_addr_r4:
786 stmia fp, {r0, r1, r2, r3, r12, lr}
787 lsr r0, r4, #12
788 b invalidate_addr_call
789 .size invalidate_addr_r4, .-invalidate_addr_r4
790 .align 2
791 .global invalidate_addr_r5
792 .type invalidate_addr_r5, %function
793invalidate_addr_r5:
794 stmia fp, {r0, r1, r2, r3, r12, lr}
795 lsr r0, r5, #12
796 b invalidate_addr_call
797 .size invalidate_addr_r5, .-invalidate_addr_r5
798 .align 2
799 .global invalidate_addr_r6
800 .type invalidate_addr_r6, %function
801invalidate_addr_r6:
802 stmia fp, {r0, r1, r2, r3, r12, lr}
803 lsr r0, r6, #12
804 b invalidate_addr_call
805 .size invalidate_addr_r6, .-invalidate_addr_r6
806 .align 2
807 .global invalidate_addr_r7
808 .type invalidate_addr_r7, %function
809invalidate_addr_r7:
810 stmia fp, {r0, r1, r2, r3, r12, lr}
811 lsr r0, r7, #12
812 b invalidate_addr_call
813 .size invalidate_addr_r7, .-invalidate_addr_r7
814 .align 2
815 .global invalidate_addr_r8
816 .type invalidate_addr_r8, %function
817invalidate_addr_r8:
818 stmia fp, {r0, r1, r2, r3, r12, lr}
819 lsr r0, r8, #12
820 b invalidate_addr_call
821 .size invalidate_addr_r8, .-invalidate_addr_r8
822 .align 2
823 .global invalidate_addr_r9
824 .type invalidate_addr_r9, %function
825invalidate_addr_r9:
826 stmia fp, {r0, r1, r2, r3, r12, lr}
827 lsr r0, r9, #12
828 b invalidate_addr_call
829 .size invalidate_addr_r9, .-invalidate_addr_r9
830 .align 2
831 .global invalidate_addr_r10
832 .type invalidate_addr_r10, %function
833invalidate_addr_r10:
834 stmia fp, {r0, r1, r2, r3, r12, lr}
835 lsr r0, r10, #12
836 b invalidate_addr_call
837 .size invalidate_addr_r10, .-invalidate_addr_r10
838 .align 2
839 .global invalidate_addr_r12
840 .type invalidate_addr_r12, %function
841invalidate_addr_r12:
842 stmia fp, {r0, r1, r2, r3, r12, lr}
843 lsr r0, r12, #12
844 .size invalidate_addr_r12, .-invalidate_addr_r12
845 .align 2
846 .global invalidate_addr_call
847 .type invalidate_addr_call, %function
848invalidate_addr_call:
849 bl invalidate_block
850 ldmia fp, {r0, r1, r2, r3, r12, pc}
851 .size invalidate_addr_call, .-invalidate_addr_call
852
853 .align 2
854 .global new_dyna_start
855 .type new_dyna_start, %function
856new_dyna_start:
857 /* ip is stored to conform EABI alignment */
858 stmfd sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
859.if HAVE_ARMV7
860 movw fp, #:lower16:dynarec_local
861 movt fp, #:upper16:dynarec_local
862.else
863 ldr fp, .dlptr
864.endif
865 ldr r0, [fp, #pcaddr-dynarec_local]
866 bl get_addr_ht
867 ldr r1, [fp, #next_interupt-dynarec_local]
868 ldr r10, [fp, #cycle-dynarec_local]
869 str r1, [fp, #last_count-dynarec_local]
870 sub r10, r10, r1
871 mov pc, r0
872.dlptr:
873 .word dynarec_local
874 .size new_dyna_start, .-new_dyna_start
875
876/* --------------------------------------- */
877
878.align 2
879.global ari_read_ram8
880.global ari_read_ram16
881.global ari_read_ram32
882.global ari_read_ram_mirror8
883.global ari_read_ram_mirror16
884.global ari_read_ram_mirror32
885.global ari_write_ram8
886.global ari_write_ram16
887.global ari_write_ram32
888.global ari_write_ram_mirror8
889.global ari_write_ram_mirror16
890.global ari_write_ram_mirror32
891.global ari_read_bios8
892.global ari_read_bios16
893.global ari_read_bios32
894.global ari_read_io8
895.global ari_read_io16
896.global ari_read_io32
897.global ari_write_io8
898.global ari_write_io16
899.global ari_write_io32
900
901.macro ari_read_ram bic_const op
902 ldr r0, [fp, #address-dynarec_local]
903.if \bic_const
904 bic r0, r0, #\bic_const
905.endif
906 \op r0, [r0]
907 str r0, [fp, #readmem_dword-dynarec_local]
908 mov pc, lr
909.endm
910
911ari_read_ram8:
912 ari_read_ram 0, ldrb
913
914ari_read_ram16:
915 ari_read_ram 1, ldrh
916
917ari_read_ram32:
918 ari_read_ram 3, ldr
919
920.macro ari_read_ram_mirror mvn_const, op
921 ldr r0, [fp, #address-dynarec_local]
922 mvn r1, #\mvn_const
923 and r0, r1, lsr #11
924 orr r0, r0, #1<<31
925 \op r0, [r0]
926 str r0, [fp, #readmem_dword-dynarec_local]
927 mov pc, lr
928.endm
929
930ari_read_ram_mirror8:
931 ari_read_ram_mirror 0, ldrb
932
933ari_read_ram_mirror16:
934 ari_read_ram_mirror (1<<11), ldrh
935
936ari_read_ram_mirror32:
937 ari_read_ram_mirror (3<<11), ldr
938
939/* invalidation is already taken care of by the caller */
940.macro ari_write_ram bic_const var pf
941 ldr r0, [fp, #address-dynarec_local]
942 ldr\pf r1, [fp, #\var-dynarec_local]
943.if \bic_const
944 bic r0, r0, #\bic_const
945.endif
946 str\pf r1, [r0]
947 mov pc, lr
948.endm
949
950ari_write_ram8:
951 ari_write_ram 0, byte, b
952
953ari_write_ram16:
954 ari_write_ram 1, hword, h
955
956ari_write_ram32:
957 ari_write_ram 3, word,
958
959.macro ari_write_ram_mirror mvn_const var pf
960 ldr r0, [fp, #address-dynarec_local]
961 mvn r3, #\mvn_const
962 ldr\pf r1, [fp, #\var-dynarec_local]
963 and r0, r3, lsr #11
964 ldr r2, [fp, #invc_ptr-dynarec_local]
965 orr r0, r0, #1<<31
966 ldrb r2, [r2, r0, lsr #12]
967 str\pf r1, [r0]
968 tst r2, r2
969 movne pc, lr
970 lsr r0, r0, #12
971 b invalidate_block
972.endm
973
974ari_write_ram_mirror8:
975 ari_write_ram_mirror 0, byte, b
976
977ari_write_ram_mirror16:
978 ari_write_ram_mirror (1<<11), hword, h
979
980ari_write_ram_mirror32:
981 ari_write_ram_mirror (3<<11), word,
982
983
984.macro ari_read_bios_mirror bic_const op
985 ldr r0, [fp, #address-dynarec_local]
986 orr r0, r0, #0x80000000
987 bic r0, r0, #(0x20000000|\bic_const) @ map to 0x9fc...
988 \op r0, [r0]
989 str r0, [fp, #readmem_dword-dynarec_local]
990 mov pc, lr
991.endm
992
993ari_read_bios8:
994 ari_read_bios_mirror 0, ldrb
995
996ari_read_bios16:
997 ari_read_bios_mirror 1, ldrh
998
999ari_read_bios32:
1000 ari_read_bios_mirror 3, ldr
1001
1002
1003@ for testing
1004.macro ari_read_io_old tab_shift
1005 str lr, [sp, #-8]! @ EABI alignment..
1006.if \tab_shift == 0
1007 bl psxHwRead32
1008.endif
1009.if \tab_shift == 1
1010 bl psxHwRead16
1011.endif
1012.if \tab_shift == 2
1013 bl psxHwRead8
1014.endif
1015 str r0, [fp, #readmem_dword-dynarec_local]
1016 ldr pc, [sp], #8
1017.endm
1018
1019.macro ari_read_io readop mem_tab tab_shift
1020 ldr r0, [fp, #address-dynarec_local]
1021 ldr r1, [fp, #psxH_ptr-dynarec_local]
1022.if \tab_shift == 0
1023 bic r0, r0, #3
1024.endif
1025.if \tab_shift == 1
1026 bic r0, r0, #1
1027.endif
1028 bic r2, r0, #0x1f800000
1029 ldr r12,[fp, #\mem_tab-dynarec_local]
1030 subs r3, r2, #0x1000
1031 blo 2f
1032@ ari_read_io_old \tab_shift
1033 cmp r3, #0x880
1034 bhs 1f
1035 ldr r12,[r12, r3, lsl #\tab_shift]
1036 tst r12,r12
1037 beq 2f
10380:
1039 str lr, [sp, #-8]! @ EABI alignment..
1040 blx r12
1041 str r0, [fp, #readmem_dword-dynarec_local]
1042 ldr pc, [sp], #8
1043
10441:
1045.if \tab_shift == 1 @ read16
1046 cmp r2, #0x1c00
1047 blo 2f
1048 cmp r2, #0x1e00
1049 bhs 2f
1050 ldr r12,[fp, #spu_readf-dynarec_local]
1051 b 0b
1052.endif
10532:
1054 @ no handler, just read psxH
1055 \readop r0, [r1, r2]
1056 str r0, [fp, #readmem_dword-dynarec_local]
1057 mov pc, lr
1058.endm
1059
1060ari_read_io8:
1061 ari_read_io ldrb, tab_read8, 2
1062
1063ari_read_io16:
1064 ari_read_io ldrh, tab_read16, 1
1065
1066ari_read_io32:
1067 ari_read_io ldr, tab_read32, 0
1068
1069.macro ari_write_io_old tab_shift
1070.if \tab_shift == 0
1071 b psxHwWrite32
1072.endif
1073.if \tab_shift == 1
1074 b psxHwWrite16
1075.endif
1076.if \tab_shift == 2
1077 b psxHwWrite8
1078.endif
1079.endm
1080
1081.macro ari_write_io pf var mem_tab tab_shift
1082 ldr r0, [fp, #address-dynarec_local]
1083 ldr\pf r1, [fp, #\var-dynarec_local]
1084.if \tab_shift == 0
1085 bic r0, r0, #3
1086.endif
1087.if \tab_shift == 1
1088 bic r0, r0, #1
1089.endif
1090 bic r2, r0, #0x1f800000
1091 ldr r12,[fp, #\mem_tab-dynarec_local]
1092 subs r3, r2, #0x1000
1093 blo 0f
1094@ ari_write_io_old \tab_shift
1095 cmp r3, #0x880
1096 bhs 1f
1097 ldr r12,[r12, r3, lsl #\tab_shift]
1098 mov r0, r1
1099 tst r12,r12
1100 bxne r12
11010:
1102 ldr r3, [fp, #psxH_ptr-dynarec_local]
1103 str\pf r1, [r2, r3]
1104 mov pc, lr
11051:
1106 cmp r2, #0x1c00
1107 blo 0b
1108 cmp r2, #0x1e00
1109.if \tab_shift != 0
1110 ldrlo pc, [fp, #spu_writef-dynarec_local]
1111.else
1112 @ write32 to SPU - very rare case (is this correct?)
1113 bhs 0b
1114 add r2, r0, #2
1115 mov r3, r1, lsr #16
1116 push {r2,r3,lr}
1117 mov lr, pc
1118 ldr pc, [fp, #spu_writef-dynarec_local]
1119 pop {r0,r1,lr}
1120 ldr pc, [fp, #spu_writef-dynarec_local]
1121.endif
1122 nop
1123 b 0b
1124.endm
1125
1126ari_write_io8:
1127 @ PCSX always writes to psxH, so do we for consistency
1128 ldr r0, [fp, #address-dynarec_local]
1129 ldr r3, [fp, #psxH_ptr-dynarec_local]
1130 ldrb r1, [fp, #byte-dynarec_local]
1131 bic r2, r0, #0x1f800000
1132 ldr r12,[fp, #tab_write8-dynarec_local]
1133 strb r1, [r2, r3]
1134 subs r3, r2, #0x1000
1135 movlo pc, lr
1136@ ari_write_io_old 2
1137 cmp r3, #0x880
1138 movhs pc, lr
1139 ldr r12,[r12, r3, lsl #2]
1140 mov r0, r1
1141 tst r12,r12
1142 bxne r12
1143 mov pc, lr
1144
1145ari_write_io16:
1146 ari_write_io h, hword, tab_write16, 1
1147
1148ari_write_io32:
1149 ari_write_io , word, tab_write32, 0
1150
1151@ vim:filetype=armasm