1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 * Mupen64plus - linkage_arm.S * 3 * Copyright (C) 2009-2011 Ari64 * 4 * * 5 * This program is free software; you can redistribute it and/or modify * 6 * it under the terms of the GNU General Public License as published by * 7 * the Free Software Foundation; either version 2 of the License, or * 8 * (at your option) any later version. * 9 * * 10 * This program is distributed in the hope that it will be useful, * 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 * GNU General Public License for more details. * 14 * * 15 * You should have received a copy of the GNU General Public License * 16 * along with this program; if not, write to the * 17 * Free Software Foundation, Inc., * 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 19 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 20 21#define GLOBAL_FUNCTION(name) \ 22 .align 2; \ 23 .globl name; \ 24 .hidden name; \ 25 .type name, %function; \ 26 name 27 28#define LOCAL_FUNCTION(name) \ 29 .align 2; \ 30 .hidden name; \ 31 .type name, %function; \ 32 name 33 34#define GLOBAL_VARIABLE(name, size_) \ 35 .global name; \ 36 .hidden name; \ 37 .type name, %object; \ 38 .size name, size_ 39 40#define BSS_SECTION .bss 41#define TEXT_SECTION .text 42#define END_SECTION 43 44#ifndef __ARM_NEON__ 45#if (defined(__VFP_FP__) && !defined(__SOFTFP__) && defined(__ARM_PCS_VFP)) 46 .fpu vfp 47#else 48 .fpu softvfp 49#endif 50#else 51 .fpu neon 52#endif 53 .eabi_attribute 20, 1 54 .eabi_attribute 21, 1 55#ifndef __ARM_NEON__ 56 .eabi_attribute 23, 3 57#endif 58 .eabi_attribute 24, 1 59 .eabi_attribute 25, 1 60 .eabi_attribute 26, 2 61#ifndef __ARM_NEON__ 62#if (defined(__VFP_FP__) && !defined(__SOFTFP__) && defined(__ARM_PCS_VFP)) 63 .eabi_attribute 28, 1 64#endif 65#endif 66 .eabi_attribute 30, 6 67 .eabi_attribute 18, 4 68 .file "linkage_arm.S" 69 70BSS_SECTION 71 72 .align 12 73 GLOBAL_VARIABLE(extra_memory, 33554432) 74 GLOBAL_VARIABLE(dynarec_local, 64) 75 GLOBAL_VARIABLE(next_interrupt, 4) 76 GLOBAL_VARIABLE(cycle_count, 4) 77 GLOBAL_VARIABLE(last_count, 4) 78 GLOBAL_VARIABLE(pending_exception, 4) 79 GLOBAL_VARIABLE(pcaddr, 4) 80 GLOBAL_VARIABLE(stop, 4) 81 GLOBAL_VARIABLE(invc_ptr, 4) 82 GLOBAL_VARIABLE(address, 4) 83 GLOBAL_VARIABLE(readmem_dword, 8) 84 GLOBAL_VARIABLE(cpu_dword, 8) 85 GLOBAL_VARIABLE(cpu_word, 4) 86 GLOBAL_VARIABLE(cpu_hword, 2) 87 GLOBAL_VARIABLE(cpu_byte, 1) 88 GLOBAL_VARIABLE(FCR0, 4) 89 GLOBAL_VARIABLE(FCR31, 4) 90 GLOBAL_VARIABLE(reg, 256) 91 GLOBAL_VARIABLE(hi, 8) 92 GLOBAL_VARIABLE(lo, 8) 93 GLOBAL_VARIABLE(g_cp0_regs, 128) 94 GLOBAL_VARIABLE(reg_cop1_simple, 128) 95 GLOBAL_VARIABLE(reg_cop1_double, 128) 96 GLOBAL_VARIABLE(rounding_modes, 16) 97 GLOBAL_VARIABLE(branch_target, 4) 98 GLOBAL_VARIABLE(PC, 4) 99 GLOBAL_VARIABLE(fake_pc, 132) 100 GLOBAL_VARIABLE(ram_offset, 4) 101 GLOBAL_VARIABLE(mini_ht, 256) 102 GLOBAL_VARIABLE(restore_candidate, 512) 103 GLOBAL_VARIABLE(memory_map, 4194304) 104 105extra_memory: 106 .space 33554432+64+4+4+4+4+4+4+4+4+8+8+4+2+2+4+4+256+8+8+128+128+128+16+4+4+132+4+256+512+4194304 107 108 dynarec_local = extra_memory + 33554432 109 next_interrupt = dynarec_local + 64 110 cycle_count = next_interrupt + 4 111 last_count = cycle_count + 4 112 pending_exception = last_count + 4 113 pcaddr = pending_exception + 4 114 stop = pcaddr + 4 115 invc_ptr = stop + 4 116 address = invc_ptr + 4 117 readmem_dword = address + 4 118 cpu_dword = readmem_dword + 8 119 cpu_word = cpu_dword + 8 120 cpu_hword = cpu_word + 4 121 cpu_byte = cpu_hword + 2 /* 1 byte free */ 122 FCR0 = cpu_hword + 4 123 FCR31 = FCR0 + 4 124 reg = FCR31 + 4 125 hi = reg + 256 126 lo = hi + 8 127 g_cp0_regs = lo + 8 128 reg_cop1_simple = g_cp0_regs + 128 129 reg_cop1_double = reg_cop1_simple + 128 130 rounding_modes = reg_cop1_double + 128 131 branch_target = rounding_modes + 16 132 PC = branch_target + 4 133 fake_pc = PC + 4 134 ram_offset = fake_pc + 132 135 mini_ht = ram_offset + 4 136 restore_candidate = mini_ht + 256 137 memory_map = restore_candidate + 512 138 139END_SECTION 140 141TEXT_SECTION 142 143 .align 2 144 .jiptr_offset1 : .word jump_in-(.jiptr_pic1+8) 145 .jiptr_offset2 : .word jump_in-(.jiptr_pic2+8) 146 .jdptr_offset1 : .word jump_dirty-(.jdptr_pic1+8) 147 .jdptr_offset2 : .word jump_dirty-(.jdptr_pic2+8) 148 .tlbptr_offset1 : .word tlb_LUT_r-(.tlbptr_pic1+8) 149 .tlbptr_offset2 : .word tlb_LUT_r-(.tlbptr_pic2+8) 150 .htptr_offset1 : .word hash_table-(.htptr_pic1+8) 151 .htptr_offset2 : .word hash_table-(.htptr_pic2+8) 152 .htptr_offset3 : .word hash_table-(.htptr_pic3+8) 153 .dlptr_offset : .word dynarec_local+28-(.dlptr_pic+8) 154 .outptr_offset : .word out-(.outptr_pic+8) 155 156GLOBAL_FUNCTION(dyna_linker): 157 /* r0 = virtual target address */ 158 /* r1 = instruction to patch */ 159 ldr r4, .tlbptr_offset1 160.tlbptr_pic1: 161 add r4, pc, r4 162 lsr r5, r0, #12 163 mov r12, r0 164 cmp r0, #0xC0000000 165 mov r6, #4096 166 ldrge r12, [r4, r5, lsl #2] 167 mov r2, #0x80000 168 ldr r3, .jiptr_offset1 169.jiptr_pic1: 170 add r3, pc, r3 171 tst r12, r12 172 sub r6, r6, #1 173 moveq r12, r0 174 ldr r7, [r1] 175 eor r2, r2, r12, lsr #12 176 and r6, r6, r12, lsr #12 177 cmp r2, #2048 178 add r12, r7, #2 179 orrcs r2, r6, #2048 180 ldr r5, [r3, r2, lsl #2] 181 lsl r12, r12, #8 182 /* jump_in lookup */ 183.A1: 184 movs r4, r5 185 beq .A3 186 ldr r3, [r5] 187 ldr r5, [r4, #12] 188 teq r3, r0 189 bne .A1 190 ldr r3, [r4, #4] 191 ldr r4, [r4, #8] 192 tst r3, r3 193 bne .A1 194.A2: 195 mov r5, r1 196 add r1, r1, r12, asr #6 197 teq r1, r4 198 moveq pc, r4 /* Stale i-cache */ 199 bl add_link 200 sub r2, r4, r5 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] 206 mov pc, r4 207.A3: 208 /* hash_table lookup */ 209 cmp r2, #2048 210 ldr r3, .jdptr_offset1 211.jdptr_pic1: 212 add r3, pc, r3 213 eor r4, r0, r0, lsl #16 214 lslcc r2, r0, #9 215 ldr r6, .htptr_offset1 216.htptr_pic1: 217 add r6, pc, r6 218 lsr r4, r4, #12 219 lsrcc r2, r2, #21 220 bic r4, r4, #15 221 ldr r5, [r3, r2, lsl #2] 222 ldr r7, [r6, r4]! 223 teq r7, r0 224 ldreq pc, [r6, #4] 225 ldr r7, [r6, #8] 226 teq r7, r0 227 ldreq pc, [r6, #12] 228 /* jump_dirty lookup */ 229.A6: 230 movs r4, r5 231 beq .A8 232 ldr r3, [r5] 233 ldr r5, [r4, #12] 234 teq r3, r0 235 bne .A6 236.A7: 237 ldr r1, [r4, #8] 238 /* hash_table insert */ 239 ldr r2, [r6] 240 ldr r3, [r6, #4] 241 str r0, [r6] 242 str r1, [r6, #4] 243 str r2, [r6, #8] 244 str r3, [r6, #12] 245 mov pc, r1 246.A8: 247 mov r4, r0 248 mov r5, r1 249 bl new_recompile_block 250 tst r0, r0 251 mov r0, r4 252 mov r1, r5 253 beq dyna_linker 254 /* pagefault */ 255 mov r1, r0 256 mov r2, #8 257 258LOCAL_FUNCTION(exec_pagefault): 259 /* r0 = instruction pointer */ 260 /* r1 = fault address */ 261 /* r2 = cause */ 262 ldr r3, [fp, #g_cp0_regs+48-dynarec_local] /* Status */ 263 mvn r6, #0xF000000F 264 ldr r4, [fp, #g_cp0_regs+16-dynarec_local] /* Context */ 265 bic r6, r6, #0x0F800000 266 str r0, [fp, #g_cp0_regs+56-dynarec_local] /* EPC */ 267 orr r3, r3, #2 268 str r1, [fp, #g_cp0_regs+32-dynarec_local] /* BadVAddr */ 269 bic r4, r4, r6 270 str r3, [fp, #g_cp0_regs+48-dynarec_local] /* Status */ 271 and r5, r6, r1, lsr #9 272 str r2, [fp, #g_cp0_regs+52-dynarec_local] /* Cause */ 273 and r1, r1, r6, lsl #9 274 str r1, [fp, #g_cp0_regs+40-dynarec_local] /* EntryHi */ 275 orr r4, r4, r5 276 str r4, [fp, #g_cp0_regs+16-dynarec_local] /* Context */ 277 mov r0, #0x80000000 278 bl get_addr_ht 279 mov pc, r0 280 281/* Special dynamic linker for the case where a page fault 282 may occur in a branch delay slot */ 283GLOBAL_FUNCTION(dyna_linker_ds): 284 /* r0 = virtual target address */ 285 /* r1 = instruction to patch */ 286 ldr r4, .tlbptr_offset2 287.tlbptr_pic2: 288 add r4, pc, r4 289 lsr r5, r0, #12 290 mov r12, r0 291 cmp r0, #0xC0000000 292 mov r6, #4096 293 ldrge r12, [r4, r5, lsl #2] 294 mov r2, #0x80000 295 ldr r3, .jiptr_offset2 296.jiptr_pic2: 297 add r3, pc, r3 298 tst r12, r12 299 sub r6, r6, #1 300 moveq r12, r0 301 ldr r7, [r1] 302 eor r2, r2, r12, lsr #12 303 and r6, r6, r12, lsr #12 304 cmp r2, #2048 305 add r12, r7, #2 306 orrcs r2, r6, #2048 307 ldr r5, [r3, r2, lsl #2] 308 lsl r12, r12, #8 309 /* jump_in lookup */ 310.B1: 311 movs r4, r5 312 beq .B3 313 ldr r3, [r5] 314 ldr r5, [r4, #12] 315 teq r3, r0 316 bne .B1 317 ldr r3, [r4, #4] 318 ldr r4, [r4, #8] 319 tst r3, r3 320 bne .B1 321.B2: 322 mov r5, r1 323 add r1, r1, r12, asr #6 324 teq r1, r4 325 moveq pc, r4 /* Stale i-cache */ 326 bl add_link 327 sub r2, r4, r5 328 and r1, r7, #0xff000000 329 lsl r2, r2, #6 330 sub r1, r1, #2 331 add r1, r1, r2, lsr #8 332 str r1, [r5] 333 mov pc, r4 334.B3: 335 /* hash_table lookup */ 336 cmp r2, #2048 337 ldr r3, .jdptr_offset2 338.jdptr_pic2: 339 add r3, pc, r3 340 eor r4, r0, r0, lsl #16 341 lslcc r2, r0, #9 342 ldr r6, .htptr_offset2 343.htptr_pic2: 344 add r6, pc, r6 345 lsr r4, r4, #12 346 lsrcc r2, r2, #21 347 bic r4, r4, #15 348 ldr r5, [r3, r2, lsl #2] 349 ldr r7, [r6, r4]! 350 teq r7, r0 351 ldreq pc, [r6, #4] 352 ldr r7, [r6, #8] 353 teq r7, r0 354 ldreq pc, [r6, #12] 355 /* jump_dirty lookup */ 356.B6: 357 movs r4, r5 358 beq .B8 359 ldr r3, [r5] 360 ldr r5, [r4, #12] 361 teq r3, r0 362 bne .B6 363.B7: 364 ldr r1, [r4, #8] 365 /* hash_table insert */ 366 ldr r2, [r6] 367 ldr r3, [r6, #4] 368 str r0, [r6] 369 str r1, [r6, #4] 370 str r2, [r6, #8] 371 str r3, [r6, #12] 372 mov pc, r1 373.B8: 374 mov r4, r0 375 bic r0, r0, #7 376 mov r5, r1 377 orr r0, r0, #1 378 bl new_recompile_block 379 tst r0, r0 380 mov r0, r4 381 mov r1, r5 382 beq dyna_linker_ds 383 /* pagefault */ 384 bic r1, r0, #7 385 mov r2, #0x80000008 /* High bit set indicates pagefault in delay slot */ 386 sub r0, r1, #4 387 b exec_pagefault 388 389GLOBAL_FUNCTION(jump_vaddr_r0): 390 eor r2, r0, r0, lsl #16 391 b jump_vaddr 392 393GLOBAL_FUNCTION(jump_vaddr_r1): 394 eor r2, r1, r1, lsl #16 395 mov r0, r1 396 b jump_vaddr 397 398GLOBAL_FUNCTION(jump_vaddr_r2): 399 mov r0, r2 400 eor r2, r2, r2, lsl #16 401 b jump_vaddr 402 403GLOBAL_FUNCTION(jump_vaddr_r3): 404 eor r2, r3, r3, lsl #16 405 mov r0, r3 406 b jump_vaddr 407 408GLOBAL_FUNCTION(jump_vaddr_r4): 409 eor r2, r4, r4, lsl #16 410 mov r0, r4 411 b jump_vaddr 412 413GLOBAL_FUNCTION(jump_vaddr_r5): 414 eor r2, r5, r5, lsl #16 415 mov r0, r5 416 b jump_vaddr 417 418GLOBAL_FUNCTION(jump_vaddr_r6): 419 eor r2, r6, r6, lsl #16 420 mov r0, r6 421 b jump_vaddr 422 423GLOBAL_FUNCTION(jump_vaddr_r8): 424 eor r2, r8, r8, lsl #16 425 mov r0, r8 426 b jump_vaddr 427 428GLOBAL_FUNCTION(jump_vaddr_r9): 429 eor r2, r9, r9, lsl #16 430 mov r0, r9 431 b jump_vaddr 432 433GLOBAL_FUNCTION(jump_vaddr_r10): 434 eor r2, r10, r10, lsl #16 435 mov r0, r10 436 b jump_vaddr 437 438GLOBAL_FUNCTION(jump_vaddr_r12): 439 eor r2, r12, r12, lsl #16 440 mov r0, r12 441 b jump_vaddr 442 443GLOBAL_FUNCTION(jump_vaddr_r7): 444 eor r2, r7, r7, lsl #16 445 add r0, r7, #0 446 447GLOBAL_FUNCTION(jump_vaddr): 448 ldr r1, .htptr_offset3 449.htptr_pic3: 450 add r1, pc, r1 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 464GLOBAL_FUNCTION(verify_code_ds): 465 str r8, [fp, #branch_target-dynarec_local] 466 467GLOBAL_FUNCTION(verify_code_vm): 468 /* r0 = instruction pointer (virtual address) */ 469 /* r1 = source (virtual address) */ 470 /* r2 = target */ 471 /* r3 = length */ 472 cmp r1, #0xC0000000 473 blt verify_code 474 add r12, fp, #memory_map-dynarec_local 475 lsr r4, r1, #12 476 add r5, r1, r3 477 sub r5, #1 478 ldr r6, [r12, r4, lsl #2] 479 lsr r5, r5, #12 480 movs r7, r6 481 bmi .D5 482 add r1, r1, r6, lsl #2 483 lsl r6, r6, #2 484.D1: 485 add r4, r4, #1 486 teq r6, r7, lsl #2 487 bne .D5 488 ldr r7, [r12, r4, lsl #2] 489 cmp r4, r5 490 bls .D1 491 492GLOBAL_FUNCTION(verify_code): 493 /* r1 = source */ 494 /* r2 = target */ 495 /* r3 = length */ 496 tst r3, #4 497 mov r4, #0 498 add r3, r1, r3 499 mov r5, #0 500 ldrne r4, [r1], #4 501 mov r12, #0 502 ldrne r5, [r2], #4 503 teq r1, r3 504 beq .D3 505.D2: 506 ldr r7, [r1], #4 507 eor r9, r4, r5 508 ldr r8, [r2], #4 509 orrs r9, r9, r12 510 bne .D4 511 ldr r4, [r1], #4 512 eor r12, r7, r8 513 ldr r5, [r2], #4 514 cmp r1, r3 515 bcc .D2 516 teq r7, r8 517.D3: 518 teqeq r4, r5 519.D4: 520 ldr r8, [fp, #branch_target-dynarec_local] 521 moveq pc, lr 522.D5: 523 bl get_addr 524 mov pc, r0 525 526GLOBAL_FUNCTION(cc_interrupt): 527 ldr r0, [fp, #last_count-dynarec_local] 528 mov r1, #0 529 mov r2, #0x1fc 530 add r10, r0, r10 531 str r1, [fp, #pending_exception-dynarec_local] 532 and r2, r2, r10, lsr #19 533 add r3, fp, #restore_candidate-dynarec_local 534 str r10, [fp, #g_cp0_regs+36-dynarec_local] /* Count */ 535 ldr r4, [r2, r3] 536 mov r10, lr 537 tst r4, r4 538 bne .E4 539.E1: 540 bl gen_interrupt 541 mov lr, r10 542 ldr r10, [fp, #g_cp0_regs+36-dynarec_local] /* Count */ 543 ldr r0, [fp, #next_interrupt-dynarec_local] 544 ldr r1, [fp, #pending_exception-dynarec_local] 545 ldr r2, [fp, #stop-dynarec_local] 546 str r0, [fp, #last_count-dynarec_local] 547 sub r10, r10, r0 548 tst r2, r2 549 bne .E3 550 tst r1, r1 551 moveq pc, lr 552.E2: 553 ldr r0, [fp, #pcaddr-dynarec_local] 554 bl get_addr_ht 555 mov pc, r0 556.E3: 557 add r12, fp, #28 558 ldmia r12, {r4, r5, r6, r7, r8, r9, sl, fp, pc} 559.E4: 560 /* Move 'dirty' blocks to the 'clean' list */ 561 lsl r5, r2, #3 562 str r1, [r2, r3] 563 mov r6, #0 564.E5: 565 lsrs r4, r4, #1 566 add r0, r5, r6 567 blcs clean_blocks 568 add r6, r6, #1 569 tst r6, #31 570 bne .E5 571 b .E1 572 573GLOBAL_FUNCTION(do_interrupt): 574 ldr r0, [fp, #pcaddr-dynarec_local] 575 bl get_addr_ht 576 ldr r1, [fp, #next_interrupt-dynarec_local] 577 ldr r10, [fp, #g_cp0_regs+36-dynarec_local] /* Count */ 578 str r1, [fp, #last_count-dynarec_local] 579 sub r10, r10, r1 580 add r10, r10, #2 581 mov pc, r0 582 583GLOBAL_FUNCTION(fp_exception): 584 mov r2, #0x10000000 585.E7: 586 ldr r1, [fp, #g_cp0_regs+48-dynarec_local] /* Status */ 587 mov r3, #0x80000000 588 str r0, [fp, #g_cp0_regs+56-dynarec_local] /* EPC */ 589 orr r1, #2 590 add r2, r2, #0x2c 591 str r1, [fp, #g_cp0_regs+48-dynarec_local] /* Status */ 592 str r2, [fp, #g_cp0_regs+52-dynarec_local] /* Cause */ 593 add r0, r3, #0x180 594 bl get_addr_ht 595 mov pc, r0 596 597GLOBAL_FUNCTION(fp_exception_ds): 598 mov r2, #0x90000000 /* Set high bit if delay slot */ 599 b .E7 600 601GLOBAL_FUNCTION(jump_syscall): 602 ldr r1, [fp, #g_cp0_regs+48-dynarec_local] /* Status */ 603 mov r3, #0x80000000 604 str r0, [fp, #g_cp0_regs+56-dynarec_local] /* EPC */ 605 orr r1, #2 606 mov r2, #0x20 607 str r1, [fp, #g_cp0_regs+48-dynarec_local] /* Status */ 608 str r2, [fp, #g_cp0_regs+52-dynarec_local] /* Cause */ 609 add r0, r3, #0x180 610 bl get_addr_ht 611 mov pc, r0 612 613GLOBAL_FUNCTION(indirect_jump_indexed): 614 ldr r0, [r0, r1, lsl #2] 615 616GLOBAL_FUNCTION(indirect_jump): 617 ldr r12, [fp, #last_count-dynarec_local] 618 add r2, r2, r12 619 str r2, [fp, #g_cp0_regs+36-dynarec_local] /* Count */ 620 mov pc, r0 621 622GLOBAL_FUNCTION(jump_eret): 623 ldr r1, [fp, #g_cp0_regs+48-dynarec_local] /* Status */ 624 ldr r0, [fp, #last_count-dynarec_local] 625 bic r1, r1, #2 626 add r10, r0, r10 627 str r1, [fp, #g_cp0_regs+48-dynarec_local] /* Status */ 628 str r10, [fp, #g_cp0_regs+36-dynarec_local] /* Count */ 629 bl check_interrupt 630 ldr r1, [fp, #next_interrupt-dynarec_local] 631 ldr r0, [fp, #g_cp0_regs+56-dynarec_local] /* EPC */ 632 str r1, [fp, #last_count-dynarec_local] 633 subs r10, r10, r1 634 bpl .E11 635.E8: 636 add r6, fp, #reg+256-dynarec_local 637 mov r5, #248 638 mov r1, #0 639.E9: 640 ldr r2, [r6, #-8]! 641 ldr r3, [r6, #4] 642 eor r3, r3, r2, asr #31 643 subs r3, r3, #1 644 adc r1, r1, r1 645 subs r5, r5, #8 646 bne .E9 647 ldr r2, [fp, #hi-dynarec_local] 648 ldr r3, [fp, #hi+4-dynarec_local] 649 eors r3, r3, r2, asr #31 650 ldr r2, [fp, #lo-dynarec_local] 651 ldreq r3, [fp, #lo+4-dynarec_local] 652 eoreq r3, r3, r2, asr #31 653 subs r3, r3, #1 654 adc r1, r1, r1 655 bl get_addr_32 656 mov pc, r0 657.E11: 658 str r0, [fp, #pcaddr-dynarec_local] 659 bl cc_interrupt 660 ldr r0, [fp, #pcaddr-dynarec_local] 661 b .E8 662 663GLOBAL_FUNCTION(new_dyna_start): 664 ldr r12, .dlptr_offset 665.dlptr_pic: 666 add r12, pc, r12 667 ldr r1, .outptr_offset 668.outptr_pic: 669 add r1, pc, r1 670 mov r0, #0xa4000000 671 stmia r12, {r4, r5, r6, r7, r8, r9, sl, fp, lr} 672 sub fp, r12, #28 673 ldr r4, [r1] 674 add r0, r0, #0x40 675 bl new_recompile_block 676 ldr r0, [fp, #next_interrupt-dynarec_local] 677 ldr r10, [fp, #g_cp0_regs+36-dynarec_local] /* Count */ 678 str r0, [fp, #last_count-dynarec_local] 679 sub r10, r10, r0 680 mov pc, r4 681 682GLOBAL_FUNCTION(invalidate_addr_r0): 683 stmia fp, {r0, r1, r2, r3, r12, lr} 684 lsr r0, r0, #12 685 b invalidate_addr_call 686 687GLOBAL_FUNCTION(invalidate_addr_r1): 688 stmia fp, {r0, r1, r2, r3, r12, lr} 689 lsr r0, r1, #12 690 b invalidate_addr_call 691 692GLOBAL_FUNCTION(invalidate_addr_r2): 693 stmia fp, {r0, r1, r2, r3, r12, lr} 694 lsr r0, r2, #12 695 b invalidate_addr_call 696 697GLOBAL_FUNCTION(invalidate_addr_r3): 698 stmia fp, {r0, r1, r2, r3, r12, lr} 699 lsr r0, r3, #12 700 b invalidate_addr_call 701 702GLOBAL_FUNCTION(invalidate_addr_r4): 703 stmia fp, {r0, r1, r2, r3, r12, lr} 704 lsr r0, r4, #12 705 b invalidate_addr_call 706 707GLOBAL_FUNCTION(invalidate_addr_r5): 708 stmia fp, {r0, r1, r2, r3, r12, lr} 709 lsr r0, r5, #12 710 b invalidate_addr_call 711 712GLOBAL_FUNCTION(invalidate_addr_r6): 713 stmia fp, {r0, r1, r2, r3, r12, lr} 714 lsr r0, r6, #12 715 b invalidate_addr_call 716 717GLOBAL_FUNCTION(invalidate_addr_r7): 718 stmia fp, {r0, r1, r2, r3, r12, lr} 719 lsr r0, r7, #12 720 b invalidate_addr_call 721 722GLOBAL_FUNCTION(invalidate_addr_r8): 723 stmia fp, {r0, r1, r2, r3, r12, lr} 724 lsr r0, r8, #12 725 b invalidate_addr_call 726 727GLOBAL_FUNCTION(invalidate_addr_r9): 728 stmia fp, {r0, r1, r2, r3, r12, lr} 729 lsr r0, r9, #12 730 b invalidate_addr_call 731 732GLOBAL_FUNCTION(invalidate_addr_r10): 733 stmia fp, {r0, r1, r2, r3, r12, lr} 734 lsr r0, r10, #12 735 b invalidate_addr_call 736 737GLOBAL_FUNCTION(invalidate_addr_r12): 738 stmia fp, {r0, r1, r2, r3, r12, lr} 739 lsr r0, r12, #12 740 741LOCAL_FUNCTION(invalidate_addr_call): 742 bl invalidate_block 743 ldmia fp, {r0, r1, r2, r3, r12, pc} 744 745GLOBAL_FUNCTION(write_rdram_new): 746 ldr r3, [fp, #ram_offset-dynarec_local] 747 ldr r2, [fp, #address-dynarec_local] 748 ldr r0, [fp, #cpu_word-dynarec_local] 749 str r0, [r2, r3, lsl #2] 750 b .E12 751 752GLOBAL_FUNCTION(write_rdramb_new): 753 ldr r3, [fp, #ram_offset-dynarec_local] 754 ldr r2, [fp, #address-dynarec_local] 755 ldrb r0, [fp, #cpu_byte-dynarec_local] 756 eor r2, r2, #3 757 strb r0, [r2, r3, lsl #2] 758 b .E12 759 760GLOBAL_FUNCTION(write_rdramh_new): 761 ldr r3, [fp, #ram_offset-dynarec_local] 762 ldr r2, [fp, #address-dynarec_local] 763 ldrh r0, [fp, #cpu_hword-dynarec_local] 764 eor r2, r2, #2 765 lsl r3, r3, #2 766 strh r0, [r2, r3] 767 b .E12 768 769GLOBAL_FUNCTION(write_rdramd_new): 770 ldr r3, [fp, #ram_offset-dynarec_local] 771 ldr r2, [fp, #address-dynarec_local] 772/* ldrd r0, [fp, #cpu_dword-dynarec_local]*/ 773 ldr r0, [fp, #cpu_dword-dynarec_local] 774 ldr r1, [fp, #cpu_dword+4-dynarec_local] 775 add r3, r2, r3, lsl #2 776 str r0, [r3, #4] 777 str r1, [r3] 778 b .E12 779 780LOCAL_FUNCTION(do_invalidate): 781 ldr r2, [fp, #address-dynarec_local] 782.E12: 783 ldr r1, [fp, #invc_ptr-dynarec_local] 784 lsr r0, r2, #12 785 ldrb r2, [r1, r0] 786 tst r2, r2 787 beq invalidate_block 788 mov pc, lr 789 790GLOBAL_FUNCTION(read_nomem_new): 791 ldr r1, [fp, #address-dynarec_local] 792 add r12, fp, #memory_map-dynarec_local 793 lsr r0, r1, #12 794 ldr r12, [r12, r0, lsl #2] 795 mov r2, #0 796 tst r12, r12 797 bmi tlb_exception 798 ldr r0, [r1, r12, lsl #2] 799 str r0, [fp, #readmem_dword-dynarec_local] 800 mov pc, lr 801 802GLOBAL_FUNCTION(read_nomemb_new): 803 ldr r1, [fp, #address-dynarec_local] 804 add r12, fp, #memory_map-dynarec_local 805 lsr r0, r1, #12 806 ldr r12, [r12, r0, lsl #2] 807 mov r2, #0 808 tst r12, r12 809 bmi tlb_exception 810 eor r1, r1, #3 811 ldrb r0, [r1, r12, lsl #2] 812 str r0, [fp, #readmem_dword-dynarec_local] 813 mov pc, lr 814 815GLOBAL_FUNCTION(read_nomemh_new): 816 ldr r1, [fp, #address-dynarec_local] 817 add r12, fp, #memory_map-dynarec_local 818 lsr r0, r1, #12 819 ldr r12, [r12, r0, lsl #2] 820 mov r2, #0 821 tst r12, r12 822 bmi tlb_exception 823 lsl r12, r12, #2 824 eor r1, r1, #2 825 ldrh r0, [r1, r12] 826 str r0, [fp, #readmem_dword-dynarec_local] 827 mov pc, lr 828 829GLOBAL_FUNCTION(read_nomemd_new): 830 ldr r1, [fp, #address-dynarec_local] 831 add r12, fp, #memory_map-dynarec_local 832 lsr r0, r1, #12 833 ldr r12, [r12, r0, lsl #2] 834 mov r2, #0 835 tst r12, r12 836 bmi tlb_exception 837 lsl r12, r12, #2 838/* ldrd r0, [r1, r12]*/ 839 add r3, r1, #4 840 ldr r0, [r1, r12] 841 ldr r1, [r3, r12] 842 str r0, [fp, #readmem_dword+4-dynarec_local] 843 str r1, [fp, #readmem_dword-dynarec_local] 844 mov pc, lr 845 846GLOBAL_FUNCTION(write_nomem_new): 847 str r3, [fp, #24] 848 str lr, [fp, #28] 849 bl do_invalidate 850 ldr r1, [fp, #address-dynarec_local] 851 add r12, fp, #memory_map-dynarec_local 852 ldr lr, [fp, #28] 853 lsr r0, r1, #12 854 ldr r3, [fp, #24] 855 ldr r12, [r12, r0, lsl #2] 856 mov r2, #1 857 tst r12, #0x40000000 858 bne tlb_exception 859 ldr r0, [fp, #cpu_word-dynarec_local] 860 str r0, [r1, r12, lsl #2] 861 mov pc, lr 862 863GLOBAL_FUNCTION(write_nomemb_new): 864 str r3, [fp, #24] 865 str lr, [fp, #28] 866 bl do_invalidate 867 ldr r1, [fp, #address-dynarec_local] 868 add r12, fp, #memory_map-dynarec_local 869 ldr lr, [fp, #28] 870 lsr r0, r1, #12 871 ldr r3, [fp, #24] 872 ldr r12, [r12, r0, lsl #2] 873 mov r2, #1 874 tst r12, #0x40000000 875 bne tlb_exception 876 eor r1, r1, #3 877 ldrb r0, [fp, #cpu_byte-dynarec_local] 878 strb r0, [r1, r12, lsl #2] 879 mov pc, lr 880 881GLOBAL_FUNCTION(write_nomemh_new): 882 str r3, [fp, #24] 883 str lr, [fp, #28] 884 bl do_invalidate 885 ldr r1, [fp, #address-dynarec_local] 886 add r12, fp, #memory_map-dynarec_local 887 ldr lr, [fp, #28] 888 lsr r0, r1, #12 889 ldr r3, [fp, #24] 890 ldr r12, [r12, r0, lsl #2] 891 mov r2, #1 892 lsls r12, #2 893 bcs tlb_exception 894 eor r1, r1, #2 895 ldrh r0, [fp, #cpu_hword-dynarec_local] 896 strh r0, [r1, r12] 897 mov pc, lr 898 899GLOBAL_FUNCTION(write_nomemd_new): 900 str r3, [fp, #24] 901 str lr, [fp, #28] 902 bl do_invalidate 903 ldr r1, [fp, #address-dynarec_local] 904 add r12, fp, #memory_map-dynarec_local 905 ldr lr, [fp, #28] 906 lsr r0, r1, #12 907 ldr r3, [fp, #24] 908 ldr r12, [r12, r0, lsl #2] 909 mov r2, #1 910 lsls r12, #2 911 bcs tlb_exception 912 add r3, r1, #4 913 ldr r0, [fp, #cpu_dword+4-dynarec_local] 914 ldr r1, [fp, #cpu_dword-dynarec_local] 915/* strd r0, [r1, r12]*/ 916 str r0, [r1, r12] 917 str r1, [r3, r12] 918 mov pc, lr 919 920GLOBAL_FUNCTION(write_mi_new): 921 str r3, [fp, #24] 922 str lr, [fp, #28] 923 add r3, #4 924 str r3, [fp, #pcaddr-dynarec_local] 925 mov r1, #0 926 str r1, [fp, #pending_exception-dynarec_local] 927 bl write_mi 928 ldr lr, [fp, #28] 929 ldr r3, [fp, #24] 930 ldr r1, [fp, #pending_exception-dynarec_local] 931 tst r1, r1 932 bne mi_exception 933 mov pc, lr 934 935GLOBAL_FUNCTION(write_mib_new): 936 str r3, [fp, #24] 937 str lr, [fp, #28] 938 add r3, #4 939 str r3, [fp, #pcaddr-dynarec_local] 940 mov r1, #0 941 str r1, [fp, #pending_exception-dynarec_local] 942 bl write_mib 943 ldr lr, [fp, #28] 944 ldr r3, [fp, #24] 945 ldr r1, [fp, #pending_exception-dynarec_local] 946 tst r1, r1 947 bne mi_exception 948 mov pc, lr 949 950GLOBAL_FUNCTION(write_mih_new): 951 str r3, [fp, #24] 952 str lr, [fp, #28] 953 add r3, #4 954 str r3, [fp, #pcaddr-dynarec_local] 955 mov r1, #0 956 str r1, [fp, #pending_exception-dynarec_local] 957 bl write_mih 958 ldr lr, [fp, #28] 959 ldr r3, [fp, #24] 960 ldr r1, [fp, #pending_exception-dynarec_local] 961 tst r1, r1 962 bne mi_exception 963 mov pc, lr 964 965GLOBAL_FUNCTION(write_mid_new): 966 str r3, [fp, #24] 967 str lr, [fp, #28] 968 add r3, #4 969 str r3, [fp, #pcaddr-dynarec_local] 970 mov r1, #0 971 str r1, [fp, #pending_exception-dynarec_local] 972 bl write_mid 973 ldr lr, [fp, #28] 974 ldr r3, [fp, #24] 975 ldr r1, [fp, #pending_exception-dynarec_local] 976 tst r1, r1 977 bne mi_exception 978 mov pc, lr 979 980LOCAL_FUNCTION(mi_exception): 981 /* r1 = mem addr */ 982 /* r3 = instr addr/flags */ 983 ldr r1, [fp, #address-dynarec_local] 984 bl wb_base_reg 985 b do_interrupt 986 987LOCAL_FUNCTION(tlb_exception): 988 /* r1 = mem addr */ 989 /* r2 = r/w */ 990 /* r3 = instr addr/flags */ 991 bl wb_base_reg 992 mov r0, r3 993 bl TLB_refill_exception_new 994 ldr r1, [fp, #next_interrupt-dynarec_local] 995 ldr r10, [fp, #g_cp0_regs+36-dynarec_local] /* Count */ 996 str r1, [fp, #last_count-dynarec_local] 997 sub r10, r10, r1 998 mov pc, r0 999 1000LOCAL_FUNCTION(wb_base_reg): 1001 /* r1 = mem addr */ 1002 /* r3 = instr addr/flags */ 1003 add r5, fp, #memory_map-dynarec_local 1004 lsr r6, r3, #12 1005 ldr r7, [r5, r6, lsl #2] 1006 bic r8, r3, #3 1007 mov r6, #0x6000000 1008 orr r6, r6, #0x22 1009 ldr r0, [r8, r7, lsl #2] 1010 add r5, fp, #reg-dynarec_local 1011 mov r7, #0xf8 1012 lsl r8, r0, #16 1013 lsr r4, r0, #26 1014 and r7, r7, r0, lsr #18 1015 sub r9, r1, r8, asr #16 1016 rors r6, r6, r4 1017 ldrcs r9, [r5, r7] 1018 tst r3, #2 1019 str r9, [r5, r7] 1020 add r6, fp, #reg+4-dynarec_local 1021 asr r5, r9, #31 1022 strne r5, [r6, r7] 1023 mov pc, lr 1024 1025GLOBAL_FUNCTION(breakpoint): 1026 /* Set breakpoint here for debugging */ 1027 mov pc, lr 1028 1029GLOBAL_FUNCTION(__clear_cache_bugfix): 1030 /* The following bug-fix implements __clear_cache (missing in Android) */ 1031 push {r7, lr} 1032 mov r2, #0 1033 mov r7, #0x2 1034 add r7, r7, #0xf0000 1035 svc 0x00000000 1036 pop {r7, pc} 1037 1038END_SECTION 1039