drc: add some hack options
[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
a80ae4a0 22/* .equiv HAVE_ARMV7, 1 */
b021ee75 23
57871462 24 .global rdram
25rdram = 0x80000000
26 .global dynarec_local
27 .global reg
28 .global hi
29 .global lo
57871462 30 .global reg_cop0
b9b61529 31 .global reg_cop2d
32 .global reg_cop2c
57871462 33 .global FCR0
34 .global FCR31
57871462 35 .global next_interupt
36 .global cycle_count
37 .global last_count
38 .global pending_exception
39 .global pcaddr
40 .global stop
41 .global invc_ptr
42 .global address
57871462 43 .global branch_target
44 .global PC
57871462 45 .global mini_ht
46 .global restore_candidate
f95a77f7 47 /* psx */
48 .global psxRegs
c6c3b1b3 49 .global mem_rtab
50 .global mem_wtab
7e605697 51 .global psxH_ptr
054175e9 52 .global zeromem_ptr
9be4ba64 53 .global inv_code_start
54 .global inv_code_end
b1be1eee 55 .global rcnts
f95a77f7 56
57871462 57 .bss
58 .align 4
59 .type dynarec_local, %object
f95a77f7 60 .size dynarec_local, dynarec_local_end-dynarec_local
57871462 61dynarec_local:
b1be1eee 62 .space dynarec_local_end-dynarec_local
57871462 63next_interupt = dynarec_local + 64
64 .type next_interupt, %object
65 .size next_interupt, 4
66cycle_count = next_interupt + 4
67 .type cycle_count, %object
68 .size cycle_count, 4
69last_count = cycle_count + 4
70 .type last_count, %object
71 .size last_count, 4
72pending_exception = last_count + 4
73 .type pending_exception, %object
74 .size pending_exception, 4
7139f3c8 75stop = pending_exception + 4
57871462 76 .type stop, %object
77 .size stop, 4
78invc_ptr = stop + 4
79 .type invc_ptr, %object
80 .size invc_ptr, 4
81address = invc_ptr + 4
82 .type address, %object
83 .size address, 4
63cb0298 84psxRegs = address + 4
f95a77f7 85
86/* psxRegs */
7e605697 87 .type psxRegs, %object
88 .size psxRegs, psxRegs_end-psxRegs
89reg = psxRegs
57871462 90 .type reg, %object
f95a77f7 91 .size reg, 128
7139f3c8 92lo = reg + 128
57871462 93 .type lo, %object
f95a77f7 94 .size lo, 4
7139f3c8 95hi = lo + 4
96 .type hi, %object
97 .size hi, 4
98reg_cop0 = hi + 4
57871462 99 .type reg_cop0, %object
100 .size reg_cop0, 128
f95a77f7 101reg_cop2d = reg_cop0 + 128
102 .type reg_cop2d, %object
103 .size reg_cop2d, 128
104reg_cop2c = reg_cop2d + 128
105 .type reg_cop2c, %object
106 .size reg_cop2c, 128
107PC = reg_cop2c + 128
7139f3c8 108pcaddr = PC
57871462 109 .type PC, %object
110 .size PC, 4
f95a77f7 111code = PC + 4
112 .type code, %object
113 .size code, 4
114cycle = code + 4
115 .type cycle, %object
116 .size cycle, 4
117interrupt = cycle + 4
118 .type interrupt, %object
119 .size interrupt, 4
120intCycle = interrupt + 4
121 .type intCycle, %object
52082bc1 122 .size intCycle, 256
123psxRegs_end = intCycle + 256
f95a77f7 124
b1be1eee 125rcnts = psxRegs_end
126 .type rcnts, %object
127 .size rcnts, 7*4*4
128rcnts_end = rcnts + 7*4*4
129
130mem_rtab = rcnts_end
c6c3b1b3 131 .type mem_rtab, %object
132 .size mem_rtab, 4
133mem_wtab = mem_rtab + 4
134 .type mem_wtab, %object
135 .size mem_wtab, 4
63cb0298 136psxH_ptr = mem_wtab + 4
7e605697 137 .type psxH_ptr, %object
138 .size psxH_ptr, 4
054175e9 139zeromem_ptr = psxH_ptr + 4
140 .type zeromem_ptr, %object
141 .size zeromem_ptr, 4
142inv_code_start = zeromem_ptr + 4
9be4ba64 143 .type inv_code_start, %object
144 .size inv_code_start, 4
145inv_code_end = inv_code_start + 4
146 .type inv_code_end, %object
147 .size inv_code_end, 4
63cb0298 148branch_target = inv_code_end + 4
f95a77f7 149 .type branch_target, %object
150 .size branch_target, 4
63cb0298 151align0 = branch_target + 4 /* unused/alignment */
152 .type align0, %object
054175e9 153 .size align0, 16
154mini_ht = align0 + 16
57871462 155 .type mini_ht, %object
156 .size mini_ht, 256
157restore_candidate = mini_ht + 256
158 .type restore_candidate, %object
159 .size restore_candidate, 512
63cb0298 160dynarec_local_end = restore_candidate + 512
161
162/* unused */
163FCR0 = align0
164 .type FCR0, %object
165 .size FCR0, 4
166FCR31 = align0
167 .type FCR31, %object
168 .size FCR31, 4
57871462 169
274c4243 170.macro load_var_adr reg var
171.if HAVE_ARMV7
172 movw \reg, #:lower16:\var
173 movt \reg, #:upper16:\var
174.else
175 ldr \reg, =\var
176.endif
177.endm
178
b1be1eee 179.macro mov_16 reg imm
180.if HAVE_ARMV7
181 movw \reg, #\imm
182.else
183 mov \reg, #(\imm & 0x00ff)
184 orr \reg, #(\imm & 0xff00)
185.endif
186.endm
187
188.macro mov_24 reg imm
189.if HAVE_ARMV7
190 movw \reg, #(\imm & 0xffff)
191 movt \reg, #(\imm >> 16)
192.else
193 mov \reg, #(\imm & 0x0000ff)
194 orr \reg, #(\imm & 0x00ff00)
195 orr \reg, #(\imm & 0xff0000)
196.endif
197.endm
198
76f71c27 199.macro dyna_linker_main
57871462 200 /* r0 = virtual target address */
201 /* r1 = instruction to patch */
57871462 202 ldr r3, .jiptr
f968d35d 203 /* get_page */
204 lsr r2, r0, #12
205 mov r6, #4096
206 bic r2, r2, #0xe0000
57871462 207 sub r6, r6, #1
f968d35d 208 cmp r2, #0x1000
57871462 209 ldr r7, [r1]
f968d35d 210 biclt r2, #0x0e00
211 and r6, r6, r2
57871462 212 cmp r2, #2048
213 add r12, r7, #2
214 orrcs r2, r6, #2048
215 ldr r5, [r3, r2, lsl #2]
216 lsl r12, r12, #8
76f71c27 217 add r6, r1, r12, asr #6
218 mov r8, #0
57871462 219 /* jump_in lookup */
76f71c27 2201:
57871462 221 movs r4, r5
76f71c27 222 beq 2f
57871462 223 ldr r3, [r5]
224 ldr r5, [r4, #12]
225 teq r3, r0
76f71c27 226 bne 1b
57871462 227 ldr r3, [r4, #4]
228 ldr r4, [r4, #8]
229 tst r3, r3
76f71c27 230 bne 1b
231 teq r4, r6
57871462 232 moveq pc, r4 /* Stale i-cache */
76f71c27 233 mov r8, r4
234 b 1b /* jump_in may have dupes, continue search */
2352:
236 tst r8, r8
237 beq 3f /* r0 not in jump_in */
238
239 mov r5, r1
240 mov r1, r6
57871462 241 bl add_link
76f71c27 242 sub r2, r8, r5
57871462 243 and r1, r7, #0xff000000
244 lsl r2, r2, #6
245 sub r1, r1, #2
246 add r1, r1, r2, lsr #8
247 str r1, [r5]
76f71c27 248 mov pc, r8
2493:
57871462 250 /* hash_table lookup */
251 cmp r2, #2048
252 ldr r3, .jdptr
253 eor r4, r0, r0, lsl #16
254 lslcc r2, r0, #9
255 ldr r6, .htptr
256 lsr r4, r4, #12
257 lsrcc r2, r2, #21
258 bic r4, r4, #15
259 ldr r5, [r3, r2, lsl #2]
260 ldr r7, [r6, r4]!
261 teq r7, r0
262 ldreq pc, [r6, #4]
263 ldr r7, [r6, #8]
264 teq r7, r0
265 ldreq pc, [r6, #12]
266 /* jump_dirty lookup */
76f71c27 2676:
57871462 268 movs r4, r5
76f71c27 269 beq 8f
57871462 270 ldr r3, [r5]
271 ldr r5, [r4, #12]
272 teq r3, r0
76f71c27 273 bne 6b
2747:
57871462 275 ldr r1, [r4, #8]
276 /* hash_table insert */
277 ldr r2, [r6]
278 ldr r3, [r6, #4]
279 str r0, [r6]
280 str r1, [r6, #4]
281 str r2, [r6, #8]
282 str r3, [r6, #12]
283 mov pc, r1
76f71c27 2848:
285.endm
286
287 .text
288 .align 2
289 .global dyna_linker
290 .type dyna_linker, %function
291dyna_linker:
292 /* r0 = virtual target address */
293 /* r1 = instruction to patch */
294 dyna_linker_main
295
57871462 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 */
76f71c27 340 dyna_linker_main
341
57871462 342 mov r4, r0
343 bic r0, r0, #7
344 mov r5, r1
345 orr r0, r0, #1
346 bl new_recompile_block
347 tst r0, r0
348 mov r0, r4
349 mov r1, r5
350 beq dyna_linker_ds
351 /* pagefault */
352 bic r1, r0, #7
353 mov r2, #0x80000008 /* High bit set indicates pagefault in delay slot */
354 sub r0, r1, #4
355 b exec_pagefault
356 .size dyna_linker_ds, .-dyna_linker_ds
357.jiptr:
358 .word jump_in
359.jdptr:
360 .word jump_dirty
57871462 361.htptr:
362 .word hash_table
7139f3c8 363
57871462 364 .align 2
365 .global jump_vaddr_r0
366 .type jump_vaddr_r0, %function
367jump_vaddr_r0:
368 eor r2, r0, r0, lsl #16
369 b jump_vaddr
370 .size jump_vaddr_r0, .-jump_vaddr_r0
371 .global jump_vaddr_r1
372 .type jump_vaddr_r1, %function
373jump_vaddr_r1:
374 eor r2, r1, r1, lsl #16
375 mov r0, r1
376 b jump_vaddr
377 .size jump_vaddr_r1, .-jump_vaddr_r1
378 .global jump_vaddr_r2
379 .type jump_vaddr_r2, %function
380jump_vaddr_r2:
381 mov r0, r2
382 eor r2, r2, r2, lsl #16
383 b jump_vaddr
384 .size jump_vaddr_r2, .-jump_vaddr_r2
385 .global jump_vaddr_r3
386 .type jump_vaddr_r3, %function
387jump_vaddr_r3:
388 eor r2, r3, r3, lsl #16
389 mov r0, r3
390 b jump_vaddr
391 .size jump_vaddr_r3, .-jump_vaddr_r3
392 .global jump_vaddr_r4
393 .type jump_vaddr_r4, %function
394jump_vaddr_r4:
395 eor r2, r4, r4, lsl #16
396 mov r0, r4
397 b jump_vaddr
398 .size jump_vaddr_r4, .-jump_vaddr_r4
399 .global jump_vaddr_r5
400 .type jump_vaddr_r5, %function
401jump_vaddr_r5:
402 eor r2, r5, r5, lsl #16
403 mov r0, r5
404 b jump_vaddr
405 .size jump_vaddr_r5, .-jump_vaddr_r5
406 .global jump_vaddr_r6
407 .type jump_vaddr_r6, %function
408jump_vaddr_r6:
409 eor r2, r6, r6, lsl #16
410 mov r0, r6
411 b jump_vaddr
412 .size jump_vaddr_r6, .-jump_vaddr_r6
413 .global jump_vaddr_r8
414 .type jump_vaddr_r8, %function
415jump_vaddr_r8:
416 eor r2, r8, r8, lsl #16
417 mov r0, r8
418 b jump_vaddr
419 .size jump_vaddr_r8, .-jump_vaddr_r8
420 .global jump_vaddr_r9
421 .type jump_vaddr_r9, %function
422jump_vaddr_r9:
423 eor r2, r9, r9, lsl #16
424 mov r0, r9
425 b jump_vaddr
426 .size jump_vaddr_r9, .-jump_vaddr_r9
427 .global jump_vaddr_r10
428 .type jump_vaddr_r10, %function
429jump_vaddr_r10:
430 eor r2, r10, r10, lsl #16
431 mov r0, r10
432 b jump_vaddr
433 .size jump_vaddr_r10, .-jump_vaddr_r10
434 .global jump_vaddr_r12
435 .type jump_vaddr_r12, %function
436jump_vaddr_r12:
437 eor r2, r12, r12, lsl #16
438 mov r0, r12
439 b jump_vaddr
440 .size jump_vaddr_r12, .-jump_vaddr_r12
441 .global jump_vaddr_r7
442 .type jump_vaddr_r7, %function
443jump_vaddr_r7:
444 eor r2, r7, r7, lsl #16
445 add r0, r7, #0
446 .size jump_vaddr_r7, .-jump_vaddr_r7
447 .global jump_vaddr
448 .type jump_vaddr, %function
449jump_vaddr:
450 ldr r1, .htptr
451 mvn r3, #15
452 and r2, r3, r2, lsr #12
453 ldr r2, [r1, r2]!
454 teq r2, r0
455 ldreq pc, [r1, #4]
456 ldr r2, [r1, #8]
457 teq r2, r0
458 ldreq pc, [r1, #12]
459 str r10, [fp, #cycle_count-dynarec_local]
460 bl get_addr
461 ldr r10, [fp, #cycle_count-dynarec_local]
462 mov pc, r0
463 .size jump_vaddr, .-jump_vaddr
7139f3c8 464
57871462 465 .align 2
466 .global verify_code_ds
467 .type verify_code_ds, %function
468verify_code_ds:
469 str r8, [fp, #branch_target-dynarec_local]
470 .size verify_code_ds, .-verify_code_ds
471 .global verify_code_vm
472 .type verify_code_vm, %function
473verify_code_vm:
57871462 474 .global verify_code
475 .type verify_code, %function
476verify_code:
477 /* r1 = source */
478 /* r2 = target */
479 /* r3 = length */
480 tst r3, #4
481 mov r4, #0
482 add r3, r1, r3
483 mov r5, #0
484 ldrne r4, [r1], #4
485 mov r12, #0
486 ldrne r5, [r2], #4
487 teq r1, r3
488 beq .D3
489.D2:
490 ldr r7, [r1], #4
491 eor r9, r4, r5
492 ldr r8, [r2], #4
493 orrs r9, r9, r12
494 bne .D4
495 ldr r4, [r1], #4
496 eor r12, r7, r8
497 ldr r5, [r2], #4
498 cmp r1, r3
499 bcc .D2
500 teq r7, r8
501.D3:
502 teqeq r4, r5
503.D4:
504 ldr r8, [fp, #branch_target-dynarec_local]
505 moveq pc, lr
506.D5:
507 bl get_addr
508 mov pc, r0
509 .size verify_code, .-verify_code
7139f3c8 510 .size verify_code_vm, .-verify_code_vm
511
57871462 512 .align 2
513 .global cc_interrupt
514 .type cc_interrupt, %function
515cc_interrupt:
516 ldr r0, [fp, #last_count-dynarec_local]
517 mov r1, #0
518 mov r2, #0x1fc
519 add r10, r0, r10
520 str r1, [fp, #pending_exception-dynarec_local]
521 and r2, r2, r10, lsr #17
522 add r3, fp, #restore_candidate-dynarec_local
822b27d1 523 str r10, [fp, #cycle-dynarec_local] /* PCSX cycles */
524@@ str r10, [fp, #reg_cop0+36-dynarec_local] /* Count */
57871462 525 ldr r4, [r2, r3]
526 mov r10, lr
527 tst r4, r4
528 bne .E4
529.E1:
530 bl gen_interupt
531 mov lr, r10
822b27d1 532 ldr r10, [fp, #cycle-dynarec_local]
57871462 533 ldr r0, [fp, #next_interupt-dynarec_local]
534 ldr r1, [fp, #pending_exception-dynarec_local]
535 ldr r2, [fp, #stop-dynarec_local]
536 str r0, [fp, #last_count-dynarec_local]
537 sub r10, r10, r0
538 tst r2, r2
b021ee75 539 ldmnefd sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}
57871462 540 tst r1, r1
541 moveq pc, lr
542.E2:
543 ldr r0, [fp, #pcaddr-dynarec_local]
544 bl get_addr_ht
545 mov pc, r0
57871462 546.E4:
547 /* Move 'dirty' blocks to the 'clean' list */
548 lsl r5, r2, #3
549 str r1, [r2, r3]
550.E5:
551 lsrs r4, r4, #1
552 mov r0, r5
553 add r5, r5, #1
554 blcs clean_blocks
555 tst r5, #31
556 bne .E5
557 b .E1
57871462 558 .size cc_interrupt, .-cc_interrupt
7139f3c8 559
57871462 560 .align 2
561 .global do_interrupt
562 .type do_interrupt, %function
563do_interrupt:
564 ldr r0, [fp, #pcaddr-dynarec_local]
565 bl get_addr_ht
57871462 566 add r10, r10, #2
567 mov pc, r0
568 .size do_interrupt, .-do_interrupt
fca1aef2 569
57871462 570 .align 2
571 .global fp_exception
572 .type fp_exception, %function
573fp_exception:
574 mov r2, #0x10000000
575.E7:
576 ldr r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
577 mov r3, #0x80000000
578 str r0, [fp, #reg_cop0+56-dynarec_local] /* EPC */
579 orr r1, #2
580 add r2, r2, #0x2c
581 str r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
582 str r2, [fp, #reg_cop0+52-dynarec_local] /* Cause */
7139f3c8 583 add r0, r3, #0x80
57871462 584 bl get_addr_ht
585 mov pc, r0
586 .size fp_exception, .-fp_exception
587 .align 2
588 .global fp_exception_ds
589 .type fp_exception_ds, %function
590fp_exception_ds:
591 mov r2, #0x90000000 /* Set high bit if delay slot */
592 b .E7
593 .size fp_exception_ds, .-fp_exception_ds
7139f3c8 594
57871462 595 .align 2
596 .global jump_syscall
597 .type jump_syscall, %function
598jump_syscall:
599 ldr r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
600 mov r3, #0x80000000
601 str r0, [fp, #reg_cop0+56-dynarec_local] /* EPC */
602 orr r1, #2
603 mov r2, #0x20
604 str r1, [fp, #reg_cop0+48-dynarec_local] /* Status */
605 str r2, [fp, #reg_cop0+52-dynarec_local] /* Cause */
7139f3c8 606 add r0, r3, #0x80
57871462 607 bl get_addr_ht
608 mov pc, r0
609 .size jump_syscall, .-jump_syscall
7139f3c8 610 .align 2
611
612 .align 2
613 .global jump_syscall_hle
614 .type jump_syscall_hle, %function
615jump_syscall_hle:
616 str r0, [fp, #pcaddr-dynarec_local] /* PC must be set to EPC for psxException */
617 ldr r2, [fp, #last_count-dynarec_local]
618 mov r1, #0 /* in delay slot */
619 add r2, r2, r10
620 mov r0, #0x20 /* cause */
621 str r2, [fp, #cycle-dynarec_local] /* PCSX cycle counter */
7139f3c8 622 bl psxException
623
624 /* note: psxException might do recorsive recompiler call from it's HLE code,
625 * so be ready for this */
822b27d1 626pcsx_return:
627 ldr r1, [fp, #next_interupt-dynarec_local]
628 ldr r10, [fp, #cycle-dynarec_local]
7139f3c8 629 ldr r0, [fp, #pcaddr-dynarec_local]
822b27d1 630 sub r10, r10, r1
631 str r1, [fp, #last_count-dynarec_local]
7139f3c8 632 bl get_addr_ht
633 mov pc, r0
634 .size jump_syscall_hle, .-jump_syscall_hle
635
636 .align 2
637 .global jump_hlecall
638 .type jump_hlecall, %function
639jump_hlecall:
640 ldr r2, [fp, #last_count-dynarec_local]
641 str r0, [fp, #pcaddr-dynarec_local]
7139f3c8 642 add r2, r2, r10
822b27d1 643 adr lr, pcsx_return
0d16cda2 644 str r2, [fp, #cycle-dynarec_local] /* PCSX cycle counter */
67ba0fb4 645 bx r1
7139f3c8 646 .size jump_hlecall, .-jump_hlecall
647
0d16cda2 648 .align 2
649 .global jump_intcall
650 .type jump_intcall, %function
651jump_intcall:
652 ldr r2, [fp, #last_count-dynarec_local]
653 str r0, [fp, #pcaddr-dynarec_local]
654 add r2, r2, r10
655 adr lr, pcsx_return
656 str r2, [fp, #cycle-dynarec_local] /* PCSX cycle counter */
657 b execI
658 .size jump_hlecall, .-jump_hlecall
659
7139f3c8 660new_dyna_leave:
661 .align 2
662 .global new_dyna_leave
663 .type new_dyna_leave, %function
664 ldr r0, [fp, #last_count-dynarec_local]
665 add r12, fp, #28
666 add r10, r0, r10
822b27d1 667 str r10, [fp, #cycle-dynarec_local]
b021ee75 668 ldmfd sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}
7139f3c8 669 .size new_dyna_leave, .-new_dyna_leave
670
0bbd1454 671 .align 2
672 .global invalidate_addr_r0
673 .type invalidate_addr_r0, %function
674invalidate_addr_r0:
675 stmia fp, {r0, r1, r2, r3, r12, lr}
0bbd1454 676 b invalidate_addr_call
677 .size invalidate_addr_r0, .-invalidate_addr_r0
678 .align 2
679 .global invalidate_addr_r1
680 .type invalidate_addr_r1, %function
681invalidate_addr_r1:
682 stmia fp, {r0, r1, r2, r3, r12, lr}
9be4ba64 683 mov r0, r1
0bbd1454 684 b invalidate_addr_call
685 .size invalidate_addr_r1, .-invalidate_addr_r1
686 .align 2
687 .global invalidate_addr_r2
688 .type invalidate_addr_r2, %function
689invalidate_addr_r2:
690 stmia fp, {r0, r1, r2, r3, r12, lr}
9be4ba64 691 mov r0, r2
0bbd1454 692 b invalidate_addr_call
693 .size invalidate_addr_r2, .-invalidate_addr_r2
694 .align 2
695 .global invalidate_addr_r3
696 .type invalidate_addr_r3, %function
697invalidate_addr_r3:
698 stmia fp, {r0, r1, r2, r3, r12, lr}
9be4ba64 699 mov r0, r3
0bbd1454 700 b invalidate_addr_call
701 .size invalidate_addr_r3, .-invalidate_addr_r3
702 .align 2
703 .global invalidate_addr_r4
704 .type invalidate_addr_r4, %function
705invalidate_addr_r4:
706 stmia fp, {r0, r1, r2, r3, r12, lr}
9be4ba64 707 mov r0, r4
0bbd1454 708 b invalidate_addr_call
709 .size invalidate_addr_r4, .-invalidate_addr_r4
710 .align 2
711 .global invalidate_addr_r5
712 .type invalidate_addr_r5, %function
713invalidate_addr_r5:
714 stmia fp, {r0, r1, r2, r3, r12, lr}
9be4ba64 715 mov r0, r5
0bbd1454 716 b invalidate_addr_call
717 .size invalidate_addr_r5, .-invalidate_addr_r5
718 .align 2
719 .global invalidate_addr_r6
720 .type invalidate_addr_r6, %function
721invalidate_addr_r6:
722 stmia fp, {r0, r1, r2, r3, r12, lr}
9be4ba64 723 mov r0, r6
0bbd1454 724 b invalidate_addr_call
725 .size invalidate_addr_r6, .-invalidate_addr_r6
726 .align 2
727 .global invalidate_addr_r7
728 .type invalidate_addr_r7, %function
729invalidate_addr_r7:
730 stmia fp, {r0, r1, r2, r3, r12, lr}
9be4ba64 731 mov r0, r7
0bbd1454 732 b invalidate_addr_call
733 .size invalidate_addr_r7, .-invalidate_addr_r7
734 .align 2
735 .global invalidate_addr_r8
736 .type invalidate_addr_r8, %function
737invalidate_addr_r8:
738 stmia fp, {r0, r1, r2, r3, r12, lr}
9be4ba64 739 mov r0, r8
0bbd1454 740 b invalidate_addr_call
741 .size invalidate_addr_r8, .-invalidate_addr_r8
742 .align 2
743 .global invalidate_addr_r9
744 .type invalidate_addr_r9, %function
745invalidate_addr_r9:
746 stmia fp, {r0, r1, r2, r3, r12, lr}
9be4ba64 747 mov r0, r9
0bbd1454 748 b invalidate_addr_call
749 .size invalidate_addr_r9, .-invalidate_addr_r9
750 .align 2
751 .global invalidate_addr_r10
752 .type invalidate_addr_r10, %function
753invalidate_addr_r10:
754 stmia fp, {r0, r1, r2, r3, r12, lr}
9be4ba64 755 mov r0, r10
0bbd1454 756 b invalidate_addr_call
757 .size invalidate_addr_r10, .-invalidate_addr_r10
758 .align 2
759 .global invalidate_addr_r12
760 .type invalidate_addr_r12, %function
761invalidate_addr_r12:
762 stmia fp, {r0, r1, r2, r3, r12, lr}
9be4ba64 763 mov r0, r12
0bbd1454 764 .size invalidate_addr_r12, .-invalidate_addr_r12
765 .align 2
766 .global invalidate_addr_call
767 .type invalidate_addr_call, %function
768invalidate_addr_call:
9be4ba64 769 ldr r12, [fp, #inv_code_start-dynarec_local]
770 ldr lr, [fp, #inv_code_end-dynarec_local]
771 cmp r0, r12
772 cmpcs lr, r0
773 blcc invalidate_addr
0bbd1454 774 ldmia fp, {r0, r1, r2, r3, r12, pc}
775 .size invalidate_addr_call, .-invalidate_addr_call
776
57871462 777 .align 2
778 .global new_dyna_start
779 .type new_dyna_start, %function
780new_dyna_start:
b021ee75 781 /* ip is stored to conform EABI alignment */
782 stmfd sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
274c4243 783 load_var_adr fp, dynarec_local
7139f3c8 784 ldr r0, [fp, #pcaddr-dynarec_local]
7139f3c8 785 bl get_addr_ht
786 ldr r1, [fp, #next_interupt-dynarec_local]
822b27d1 787 ldr r10, [fp, #cycle-dynarec_local]
7139f3c8 788 str r1, [fp, #last_count-dynarec_local]
789 sub r10, r10, r1
790 mov pc, r0
57871462 791 .size new_dyna_start, .-new_dyna_start
7139f3c8 792
7e605697 793/* --------------------------------------- */
7139f3c8 794
7e605697 795.align 2
c6c3b1b3 796.global jump_handler_read8
797.global jump_handler_read16
798.global jump_handler_read32
b96d3df7 799.global jump_handler_write8
800.global jump_handler_write16
801.global jump_handler_write32
802.global jump_handler_write_h
803.global jump_handle_swl
804.global jump_handle_swr
b1be1eee 805.global rcnt0_read_count_m0
806.global rcnt0_read_count_m1
807.global rcnt1_read_count_m0
808.global rcnt1_read_count_m1
809.global rcnt2_read_count_m0
810.global rcnt2_read_count_m1
7139f3c8 811
c6c3b1b3 812
813.macro pcsx_read_mem readop tab_shift
814 /* r0 = address, r1 = handler_tab, r2 = cycles */
815 lsl r3, r0, #20
816 lsr r3, #(20+\tab_shift)
817 ldr r12, [fp, #last_count-dynarec_local]
818 ldr r1, [r1, r3, lsl #2]
819 add r2, r2, r12
820 lsls r1, #1
821.if \tab_shift == 1
822 lsl r3, #1
823 \readop r0, [r1, r3]
824.else
825 \readop r0, [r1, r3, lsl #\tab_shift]
826.endif
827 movcc pc, lr
828 str r2, [fp, #cycle-dynarec_local]
829 bx r1
830.endm
831
832jump_handler_read8:
833 add r1, #0x1000/4*4 + 0x1000/2*4 @ shift to r8 part
834 pcsx_read_mem ldrccb, 0
835
836jump_handler_read16:
837 add r1, #0x1000/4*4 @ shift to r16 part
838 pcsx_read_mem ldrcch, 1
839
840jump_handler_read32:
841 pcsx_read_mem ldrcc, 2
842
b96d3df7 843
844.macro pcsx_write_mem wrtop tab_shift
845 /* r0 = address, r1 = data, r2 = cycles, r3 = handler_tab */
846 lsl r12,r0, #20
847 lsr r12, #(20+\tab_shift)
848 ldr r3, [r3, r12, lsl #2]
849 str r0, [fp, #address-dynarec_local] @ some handlers still need it..
850 lsls r3, #1
851 mov r0, r2 @ cycle return in case of direct store
852.if \tab_shift == 1
853 lsl r12, #1
854 \wrtop r1, [r3, r12]
855.else
856 \wrtop r1, [r3, r12, lsl #\tab_shift]
857.endif
858 movcc pc, lr
859 ldr r12, [fp, #last_count-dynarec_local]
860 mov r0, r1
861 add r2, r2, r12
862 push {r2, lr}
863 str r2, [fp, #cycle-dynarec_local]
864 blx r3
865
866 ldr r0, [fp, #next_interupt-dynarec_local]
867 pop {r2, r3}
868 str r0, [fp, #last_count-dynarec_local]
869 sub r0, r2, r0
870 bx r3
871.endm
872
873jump_handler_write8:
874 add r3, #0x1000/4*4 + 0x1000/2*4 @ shift to r8 part
875 pcsx_write_mem strccb, 0
876
877jump_handler_write16:
878 add r3, #0x1000/4*4 @ shift to r16 part
879 pcsx_write_mem strcch, 1
880
881jump_handler_write32:
882 pcsx_write_mem strcc, 2
883
884jump_handler_write_h:
885 /* r0 = address, r1 = data, r2 = cycles, r3 = handler */
886 ldr r12, [fp, #last_count-dynarec_local]
887 str r0, [fp, #address-dynarec_local] @ some handlers still need it..
888 add r2, r2, r12
889 mov r0, r1
890 push {r2, lr}
891 str r2, [fp, #cycle-dynarec_local]
892 blx r3
893
894 ldr r0, [fp, #next_interupt-dynarec_local]
895 pop {r2, r3}
896 str r0, [fp, #last_count-dynarec_local]
897 sub r0, r2, r0
898 bx r3
899
900jump_handle_swl:
901 /* r0 = address, r1 = data, r2 = cycles */
902 ldr r3, [fp, #mem_wtab-dynarec_local]
903 mov r12,r0,lsr #12
904 ldr r3, [r3, r12, lsl #2]
905 lsls r3, #1
906 bcs 4f
907 add r3, r0, r3
908 mov r0, r2
909 tst r3, #2
910 beq 101f
911 tst r3, #1
912 beq 2f
9133:
914 str r1, [r3, #-3]
915 bx lr
9162:
917 lsr r2, r1, #8
918 lsr r1, #24
919 strh r2, [r3, #-2]
920 strb r1, [r3]
921 bx lr
922101:
923 tst r3, #1
924 lsrne r1, #16 @ 1
925 lsreq r12, r1, #24 @ 0
926 strneh r1, [r3, #-1]
927 streqb r12, [r3]
928 bx lr
9294:
930 mov r0, r2
63cb0298 931@ b abort
b96d3df7 932 bx lr @ TODO?
933
934
935jump_handle_swr:
936 /* r0 = address, r1 = data, r2 = cycles */
937 ldr r3, [fp, #mem_wtab-dynarec_local]
938 mov r12,r0,lsr #12
939 ldr r3, [r3, r12, lsl #2]
940 lsls r3, #1
941 bcs 4f
942 add r3, r0, r3
943 and r12,r3, #3
944 mov r0, r2
945 cmp r12,#2
946 strgtb r1, [r3] @ 3
947 streqh r1, [r3] @ 2
948 cmp r12,#1
949 strlt r1, [r3] @ 0
950 bxne lr
951 lsr r2, r1, #8 @ 1
952 strb r1, [r3]
953 strh r2, [r3, #1]
954 bx lr
9554:
956 mov r0, r2
63cb0298 957@ b abort
b96d3df7 958 bx lr @ TODO?
959
960
b1be1eee 961.macro rcntx_read_mode0 num
962 /* r0 = address, r2 = cycles */
963 ldr r3, [fp, #rcnts-dynarec_local+6*4+7*4*\num] @ cycleStart
964 mov r0, r2, lsl #16
965 sub r0, r3, lsl #16
966 lsr r0, #16
967 bx lr
968.endm
969
970rcnt0_read_count_m0:
971 rcntx_read_mode0 0
972
973rcnt1_read_count_m0:
974 rcntx_read_mode0 1
975
976rcnt2_read_count_m0:
977 rcntx_read_mode0 2
978
979rcnt0_read_count_m1:
980 /* r0 = address, r2 = cycles */
981 ldr r3, [fp, #rcnts-dynarec_local+6*4+7*4*0] @ cycleStart
982 mov_16 r1, 0x3334
983 sub r2, r2, r3
984 mul r0, r1, r2 @ /= 5
985 lsr r0, #16
986 bx lr
987
988rcnt1_read_count_m1:
989 /* r0 = address, r2 = cycles */
990 ldr r3, [fp, #rcnts-dynarec_local+6*4+7*4*1]
991 mov_24 r1, 0x1e6cde
992 sub r2, r2, r3
993 umull r3, r0, r1, r2 @ ~ /= hsync_cycles, max ~0x1e6cdd
994 bx lr
995
996rcnt2_read_count_m1:
997 /* r0 = address, r2 = cycles */
998 ldr r3, [fp, #rcnts-dynarec_local+6*4+7*4*2]
999 mov r0, r2, lsl #16-3
1000 sub r0, r3, lsl #16-3
1001 lsr r0, #16 @ /= 8
1002 bx lr
1003
7e605697 1004@ vim:filetype=armasm