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