1 /* Mednafen - Multi-system Emulator
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
17
18 #include "pce.h"
19 #include "vdc.h"
20
21 namespace PCE_Fast
22 {
23
24 static uint8 dummy_bank[8192 + 8192]; // + 8192 for PC-as-ptr safety padding
25 HuC6280 HuCPU;
26
27 #define HU_PC PC_local //HuCPU.PC
28 #define HU_PC_base HuCPU.PC_base
29 #define HU_A HuCPU.A
30 #define HU_X X_local //HuCPU.X
31 #define HU_Y Y_local //HuCPU.Y
32 #define HU_S HuCPU.S
33 #define HU_P P_local //HuCPU.P
34 #define HU_PI HuCPU.mooPI
35 #define HU_IRQlow HuCPU.IRQlow
36 #define HU_Page1 Page1_local
37 //HuCPU.Page1
38 //Page1_local //HuCPU.Page1
39
40 #ifdef HUC6280_LAZY_FLAGS
41 #define HU_ZNFlags HuCPU.ZNFlags
42 #endif
43
44
45 #ifdef HUC6280_CRAZY_VERSION
46 #define LOAD_LOCALS_PC() uintptr_t PC_local = HuCPU.PC;
47 #else
48 #define LOAD_LOCALS_PC() uint32 PC_local /*asm ("edi")*/ = HuCPU.PC; // asm ("edi") = HuCPU.PC;
49 #endif
50
51 #define LOAD_LOCALS() \
52 LOAD_LOCALS_PC(); \
53 uint8 X_local = HuCPU.X; \
54 uint8 Y_local = HuCPU.Y; \
55 uint8 P_local = HuCPU.P; \
56 uint8 *Page1_local = HuCPU.Page1;
57
58 #define SAVE_LOCALS() HuCPU.PC = PC_local; \
59 HuCPU.X = X_local; \
60 HuCPU.Y = Y_local; \
61 HuCPU.P = P_local; \
62 HuCPU.Page1 = Page1_local;
63
64 #ifdef HUC6280_LAZY_FLAGS
65 #define COMPRESS_FLAGS() HU_P &= ~(N_FLAG | Z_FLAG); HU_P |= ((HU_ZNFlags >> 24) & 0x80) | ((HU_ZNFlags & 0xFF) ? 0 : Z_FLAG);
66 //((((HU_ZNFlags & 0xFF) - 1) >> 8) & Z_FLAG);
67 #define EXPAND_FLAGS() HU_ZNFlags = (HU_P << 24) | ((HU_P & Z_FLAG) ^ Z_FLAG);
68 #else
69 #define COMPRESS_FLAGS()
70 #define EXPAND_FLAGS()
71 #endif
72
73 #ifdef HUC6280_CRAZY_VERSION
74 #define GetRealPC() ((unsigned int)(HU_PC - HU_PC_base))
75 #define GetRealPC_EXTERNAL() ((unsigned int)(HuCPU.PC - HuCPU.PC_base))
76 #else
77 #define GetRealPC() (HU_PC)
78 #define GetRealPC_EXTERNAL() (HuCPU.PC)
79 #endif
80
81 #ifdef HUC6280_CRAZY_VERSION
82 #define SetPC(value) { unsigned int tempmoo = value; HU_PC = HuCPU.FastPageR[tempmoo >> 13] + tempmoo; \
83 HU_PC_base = HU_PC - tempmoo; }
84 #define SetPC_EXTERNAL(value) { unsigned int tempmoo = value; \
85 HuCPU.PC = HuCPU.FastPageR[tempmoo >> 13] + tempmoo; HuCPU.PC_base = HuCPU.PC - tempmoo; }
86 #else
87 #define SetPC(value) { HU_PC = (value); }
88 #define SetPC_EXTERNAL(value) { HuCPU.PC = (value); }
89 #endif
90
91 // Page change PC, GET IT?!
92 #ifdef HUC6280_CRAZY_VERSION
93 #define FixPC_PC() SetPC(GetRealPC());
94 #else
95 #define FixPC_PC()
96 #endif
97
98 //#define IncPC() { HU_PC++; if(!(GetRealPC() & 0x1FFF)) printf("Bank crossing: %04x\n", GetRealPC()); }
99 //#define IncPC() HU_PC++;
100 #if 0
101 #define IncPC() { HU_PC++; if(!(GetRealPC() & 0x1FFF) && \
102 HuCPU.MPR[(GetRealPC() - 1) >> 13] != (HuCPU.MPR[(GetRealPC()) >> 13] - 1)) \
103 printf("Bank crossing: %04x, %02x, %02x\n", GetRealPC(), HuCPU.MPR[(GetRealPC() - 1) >> 13], \
104 HuCPU.MPR[GetRealPC() >> 13]); }
105 #else
106 #define IncPC() HU_PC++;
107 #endif
108
109 #ifdef HUC6280_CRAZY_VERSION
110 #define RdAtPC() (*(uint8*)HU_PC)
111 #else
112 #define RdAtPC() RdOp(HU_PC)
113 #endif
114
115 // If we change this definition, we'll need to also fix HuC6280_StealCycle() in huc6280.h
116 #define ADDCYC(x) { HuCPU.timestamp += x; }
117
118 #define SET_MPR(arg_i, arg_v) \
119 { \
120 const unsigned int wmpr = arg_i, wbank = arg_v; \
121 if(wmpr == 1) \
122 { \
123 HU_Page1 = HuCPU.FastMap[wbank]; \
124 } \
125 HuCPU.MPR[wmpr] = wbank; \
126 HuCPU.FastPageR[wmpr] = (uintptr_t)HuCPU.FastMap[wbank] - wmpr * 8192; \
127 }
128
HuC6280_SetMPR(int i,int v)129 void HuC6280_SetMPR(int i, int v)
130 {
131 uint8 *Page1_local = HuCPU.Page1;
132
133 SET_MPR(i, v);
134
135 HuCPU.Page1 = Page1_local;
136 }
137
138
HuC6280_FlushMPRCache(void)139 static void HuC6280_FlushMPRCache(void)
140 {
141 for(int x = 0; x < 9; x++)
142 HuC6280_SetMPR(x, HuCPU.MPR[x & 0x7]);
143 }
144
RdMem(unsigned int A)145 static INLINE uint8 RdMem(unsigned int A)
146 {
147 uint8 wmpr = HuCPU.MPR[A >> 13];
148 return(HuCPU.PCERead[wmpr]((wmpr << 13) | (A & 0x1FFF)));
149 }
150
RdMem16(unsigned int A)151 static INLINE uint16 RdMem16(unsigned int A)
152 {
153 uint16 ret;
154
155 ret = RdMem(A);
156 ret |= RdMem(A + 1) << 8;
157
158 return(ret);
159 }
160
WrMem(unsigned int A,uint8 V)161 static INLINE void WrMem(unsigned int A, uint8 V)
162 {
163 uint8 wmpr = HuCPU.MPR[A >> 13];
164 HuCPU.PCEWrite[wmpr]((wmpr << 13) | (A & 0x1FFF), V);
165 }
166
RdOp(unsigned int A)167 static INLINE uint8 RdOp(unsigned int A)
168 {
169 return *(uint8*)(HuCPU.FastPageR[A >> 13] + A);
170 }
171
172 #define PUSH(V) \
173 { \
174 HU_Page1[0x100 + HU_S] = V; \
175 HU_S--; \
176 }
177
178 #define PUSH_PC() \
179 { \
180 unsigned int real_pc = GetRealPC(); \
181 PUSH(real_pc >> 8); \
182 PUSH(real_pc); \
183 }
184
185 #define POP() HU_Page1[0x100 + ++HU_S]
186
187 #define POP_PC() \
188 { \
189 unsigned int npc; \
190 npc = POP(); \
191 npc |= POP() << 8; \
192 SetPC(npc); \
193 }
194
195 // Hopefully we never RTS to 0x0000. ;)
196 #define POP_PC_AP() \
197 { \
198 uint32 npc; \
199 npc = POP(); \
200 npc |= POP() << 8; \
201 npc++; \
202 SetPC(npc); \
203 }
204
205 /* Some of these operations will only make sense if you know what the flag
206 constants are. */
207
208 #ifdef HUC6280_LAZY_FLAGS
209 #define X_ZN(zort) { HU_ZNFlags = (int32)(int8)(uint8)(zort); }
210 #define X_ZN_BIT(opres, argie) { HU_ZNFlags = (opres) | ((argie) << 24); }
211 #else
212 static uint8 ZNTable[256];
213 #define X_ZN(zort) HU_P&=~(Z_FLAG|N_FLAG);HU_P|=ZNTable[zort]
214 #define X_ZN_BIT(opres, argie) { HU_P &= ~(Z_FLAG | N_FLAG); HU_P |= ZNTable[opres] & Z_FLAG; HU_P |= argie & N_FLAG; }
215 #endif
216
217 #define JR(cond) \
218 { \
219 if(cond) \
220 { \
221 int32 disp; \
222 disp = 1 + (int8)RdAtPC(); \
223 ADDCYC(2); \
224 HU_PC+=disp; \
225 } \
226 else IncPC(); \
227 }
228
229 #define BRA \
230 { \
231 int32 disp; \
232 disp = 1 + (int8)RdAtPC(); \
233 HU_PC+=disp; \
234 }
235
236 #define BBRi(bitto) JR(!(x & (1 << bitto)))
237 #define BBSi(bitto) JR(x & (1 << bitto))
238
239 #define ST0 VDC_Write_ST(0, x)
240 #define ST1 VDC_Write_ST(2, x)
241 #define ST2 VDC_Write_ST(3, x)
242
243 #define LDA HU_A=x;X_ZN(HU_A)
244 #define LDX HU_X=x;X_ZN(HU_X)
245 #define LDY HU_Y=x;X_ZN(HU_Y)
246
247 /* All of the freaky arithmetic operations. */
248 #define AND HU_A&=x;X_ZN(HU_A);
249
250 #define BIT HU_P&=~V_FLAG; X_ZN_BIT(x & HU_A, x); HU_P |= x & V_FLAG;
251 #define EOR HU_A^=x;X_ZN(HU_A);
252 #define ORA HU_A|=x;X_ZN(HU_A);
253
254 #define ADC { \
255 if(HU_P & D_FLAG) \
256 { \
257 uint32 tmp; \
258 tmp = (HU_A & 0x0F) + (x & 0x0F) + (HU_P & 1); \
259 if(tmp >= 0x0A) \
260 tmp += 0x06; \
261 tmp += (HU_A & 0xF0) + (x & 0xF0); \
262 if(tmp >= 0xA0) \
263 tmp += 0x60; \
264 HU_P &= ~C_FLAG; \
265 if(tmp & 0xFF00) \
266 HU_P |= C_FLAG; \
267 HU_A = tmp; \
268 X_ZN(HU_A); \
269 } \
270 else \
271 { \
272 uint32 l=HU_A+x+(HU_P&1); \
273 HU_P&=~(C_FLAG|V_FLAG); \
274 HU_P|=((((HU_A^x)&0x80)^0x80) & ((HU_A^l)&0x80))>>1; \
275 HU_P|=(l>>8)&C_FLAG; \
276 HU_A=l; \
277 X_ZN(HU_A); \
278 } \
279 }
280
281 #define SBC if(HU_P & D_FLAG) \
282 { \
283 const uint8 m = (HU_A & 0xF) - (x & 0xF) - ((HU_P & 1) ^ 1); \
284 const uint8 n = (HU_A >> 4) - (x >> 4) - ((m >> 4) & 1); \
285 uint8 res = (n << 4) | (m & 0xF); \
286 if(m & 0x10) \
287 res -= 0x06; \
288 if(n & 0x10) \
289 res -= 0x60; \
290 HU_A = res; \
291 HU_P &= ~C_FLAG; \
292 HU_P |= ((n >> 4) & 0x1) ^ 1; \
293 X_ZN(HU_A); \
294 } else { \
295 uint32 l=HU_A-x-((HU_P&1)^1); \
296 HU_P&=~(C_FLAG|V_FLAG); \
297 HU_P|=((HU_A^l)&(HU_A^x)&0x80)>>1; \
298 HU_P|=((l>>8)&C_FLAG)^C_FLAG; \
299 HU_A=l; \
300 X_ZN(HU_A); \
301 }
302
303 #define CMPL(a1,a2) { \
304 uint32 t=a1-a2; \
305 X_ZN(t&0xFF); \
306 HU_P&=~C_FLAG; \
307 HU_P|=((t>>8)&C_FLAG)^C_FLAG; \
308 }
309
310 #define TAM for(int i = 0; i < 8; i ++) { \
311 if(x & (1 << i)) \
312 { \
313 SET_MPR(i, HU_A); \
314 } \
315 } SET_MPR(8, HuCPU.MPR[0]);
316
317 #define TMA for(int i = 0; i < 8; i ++) { \
318 if(x & (1 << i)) \
319 HU_A = HuCPU.MPR[i]; \
320 }
321
322 #define CSL
323 #define CSH
324
325 #define RMB(bitto) x &= ~(1 << (bitto & 7))
326 #define SMB(bitto) x |= 1 << (bitto & 7)
327
328 #define TSB { HU_P &= ~V_FLAG; X_ZN_BIT(x | HU_A, x); HU_P |= x & V_FLAG; x |= HU_A; }
329 #define TRB { HU_P &= ~V_FLAG; X_ZN_BIT(x & ~HU_A, x); HU_P |= x & V_FLAG; x &= ~HU_A; }
330 #define TST { HU_P &= ~V_FLAG; X_ZN_BIT(x & zoomhack, x); HU_P |= x & V_FLAG; }
331
332 #define CMP CMPL(HU_A,x)
333 #define CPX CMPL(HU_X,x)
334 #define CPY CMPL(HU_Y,x)
335
336 /* The following operations modify the byte being worked on. */
337 #define DEC x--;X_ZN(x)
338 #define INC x++;X_ZN(x)
339
340 #define ASL HU_P&=~C_FLAG;HU_P|=x>>7;x<<=1;X_ZN(x)
341 #define LSR HU_P&=~C_FLAG;HU_P|=x&1;x>>=1;X_ZN(x)
342
343 #define ROL { \
344 uint8 l=x>>7; \
345 x<<=1; \
346 x|=HU_P&C_FLAG; \
347 HU_P&=~C_FLAG; \
348 HU_P|=l; \
349 X_ZN(x); \
350 }
351 #define ROR { \
352 uint8 l=x&1; \
353 x>>=1; \
354 x|=(HU_P&C_FLAG)<<7; \
355 HU_P&=~C_FLAG; \
356 HU_P|=l; \
357 X_ZN(x); \
358 }
359
360 /* Absolute */
361 #define GetAB(target) \
362 { \
363 target=RdAtPC(); \
364 IncPC(); \
365 target|=RdAtPC()<<8; \
366 IncPC(); \
367 }
368
369 /* Absolute Indexed(for reads) */
370 #define GetABI(target, i) \
371 { \
372 unsigned int tmp; \
373 GetAB(tmp); \
374 target=tmp; \
375 target+=i; \
376 }
377
378 /* Zero Page */
379 #define GetZP(target) \
380 { \
381 target=RdAtPC(); \
382 IncPC(); \
383 }
384
385 /* Zero Page Indexed */
386 #define GetZPI(target,i) \
387 { \
388 target=i+RdAtPC(); \
389 IncPC(); \
390 }
391
392 /* Indirect */
393 #define GetIND(target) \
394 { \
395 uint8 tmp; \
396 tmp=RdAtPC(); \
397 IncPC(); \
398 target=HU_Page1[tmp]; \
399 tmp++; \
400 target|=HU_Page1[tmp]<<8; \
401 }
402
403
404 /* Indexed Indirect */
405 #define GetIX(target) \
406 { \
407 uint8 tmp; \
408 tmp=RdAtPC(); \
409 IncPC(); \
410 tmp+=HU_X; \
411 target=HU_Page1[tmp]; \
412 tmp++; \
413 target|=HU_Page1[tmp] <<8; \
414 }
415
416 /* Indirect Indexed(for reads) */
417 #define GetIY(target) \
418 { \
419 unsigned int rt; \
420 uint8 tmp; \
421 tmp=RdAtPC(); \
422 rt=HU_Page1[tmp]; \
423 tmp++; \
424 rt|=HU_Page1[tmp]<<8; \
425 target = (rt + HU_Y); \
426 IncPC(); \
427 }
428
429 /* Now come the macros to wrap up all of the above stuff addressing mode functions
430 and operation macros. Note that operation macros will always operate(redundant
431 redundant) on the variable "x".
432 */
433
434 #define RMW_A(op) {uint8 x=HU_A; op; HU_A=x; break; } /* Meh... */
435 #define RMW_AB(op) {unsigned int EA; uint8 x; GetAB(EA); x=RdMem(EA); op; WrMem(EA,x); break; }
436 #define RMW_ABI(reg,op) {unsigned int EA; uint8 x; GetABI(EA,reg); x=RdMem(EA); op; WrMem(EA,x); break; }
437 #define RMW_ABX(op) RMW_ABI(HU_X,op)
438 #define RMW_ABY(op) RMW_ABI(HU_Y,op)
439 #define RMW_IND(op) { unsigned int EA; uint8 x; GetIND(EA); x = RdMem(EA); op; WrMem(EA, x); break; }
440 #define RMW_IX(op) { unsigned int EA; uint8 x; GetIX(EA); x=RdMem(EA); op; WrMem(EA,x); break; }
441 #define RMW_IY(op) { unsigned int EA; uint8 x; GetIY(EA); x=RdMem(EA); op; WrMem(EA,x); break; }
442 #define RMW_ZP(op) { uint8 EA; uint8 x; GetZP(EA); x=HU_Page1[EA]; op; HU_Page1[EA] = x; break; }
443 #define RMW_ZPX(op) { uint8 EA; uint8 x; GetZPI(EA,HU_X); x=HU_Page1[EA]; op; HU_Page1[EA] = x; break;}
444
445 #define LD_IM(op) { uint8 x; x=RdAtPC(); IncPC(); op; break; }
446 #define LD_ZP(op) { uint8 EA; uint8 x; GetZP(EA); x=HU_Page1[EA]; op; break; }
447 #define LD_ZPX(op) { uint8 EA; uint8 x; GetZPI(EA,HU_X); x=HU_Page1[EA]; op; break; }
448 #define LD_ZPY(op) { uint8 EA; uint8 x; GetZPI(EA,HU_Y); x=HU_Page1[EA]; op; break; }
449 #define LD_AB(op) { unsigned int EA; uint8 x; GetAB(EA); x=RdMem(EA); op; break; }
450 #define LD_ABI(reg,op) { unsigned int EA; uint8 x; GetABI(EA,reg); x=RdMem(EA); op; break; }
451 #define LD_ABX(op) LD_ABI(HU_X,op)
452 #define LD_ABY(op) LD_ABI(HU_Y,op)
453
454 #define LD_IND(op) { unsigned int EA; uint8 x; GetIND(EA); x=RdMem(EA); op; break; }
455 #define LD_IX(op) { unsigned int EA; uint8 x; GetIX(EA); x=RdMem(EA); op; break; }
456 #define LD_IY(op) { unsigned int EA; uint8 x; GetIY(EA); x=RdMem(EA); op; break; }
457
458 #define BMT_PREHONK(pork) HuCPU.in_block_move = IBM_##pork;
459 #define BMT_HONKHONK(pork) if(HuCPU.timestamp >= next_user_event) goto GetOutBMT; continue_the_##pork:
460
461 #define BMT_TDD BMT_PREHONK(TDD); do { ADDCYC(6); WrMem(HuCPU.bmt_dest, RdMem(HuCPU.bmt_src)); HuCPU.bmt_src--; HuCPU.bmt_dest--; BMT_HONKHONK(TDD); HuCPU.bmt_length--; } while(HuCPU.bmt_length);
462 #define BMT_TAI BMT_PREHONK(TAI); {HuCPU.bmt_alternate = 0; do { ADDCYC(6); WrMem(HuCPU.bmt_dest, RdMem(HuCPU.bmt_src + HuCPU.bmt_alternate)); HuCPU.bmt_dest++; HuCPU.bmt_alternate ^= 1; BMT_HONKHONK(TAI); HuCPU.bmt_length--; } while(HuCPU.bmt_length); }
463 #define BMT_TIA BMT_PREHONK(TIA); {HuCPU.bmt_alternate = 0; do { ADDCYC(6); WrMem(HuCPU.bmt_dest + HuCPU.bmt_alternate, RdMem(HuCPU.bmt_src)); HuCPU.bmt_src++; HuCPU.bmt_alternate ^= 1; BMT_HONKHONK(TIA); HuCPU.bmt_length--; } while(HuCPU.bmt_length); }
464 #define BMT_TII BMT_PREHONK(TII); do { ADDCYC(6); WrMem(HuCPU.bmt_dest, RdMem(HuCPU.bmt_src)); HuCPU.bmt_src++; HuCPU.bmt_dest++; BMT_HONKHONK(TII); HuCPU.bmt_length--; } while(HuCPU.bmt_length);
465 #define BMT_TIN BMT_PREHONK(TIN); do { ADDCYC(6); WrMem(HuCPU.bmt_dest, RdMem(HuCPU.bmt_src)); HuCPU.bmt_src++; BMT_HONKHONK(TIN); HuCPU.bmt_length--; } while(HuCPU.bmt_length);
466
467 // Block memory transfer load
468 #define LD_BMT(op) { PUSH(HU_Y); PUSH(HU_A); PUSH(HU_X); GetAB(HuCPU.bmt_src); GetAB(HuCPU.bmt_dest); GetAB(HuCPU.bmt_length); op; HuCPU.in_block_move = 0; HU_X = POP(); HU_A = POP(); HU_Y = POP(); break; }
469
470 #define ST_ZP(r) {uint8 EA; GetZP(EA); HU_Page1[EA] = r; break;}
471 #define ST_ZPX(r) {uint8 EA; GetZPI(EA,HU_X); HU_Page1[EA] = r; break;}
472 #define ST_ZPY(r) {uint8 EA; GetZPI(EA,HU_Y); HU_Page1[EA] = r; break;}
473 #define ST_AB(r) {unsigned int EA; GetAB(EA); WrMem(EA, r); break;}
474 #define ST_ABI(reg,r) {unsigned int EA; GetABI(EA,reg); WrMem(EA,r); break; }
475 #define ST_ABX(r) ST_ABI(HU_X,r)
476 #define ST_ABY(r) ST_ABI(HU_Y,r)
477
478 #define ST_IND(r) {unsigned int EA; GetIND(EA); WrMem(EA,r); break; }
479 #define ST_IX(r) {unsigned int EA; GetIX(EA); WrMem(EA,r); break; }
480 #define ST_IY(r) {unsigned int EA; GetIY(EA); WrMem(EA,r); break; }
481
482 static const uint8 CycTable[256] =
483 {
484 /*0x00*/ 8, 7, 3, 4, 6, 4, 6, 7, 3, 2, 2, 2, 7, 5, 7, 6,
485 /*0x10*/ 2, 7, 7, 4, 6, 4, 6, 7, 2, 5, 2, 2, 7, 5, 7, 6,
486 /*0x20*/ 7, 7, 3, 4, 4, 4, 6, 7, 4, 2, 2, 2, 5, 5, 7, 6,
487 /*0x30*/ 2, 7, 7, 2, 4, 4, 6, 7, 2, 5, 2, 2, 5, 5, 7, 6,
488 /*0x40*/ 7, 7, 3, 4, 8, 4, 6, 7, 3, 2, 2, 2, 4, 5, 7, 6,
489 /*0x50*/ 2, 7, 7, 5, 3, 4, 6, 7, 2, 5, 3, 2, 2, 5, 7, 6,
490 /*0x60*/ 7, 7, 2, 2, 4, 4, 6, 7, 4, 2, 2, 2, 7, 5, 7, 6,
491 /*0x70*/ 2, 7, 7, 17, 4, 4, 6, 7, 2, 5, 4, 2, 7, 5, 7, 6,
492
493 /*0x80*/ 4, 7, 2, 7, 4, 4, 4, 7, 2, 2, 2, 2, 5, 5, 5, 6,
494 /*0x90*/ 2, 7, 7, 8, 4, 4, 4, 7, 2, 5, 2, 2, 5, 5, 5, 6,
495 /*0xA0*/ 2, 7, 2, 7, 4, 4, 4, 7, 2, 2, 2, 2, 5, 5, 5, 6,
496 /*0xB0*/ 2, 7, 7, 8, 4, 4, 4, 7, 2, 5, 2, 2, 5, 5, 5, 6,
497 /*0xC0*/ 2, 7, 2, 17, 4, 4, 6, 7, 2, 2, 2, 2, 5, 5, 7, 6,
498 /*0xD0*/ 2, 7, 7, 17, 3, 4, 6, 7, 2, 5, 3, 2, 2, 5, 7, 6,
499 /*0xE0*/ 2, 7, 2, 17, 4, 4, 6, 7, 2, 2, 2, 2, 5, 5, 7, 6,
500 /*0xF0*/ 2, 7, 7, 17, 2, 4, 6, 7, 2, 5, 4, 2, 2, 5, 7, 6,
501 };
502 #if 0
503 static NO_INLINE bool WillIRQOccur(void)
504 {
505 bool ret = false;
506
507 if(HU_IRQlow)
508 {
509 if(!(HU_PI&I_FLAG))
510 {
511 if(HU_IRQlow & MDFN_IQTIMER & HuCPU.IRQMaskDelay)
512 ret = true;
513 else if((HU_IRQlow & MDFN_IQIRQ1 & HuCPU.IRQMaskDelay) || ((HU_IRQlow >> 8) & MDFN_IQIRQ1 & HuCPU.IRQMaskDelay))
514 ret = true;
515 else if(HU_IRQlow & MDFN_IQIRQ2 & HuCPU.IRQMaskDelay)
516 ret = true;
517 }
518 }
519
520 return(true);
521 }
522 #endif
523
HuC6280_Reset(void)524 void HuC6280_Reset(void)
525 {
526 HuCPU.timer_next_timestamp = HuCPU.timestamp + 1024;
527
528 HuCPU.timer_load = 0;
529 HuCPU.timer_value = 0;
530 HuCPU.timer_status = 0;
531 HuCPU.in_block_move = 0;
532
533 unsigned int npc;
534
535 HuCPU.IRQMask = HuCPU.IRQMaskDelay = 7;
536
537 HuC6280_SetMPR(0, 0xFF);
538 HuC6280_SetMPR(8, 0xFF);
539 HuC6280_SetMPR(1, 0xF8);
540
541 for(int i = 2; i < 8; i++)
542 HuC6280_SetMPR(i, 0);
543
544 npc = RdMem16(0xFFFE);
545
546 #define PC_local HuCPU.PC
547 SetPC(npc);
548 #undef PC_local
549
550 HuCPU.mooPI = I_FLAG;
551 HuCPU.P = I_FLAG;
552
553 HU_IRQlow = 0;
554 }
555
HuC6280_Init(void)556 void HuC6280_Init(void)
557 {
558 //printf("%zu\n", sizeof(HuC6280));
559 //printf("%d\n", (int)((uint8*)&HuCPU.previous_next_user_event - (uint8*)&HuCPU));
560 //printf("%d\n", (int)((uint8*)&HuCPU.IRQlow - (uint8*)&HuCPU));
561
562 memset(&HuCPU, 0, sizeof(HuCPU));
563
564 #ifdef HUC6280_LAZY_FLAGS
565 #else
566 for(int x=0; x < 256; x++)
567 {
568 if(!x) ZNTable[x]=Z_FLAG;
569 else if (x&0x80) ZNTable[x]=N_FLAG;
570 else ZNTable[x]=0;
571 }
572 #endif
573
574 for(unsigned i = 0; i < 0x100; i++)
575 HuCPU.FastMap[i] = dummy_bank;
576 }
577
HuC6280_Power(void)578 void HuC6280_Power(void)
579 {
580 memset(dummy_bank, 0, sizeof(dummy_bank));
581
582 HuCPU.IRQlow = 0;
583
584 HuCPU.A = 0;
585 HuCPU.X = 0;
586 HuCPU.Y = 0;
587 HuCPU.S = 0;
588 HuCPU.P = 0;
589 HuCPU.mooPI = 0;
590
591 #if 0
592 HU_PC = HU_PC_base = NULL;
593 #else
594 HuCPU.PC = 0;
595 #endif
596
597 HuCPU.timestamp = 0;
598
599 for(int i = 0; i < 9; i++)
600 {
601 HuCPU.MPR[i] = 0;
602 HuCPU.FastPageR[i] = 0;
603 }
604 HuC6280_Reset();
605 }
606
HuC6280_Run(int32 cycles)607 void HuC6280_Run(int32 cycles)
608 {
609 const int32 next_user_event = HuCPU.previous_next_user_event + cycles * pce_overclocked;
610
611 HuCPU.previous_next_user_event = next_user_event;
612
613 LOAD_LOCALS();
614
615 if(HuCPU.timestamp >= next_user_event)
616 return;
617
618 int32 next_event;
619
620 if(HuCPU.in_block_move)
621 {
622 next_event = (next_user_event < HuCPU.timer_next_timestamp) ? next_user_event : HuCPU.timer_next_timestamp;
623
624 switch(HuCPU.in_block_move)
625 {
626 case IBM_TIA: goto continue_the_TIA;
627 case IBM_TAI: goto continue_the_TAI;
628 case IBM_TDD: goto continue_the_TDD;
629 case IBM_TII: goto continue_the_TII;
630 case IBM_TIN: goto continue_the_TIN;
631 }
632 }
633
634 while(MDFN_LIKELY(HuCPU.timestamp < next_user_event))
635 {
636 next_event = (next_user_event < HuCPU.timer_next_timestamp) ? next_user_event : HuCPU.timer_next_timestamp;
637
638 while(MDFN_LIKELY(HuCPU.timestamp < next_event))
639 {
640 uint8 b1;
641
642 if(HU_IRQlow)
643 {
644 if(!(HU_PI&I_FLAG))
645 {
646 uint32 tmpa = 0;
647
648 if(HU_IRQlow & MDFN_IQTIMER & HuCPU.IRQMaskDelay)
649 tmpa = 0xFFFA;
650 else if((HU_IRQlow & MDFN_IQIRQ1 & HuCPU.IRQMaskDelay) || ((HU_IRQlow >> 8) & MDFN_IQIRQ1 & HuCPU.IRQMaskDelay))
651 tmpa = 0xFFF8;
652 else if(HU_IRQlow & MDFN_IQIRQ2 & HuCPU.IRQMaskDelay)
653 tmpa = 0xFFF6;
654
655 if(tmpa)
656 {
657 unsigned int npc;
658
659 ADDCYC(8);
660 PUSH_PC();
661
662 COMPRESS_FLAGS();
663 PUSH((HU_P&~B_FLAG));
664 HU_P |= I_FLAG;
665 HU_P &= ~(T_FLAG | D_FLAG);
666 HU_PI = HU_P;
667
668 npc = RdMem16(tmpa);
669 SetPC(npc);
670
671 if(tmpa == 0xFFF8)
672 HU_IRQlow &= ~0x200;
673
674 continue;
675 }
676 }
677 } // end if(HU_IRQlow)
678
679 //printf("%04x\n", GetRealPC());
680 HU_PI = HU_P;
681 HuCPU.IRQMaskDelay = HuCPU.IRQMask;
682
683 b1 = RdAtPC();
684
685 ADDCYC(CycTable[b1]);
686
687 IncPC();
688
689 switch(b1)
690 {
691 #include "huc6280_ops.inc"
692 }
693
694 #ifndef HUC6280_EXTRA_CRAZY
695 FixPC_PC();
696 #endif
697 } // end while(HuCPU.timestamp < next_event)
698
699 while(HuCPU.timestamp >= HuCPU.timer_next_timestamp)
700 {
701 HuCPU.timer_next_timestamp += 1024 * pce_overclocked;
702
703 if(HuCPU.timer_status)
704 {
705 HuCPU.timer_value --;
706 if(HuCPU.timer_value < 0)
707 {
708 HuCPU.timer_value = HuCPU.timer_load;
709 HuC6280_IRQBegin(MDFN_IQTIMER);
710 }
711 }
712 }
713 } // end while(HuCPU.timestamp < next_user_event)
714
715 GetOutBMT:
716
717 SAVE_LOCALS();
718 }
719
HuC6280_ResetTS(void)720 void HuC6280_ResetTS(void)
721 {
722 HuCPU.timer_next_timestamp -= HuCPU.timestamp;
723 HuCPU.previous_next_user_event -= HuCPU.timestamp;
724 HuCPU.timestamp = 0;
725 }
726
HuC6280_StateAction(StateMem * sm,int load,int data_only)727 void HuC6280_StateAction(StateMem *sm, int load, int data_only)
728 {
729 uint16 tmp_PC = GetRealPC_EXTERNAL();
730
731 #define P_local HuCPU.P
732 COMPRESS_FLAGS();
733
734 SFORMAT SFCPU[]=
735 {
736 SFVARN(tmp_PC, "PC"),
737 SFVARN(HuCPU.A, "A"),
738 SFVARN(HuCPU.P, "P"),
739 SFVARN(HuCPU.X, "X"),
740 SFVARN(HuCPU.Y, "Y"),
741 SFVARN(HuCPU.S, "S"),
742 SFVARN(HuCPU.mooPI, "PI"),
743
744 SFVARN(HuCPU.IRQMask, "IRQMask"),
745 SFVARN(HuCPU.IRQMaskDelay, "IRQMaskDelay"),
746 SFPTR8N(HuCPU.MPR, 8, "MPR"),
747 SFVARN(HuCPU.timer_status, "timer_status"),
748 SFVARN(HuCPU.timer_value, "timer_value"),
749 SFVARN(HuCPU.timer_load, "timer_load"),
750
751
752 SFVARN(HuCPU.IRQlow, "IRQlow"),
753 SFVARN(HuCPU.in_block_move, "IBM"),
754 SFVARN(HuCPU.bmt_src, "IBM_SRC"),
755 SFVARN(HuCPU.bmt_dest, "IBM_DEST"),
756 SFVARN(HuCPU.bmt_length, "IBM_LENGTH"),
757 SFVARN(HuCPU.bmt_alternate, "IBM_ALTERNATE"),
758
759 SFVARN(HuCPU.timer_next_timestamp, "timer_next_timestamp"),
760 SFVARN(HuCPU.previous_next_user_event, "previous_next_user_event"),
761
762 SFEND
763 };
764
765 HuCPU.timer_next_timestamp -= HuCPU.timestamp;
766 HuCPU.previous_next_user_event -= HuCPU.timestamp;
767
768 MDFNSS_StateAction(sm, load, data_only, SFCPU, "CPU");
769
770 if(load)
771 {
772 if(HuCPU.previous_next_user_event > 455 * pce_overclocked)
773 HuCPU.previous_next_user_event = 455 * pce_overclocked;
774
775 //
776 //
777 //
778
779 // Update MPR cache
780 HuC6280_FlushMPRCache();
781
782 // This must be after the MPR cache is updated:
783 SetPC_EXTERNAL(tmp_PC);
784 }
785
786 HuCPU.timer_next_timestamp += HuCPU.timestamp;
787 HuCPU.previous_next_user_event += HuCPU.timestamp;
788
789
790 EXPAND_FLAGS();
791 #undef P_local
792 }
793
794
795 };
796