spu: split out mixing, use NEON for that on ARM
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / linkage_arm.s
CommitLineData
57871462 1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7e605697 2 * linkage_arm.s for PCSX *
0bbd1454 3 * Copyright (C) 2009-2011 Ari64 *
576bbd8f 4 * Copyright (C) 2010-2011 GraÅžvydas "notaz" Ignotas *
57871462 5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
20 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
b021ee75 21
22.equiv HAVE_ARMV7, 1
23
24.if HAVE_ARMV7
25 .cpu cortex-a8
26 .fpu vfp
27.else
57871462 28 .cpu arm9tdmi
29 .fpu softvfp
b021ee75 30.endif
57871462 31 .global rdram
32rdram = 0x80000000
33 .global dynarec_local
34 .global reg
35 .global hi
36 .global lo
57871462 37 .global reg_cop0
b9b61529 38 .global reg_cop2d
39 .global reg_cop2c
57871462 40 .global FCR0
41 .global FCR31
57871462 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
f95a77f7 51 .global readmem_word
57871462 52 .global dword
53 .global word
54 .global hword
55 .global byte
56 .global branch_target
57 .global PC
57871462 58 .global mini_ht
59 .global restore_candidate
60 .global memory_map
f95a77f7 61 /* psx */
62 .global psxRegs
7e605697 63 .global nd_pcsx_io
64 .global psxH_ptr
f95a77f7 65
57871462 66 .bss
67 .align 4
68 .type dynarec_local, %object
f95a77f7 69 .size dynarec_local, dynarec_local_end-dynarec_local
57871462 70dynarec_local:
f95a77f7 71 .space dynarec_local_end-dynarec_local /*0x400630*/
57871462 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
7139f3c8 84stop = pending_exception + 4
57871462 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
f95a77f7 94readmem_word = readmem_dword
57871462 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
7e605697 115psxRegs = FCR31 + 4
f95a77f7 116
117/* psxRegs */
7e605697 118 .type psxRegs, %object
119 .size psxRegs, psxRegs_end-psxRegs
120reg = psxRegs
57871462 121 .type reg, %object
f95a77f7 122 .size reg, 128
7139f3c8 123lo = reg + 128
57871462 124 .type lo, %object
f95a77f7 125 .size lo, 4
7139f3c8 126hi = lo + 4
127 .type hi, %object
128 .size hi, 4
129reg_cop0 = hi + 4
57871462 130 .type reg_cop0, %object
131 .size reg_cop0, 128
f95a77f7 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
7139f3c8 139pcaddr = PC
57871462 140 .type PC, %object
141 .size PC, 4
f95a77f7 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
52082bc1 153 .size intCycle, 256
154psxRegs_end = intCycle + 256
f95a77f7 155
7e605697 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 */
f95a77f7 190 .type align0, %object
7e605697 191 .size align0, 4
192branch_target = align0 + 4
f95a77f7 193 .type branch_target, %object
194 .size branch_target, 4
195mini_ht = branch_target + 4
57871462 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
f95a77f7 204dynarec_local_end = memory_map + 4194304
57871462 205
274c4243 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
57871462 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 */
57871462 222 mov r12, r0
57871462 223 mov r6, #4096
57871462 224 mov r2, #0x80000
225 ldr r3, .jiptr
57871462 226 sub r6, r6, #1
57871462 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
7139f3c8 332
57871462 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 */
57871462 340 mov r12, r0
57871462 341 mov r6, #4096
57871462 342 mov r2, #0x80000
343 ldr r3, .jiptr
57871462 344 sub r6, r6, #1
57871462 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
57871462 433.htptr:
434 .word hash_table
7139f3c8 435
57871462 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
7139f3c8 536
57871462 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:
57871462 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
7139f3c8 582 .size verify_code_vm, .-verify_code_vm
583
57871462 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
822b27d1 595 str r10, [fp, #cycle-dynarec_local] /* PCSX cycles */
596@@ str r10, [fp, #reg_cop0+36-dynarec_local] /* Count */
57871462 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
822b27d1 604 ldr r10, [fp, #cycle-dynarec_local]
57871462 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
b021ee75 611 ldmnefd sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}
57871462 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
57871462 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
57871462 630 .size cc_interrupt, .-cc_interrupt
7139f3c8 631
57871462 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
57871462 638 add r10, r10, #2
639 mov pc, r0
640 .size do_interrupt, .-do_interrupt
fca1aef2 641
57871462 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 */
7139f3c8 655 add r0, r3, #0x80
57871462 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
7139f3c8 666
57871462 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 */
7139f3c8 678 add r0, r3, #0x80
57871462 679 bl get_addr_ht
680 mov pc, r0
681 .size jump_syscall, .-jump_syscall
7139f3c8 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 */
7139f3c8 694 bl psxException
695
696 /* note: psxException might do recorsive recompiler call from it's HLE code,
697 * so be ready for this */
822b27d1 698pcsx_return:
699 ldr r1, [fp, #next_interupt-dynarec_local]
700 ldr r10, [fp, #cycle-dynarec_local]
7139f3c8 701 ldr r0, [fp, #pcaddr-dynarec_local]
822b27d1 702 sub r10, r10, r1
703 str r1, [fp, #last_count-dynarec_local]
7139f3c8 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]
7139f3c8 714 add r2, r2, r10
822b27d1 715 adr lr, pcsx_return
0d16cda2 716 str r2, [fp, #cycle-dynarec_local] /* PCSX cycle counter */
67ba0fb4 717 bx r1
7139f3c8 718 .size jump_hlecall, .-jump_hlecall
719
0d16cda2 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
7139f3c8 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
822b27d1 739 str r10, [fp, #cycle-dynarec_local]
b021ee75 740 ldmfd sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}
7139f3c8 741 .size new_dyna_leave, .-new_dyna_leave
742
822b27d1 743 /* these are used to call memhandlers */
57871462 744 .align 2
745 .global indirect_jump_indexed
746 .type indirect_jump_indexed, %function
747indirect_jump_indexed:
748 ldr r0, [r0, r1, lsl #2]
57871462 749 .global indirect_jump
750 .type indirect_jump, %function
751indirect_jump:
752 ldr r12, [fp, #last_count-dynarec_local]
753 add r2, r2, r12
822b27d1 754 str r2, [fp, #cycle-dynarec_local]
57871462 755 mov pc, r0
756 .size indirect_jump, .-indirect_jump
7139f3c8 757 .size indirect_jump_indexed, .-indirect_jump_indexed
758
0bbd1454 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
57871462 862 .align 2
863 .global new_dyna_start
864 .type new_dyna_start, %function
865new_dyna_start:
b021ee75 866 /* ip is stored to conform EABI alignment */
867 stmfd sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
274c4243 868 load_var_adr fp, dynarec_local
7139f3c8 869 ldr r0, [fp, #pcaddr-dynarec_local]
7139f3c8 870 bl get_addr_ht
871 ldr r1, [fp, #next_interupt-dynarec_local]
822b27d1 872 ldr r10, [fp, #cycle-dynarec_local]
7139f3c8 873 str r1, [fp, #last_count-dynarec_local]
874 sub r10, r10, r1
875 mov pc, r0
57871462 876 .size new_dyna_start, .-new_dyna_start
7139f3c8 877
7e605697 878/* --------------------------------------- */
7139f3c8 879
7e605697 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
274c4243 893.global ari_write_ram_mirror_ro32
a06c1d6e 894.global ari_read_bios8
895.global ari_read_bios16
896.global ari_read_bios32
7e605697 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
7139f3c8 903
7e605697 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]
57871462 910 str r0, [fp, #readmem_dword-dynarec_local]
911 mov pc, lr
7e605697 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]
57871462 930 mov pc, lr
7e605697 931.endm
7139f3c8 932
7e605697 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 */
0d16cda2 943.macro ari_write_ram bic_const var pf
7e605697 944 ldr r0, [fp, #address-dynarec_local]
0d16cda2 945 ldr\pf r1, [fp, #\var-dynarec_local]
7e605697 946.if \bic_const
947 bic r0, r0, #\bic_const
948.endif
0d16cda2 949 str\pf r1, [r0]
57871462 950 mov pc, lr
7e605697 951.endm
7139f3c8 952
7e605697 953ari_write_ram8:
0d16cda2 954 ari_write_ram 0, byte, b
7e605697 955
956ari_write_ram16:
0d16cda2 957 ari_write_ram 1, hword, h
7e605697 958
959ari_write_ram32:
0d16cda2 960 ari_write_ram 3, word,
7e605697 961
0d16cda2 962.macro ari_write_ram_mirror mvn_const var pf
7e605697 963 ldr r0, [fp, #address-dynarec_local]
964 mvn r3, #\mvn_const
0d16cda2 965 ldr\pf r1, [fp, #\var-dynarec_local]
7e605697 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]
0d16cda2 970 str\pf r1, [r0]
7e605697 971 tst r2, r2
972 movne pc, lr
973 lsr r0, r0, #12
974 b invalidate_block
975.endm
976
977ari_write_ram_mirror8:
0d16cda2 978 ari_write_ram_mirror 0, byte, b
7e605697 979
980ari_write_ram_mirror16:
0d16cda2 981 ari_write_ram_mirror (1<<11), hword, h
7e605697 982
983ari_write_ram_mirror32:
0d16cda2 984 ari_write_ram_mirror (3<<11), word,
7e605697 985
274c4243 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
7e605697 994
a06c1d6e 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
7e605697 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]
57871462 1068 mov pc, lr
7e605697 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
0d16cda2 1092.macro ari_write_io pf var mem_tab tab_shift
7e605697 1093 ldr r0, [fp, #address-dynarec_local]
0d16cda2 1094 ldr\pf r1, [fp, #\var-dynarec_local]
7e605697 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]
0d16cda2 1114 str\pf r1, [r2, r3]
57871462 1115 mov pc, lr
7e605697 11161:
7e605697 1117 cmp r2, #0x1c00
1118 blo 0b
1119 cmp r2, #0x1e00
018f9fea 1120.if \tab_shift != 0
7e605697 1121 ldrlo pc, [fp, #spu_writef-dynarec_local]
018f9fea 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]
7e605697 1132.endif
018f9fea 1133 nop
7e605697 1134 b 0b
1135.endm
1136
1137ari_write_io8:
80e38194 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
7e605697 1155
1156ari_write_io16:
0d16cda2 1157 ari_write_io h, hword, tab_write16, 1
7e605697 1158
1159ari_write_io32:
0d16cda2 1160 ari_write_io , word, tab_write32, 0
7e605697 1161
1162@ vim:filetype=armasm