1 /******************************************************************************
\r
3 * CZ80 (Z80 CPU emulator) version 0.9
\r
4 * Compiled with Dev-C++
\r
5 * Copyright 2004-2005 Stéphane Dallongeville
\r
9 *****************************************************************************/
\r
18 #include <Pico/PicoInt.h>
\r
25 #undef CZ80_USE_JUMPTABLE
\r
26 #define CZ80_USE_JUMPTABLE 0
\r
28 #define ALIGN_DATA __attribute__((aligned(4)))
\r
43 /******************************************************************************
\r
45 ******************************************************************************/
\r
47 #include "cz80macro.h"
\r
50 /******************************************************************************
\r
51 \83O
\83\8d\81[
\83o
\83\8b\8d\
\91¢
\91Ì
\r
52 ******************************************************************************/
\r
54 cz80_struc ALIGN_DATA CZ80;
\r
57 /******************************************************************************
\r
58 \83\8d\81[
\83J
\83\8b\95Ï
\90\94\r
59 ******************************************************************************/
\r
61 static UINT8 ALIGN_DATA cz80_bad_address[1 << CZ80_FETCH_SFT];
\r
63 static UINT8 ALIGN_DATA SZ[256];
\r
64 static UINT8 ALIGN_DATA SZP[256];
\r
65 static UINT8 ALIGN_DATA SZ_BIT[256];
\r
66 static UINT8 ALIGN_DATA SZHV_inc[256];
\r
67 static UINT8 ALIGN_DATA SZHV_dec[256];
\r
68 #if CZ80_BIG_FLAGS_ARRAY
\r
69 static UINT8 ALIGN_DATA SZHVC_add[2*256*256];
\r
70 static UINT8 ALIGN_DATA SZHVC_sub[2*256*256];
\r
74 /******************************************************************************
\r
75 \83\8d\81[
\83J
\83\8b\8aÖ
\90\94\r
76 ******************************************************************************/
\r
78 /*--------------------------------------------------------
\r
79 \8a\84\82è
\8d\9e\82Ý
\83R
\81[
\83\8b\83o
\83b
\83N
\r
80 --------------------------------------------------------*/
\r
82 static INT32 Cz80_Interrupt_Callback(INT32 line)
\r
88 /******************************************************************************
\r
89 CZ80
\83C
\83\93\83^
\83t
\83F
\81[
\83X
\8aÖ
\90\94\r
90 ******************************************************************************/
\r
92 /*--------------------------------------------------------
\r
94 --------------------------------------------------------*/
\r
96 void Cz80_Init(cz80_struc *CPU)
\r
99 #if CZ80_BIG_FLAGS_ARRAY
\r
100 int oldval, newval, val;
\r
101 UINT8 *padd, *padc, *psub, *psbc;
\r
104 memset(CPU, 0, sizeof(cz80_struc));
\r
106 memset(cz80_bad_address, 0xff, sizeof(cz80_bad_address));
\r
108 for (i = 0; i < CZ80_FETCH_BANK; i++)
\r
110 CPU->Fetch[i] = (UINT32)cz80_bad_address;
\r
111 #if CZ80_ENCRYPTED_ROM
\r
112 CPU->OPFetch[i] = 0;
\r
116 // flags tables initialisation
\r
117 for (i = 0; i < 256; i++)
\r
119 SZ[i] = i & (SF | YF | XF);
\r
120 if (!i) SZ[i] |= ZF;
\r
122 SZ_BIT[i] = i & (SF | YF | XF);
\r
123 if (!i) SZ_BIT[i] |= ZF | PF;
\r
125 for (j = 0, p = 0; j < 8; j++) if (i & (1 << j)) p++;
\r
127 if (!(p & 1)) SZP[i] |= PF;
\r
129 SZHV_inc[i] = SZ[i];
\r
130 if(i == 0x80) SZHV_inc[i] |= VF;
\r
131 if((i & 0x0f) == 0x00) SZHV_inc[i] |= HF;
\r
133 SZHV_dec[i] = SZ[i] | NF;
\r
134 if (i == 0x7f) SZHV_dec[i] |= VF;
\r
135 if ((i & 0x0f) == 0x0f) SZHV_dec[i] |= HF;
\r
138 #if CZ80_BIG_FLAGS_ARRAY
\r
139 padd = &SZHVC_add[ 0*256];
\r
140 padc = &SZHVC_add[256*256];
\r
141 psub = &SZHVC_sub[ 0*256];
\r
142 psbc = &SZHVC_sub[256*256];
\r
144 for (oldval = 0; oldval < 256; oldval++)
\r
146 for (newval = 0; newval < 256; newval++)
\r
148 /* add or adc w/o carry set */
\r
149 val = newval - oldval;
\r
150 *padd = (newval) ? ((newval & 0x80) ? SF : 0) : ZF;
\r
151 *padd |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */
\r
152 if ((newval & 0x0f) < (oldval & 0x0f)) *padd |= HF;
\r
153 if (newval < oldval ) *padd |= CF;
\r
154 if ((val ^ oldval ^ 0x80) & (val ^ newval) & 0x80) *padd |= VF;
\r
157 /* adc with carry set */
\r
158 val = newval - oldval - 1;
\r
159 *padc = (newval) ? ((newval & 0x80) ? SF : 0) : ZF;
\r
160 *padc |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */
\r
161 if ((newval & 0x0f) <= (oldval & 0x0f)) *padc |= HF;
\r
162 if (newval <= oldval) *padc |= CF;
\r
163 if ((val ^ oldval ^ 0x80) & (val ^ newval) & 0x80) *padc |= VF;
\r
166 /* cp, sub or sbc w/o carry set */
\r
167 val = oldval - newval;
\r
168 *psub = NF | ((newval) ? ((newval & 0x80) ? SF : 0) : ZF);
\r
169 *psub |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */
\r
170 if ((newval & 0x0f) > (oldval & 0x0f)) *psub |= HF;
\r
171 if (newval > oldval) *psub |= CF;
\r
172 if ((val^oldval) & (oldval^newval) & 0x80) *psub |= VF;
\r
175 /* sbc with carry set */
\r
176 val = oldval - newval - 1;
\r
177 *psbc = NF | ((newval) ? ((newval & 0x80) ? SF : 0) : ZF);
\r
178 *psbc |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */
\r
179 if ((newval & 0x0f) >= (oldval & 0x0f)) *psbc |= HF;
\r
180 if (newval >= oldval) *psbc |= CF;
\r
181 if ((val ^ oldval) & (oldval^newval) & 0x80) *psbc |= VF;
\r
187 CPU->pzR8[0] = &zB;
\r
188 CPU->pzR8[1] = &zC;
\r
189 CPU->pzR8[2] = &zD;
\r
190 CPU->pzR8[3] = &zE;
\r
191 CPU->pzR8[4] = &zH;
\r
192 CPU->pzR8[5] = &zL;
\r
193 CPU->pzR8[6] = &zF; //
\8f\88\97\9d\82Ì
\93s
\8d\87\8fã
\81AA
\82Æ
\93ü
\82ê
\91Ö
\82¦
\r
194 CPU->pzR8[7] = &zA; //
\8f\88\97\9d\82Ì
\93s
\8d\87\8fã
\81AF
\82Æ
\93ü
\82ê
\91Ö
\82¦
\r
196 CPU->pzR16[0] = pzBC;
\r
197 CPU->pzR16[1] = pzDE;
\r
198 CPU->pzR16[2] = pzHL;
\r
199 CPU->pzR16[3] = pzAF;
\r
201 zIX = zIY = 0xffff;
\r
204 CPU->Interrupt_Callback = Cz80_Interrupt_Callback;
\r
208 /*--------------------------------------------------------
\r
209 CPU
\83\8a\83Z
\83b
\83g
\r
210 --------------------------------------------------------*/
\r
212 void Cz80_Reset(cz80_struc *CPU)
\r
214 memset(CPU, 0, (INT32)&CPU->BasePC - (INT32)CPU);
\r
215 Cz80_Set_Reg(CPU, CZ80_PC, 0);
\r
219 #if PICODRIVE_HACKS
\r
220 static inline unsigned char picodrive_read(unsigned short a)
\r
222 return (a < 0x4000) ? Pico.zram[a&0x1fff] : z80_read(a);
\r
226 /*--------------------------------------------------------
\r
228 --------------------------------------------------------*/
\r
230 INT32 Cz80_Exec(cz80_struc *CPU, INT32 cycles)
\r
232 #if CZ80_USE_JUMPTABLE
\r
233 #include "cz80jmp.c"
\r
237 #if CZ80_ENCRYPTED_ROM
\r
247 #if CZ80_ENCRYPTED_ROM
\r
248 OPBase = CPU->OPBase;
\r
250 CPU->ICount = cycles - CPU->ExtraCycles;
\r
251 CPU->ExtraCycles = 0;
\r
253 if (!CPU->HaltState)
\r
256 if (CPU->ICount > 0)
\r
258 union16 *data = pzHL;
\r
259 Opcode = READ_OP();
\r
260 #if CZ80_EMULATE_R_EXACTLY
\r
263 #include "cz80_op.c"
\r
269 Cz80_Check_Interrupt:
\r
270 if (CPU->IRQState != CLEAR_LINE)
\r
277 else CPU->ICount = 0;
\r
281 #if CZ80_ENCRYPTED_ROM
\r
282 CPU->OPBase = OPBase;
\r
284 cycles -= CPU->ICount;
\r
285 #if !CZ80_EMULATE_R_EXACTLY
\r
286 zR = (zR + (cycles >> 2)) & 0x7f;
\r
293 /*--------------------------------------------------------
\r
294 \8a\84\82è
\8d\9e\82Ý
\8f\88\97\9d\r
295 --------------------------------------------------------*/
\r
297 void Cz80_Set_IRQ(cz80_struc *CPU, INT32 line, INT32 state)
\r
299 if (line == IRQ_LINE_NMI)
\r
302 CPU->ExtraCycles += 11;
\r
303 CPU->HaltState = 0;
\r
304 PUSH_16(CPU->PC - CPU->BasePC)
\r
305 Cz80_Set_Reg(CPU, CZ80_PC, 0x66);
\r
309 CPU->IRQState = state;
\r
311 if (state != CLEAR_LINE)
\r
313 UINT32 PC = CPU->PC;
\r
314 #if CZ80_ENCRYPTED_ROM
\r
315 INT32 OPBase = CPU->OPBase;
\r
318 CPU->IRQLine = line;
\r
321 #if CZ80_ENCRYPTED_ROM
\r
322 CPU->OPBase = OPBase;
\r
329 /*--------------------------------------------------------
\r
330 \83\8c\83W
\83X
\83^
\8eæ
\93¾
\r
331 --------------------------------------------------------*/
\r
333 UINT32 Cz80_Get_Reg(cz80_struc *CPU, INT32 regnum)
\r
337 case CZ80_PC: return (CPU->PC - CPU->BasePC);
\r
338 case CZ80_SP: return zSP;
\r
339 case CZ80_AF: return zAF;
\r
340 case CZ80_BC: return zBC;
\r
341 case CZ80_DE: return zDE;
\r
342 case CZ80_HL: return zHL;
\r
343 case CZ80_IX: return zIX;
\r
344 case CZ80_IY: return zIY;
\r
345 case CZ80_AF2: return zAF2;
\r
346 case CZ80_BC2: return zBC2;
\r
347 case CZ80_DE2: return zDE2;
\r
348 case CZ80_HL2: return zHL2;
\r
349 case CZ80_R: return zR;
\r
350 case CZ80_I: return zI;
\r
351 case CZ80_IM: return zIM;
\r
352 case CZ80_IFF1: return zIFF1;
\r
353 case CZ80_IFF2: return zIFF2;
\r
354 case CZ80_HALT: return CPU->HaltState;
\r
355 case CZ80_IRQ: return CPU->IRQState;
\r
361 /*--------------------------------------------------------
\r
362 \83\8c\83W
\83X
\83^
\90Ý
\92è
\r
363 --------------------------------------------------------*/
\r
365 void Cz80_Set_Reg(cz80_struc *CPU, INT32 regnum, UINT32 val)
\r
370 CPU->BasePC = CPU->Fetch[val >> CZ80_FETCH_SFT];
\r
371 #if CZ80_ENCRYPTED_ROM
\r
372 CPU->OPBase = CPU->OPFetch[val >> CZ80_FETCH_SFT];
\r
374 CPU->PC = val + CPU->BasePC;
\r
377 case CZ80_SP: zSP = val; break;
\r
378 case CZ80_AF: zAF = val; break;
\r
379 case CZ80_BC: zBC = val; break;
\r
380 case CZ80_DE: zDE = val; break;
\r
381 case CZ80_HL: zHL = val; break;
\r
382 case CZ80_IX: zIX = val; break;
\r
383 case CZ80_IY: zIY = val; break;
\r
384 case CZ80_AF2: zAF2 = val; break;
\r
385 case CZ80_BC2: zBC2 = val; break;
\r
386 case CZ80_DE2: zDE2 = val; break;
\r
387 case CZ80_HL2: zHL2 = val; break;
\r
388 case CZ80_R: zR = val; break;
\r
389 case CZ80_I: zI = val; break;
\r
390 case CZ80_IM: zIM = val; break;
\r
391 case CZ80_IFF1: zIFF1 = val; break;
\r
392 case CZ80_IFF2: zIFF2 = val; break;
\r
393 case CZ80_HALT: CPU->HaltState = val; break;
\r
394 case CZ80_IRQ: CPU->IRQState = val; break;
\r
400 /*--------------------------------------------------------
\r
401 \83t
\83F
\83b
\83`
\83A
\83h
\83\8c\83X
\90Ý
\92è
\r
402 --------------------------------------------------------*/
\r
404 void Cz80_Set_Fetch(cz80_struc *CPU, UINT32 low_adr, UINT32 high_adr, UINT32 fetch_adr)
\r
408 i = low_adr >> CZ80_FETCH_SFT;
\r
409 j = high_adr >> CZ80_FETCH_SFT;
\r
410 fetch_adr -= i << CZ80_FETCH_SFT;
\r
414 CPU->Fetch[i] = fetch_adr;
\r
415 #if CZ80_ENCRYPTED_ROM
\r
416 CPU->OPFetch[i] = 0;
\r
423 /*--------------------------------------------------------
\r
424 \83t
\83F
\83b
\83`
\83A
\83h
\83\8c\83X
\90Ý
\92è (
\88Ã
\8d\86\89»ROM
\91Î
\89\9e)
\r
425 --------------------------------------------------------*/
\r
427 #if CZ80_ENCRYPTED_ROM
\r
428 void Cz80_Set_Encrypt_Range(cz80_struc *CPU, UINT32 low_adr, UINT32 high_adr, UINT32 decrypted_rom)
\r
432 i = low_adr >> CZ80_FETCH_SFT;
\r
433 j = high_adr >> CZ80_FETCH_SFT;
\r
434 decrypted_rom -= i << CZ80_FETCH_SFT;
\r
438 CPU->OPFetch[i] = (INT32)decrypted_rom - (INT32)CPU->Fetch[i];
\r
445 /*--------------------------------------------------------
\r
446 \83\81\83\82\83\8a\83\8a\81[
\83h/
\83\89\83C
\83g
\8aÖ
\90\94\90Ý
\92è
\r
447 --------------------------------------------------------*/
\r
449 void Cz80_Set_ReadB(cz80_struc *CPU, UINT8 (*Func)(UINT32 address))
\r
451 CPU->Read_Byte = Func;
\r
454 void Cz80_Set_WriteB(cz80_struc *CPU, void (*Func)(UINT32 address, UINT8 data))
\r
456 CPU->Write_Byte = Func;
\r
460 /*--------------------------------------------------------
\r
461 \83|
\81[
\83g
\83\8a\81[
\83h/
\83\89\83C
\83g
\8aÖ
\90\94\90Ý
\92è
\r
462 --------------------------------------------------------*/
\r
464 void Cz80_Set_INPort(cz80_struc *CPU, UINT8 (*Func)(UINT16 port))
\r
466 CPU->IN_Port = Func;
\r
469 void Cz80_Set_OUTPort(cz80_struc *CPU, void (*Func)(UINT16 port, UINT8 value))
\r
471 CPU->OUT_Port = Func;
\r
475 /*--------------------------------------------------------
\r
476 \83R
\81[
\83\8b\83o
\83b
\83N
\8aÖ
\90\94\90Ý
\92è
\r
477 --------------------------------------------------------*/
\r
479 void Cz80_Set_IRQ_Callback(cz80_struc *CPU, INT32 (*Func)(INT32 irqline))
\r
481 CPU->Interrupt_Callback = Func;
\r