7336a99a |
1 | @ vim:filetype=armasm |
2 | |
3aa1e148 |
3 | @ SekRunPS runs PicoCpuCM68k and PicoCpuCS68k interleaved in steps of PS_STEP_M68K |
7336a99a |
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 |
3aa1e148 |
16 | .extern PicoCpuCM68k |
17 | .extern PicoCpuCS68k |
7336a99a |
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 |
3aa1e148 |
35 | ldr r7, =PicoCpuCM68k |
36 | ldr lr, =PicoCpuCS68k |
7336a99a |
37 | ldr r2, =CycloneEnd_M68k |
38 | ldr r3, =CycloneEnd_S68k |
0af33fe0 |
39 | str r2, [r7,#0x98] |
40 | str r3, [lr,#0x98] |
7336a99a |
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 |
66fdc0f0 |
86 | mov r2, r3 |
87 | add r3, r3, r2, asr #1 |
88 | add r3, r3, r2, asr #3 @ cycn_s68k = (cycn + cycn/2 + cycn/8) |
7336a99a |
89 | |
90 | subs r5, r0, r3, asr #16 |
91 | ble schedule_m68k @ s68k has not enough cycles |
92 | |
3aa1e148 |
93 | ldr r7, =PicoCpuCS68k |
7336a99a |
94 | str r5, [sp,#4] @ run_cycle_cnt |
95 | b CycloneRunLocal |
96 | |
97 | |
98 | |
99 | CycloneEnd_S68k: |
100 | ldr r3, =SekCycleCntS68k |
101 | ldr r0, [sp,#4] @ run_cycle_cnt |
102 | ldr r1, [r3] |
103 | str r4, [r7,#0x40] ;@ Save Current PC + Memory Base |
104 | strb r9, [r7,#0x46] ;@ Save Flags (NZCV) |
105 | sub r0, r0, r5 @ subtract leftover cycles (should be negative) |
106 | add r0, r0, r1 |
107 | str r0, [r3] |
108 | |
109 | schedule_m68k: |
110 | ldr r1, =PS_STEP_M68K |
111 | ldr r3, [sp] @ main_cycle_cnt |
112 | ldr r8, =SekCycleCnt |
113 | ldr r9, =SekCycleAim |
114 | subs r3, r3, r1 |
115 | bmi SekRunPS_end |
116 | |
117 | ldr r8, [r8] |
118 | ldr r9, [r9] |
119 | str r3, [sp] @ update main_cycle_cnt |
120 | sub r0, r9, r8 |
121 | |
122 | subs r5, r0, r3, asr #16 |
123 | ble schedule_s68k @ m68k has not enough cycles |
124 | |
3aa1e148 |
125 | ldr r7, =PicoCpuCM68k |
7336a99a |
126 | str r5, [sp,#4] @ run_cycle_cnt |
127 | b CycloneRunLocal |
128 | |
129 | |
130 | |
131 | SekRunPS_end: |
3aa1e148 |
132 | ldr r7, =PicoCpuCM68k |
133 | ldr lr, =PicoCpuCS68k |
7336a99a |
134 | mov r0, #0 |
0af33fe0 |
135 | str r0, [r7,#0x98] @ remove CycloneEnd handler |
136 | str r0, [lr,#0x98] |
7336a99a |
137 | @ return |
138 | add sp, sp, #2*4 |
139 | ldmfd sp!, {r4-r11,pc} |
140 | |
141 | |
142 | |
7336a99a |
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) |
66fdc0f0 |
151 | ldr r1,[r7,#0x44] ;@ get SR high and IRQ level |
152 | orr r9,r9,r9,lsl #28 ;@ r9 = Flags 0xf0000000, cpsr format |
7336a99a |
153 | ;@ r10 = Source value / Memory Base |
154 | |
155 | ;@ CheckInterrupt: |
66fdc0f0 |
156 | movs r0,r1,lsr #24 ;@ Get IRQ level |
7336a99a |
157 | beq NoIntsLocal |
158 | cmp r0,#6 ;@ irq>6 ? |
7336a99a |
159 | andle r1,r1,#7 ;@ Get interrupt mask |
160 | cmple r0,r1 ;@ irq<=6: Is irq<=mask ? |
0af33fe0 |
161 | bgt CycloneDoInterrupt |
7336a99a |
162 | NoIntsLocal: |
163 | |
0af33fe0 |
164 | ;@ Check if our processor is in special state |
165 | ;@ and jump to opcode handler if not |
166 | ldr r0,[r7,#0x58] ;@ state_flags |
7336a99a |
167 | ldrh r8,[r4],#2 ;@ Fetch first opcode |
0af33fe0 |
168 | tst r0,#0x03 ;@ special state? |
66fdc0f0 |
169 | andeq r9,r9,#0xf0000000 |
7336a99a |
170 | ldreq pc,[r6,r8,asl #2] ;@ Jump to opcode handler |
171 | |
0af33fe0 |
172 | CycloneSpecial2: |
173 | tst r0,#2 ;@ tracing? |
174 | bne CycloneDoTrace |
175 | ;@ stopped or halted |
66fdc0f0 |
176 | sub r4,r4,#2 |
0af33fe0 |
177 | ldr r1,[r7,#0x98] |
7336a99a |
178 | mov r5,#0 |
179 | bx r1 |
180 | |