@ 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 @ 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_OFFS_EMUSTAT 0x484 // emu_status #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