SekRunPS Cyclone integration
[picodrive.git] / Pico / cd / Pico.s
CommitLineData
7336a99a 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
30SekRunPS:
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
68CycloneEnd_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
78schedule_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
98CycloneEnd_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
108schedule_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
130SekRunPS_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
143CycloneRunLocal:
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
167NoIntsLocal:
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