drc: don't delay block restoration
[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 *
b1f89e6f 4 * Copyright (C) 2010-2013 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
665f33e1 22#include "arm_features.h"
d148d265 23#include "new_dynarec_config.h"
b1f89e6f 24#include "linkage_offsets.h"
25
26
27#ifdef __MACH__
28#define dynarec_local ESYM(dynarec_local)
3d680478 29#define add_jump_out ESYM(add_jump_out)
b1f89e6f 30#define new_recompile_block ESYM(new_recompile_block)
398d6924 31#define ndrc_try_restore_block ESYM(ndrc_try_restore_block)
b1f89e6f 32#define get_addr ESYM(get_addr)
33#define get_addr_ht ESYM(get_addr_ht)
b1f89e6f 34#define gen_interupt ESYM(gen_interupt)
b1f89e6f 35#define invalidate_addr ESYM(invalidate_addr)
81dbbf4c 36#define gteCheckStallRaw ESYM(gteCheckStallRaw)
d1150cd6 37#define psxException ESYM(psxException)
b1f89e6f 38#endif
f95a77f7 39
57871462 40 .bss
41 .align 4
b1f89e6f 42 .global dynarec_local
57871462 43 .type dynarec_local, %object
b1f89e6f 44 .size dynarec_local, LO_dynarec_local_size
57871462 45dynarec_local:
b1f89e6f 46 .space LO_dynarec_local_size
47
48#define DRC_VAR_(name, vname, size_) \
49 vname = dynarec_local + LO_##name; \
50 .global vname; \
51 .type vname, %object; \
52 .size vname, size_
53
54#define DRC_VAR(name, size_) \
55 DRC_VAR_(name, ESYM(name), size_)
56
57DRC_VAR(next_interupt, 4)
58DRC_VAR(cycle_count, 4)
59DRC_VAR(last_count, 4)
60DRC_VAR(pending_exception, 4)
61DRC_VAR(stop, 4)
687b4580 62DRC_VAR(branch_target, 4)
b1f89e6f 63DRC_VAR(address, 4)
7f94b097 64DRC_VAR(hack_addr, 4)
b1f89e6f 65DRC_VAR(psxRegs, LO_psxRegs_end - LO_psxRegs)
f95a77f7 66
67/* psxRegs */
7c3a5182 68@DRC_VAR(reg, 128)
b1f89e6f 69DRC_VAR(lo, 4)
70DRC_VAR(hi, 4)
71DRC_VAR(reg_cop0, 128)
72DRC_VAR(reg_cop2d, 128)
73DRC_VAR(reg_cop2c, 128)
74DRC_VAR(pcaddr, 4)
75@DRC_VAR(code, 4)
76@DRC_VAR(cycle, 4)
77@DRC_VAR(interrupt, 4)
78@DRC_VAR(intCycle, 256)
79
80DRC_VAR(rcnts, 7*4*4)
687b4580 81DRC_VAR(inv_code_start, 4)
82DRC_VAR(inv_code_end, 4)
b1f89e6f 83DRC_VAR(mem_rtab, 4)
84DRC_VAR(mem_wtab, 4)
85DRC_VAR(psxH_ptr, 4)
86DRC_VAR(zeromem_ptr, 4)
687b4580 87DRC_VAR(invc_ptr, 4)
c6d5790c 88DRC_VAR(scratch_buf_ptr, 4)
37387d8b 89DRC_VAR(ram_offset, 4)
b1f89e6f 90DRC_VAR(mini_ht, 256)
63cb0298 91
57871462 92
0e4ad319 93#ifdef TEXRELS_FORBIDDEN
b861c0a9 94 .data
95 .align 2
96ptr_jump_in:
97 .word ESYM(jump_in)
b861c0a9 98ptr_hash_table:
99 .word ESYM(hash_table)
100#endif
101
102
103 .syntax unified
104 .text
105 .align 2
106
665f33e1 107#ifndef HAVE_ARMV5
108.macro blx rd
109 mov lr, pc
110 bx \rd
111.endm
112#endif
113
c67af2ac 114.macro load_varadr reg var
0e4ad319 115#if defined(HAVE_ARMV7) && defined(TEXRELS_FORBIDDEN)
1f4e070a 116 movw \reg, #:lower16:(\var-(1678f+8))
117 movt \reg, #:upper16:(\var-(1678f+8))
b861c0a9 1181678:
119 add \reg, pc
0e4ad319 120#elif defined(HAVE_ARMV7) && !defined(__PIC__)
121 movw \reg, #:lower16:\var
122 movt \reg, #:upper16:\var
c67af2ac 123#else
274c4243 124 ldr \reg, =\var
c67af2ac 125#endif
274c4243 126.endm
127
b861c0a9 128.macro load_varadr_ext reg var
0e4ad319 129#if defined(HAVE_ARMV7) && defined(TEXRELS_FORBIDDEN)
1f4e070a 130 movw \reg, #:lower16:(ptr_\var-(1678f+8))
131 movt \reg, #:upper16:(ptr_\var-(1678f+8))
b861c0a9 1321678:
133 ldr \reg, [pc, \reg]
134#else
135 load_varadr \reg \var
136#endif
137.endm
138
b1be1eee 139.macro mov_16 reg imm
8f2bb0cb 140#ifdef HAVE_ARMV7
b1be1eee 141 movw \reg, #\imm
c67af2ac 142#else
b1be1eee 143 mov \reg, #(\imm & 0x00ff)
144 orr \reg, #(\imm & 0xff00)
c67af2ac 145#endif
b1be1eee 146.endm
147
148.macro mov_24 reg imm
8f2bb0cb 149#ifdef HAVE_ARMV7
b1be1eee 150 movw \reg, #(\imm & 0xffff)
151 movt \reg, #(\imm >> 16)
c67af2ac 152#else
b1be1eee 153 mov \reg, #(\imm & 0x0000ff)
154 orr \reg, #(\imm & 0x00ff00)
155 orr \reg, #(\imm & 0xff0000)
c67af2ac 156#endif
b1be1eee 157.endm
158
398d6924 159/* r4 = virtual target address */
160/* r5 = instruction to patch */
76f71c27 161.macro dyna_linker_main
d148d265 162#ifndef NO_WRITE_EXEC
b861c0a9 163 load_varadr_ext r3, jump_in
f968d35d 164 /* get_page */
398d6924 165 lsr r2, r4, #12
f968d35d 166 mov r6, #4096
167 bic r2, r2, #0xe0000
57871462 168 sub r6, r6, #1
f968d35d 169 cmp r2, #0x1000
398d6924 170 ldr r7, [r5]
f968d35d 171 biclt r2, #0x0e00
172 and r6, r6, r2
57871462 173 cmp r2, #2048
174 add r12, r7, #2
175 orrcs r2, r6, #2048
398d6924 176 ldr r1, [r3, r2, lsl #2]
57871462 177 lsl r12, r12, #8
398d6924 178 add r6, r5, r12, asr #6 /* old target */
76f71c27 179 mov r8, #0
57871462 180 /* jump_in lookup */
76f71c27 1811:
398d6924 182 movs r0, r1
76f71c27 183 beq 2f
398d6924 184 ldr r3, [r1] /* ll_entry .vaddr */
185 ldrd r0, r1, [r0, #8] /* ll_entry .addr, .next */
186 teq r3, r4
76f71c27 187 bne 1b
398d6924 188 teq r0, r6
189 moveq pc, r0 /* Stale i-cache */
190 mov r8, r0
76f71c27 191 b 1b /* jump_in may have dupes, continue search */
1922:
193 tst r8, r8
398d6924 194 beq 3f /* r4 not in jump_in */
76f71c27 195
398d6924 196 mov r0, r4
76f71c27 197 mov r1, r6
3d680478 198 bl add_jump_out
76f71c27 199 sub r2, r8, r5
57871462 200 and r1, r7, #0xff000000
201 lsl r2, r2, #6
202 sub r1, r1, #2
203 add r1, r1, r2, lsr #8
204 str r1, [r5]
76f71c27 205 mov pc, r8
2063:
398d6924 207 mov r0, r4
208 bl ndrc_try_restore_block
209 tst r0, r0
210 movne pc, r0
d148d265 211#else
212 /* XXX: should be able to do better than this... */
398d6924 213 mov r0, r4
d148d265 214 bl get_addr_ht
215 mov pc, r0
216#endif
76f71c27 217.endm
218
5c6457c3 219
220FUNCTION(dyna_linker):
76f71c27 221 /* r0 = virtual target address */
222 /* r1 = instruction to patch */
57871462 223 mov r4, r0
224 mov r5, r1
398d6924 22510:
226 dyna_linker_main
227
228 mov r0, r4
57871462 229 bl new_recompile_block
230 tst r0, r0
398d6924 231 beq 10b
232
57871462 233 /* pagefault */
398d6924 234 mov r0, r4
57871462 235 mov r1, r0
b4ab351d 236 mov r2, #(4<<2) /* Address error (fetch) */
57871462 237 .size dyna_linker, .-dyna_linker
5c6457c3 238
239FUNCTION(exec_pagefault):
57871462 240 /* r0 = instruction pointer */
241 /* r1 = fault address */
242 /* r2 = cause */
b1f89e6f 243 ldr r3, [fp, #LO_reg_cop0+48] /* Status */
b1f89e6f 244 str r0, [fp, #LO_reg_cop0+56] /* EPC */
57871462 245 orr r3, r3, #2
b1f89e6f 246 str r1, [fp, #LO_reg_cop0+32] /* BadVAddr */
b1f89e6f 247 str r3, [fp, #LO_reg_cop0+48] /* Status */
b1f89e6f 248 str r2, [fp, #LO_reg_cop0+52] /* Cause */
57871462 249 mov r0, #0x80000000
b4ab351d 250 orr r0, r0, #0x80
57871462 251 bl get_addr_ht
252 mov pc, r0
253 .size exec_pagefault, .-exec_pagefault
7139f3c8 254
57871462 255/* Special dynamic linker for the case where a page fault
256 may occur in a branch delay slot */
5c6457c3 257FUNCTION(dyna_linker_ds):
57871462 258 /* r0 = virtual target address */
259 /* r1 = instruction to patch */
57871462 260 mov r4, r0
57871462 261 mov r5, r1
398d6924 26210:
263 dyna_linker_main
264
265 bic r0, r4, #7
57871462 266 orr r0, r0, #1
267 bl new_recompile_block
268 tst r0, r0
398d6924 269 beq 10b
270
57871462 271 /* pagefault */
398d6924 272 mov r0, r4
57871462 273 bic r1, r0, #7
274 mov r2, #0x80000008 /* High bit set indicates pagefault in delay slot */
275 sub r0, r1, #4
276 b exec_pagefault
277 .size dyna_linker_ds, .-dyna_linker_ds
7139f3c8 278
57871462 279 .align 2
5c6457c3 280
281FUNCTION(jump_vaddr_r0):
57871462 282 eor r2, r0, r0, lsl #16
283 b jump_vaddr
284 .size jump_vaddr_r0, .-jump_vaddr_r0
5c6457c3 285FUNCTION(jump_vaddr_r1):
57871462 286 eor r2, r1, r1, lsl #16
287 mov r0, r1
288 b jump_vaddr
289 .size jump_vaddr_r1, .-jump_vaddr_r1
5c6457c3 290FUNCTION(jump_vaddr_r2):
57871462 291 mov r0, r2
292 eor r2, r2, r2, lsl #16
293 b jump_vaddr
294 .size jump_vaddr_r2, .-jump_vaddr_r2
5c6457c3 295FUNCTION(jump_vaddr_r3):
57871462 296 eor r2, r3, r3, lsl #16
297 mov r0, r3
298 b jump_vaddr
299 .size jump_vaddr_r3, .-jump_vaddr_r3
5c6457c3 300FUNCTION(jump_vaddr_r4):
57871462 301 eor r2, r4, r4, lsl #16
302 mov r0, r4
303 b jump_vaddr
304 .size jump_vaddr_r4, .-jump_vaddr_r4
5c6457c3 305FUNCTION(jump_vaddr_r5):
57871462 306 eor r2, r5, r5, lsl #16
307 mov r0, r5
308 b jump_vaddr
309 .size jump_vaddr_r5, .-jump_vaddr_r5
5c6457c3 310FUNCTION(jump_vaddr_r6):
57871462 311 eor r2, r6, r6, lsl #16
312 mov r0, r6
313 b jump_vaddr
314 .size jump_vaddr_r6, .-jump_vaddr_r6
5c6457c3 315FUNCTION(jump_vaddr_r8):
57871462 316 eor r2, r8, r8, lsl #16
317 mov r0, r8
318 b jump_vaddr
319 .size jump_vaddr_r8, .-jump_vaddr_r8
5c6457c3 320FUNCTION(jump_vaddr_r9):
57871462 321 eor r2, r9, r9, lsl #16
322 mov r0, r9
323 b jump_vaddr
324 .size jump_vaddr_r9, .-jump_vaddr_r9
5c6457c3 325FUNCTION(jump_vaddr_r10):
57871462 326 eor r2, r10, r10, lsl #16
327 mov r0, r10
328 b jump_vaddr
329 .size jump_vaddr_r10, .-jump_vaddr_r10
5c6457c3 330FUNCTION(jump_vaddr_r12):
57871462 331 eor r2, r12, r12, lsl #16
332 mov r0, r12
333 b jump_vaddr
334 .size jump_vaddr_r12, .-jump_vaddr_r12
5c6457c3 335FUNCTION(jump_vaddr_r7):
57871462 336 eor r2, r7, r7, lsl #16
337 add r0, r7, #0
338 .size jump_vaddr_r7, .-jump_vaddr_r7
5c6457c3 339FUNCTION(jump_vaddr):
b861c0a9 340 load_varadr_ext r1, hash_table
57871462 341 mvn r3, #15
342 and r2, r3, r2, lsr #12
343 ldr r2, [r1, r2]!
344 teq r2, r0
df4dc2b1 345 ldreq pc, [r1, #8]
346 ldr r2, [r1, #4]
57871462 347 teq r2, r0
348 ldreq pc, [r1, #12]
b1f89e6f 349 str r10, [fp, #LO_cycle_count]
57871462 350 bl get_addr
b1f89e6f 351 ldr r10, [fp, #LO_cycle_count]
57871462 352 mov pc, r0
353 .size jump_vaddr, .-jump_vaddr
7139f3c8 354
57871462 355 .align 2
5c6457c3 356
357FUNCTION(verify_code_ds):
3968e69e 358 str r8, [fp, #LO_branch_target] @ preserve HOST_BTREG?
5c6457c3 359FUNCTION(verify_code):
57871462 360 /* r1 = source */
361 /* r2 = target */
362 /* r3 = length */
363 tst r3, #4
364 mov r4, #0
365 add r3, r1, r3
366 mov r5, #0
367 ldrne r4, [r1], #4
368 mov r12, #0
369 ldrne r5, [r2], #4
370 teq r1, r3
371 beq .D3
372.D2:
373 ldr r7, [r1], #4
374 eor r9, r4, r5
375 ldr r8, [r2], #4
376 orrs r9, r9, r12
377 bne .D4
378 ldr r4, [r1], #4
379 eor r12, r7, r8
380 ldr r5, [r2], #4
381 cmp r1, r3
382 bcc .D2
383 teq r7, r8
384.D3:
385 teqeq r4, r5
386.D4:
b1f89e6f 387 ldr r8, [fp, #LO_branch_target]
57871462 388 moveq pc, lr
389.D5:
390 bl get_addr
391 mov pc, r0
392 .size verify_code, .-verify_code
7c3a5182 393 .size verify_code_ds, .-verify_code_ds
7139f3c8 394
57871462 395 .align 2
5c6457c3 396FUNCTION(cc_interrupt):
b1f89e6f 397 ldr r0, [fp, #LO_last_count]
57871462 398 mov r1, #0
57871462 399 add r10, r0, r10
b1f89e6f 400 str r1, [fp, #LO_pending_exception]
b1f89e6f 401 str r10, [fp, #LO_cycle] /* PCSX cycles */
b4ab351d 402@@ str r10, [fp, #LO_reg_cop0+36] /* Count - not on PSX */
57871462 403 mov r10, lr
398d6924 404
57871462 405 bl gen_interupt
406 mov lr, r10
b1f89e6f 407 ldr r10, [fp, #LO_cycle]
408 ldr r0, [fp, #LO_next_interupt]
409 ldr r1, [fp, #LO_pending_exception]
410 ldr r2, [fp, #LO_stop]
411 str r0, [fp, #LO_last_count]
57871462 412 sub r10, r10, r0
413 tst r2, r2
b861c0a9 414 ldmfdne sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}
57871462 415 tst r1, r1
416 moveq pc, lr
b1f89e6f 417 ldr r0, [fp, #LO_pcaddr]
57871462 418 bl get_addr_ht
419 mov pc, r0
57871462 420 .size cc_interrupt, .-cc_interrupt
7139f3c8 421
57871462 422 .align 2
5c6457c3 423FUNCTION(fp_exception):
57871462 424 mov r2, #0x10000000
425.E7:
b1f89e6f 426 ldr r1, [fp, #LO_reg_cop0+48] /* Status */
57871462 427 mov r3, #0x80000000
b1f89e6f 428 str r0, [fp, #LO_reg_cop0+56] /* EPC */
57871462 429 orr r1, #2
430 add r2, r2, #0x2c
b1f89e6f 431 str r1, [fp, #LO_reg_cop0+48] /* Status */
432 str r2, [fp, #LO_reg_cop0+52] /* Cause */
7139f3c8 433 add r0, r3, #0x80
57871462 434 bl get_addr_ht
435 mov pc, r0
436 .size fp_exception, .-fp_exception
437 .align 2
5c6457c3 438FUNCTION(fp_exception_ds):
57871462 439 mov r2, #0x90000000 /* Set high bit if delay slot */
440 b .E7
441 .size fp_exception_ds, .-fp_exception_ds
7139f3c8 442
57871462 443 .align 2
d1150cd6 444FUNCTION(jump_break_ds):
445 mov r0, #0x24
446 mov r1, #1
447 b call_psxException
448FUNCTION(jump_break):
449 mov r0, #0x24
450 mov r1, #0
451 b call_psxException
452FUNCTION(jump_syscall_ds):
453 mov r0, #0x20
454 mov r1, #1
455 b call_psxException
5c6457c3 456FUNCTION(jump_syscall):
d1150cd6 457 mov r0, #0x20
458 mov r1, #0
459
460call_psxException:
461 ldr r3, [fp, #LO_last_count]
462 str r2, [fp, #LO_pcaddr]
463 add r10, r3, r10
464 str r10, [fp, #LO_cycle] /* PCSX cycles */
465 bl psxException
7139f3c8 466
b1f89e6f 467 /* note: psxException might do recursive recompiler call from it's HLE code,
7139f3c8 468 * so be ready for this */
3968e69e 469FUNCTION(jump_to_new_pc):
b1f89e6f 470 ldr r1, [fp, #LO_next_interupt]
471 ldr r10, [fp, #LO_cycle]
472 ldr r0, [fp, #LO_pcaddr]
822b27d1 473 sub r10, r10, r1
b1f89e6f 474 str r1, [fp, #LO_last_count]
7139f3c8 475 bl get_addr_ht
476 mov pc, r0
3968e69e 477 .size jump_to_new_pc, .-jump_to_new_pc
0d16cda2 478
7139f3c8 479 .align 2
5c6457c3 480FUNCTION(new_dyna_leave):
b1f89e6f 481 ldr r0, [fp, #LO_last_count]
7139f3c8 482 add r12, fp, #28
483 add r10, r0, r10
b1f89e6f 484 str r10, [fp, #LO_cycle]
b021ee75 485 ldmfd sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}
7139f3c8 486 .size new_dyna_leave, .-new_dyna_leave
487
0bbd1454 488 .align 2
5c6457c3 489FUNCTION(invalidate_addr_r0):
5df0e313 490 stmia fp, {r0, r1, r2, r3, EXTRA_UNSAVED_REGS r12, lr}
0bbd1454 491 b invalidate_addr_call
492 .size invalidate_addr_r0, .-invalidate_addr_r0
493 .align 2
5c6457c3 494FUNCTION(invalidate_addr_r1):
5df0e313 495 stmia fp, {r0, r1, r2, r3, EXTRA_UNSAVED_REGS r12, lr}
9be4ba64 496 mov r0, r1
0bbd1454 497 b invalidate_addr_call
498 .size invalidate_addr_r1, .-invalidate_addr_r1
499 .align 2
5c6457c3 500FUNCTION(invalidate_addr_r2):
5df0e313 501 stmia fp, {r0, r1, r2, r3, EXTRA_UNSAVED_REGS r12, lr}
9be4ba64 502 mov r0, r2
0bbd1454 503 b invalidate_addr_call
504 .size invalidate_addr_r2, .-invalidate_addr_r2
505 .align 2
5c6457c3 506FUNCTION(invalidate_addr_r3):
5df0e313 507 stmia fp, {r0, r1, r2, r3, EXTRA_UNSAVED_REGS r12, lr}
9be4ba64 508 mov r0, r3
0bbd1454 509 b invalidate_addr_call
510 .size invalidate_addr_r3, .-invalidate_addr_r3
511 .align 2
5c6457c3 512FUNCTION(invalidate_addr_r4):
5df0e313 513 stmia fp, {r0, r1, r2, r3, EXTRA_UNSAVED_REGS r12, lr}
9be4ba64 514 mov r0, r4
0bbd1454 515 b invalidate_addr_call
516 .size invalidate_addr_r4, .-invalidate_addr_r4
517 .align 2
5c6457c3 518FUNCTION(invalidate_addr_r5):
5df0e313 519 stmia fp, {r0, r1, r2, r3, EXTRA_UNSAVED_REGS r12, lr}
9be4ba64 520 mov r0, r5
0bbd1454 521 b invalidate_addr_call
522 .size invalidate_addr_r5, .-invalidate_addr_r5
523 .align 2
5c6457c3 524FUNCTION(invalidate_addr_r6):
5df0e313 525 stmia fp, {r0, r1, r2, r3, EXTRA_UNSAVED_REGS r12, lr}
9be4ba64 526 mov r0, r6
0bbd1454 527 b invalidate_addr_call
528 .size invalidate_addr_r6, .-invalidate_addr_r6
529 .align 2
5c6457c3 530FUNCTION(invalidate_addr_r7):
5df0e313 531 stmia fp, {r0, r1, r2, r3, EXTRA_UNSAVED_REGS r12, lr}
9be4ba64 532 mov r0, r7
0bbd1454 533 b invalidate_addr_call
534 .size invalidate_addr_r7, .-invalidate_addr_r7
535 .align 2
5c6457c3 536FUNCTION(invalidate_addr_r8):
5df0e313 537 stmia fp, {r0, r1, r2, r3, EXTRA_UNSAVED_REGS r12, lr}
9be4ba64 538 mov r0, r8
0bbd1454 539 b invalidate_addr_call
540 .size invalidate_addr_r8, .-invalidate_addr_r8
541 .align 2
5c6457c3 542FUNCTION(invalidate_addr_r9):
5df0e313 543 stmia fp, {r0, r1, r2, r3, EXTRA_UNSAVED_REGS r12, lr}
9be4ba64 544 mov r0, r9
0bbd1454 545 b invalidate_addr_call
546 .size invalidate_addr_r9, .-invalidate_addr_r9
547 .align 2
5c6457c3 548FUNCTION(invalidate_addr_r10):
5df0e313 549 stmia fp, {r0, r1, r2, r3, EXTRA_UNSAVED_REGS r12, lr}
9be4ba64 550 mov r0, r10
0bbd1454 551 b invalidate_addr_call
552 .size invalidate_addr_r10, .-invalidate_addr_r10
553 .align 2
5c6457c3 554FUNCTION(invalidate_addr_r12):
5df0e313 555 stmia fp, {r0, r1, r2, r3, EXTRA_UNSAVED_REGS r12, lr}
9be4ba64 556 mov r0, r12
0bbd1454 557 .size invalidate_addr_r12, .-invalidate_addr_r12
558 .align 2
b1f89e6f 559invalidate_addr_call:
560 ldr r12, [fp, #LO_inv_code_start]
561 ldr lr, [fp, #LO_inv_code_end]
9be4ba64 562 cmp r0, r12
563 cmpcs lr, r0
564 blcc invalidate_addr
5df0e313 565 ldmia fp, {r0, r1, r2, r3, EXTRA_UNSAVED_REGS r12, pc}
0bbd1454 566 .size invalidate_addr_call, .-invalidate_addr_call
567
57871462 568 .align 2
5c6457c3 569FUNCTION(new_dyna_start):
b021ee75 570 /* ip is stored to conform EABI alignment */
571 stmfd sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
be516ebe 572 mov fp, r0 /* dynarec_local */
b1f89e6f 573 ldr r0, [fp, #LO_pcaddr]
7139f3c8 574 bl get_addr_ht
b1f89e6f 575 ldr r1, [fp, #LO_next_interupt]
576 ldr r10, [fp, #LO_cycle]
577 str r1, [fp, #LO_last_count]
7139f3c8 578 sub r10, r10, r1
579 mov pc, r0
57871462 580 .size new_dyna_start, .-new_dyna_start
7139f3c8 581
7e605697 582/* --------------------------------------- */
7139f3c8 583
7e605697 584.align 2
c6c3b1b3 585
586.macro pcsx_read_mem readop tab_shift
587 /* r0 = address, r1 = handler_tab, r2 = cycles */
588 lsl r3, r0, #20
589 lsr r3, #(20+\tab_shift)
b1f89e6f 590 ldr r12, [fp, #LO_last_count]
c6c3b1b3 591 ldr r1, [r1, r3, lsl #2]
592 add r2, r2, r12
593 lsls r1, #1
594.if \tab_shift == 1
595 lsl r3, #1
596 \readop r0, [r1, r3]
597.else
598 \readop r0, [r1, r3, lsl #\tab_shift]
599.endif
600 movcc pc, lr
b1f89e6f 601 str r2, [fp, #LO_cycle]
c6c3b1b3 602 bx r1
603.endm
604
5c6457c3 605FUNCTION(jump_handler_read8):
c6c3b1b3 606 add r1, #0x1000/4*4 + 0x1000/2*4 @ shift to r8 part
b861c0a9 607 pcsx_read_mem ldrbcc, 0
c6c3b1b3 608
5c6457c3 609FUNCTION(jump_handler_read16):
c6c3b1b3 610 add r1, #0x1000/4*4 @ shift to r16 part
10858959 611 pcsx_read_mem ldrhcc, 1
c6c3b1b3 612
5c6457c3 613FUNCTION(jump_handler_read32):
c6c3b1b3 614 pcsx_read_mem ldrcc, 2
615
b96d3df7 616
9b9af0d1 617.macro memhandler_post
618 ldr r0, [fp, #LO_next_interupt]
619 ldr r2, [fp, #LO_cycle] @ memhandlers can modify cc, like dma
620 str r0, [fp, #LO_last_count]
621 sub r0, r2, r0
622.endm
623
b96d3df7 624.macro pcsx_write_mem wrtop tab_shift
625 /* r0 = address, r1 = data, r2 = cycles, r3 = handler_tab */
626 lsl r12,r0, #20
627 lsr r12, #(20+\tab_shift)
628 ldr r3, [r3, r12, lsl #2]
b1f89e6f 629 str r0, [fp, #LO_address] @ some handlers still need it..
b96d3df7 630 lsls r3, #1
9b9af0d1 631 mov r0, r2 @ cycle return in case of direct store
b96d3df7 632.if \tab_shift == 1
633 lsl r12, #1
634 \wrtop r1, [r3, r12]
635.else
636 \wrtop r1, [r3, r12, lsl #\tab_shift]
637.endif
638 movcc pc, lr
b1f89e6f 639 ldr r12, [fp, #LO_last_count]
b96d3df7 640 mov r0, r1
641 add r2, r2, r12
b1f89e6f 642 str r2, [fp, #LO_cycle]
9b9af0d1 643
644 str lr, [fp, #LO_saved_lr]
b96d3df7 645 blx r3
9b9af0d1 646 ldr lr, [fp, #LO_saved_lr]
b96d3df7 647
9b9af0d1 648 memhandler_post
687b4580 649 bx lr
b96d3df7 650.endm
651
5c6457c3 652FUNCTION(jump_handler_write8):
b96d3df7 653 add r3, #0x1000/4*4 + 0x1000/2*4 @ shift to r8 part
b861c0a9 654 pcsx_write_mem strbcc, 0
b96d3df7 655
5c6457c3 656FUNCTION(jump_handler_write16):
b96d3df7 657 add r3, #0x1000/4*4 @ shift to r16 part
b861c0a9 658 pcsx_write_mem strhcc, 1
b96d3df7 659
5c6457c3 660FUNCTION(jump_handler_write32):
b96d3df7 661 pcsx_write_mem strcc, 2
662
5c6457c3 663FUNCTION(jump_handler_write_h):
b96d3df7 664 /* r0 = address, r1 = data, r2 = cycles, r3 = handler */
b1f89e6f 665 ldr r12, [fp, #LO_last_count]
666 str r0, [fp, #LO_address] @ some handlers still need it..
b96d3df7 667 add r2, r2, r12
668 mov r0, r1
b1f89e6f 669 str r2, [fp, #LO_cycle]
9b9af0d1 670
671 str lr, [fp, #LO_saved_lr]
b96d3df7 672 blx r3
9b9af0d1 673 ldr lr, [fp, #LO_saved_lr]
b96d3df7 674
9b9af0d1 675 memhandler_post
687b4580 676 bx lr
b96d3df7 677
5c6457c3 678FUNCTION(jump_handle_swl):
b96d3df7 679 /* r0 = address, r1 = data, r2 = cycles */
b1f89e6f 680 ldr r3, [fp, #LO_mem_wtab]
b96d3df7 681 mov r12,r0,lsr #12
682 ldr r3, [r3, r12, lsl #2]
683 lsls r3, #1
684 bcs 4f
685 add r3, r0, r3
686 mov r0, r2
687 tst r3, #2
688 beq 101f
689 tst r3, #1
690 beq 2f
6913:
692 str r1, [r3, #-3]
693 bx lr
6942:
695 lsr r2, r1, #8
696 lsr r1, #24
697 strh r2, [r3, #-2]
698 strb r1, [r3]
699 bx lr
700101:
701 tst r3, #1
702 lsrne r1, #16 @ 1
703 lsreq r12, r1, #24 @ 0
b861c0a9 704 strhne r1, [r3, #-1]
705 strbeq r12, [r3]
b96d3df7 706 bx lr
7074:
708 mov r0, r2
63cb0298 709@ b abort
b96d3df7 710 bx lr @ TODO?
711
712
5c6457c3 713FUNCTION(jump_handle_swr):
b96d3df7 714 /* r0 = address, r1 = data, r2 = cycles */
b1f89e6f 715 ldr r3, [fp, #LO_mem_wtab]
b96d3df7 716 mov r12,r0,lsr #12
717 ldr r3, [r3, r12, lsl #2]
718 lsls r3, #1
719 bcs 4f
720 add r3, r0, r3
721 and r12,r3, #3
722 mov r0, r2
723 cmp r12,#2
b861c0a9 724 strbgt r1, [r3] @ 3
725 strheq r1, [r3] @ 2
b96d3df7 726 cmp r12,#1
727 strlt r1, [r3] @ 0
728 bxne lr
729 lsr r2, r1, #8 @ 1
730 strb r1, [r3]
731 strh r2, [r3, #1]
732 bx lr
7334:
734 mov r0, r2
63cb0298 735@ b abort
b96d3df7 736 bx lr @ TODO?
737
738
b1be1eee 739.macro rcntx_read_mode0 num
740 /* r0 = address, r2 = cycles */
b1f89e6f 741 ldr r3, [fp, #LO_rcnts+6*4+7*4*\num] @ cycleStart
b1be1eee 742 mov r0, r2, lsl #16
b861c0a9 743 sub r0, r0, r3, lsl #16
b1be1eee 744 lsr r0, #16
745 bx lr
746.endm
747
5c6457c3 748FUNCTION(rcnt0_read_count_m0):
b1be1eee 749 rcntx_read_mode0 0
750
5c6457c3 751FUNCTION(rcnt1_read_count_m0):
b1be1eee 752 rcntx_read_mode0 1
753
5c6457c3 754FUNCTION(rcnt2_read_count_m0):
b1be1eee 755 rcntx_read_mode0 2
756
5c6457c3 757FUNCTION(rcnt0_read_count_m1):
b1be1eee 758 /* r0 = address, r2 = cycles */
b1f89e6f 759 ldr r3, [fp, #LO_rcnts+6*4+7*4*0] @ cycleStart
b1be1eee 760 mov_16 r1, 0x3334
761 sub r2, r2, r3
762 mul r0, r1, r2 @ /= 5
763 lsr r0, #16
764 bx lr
765
5c6457c3 766FUNCTION(rcnt1_read_count_m1):
b1be1eee 767 /* r0 = address, r2 = cycles */
b1f89e6f 768 ldr r3, [fp, #LO_rcnts+6*4+7*4*1]
b1be1eee 769 mov_24 r1, 0x1e6cde
770 sub r2, r2, r3
771 umull r3, r0, r1, r2 @ ~ /= hsync_cycles, max ~0x1e6cdd
772 bx lr
773
5c6457c3 774FUNCTION(rcnt2_read_count_m1):
b1be1eee 775 /* r0 = address, r2 = cycles */
b1f89e6f 776 ldr r3, [fp, #LO_rcnts+6*4+7*4*2]
b1be1eee 777 mov r0, r2, lsl #16-3
b861c0a9 778 sub r0, r0, r3, lsl #16-3
b1be1eee 779 lsr r0, #16 @ /= 8
780 bx lr
781
81dbbf4c 782FUNCTION(call_gteStall):
783 /* r0 = op_cycles, r1 = cycles */
784 ldr r2, [fp, #LO_last_count]
785 str lr, [fp, #LO_saved_lr]
786 add r1, r1, r2
787 str r1, [fp, #LO_cycle]
788 add r1, fp, #LO_psxRegs
789 bl gteCheckStallRaw
790 ldr lr, [fp, #LO_saved_lr]
791 add r10, r10, r0
792 bx lr
793
cdc2da64 794#ifdef HAVE_ARMV6
795
796FUNCTION(get_reg):
797 ldr r12, [r0]
798 and r1, r1, #0xff
799 ldr r2, [r0, #4]
800 orr r1, r1, r1, lsl #8
801 ldr r3, [r0, #8]
802 orr r1, r1, r1, lsl #16 @ searched char in every byte
803 ldrb r0, [r0, #12] @ last byte
804 eor r12, r12, r1
805 eor r2, r2, r1
806 eor r3, r3, r1
807 cmp r0, r1, lsr #24
808 mov r0, #12
809 mvn r1, #0 @ r1=~0
810 bxeq lr
811 orr r3, r3, #0xff000000 @ EXCLUDE_REG
812 uadd8 r0, r12, r1 @ add and set GE bits when not 0 (match)
813 mov r12, #0
814 sel r0, r12, r1 @ 0 if no match, else ff in some byte
815 uadd8 r2, r2, r1
816 sel r2, r12, r1
817 uadd8 r3, r3, r1
818 sel r3, r12, r1
819 mov r12, #3
820 clz r0, r0 @ 0, 8, 16, 24 or 32
821 clz r2, r2
822 clz r3, r3
823 sub r0, r12, r0, lsr #3 @ 3, 2, 1, 0 or -1
824 sub r2, r12, r2, lsr #3
825 sub r3, r12, r3, lsr #3
826 orr r2, r2, #4
827 orr r3, r3, #8
828 and r0, r0, r2
829 and r0, r0, r3
830 bx lr
831
832#endif /* HAVE_ARMV6 */
833
7e605697 834@ vim:filetype=armasm