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: |
ce5be1b5 |
31 | stmfd sp!, {r4-r8,r10,r11,lr} |
7336a99a |
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 |
99464b62 |
44 | ldr r10,=SekCycleAimS68k |
7336a99a |
45 | ldr r2, [r8] |
99464b62 |
46 | ldr r3, [r10] |
7336a99a |
47 | add r2, r2, r0 |
48 | add r3, r3, r1 |
49 | str r2, [r8] |
99464b62 |
50 | str r3, [r10] |
7336a99a |
51 | |
58b75cc5 |
52 | ldr r6, =CycloneJumpTab |
7336a99a |
53 | ldr r1, =SekCycleCnt |
54 | ldr r0, =((488<<16)-PS_STEP_M68K) |
58b75cc5 |
55 | str r6, [r7,#0x54] |
56 | str r6, [lr,#0x54] @ make copies to avoid literal pools |
7336a99a |
57 | |
58 | @ schedule m68k for the first time.. |
59 | ldr r1, [r1] |
60 | str r0, [sp] @ main target 'left cycle' counter |
61 | sub r1, r2, r1 |
62 | subs r5, r1, r0, asr #16 |
63 | ble schedule_s68k @ m68k has not enough cycles |
64 | |
65 | str r5, [sp,#4] @ run_cycle_cnt |
66 | b CycloneRunLocal |
67 | |
68 | |
69 | |
70 | CycloneEnd_M68k: |
71 | ldr r3, =SekCycleCnt |
72 | ldr r0, [sp,#4] @ run_cycle_cnt |
73 | ldr r1, [r3] |
74 | str r4, [r7,#0x40] ;@ Save Current PC + Memory Base |
99464b62 |
75 | strb r10,[r7,#0x46] ;@ Save Flags (NZCV) |
7336a99a |
76 | sub r0, r0, r5 @ subtract leftover cycles (which should be negative) |
77 | add r0, r0, r1 |
78 | str r0, [r3] |
79 | |
80 | schedule_s68k: |
81 | ldr r8, =SekCycleCntS68k |
99464b62 |
82 | ldr r10,=SekCycleAimS68k |
7336a99a |
83 | ldr r3, [sp] |
84 | ldr r8, [r8] |
99464b62 |
85 | ldr r10,[r10] |
7336a99a |
86 | |
99464b62 |
87 | sub r0, r10, r8 |
66fdc0f0 |
88 | mov r2, r3 |
89 | add r3, r3, r2, asr #1 |
90 | add r3, r3, r2, asr #3 @ cycn_s68k = (cycn + cycn/2 + cycn/8) |
7336a99a |
91 | |
92 | subs r5, r0, r3, asr #16 |
93 | ble schedule_m68k @ s68k has not enough cycles |
94 | |
3aa1e148 |
95 | ldr r7, =PicoCpuCS68k |
7336a99a |
96 | str r5, [sp,#4] @ run_cycle_cnt |
97 | b CycloneRunLocal |
98 | |
99 | |
100 | |
101 | CycloneEnd_S68k: |
102 | ldr r3, =SekCycleCntS68k |
103 | ldr r0, [sp,#4] @ run_cycle_cnt |
104 | ldr r1, [r3] |
105 | str r4, [r7,#0x40] ;@ Save Current PC + Memory Base |
99464b62 |
106 | strb r10,[r7,#0x46] ;@ Save Flags (NZCV) |
7336a99a |
107 | sub r0, r0, r5 @ subtract leftover cycles (should be negative) |
108 | add r0, r0, r1 |
109 | str r0, [r3] |
110 | |
111 | schedule_m68k: |
112 | ldr r1, =PS_STEP_M68K |
113 | ldr r3, [sp] @ main_cycle_cnt |
114 | ldr r8, =SekCycleCnt |
99464b62 |
115 | ldr r10,=SekCycleAim |
7336a99a |
116 | subs r3, r3, r1 |
117 | bmi SekRunPS_end |
118 | |
119 | ldr r8, [r8] |
99464b62 |
120 | ldr r10,[r10] |
7336a99a |
121 | str r3, [sp] @ update main_cycle_cnt |
99464b62 |
122 | sub r0, r10, r8 |
7336a99a |
123 | |
124 | subs r5, r0, r3, asr #16 |
125 | ble schedule_s68k @ m68k has not enough cycles |
126 | |
3aa1e148 |
127 | ldr r7, =PicoCpuCM68k |
7336a99a |
128 | str r5, [sp,#4] @ run_cycle_cnt |
129 | b CycloneRunLocal |
130 | |
131 | |
132 | |
133 | SekRunPS_end: |
3aa1e148 |
134 | ldr r7, =PicoCpuCM68k |
135 | ldr lr, =PicoCpuCS68k |
7336a99a |
136 | mov r0, #0 |
0af33fe0 |
137 | str r0, [r7,#0x98] @ remove CycloneEnd handler |
138 | str r0, [lr,#0x98] |
7336a99a |
139 | @ return |
140 | add sp, sp, #2*4 |
ce5be1b5 |
141 | ldmfd sp!, {r4-r8,r10,r11,pc} |
7336a99a |
142 | |
143 | |
144 | |
7336a99a |
145 | CycloneRunLocal: |
146 | ;@ r0-3 = Temporary registers |
147 | ldr r4,[r7,#0x40] ;@ r4 = Current PC + Memory Base |
148 | ;@ r5 = Cycles |
149 | ;@ r6 = Opcode Jump table |
150 | ;@ r7 = Pointer to Cpu Context |
151 | ;@ r8 = Current Opcode |
99464b62 |
152 | ldrb r10,[r7,#0x46];@ r10 = Flags (NZCV) |
66fdc0f0 |
153 | ldr r1,[r7,#0x44] ;@ get SR high and IRQ level |
99464b62 |
154 | orr r10,r10,r10,lsl #28 ;@ r10 = Flags 0xf0000000, cpsr format |
7336a99a |
155 | |
156 | ;@ CheckInterrupt: |
66fdc0f0 |
157 | movs r0,r1,lsr #24 ;@ Get IRQ level |
7336a99a |
158 | beq NoIntsLocal |
159 | cmp r0,#6 ;@ irq>6 ? |
7336a99a |
160 | andle r1,r1,#7 ;@ Get interrupt mask |
161 | cmple r0,r1 ;@ irq<=6: Is irq<=mask ? |
0af33fe0 |
162 | bgt CycloneDoInterrupt |
7336a99a |
163 | NoIntsLocal: |
164 | |
0af33fe0 |
165 | ;@ Check if our processor is in special state |
166 | ;@ and jump to opcode handler if not |
167 | ldr r0,[r7,#0x58] ;@ state_flags |
7336a99a |
168 | ldrh r8,[r4],#2 ;@ Fetch first opcode |
0af33fe0 |
169 | tst r0,#0x03 ;@ special state? |
99464b62 |
170 | andeq r10,r10,#0xf0000000 |
7336a99a |
171 | ldreq pc,[r6,r8,asl #2] ;@ Jump to opcode handler |
172 | |
0af33fe0 |
173 | CycloneSpecial2: |
174 | tst r0,#2 ;@ tracing? |
175 | bne CycloneDoTrace |
176 | ;@ stopped or halted |
66fdc0f0 |
177 | sub r4,r4,#2 |
0af33fe0 |
178 | ldr r1,[r7,#0x98] |
7336a99a |
179 | mov r5,#0 |
180 | bx r1 |
181 | |