@ vim:filetype=armasm @ ranges/opcodes (idle, normal): @ 71xx, 73xx - bne.s (8bit offset) @ 75xx, 77xx - beq.s (8bit offset) @ 7dxx, 7fxx - bra.s (8bit offset) .data .align 2 have_patches: .word 0 .equ patch_desc_table_size, 10 patch_desc_table: .word (0x71fa<<16) | 0x66fa, idle_detector_bcc8, idle_bne, Op6602 @ bne.s .word (0x71f8<<16) | 0x66f8, idle_detector_bcc8, idle_bne, Op6602 @ bne.s .word (0x71f6<<16) | 0x66f6, idle_detector_bcc8, idle_bne, Op6602 @ bne.s .word (0x71f2<<16) | 0x66f2, idle_detector_bcc8, idle_bne, Op6602 @ bne.s .word (0x75fa<<16) | 0x67fa, idle_detector_bcc8, idle_beq, Op6702 @ beq.s .word (0x75f8<<16) | 0x67f8, idle_detector_bcc8, idle_beq, Op6702 @ beq.s .word (0x75f6<<16) | 0x67f6, idle_detector_bcc8, idle_beq, Op6702 @ beq.s .word (0x75f2<<16) | 0x67f2, idle_detector_bcc8, idle_beq, Op6702 @ beq.s .word (0x7dfe<<16) | 0x60fe, idle_detector_bcc8, idle_bra, Op6002 @ bra.s .word (0x7dfc<<16) | 0x60fc, idle_detector_bcc8, idle_bra, Op6002 @ bra.s .text .align 2 .global CycloneInitIdle CycloneInitIdle: adr r12,offset_table ldr r3, [r12, #2*4] @ =CycloneJumpTab-ot ldr r2, [r12, #1*4] @ =patch_desc_table-ot add r3, r3, r12 add r2, r2, r12 mov r12,#patch_desc_table_size cii_loop: ldrh r0, [r2] ldr r1, [r2, #4] @ detector str r1, [r3, r0, lsl #2] ldrh r0, [r2, #2] ldr r1, [r2, #8] @ idle add r0, r3, r0, lsl #2 str r1, [r0] ldr r1, [r2, #12] @ normal str r1, [r0, #0x800] add r2, r2, #16 subs r12,r12,#1 bgt cii_loop adr r12,offset_table ldr r0, [r12, #0*4] @ =have_patches-ot mov r1, #1 str r1, [r0, r12] bx lr .global CycloneFinishIdle CycloneFinishIdle: adr r12,offset_table ldr r3, [r12, #0*4] @ =have_patches-ot ldr r0, [r3, r12]! tst r0, r0 bxeq lr stmfd sp!, {r4,r5} mov r5, r3 ldr r2, [r12, #1*4] @ =patch_desc_table-ot ldr r3, [r12, #2*4] @ =CycloneJumpTab-ot ldr r4, [r12, #3*4] @ =Op____-ot add r2, r2, r12 add r3, r3, r12 add r4, r4, r12 mov r12,#patch_desc_table_size cfi_loop: ldrh r0, [r2] ldr r1, [r2, #12] @ normal str r1, [r3, r0, lsl #2] ldrh r0, [r2, #2] add r0, r3, r0, lsl #2 str r4, [r0] @ Op____ str r4, [r0, #0x800] add r2, r2, #16 subs r12,r12,#1 bgt cfi_loop mov r1, #0 str r1, [r5] @ have_patches ldmfd sp!, {r4,r5} bx lr .macro inc_counter cond @ ldr\cond r0, [r7, #0x60] @ mov r11,lr @ sub r0, r4, r0 @ sub r0, r0, #2 @ bl\cond SekRegisterIdleHit @ mov lr, r11 .endm idle_bra: mov r5, #2 inc_counter b Op6002 idle_bne: tst r10, #0x40000000 @ Z set? moveq r5, #2 @ 2 is intentional due to strange timing issues inc_counter eq b Op6602 idle_beq: tst r10, #0x40000000 @ Z set? movne r5, #2 inc_counter ne b Op6702 @ @@@ @ idle_detector_bcc8: bl SekIsIdleReady tst r0, r0 beq exit_detector @ not yet mov r0, r8, asl #24 @ Shift 8-bit signed offset up... add r0, r4, r0, asr #24 @ jump dest bic r0, r0, #1 mov r1, #0 sub r1, r1, r8, lsl #24 mov r1, r1, lsr #24 sub r1, r1, #2 bic r1, r1, #1 bl SekIsIdleCode tst r0, r0 and r2, r8, #0x00ff orr r2, r2, #0x7100 orreq r2, r2, #0x0200 mov r0, r8, lsr #8 cmp r0, #0x66 orrgt r2, r2, #0x0400 @ 67xx (beq) orrlt r2, r2, #0x0c00 @ 60xx (bra) @ r2 = patch_opcode sub r0, r4, #2 ldrh r1, [r0] mov r11,r2 mov r3, r7 bl SekRegisterIdlePatch cmp r0, #1 @ 0 - ok to patch, 1 - no patch, 2 - remove detector strlth r11,[r4, #-2] ble exit_detector @ remove detector from Cyclone adr r12,offset_table mov r0, r8, lsr #8 cmp r0, #0x66 ldrlt r1, [r12, #4*4] @ =Op6002-ot ldreq r1, [r12, #4*5] @ =Op6602-ot ldrgt r1, [r12, #4*6] @ =Op6702-ot add r1, r1, r12 str r1, [r6, r8, lsl #2] bx r1 exit_detector: mov r0, r8, lsr #8 cmp r0, #0x66 blt Op6002 beq Op6602 b Op6702 offset_table: .word have_patches - offset_table .word patch_desc_table - offset_table .word CycloneJumpTab - offset_table .word Op____ - offset_table .word Op6002 - offset_table .word Op6602 - offset_table @ 5 .word Op6702 - offset_table