SekRunPS Cyclone integration
[picodrive.git] / Pico / cd / Pico.s
1 @ vim:filetype=armasm
2
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.
6
7 @ (c) Copyright 2007, Grazvydas "notaz" Ignotas
8 @ All Rights Reserved
9
10
11 .equiv PS_STEP_M68K, ((488<<16)/20) @ ~24
12
13 @ .extern is ignored by gas, we add these here just to see what we depend on.
14 .extern CycloneJumpTab
15 .extern CycloneDoInterrupt
16 .extern PicoCpu
17 .extern PicoCpuS68k
18 .extern SekCycleAim
19 .extern SekCycleCnt
20 .extern SekCycleAimS68k
21 .extern SekCycleCntS68k
22
23
24 .text
25 .align 4
26
27
28 .global SekRunPS @ cyc_m68k, cyc_s68k
29
30 SekRunPS:
31     stmfd   sp!, {r4-r11,lr}
32     sub     sp, sp, #2*4          @ sp[0] = main_cycle_cnt, sp[4] = run_cycle_cnt
33
34     @ override CycloneEnd for both contexts
35     ldr     r7, =PicoCpu
36     ldr     lr, =PicoCpuS68k
37     ldr     r2, =CycloneEnd_M68k
38     ldr     r3, =CycloneEnd_S68k
39     str     r2, [r7,#0x54]
40     str     r3, [lr,#0x54]
41
42     @ update aims
43     ldr     r8, =SekCycleAim
44     ldr     r9, =SekCycleAimS68k
45     ldr     r2, [r8]
46     ldr     r3, [r9]
47     add     r2, r2, r0
48     add     r3, r3, r1
49     str     r2, [r8]
50     str     r3, [r9]
51
52     ldr     r1, =SekCycleCnt
53     ldr     r0, =((488<<16)-PS_STEP_M68K)
54     ldr     r6, =CycloneJumpTab
55
56     @ schedule m68k for the first time..
57     ldr     r1, [r1]
58     str     r0, [sp]                  @ main target 'left cycle' counter
59     sub     r1, r2, r1
60     subs    r5, r1, r0, asr #16
61     ble     schedule_s68k             @ m68k has not enough cycles
62
63     str     r5, [sp,#4]               @ run_cycle_cnt
64     b       CycloneRunLocal
65
66
67
68 CycloneEnd_M68k:
69     ldr     r3, =SekCycleCnt
70     ldr     r0, [sp,#4]               @ run_cycle_cnt
71     ldr     r1, [r3]
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)
75     add     r0, r0, r1
76     str     r0, [r3]
77
78 schedule_s68k:
79     ldr     r8, =SekCycleCntS68k
80     ldr     r9, =SekCycleAimS68k
81     ldr     r3, [sp]
82     ldr     r8, [r8]
83     ldr     r9, [r9]
84
85     sub     r0, r9, r8
86     add     r3, r3, r3, asr #1
87     add     r3, r3, r3, asr #3        @ cycn_s68k = (cycn + cycn/2 + cycn/8)
88
89     subs    r5, r0, r3, asr #16
90     ble     schedule_m68k             @ s68k has not enough cycles
91
92     ldr     r7, =PicoCpuS68k
93     str     r5, [sp,#4]               @ run_cycle_cnt
94     b       CycloneRunLocal
95
96
97
98 CycloneEnd_S68k:
99     ldr     r3, =SekCycleCntS68k
100     ldr     r0, [sp,#4]               @ run_cycle_cnt
101     ldr     r1, [r3]
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)
105     add     r0, r0, r1
106     str     r0, [r3]
107
108 schedule_m68k:
109     ldr     r1, =PS_STEP_M68K
110     ldr     r3, [sp]                  @ main_cycle_cnt
111     ldr     r8, =SekCycleCnt
112     ldr     r9, =SekCycleAim
113     subs    r3, r3, r1
114     bmi     SekRunPS_end
115
116     ldr     r8, [r8]
117     ldr     r9, [r9]
118     str     r3, [sp]                  @ update main_cycle_cnt
119     sub     r0, r9, r8
120
121     subs    r5, r0, r3, asr #16
122     ble     schedule_s68k             @ m68k has not enough cycles
123
124     ldr     r7, =PicoCpu
125     str     r5, [sp,#4]               @ run_cycle_cnt
126     b       CycloneRunLocal
127
128
129
130 SekRunPS_end:
131     ldr     r7, =PicoCpu
132     ldr     lr, =PicoCpuS68k
133     mov     r0, #0
134     str     r0, [r7,#0x54]            @ remove CycloneEnd handler
135     str     r0, [lr,#0x54]
136     @ return
137     add     sp, sp, #2*4
138     ldmfd   sp!, {r4-r11,pc}
139
140
141
142
143 CycloneRunLocal:
144                      ;@ r0-3 = Temporary registers
145   ldr r4,[r7,#0x40]  ;@ r4 = Current PC + Memory Base
146                      ;@ r5 = Cycles
147                      ;@ r6 = Opcode Jump table
148                      ;@ r7 = Pointer to Cpu Context
149                      ;@ r8 = Current Opcode
150   ldrb r9,[r7,#0x46] ;@ r9 = Flags (NZCV)
151   ldr r0,[r7,#0x44]
152   mov r9,r9,lsl #28  ;@ r9 = Flags 0xf0000000, cpsr format
153                      ;@ r10 = Source value / Memory Base
154
155 ;@ CheckInterrupt:
156   movs r0,r0,lsr #24 ;@ Get IRQ level
157   beq NoIntsLocal
158   cmp r0,#6 ;@ irq>6 ?
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:
164   subs r5,r5,#0
165   ldrlt r1,[r7,#0x54]
166   bxlt r1            ;@ jump to alternative CycloneEnd
167 NoIntsLocal:
168
169 ;@ Check if our processor is in stopped state and jump to opcode handler if not
170   ldr r0,[r7,#0x58]
171   ldrh r8,[r4],#2 ;@ Fetch first opcode
172   tst r0,r0 ;@ stopped?
173   ldreq pc,[r6,r8,asl #2] ;@ Jump to opcode handler
174
175   @ stopped
176   ldr r1,[r7,#0x54]
177   mov r5,#0
178   bx r1
179