3 @ SekRunPS runs PicoCpu and PicoCpuS68k interleaved in steps of PS_STEP_M68K
4 @ cycles. This is done without calling CycloneRun and jumping directly to
5 @ Cyclone code to avoid pushing/popping all the registers every time.
7 @ (c) Copyright 2007, Grazvydas "notaz" Ignotas
11 .equiv PS_STEP_M68K, ((488<<16)/20) @ ~24
13 @ .extern is ignored by gas, we add these here just to see what we depend on.
14 .extern CycloneJumpTab
15 .extern CycloneDoInterrupt
20 .extern SekCycleAimS68k
21 .extern SekCycleCntS68k
28 .global SekRunPS @ cyc_m68k, cyc_s68k
31 stmfd sp!, {r4-r11,lr}
32 sub sp, sp, #2*4 @ sp[0] = main_cycle_cnt, sp[4] = run_cycle_cnt
34 @ override CycloneEnd for both contexts
37 ldr r2, =CycloneEnd_M68k
38 ldr r3, =CycloneEnd_S68k
44 ldr r9, =SekCycleAimS68k
53 ldr r0, =((488<<16)-PS_STEP_M68K)
54 ldr r6, =CycloneJumpTab
56 @ schedule m68k for the first time..
58 str r0, [sp] @ main target 'left cycle' counter
60 subs r5, r1, r0, asr #16
61 ble schedule_s68k @ m68k has not enough cycles
63 str r5, [sp,#4] @ run_cycle_cnt
70 ldr r0, [sp,#4] @ run_cycle_cnt
72 str r4, [r7,#0x40] ;@ Save Current PC + Memory Base
73 strb r9, [r7,#0x46] ;@ Save Flags (NZCV)
74 sub r0, r0, r5 @ subtract leftover cycles (which should be negative)
79 ldr r8, =SekCycleCntS68k
80 ldr r9, =SekCycleAimS68k
86 add r3, r3, r3, asr #1
87 add r3, r3, r3, asr #3 @ cycn_s68k = (cycn + cycn/2 + cycn/8)
89 subs r5, r0, r3, asr #16
90 ble schedule_m68k @ s68k has not enough cycles
93 str r5, [sp,#4] @ run_cycle_cnt
99 ldr r3, =SekCycleCntS68k
100 ldr r0, [sp,#4] @ run_cycle_cnt
102 str r4, [r7,#0x40] ;@ Save Current PC + Memory Base
103 strb r9, [r7,#0x46] ;@ Save Flags (NZCV)
104 sub r0, r0, r5 @ subtract leftover cycles (should be negative)
109 ldr r1, =PS_STEP_M68K
110 ldr r3, [sp] @ main_cycle_cnt
118 str r3, [sp] @ update main_cycle_cnt
121 subs r5, r0, r3, asr #16
122 ble schedule_s68k @ m68k has not enough cycles
125 str r5, [sp,#4] @ run_cycle_cnt
134 str r0, [r7,#0x54] @ remove CycloneEnd handler
138 ldmfd sp!, {r4-r11,pc}
144 ;@ r0-3 = Temporary registers
145 ldr r4,[r7,#0x40] ;@ r4 = Current PC + Memory Base
147 ;@ r6 = Opcode Jump table
148 ;@ r7 = Pointer to Cpu Context
149 ;@ r8 = Current Opcode
150 ldrb r9,[r7,#0x46] ;@ r9 = Flags (NZCV)
152 mov r9,r9,lsl #28 ;@ r9 = Flags 0xf0000000, cpsr format
153 ;@ r10 = Source value / Memory Base
156 movs r0,r0,lsr #24 ;@ Get IRQ level
159 ldrleb r1,[r7,#0x44] ;@ Get SR high: T_S__III
160 andle r1,r1,#7 ;@ Get interrupt mask
161 cmple r0,r1 ;@ irq<=6: Is irq<=mask ?
162 blgt CycloneDoInterrupt
163 ;@ Check if interrupt used up all the cycles:
166 bxlt r1 ;@ jump to alternative CycloneEnd
169 ;@ Check if our processor is in stopped state and jump to opcode handler if not
171 ldrh r8,[r4],#2 ;@ Fetch first opcode
172 tst r0,r0 ;@ stopped?
173 ldreq pc,[r6,r8,asl #2] ;@ Jump to opcode handler