@ vim:filetype=armasm .if 0 #include "compiler.h" .endif .global tcache .global flush_inval_caches .global ssp_drc_entry .global ssp_drc_next .global ssp_drc_next_patch .global ssp_drc_end .global ssp_hle_800 .global ssp_hle_902 @ translation cache buffer .text .align 12 @ 4096 .size tcache, TCACHE_SIZE tcache: .space TCACHE_SIZE .text .align 2 flush_inval_caches: mov r2, #0x0 @ must be 0 swi 0x9f0002 bx lr @ SSP_GR0, SSP_X, SSP_Y, SSP_A, @ SSP_ST, SSP_STACK, SSP_PC, SSP_P, @ SSP_PM0, SSP_PM1, SSP_PM2, SSP_XST, @ SSP_PM4, SSP_gr13, SSP_PMC, SSP_AL @ register map: @ r4: XXYY @ r5: A @ r6: STACK and emu flags: sss0 * .uu. .lll NZCV (NZCV is PSR bits from ARM) @ r7: SSP context @ r8: r0-r2 (.210) @ r9: r4-r6 (.654) @ r10: P @ r11: cycles #define SSP_OFFS_GR 0x400 #define SSP_PC 6 #define SSP_P 7 #define SSP_PM0 8 #define SSP_PMC 14 #define SSP_OFFS_PM_WRITE 0x46c // pmac_write[] #define SSP_OFFS_EMUSTAT 0x484 // emu_status #define SSP_OFFS_IRAM_ROM 0x48c // ptr_iram_rom #define SSP_OFFS_IRAM_DIRTY 0x494 #define SSP_OFFS_IRAM_CTX 0x498 // iram_context #define SSP_OFFS_BLTAB 0x49c // block_table #define SSP_OFFS_BLTAB_IRAM 0x4a0 #define SSP_OFFS_TMP0 0x4a4 // for entry PC #define SSP_OFFS_TMP1 0x4a8 #define SSP_OFFS_TMP2 0x4ac #define SSP_WAIT_PM0 0x2000 .macro ssp_drc_do_next patch_jump=0 .if \patch_jump str lr, [r7, #SSP_OFFS_TMP2] @ jump instr. (actually call) address + 4 .endif mov r0, r0, lsl #16 mov r0, r0, lsr #16 str r0, [r7, #SSP_OFFS_TMP0] cmp r0, #0x400 blt 0f @ ssp_de_iram ldr r2, [r7, #SSP_OFFS_BLTAB] ldr r2, [r2, r0, lsl #2] tst r2, r2 .if \patch_jump bne ssp_drc_do_patch .else bxne r2 .endif bl ssp_translate_block mov r2, r0 ldr r0, [r7, #SSP_OFFS_TMP0] @ entry PC ldr r1, [r7, #SSP_OFFS_BLTAB] str r2, [r1, r0, lsl #2] .if \patch_jump b ssp_drc_do_patch .else bx r2 .endif 0: @ ssp_de_iram: ldr r1, [r7, #SSP_OFFS_IRAM_DIRTY] tst r1, r1 ldreq r1, [r7, #SSP_OFFS_IRAM_CTX] beq 1f @ ssp_de_iram_ctx bl ssp_get_iram_context mov r1, #0 str r1, [r7, #SSP_OFFS_IRAM_DIRTY] mov r1, r0 str r1, [r7, #SSP_OFFS_IRAM_CTX] ldr r0, [r7, #SSP_OFFS_TMP0] @ entry PC 1: @ ssp_de_iram_ctx: ldr r2, [r7, #SSP_OFFS_BLTAB_IRAM] add r2, r2, r1, lsl #12 @ block_tab_iram + iram_context * 0x800/2*4 add r1, r2, r0, lsl #2 ldr r2, [r1] tst r2, r2 .if \patch_jump bne ssp_drc_do_patch .else bxne r2 .endif str r1, [r7, #SSP_OFFS_TMP1] bl ssp_translate_block mov r2, r0 ldr r0, [r7, #SSP_OFFS_TMP0] @ entry PC ldr r1, [r7, #SSP_OFFS_TMP1] @ &block_table_iram[iram_context][rPC] str r2, [r1] .if \patch_jump b ssp_drc_do_patch .else bx r2 .endif .endm @ ssp_drc_do_next ssp_drc_entry: stmfd sp!, {r4-r11, lr} mov r11, r0 ssp_regfile_load: ldr r7, =ssp ldr r7, [r7] add r2, r7, #0x400 add r2, r2, #4 ldmia r2, {r3,r4,r5,r6,r8} mov r3, r3, lsr #16 mov r3, r3, lsl #16 orr r4, r3, r4, lsr #16 @ XXYY and r8, r8, #0x0f0000 mov r8, r8, lsl #13 @ sss0 * and r9, r6, #0x670000 tst r6, #0x80000000 orrne r8, r8, #0x8 tst r6, #0x20000000 orrne r8, r8, #0x4 @ sss0 * NZ.. orr r6, r8, r9, lsr #12 @ sss0 * .uu. .lll NZ.. ldr r8, [r7, #0x440] @ r0-r2 ldr r9, [r7, #0x444] @ r4-r6 ldr r10,[r7, #(0x400+SSP_P*4)] @ P ldr r0, [r7, #(SSP_OFFS_GR+SSP_PC*4)] mov r0, r0, lsr #16 ssp_drc_next: ssp_drc_do_next 0 ssp_drc_next_patch: ssp_drc_do_next 1 ssp_drc_do_patch: ldr r1, [r7, #SSP_OFFS_TMP2] @ jump instr. (actually call) address + 4 subs r12,r2, r1 moveq r3, #0xe1000000 orreq r3, r3, #0x00a00000 @ nop streq r3, [r1, #-4] beq ssp_drc_dp_end cmp r12,#4 ldreq r3, [r1] addeq r3, r3, #1 streq r3, [r1, #-4] @ move the other cond up moveq r3, #0xe1000000 orreq r3, r3, #0x00a00000 streq r3, [r1] @ fill it's place with nop beq ssp_drc_dp_end ldr r3, [r1, #-4] sub r12,r12,#4 mov r3, r3, lsr #24 bic r3, r3, #1 @ L bit orr r3, r3, r12,lsl #6 mov r3, r3, ror #8 @ patched branch instruction str r3, [r1, #-4] ssp_drc_dp_end: str r2, [r7, #SSP_OFFS_TMP1] sub r0, r1, #4 add r1, r1, #4 bl flush_inval_caches ldr r2, [r7, #SSP_OFFS_TMP1] ldr r0, [r7, #SSP_OFFS_TMP0] bx r2 ssp_drc_end: mov r0, r0, lsl #16 str r0, [r7, #(SSP_OFFS_GR+SSP_PC*4)] ssp_regfile_store: str r10,[r7, #(0x400+SSP_P*4)] @ P str r8, [r7, #0x440] @ r0-r2 str r9, [r7, #0x444] @ r4-r6 mov r9, r6, lsr #13 and r9, r9, #(7<<16) @ STACK mov r3, r6, lsl #28 msr cpsr_flg, r3 @ to to ARM PSR and r6, r6, #0x670 mov r6, r6, lsl #12 orrmi r6, r6, #0x80000000 @ N orreq r6, r6, #0x20000000 @ Z mov r3, r4, lsl #16 @ Y mov r2, r4, lsr #16 mov r2, r2, lsl #16 @ X add r8, r7, #0x400 add r8, r8, #4 stmia r8, {r2,r3,r5,r6,r9} mov r0, r11 ldmfd sp!, {r4-r11, lr} bx lr @ ld A, PM0 @ andi 2 @ bra z=1, gloc_0800 ssp_hle_800: ldr r0, [r7, #(SSP_OFFS_GR+SSP_PM0*4)] ldr r1, [r7, #SSP_OFFS_EMUSTAT] tst r0, #0x20000 orreq r1, r1, #SSP_WAIT_PM0 subeq r11,r11, #1024 streq r1, [r7, #SSP_OFFS_EMUSTAT] mov r0, #0x400 beq ssp_drc_end orrne r0, r0, #0x004 b ssp_drc_next ssp_hle_902: cmp r11, #0 ble ssp_drc_end add r1, r7, #0x200 ldrh r0, [r1] ldr r3, [r7, #SSP_OFFS_IRAM_ROM] add r2, r3, r0, lsl #1 @ (r7|00) ldrh r0, [r2], #2 mov r5, r5, lsl #16 mov r5, r5, lsr #16 bic r0, r0, #0xfc00 add r3, r3, r0, lsl #1 @ IRAM dest ldrh r12,[r2], #2 @ length bic r3, r3, #3 @ always seen aligned @ orr r5, r5, #0x08000000 @ orr r5, r5, #0x00880000 @ sub r5, r5, r12, lsl #16 bic r6, r6, #0xf add r12,r12,#1 mov r0, #1 str r0, [r7, #SSP_OFFS_IRAM_DIRTY] sub r11,r11,r12,lsl #1 sub r11,r11,r12 @ -= length*3 ssp_hle_902_loop: ldrh r0, [r2], #2 ldrh r1, [r2], #2 subs r12,r12,#2 orr r0, r0, r1, lsl #16 str r0, [r3], #4 bgt ssp_hle_902_loop tst r12, #1 ldrneh r0, [r2], #2 strneh r0, [r3], #2 ldr r0, [r7, #SSP_OFFS_IRAM_ROM] add r1, r7, #0x200 sub r2, r2, r0 mov r2, r2, lsr #1 strh r2, [r1] @ (r7|00) sub r0, r3, r0 mov r0, r0, lsr #1 orr r0, r0, #0x08000000 orr r0, r0, #0x001c8000 str r0, [r7, #(SSP_OFFS_GR+SSP_PMC*4)] str r0, [r7, #(SSP_OFFS_PM_WRITE+4*4)] sub r6, r6, #0x20000000 add r1, r7, #0x400 add r1, r1, #0x048 @ stack add r1, r1, r6, lsr #28 ldrh r0, [r1] subs r11,r11,#16 @ timeslice is likely to end ble ssp_drc_end b ssp_drc_next