From a4221917e147ba303f2cf6c09d12362bf2802084 Mon Sep 17 00:00:00 2001 From: notaz Date: Fri, 26 Oct 2007 20:08:13 +0000 Subject: [PATCH] basic psp snd + cz80 git-svn-id: file:///home/notaz/opt/svn/PicoDrive@280 be3aeb3a-fb24-0410-a615-afba39da0efa --- Pico/Memory.c | 20 +- Pico/PicoInt.h | 6 +- Pico/sound/sound.c | 35 +- cpu/cz80/cz80.c | 460 ++++++++++++++++ cpu/cz80/cz80.h | 303 +++++++++++ cpu/cz80/cz80_op.c | 1145 ++++++++++++++++++++++++++++++++++++++++ cpu/cz80/cz80_opCB.c | 470 +++++++++++++++++ cpu/cz80/cz80_opED.c | 731 +++++++++++++++++++++++++ cpu/cz80/cz80_opXY.c | 786 +++++++++++++++++++++++++++ cpu/cz80/cz80_opXYCB.c | 474 +++++++++++++++++ cpu/cz80/cz80jmp.c | 422 +++++++++++++++ cpu/cz80/cz80macro.h | 113 ++++ platform/psp/Makefile | 7 +- platform/psp/emu.c | 195 +++++-- platform/psp/menu.c | 14 +- platform/psp/psp.c | 8 +- 16 files changed, 5127 insertions(+), 62 deletions(-) create mode 100644 cpu/cz80/cz80.c create mode 100644 cpu/cz80/cz80.h create mode 100644 cpu/cz80/cz80_op.c create mode 100644 cpu/cz80/cz80_opCB.c create mode 100644 cpu/cz80/cz80_opED.c create mode 100644 cpu/cz80/cz80_opXY.c create mode 100644 cpu/cz80/cz80_opXYCB.c create mode 100644 cpu/cz80/cz80jmp.c create mode 100644 cpu/cz80/cz80macro.h diff --git a/Pico/Memory.c b/Pico/Memory.c index 527b80b..3c7b70c 100644 --- a/Pico/Memory.c +++ b/Pico/Memory.c @@ -684,14 +684,11 @@ end: return ret; } -PICO_INTERNAL unsigned short z80_read16(unsigned short a) -{ - //dprintf("z80_read16"); - - return (u16) ( (u16)z80_read(a) | ((u16)z80_read((u16)(a+1))<<8) ); -} - +#ifndef _USE_CZ80 PICO_INTERNAL_ASM void z80_write(unsigned char data, unsigned short a) +#else +PICO_INTERNAL_ASM void z80_write(unsigned int a, unsigned char data) +#endif { //if (a<0x4000) // dprintf("z80 w8 : %06x, %02x @%04x", a, data, mz80GetRegisterValue(NULL, 0)); @@ -732,6 +729,14 @@ PICO_INTERNAL_ASM void z80_write(unsigned char data, unsigned short a) elprintf(EL_ANOMALY, "z80 invalid w8 [%06x] %02x", a, data); } +#ifndef _USE_CZ80 +PICO_INTERNAL unsigned short z80_read16(unsigned short a) +{ + //dprintf("z80_read16"); + + return (u16) ( (u16)z80_read(a) | ((u16)z80_read((u16)(a+1))<<8) ); +} + PICO_INTERNAL void z80_write16(unsigned short data, unsigned short a) { //dprintf("z80_write16"); @@ -739,4 +744,5 @@ PICO_INTERNAL void z80_write16(unsigned short data, unsigned short a) z80_write((unsigned char) data,a); z80_write((unsigned char)(data>>8),(u16)(a+1)); } +#endif diff --git a/Pico/PicoInt.h b/Pico/PicoInt.h index 7a81ba6..c98ba8b 100644 --- a/Pico/PicoInt.h +++ b/Pico/PicoInt.h @@ -318,9 +318,13 @@ PICO_INTERNAL void PicoMemSetup(void); PICO_INTERNAL_ASM void PicoMemReset(void); PICO_INTERNAL int PadRead(int i); PICO_INTERNAL unsigned char z80_read(unsigned short a); -PICO_INTERNAL unsigned short z80_read16(unsigned short a); +#ifndef _USE_CZ80 PICO_INTERNAL_ASM void z80_write(unsigned char data, unsigned short a); PICO_INTERNAL void z80_write16(unsigned short data, unsigned short a); +PICO_INTERNAL unsigned short z80_read16(unsigned short a); +#else +PICO_INTERNAL_ASM void z80_write(unsigned int a, unsigned char data); +#endif // cd/Memory.c PICO_INTERNAL void PicoMemSetupCD(void); diff --git a/Pico/sound/sound.c b/Pico/sound/sound.c index ab56bb9..1b12696 100644 --- a/Pico/sound/sound.c +++ b/Pico/sound/sound.c @@ -15,6 +15,8 @@ #include "../../cpu/mz80/mz80.h" #elif defined(_USE_DRZ80) #include "../../cpu/DrZ80/drz80.h" +#elif defined(_USE_CZ80) +#include "../../cpu/cz80/cz80.h" #endif #include "../PicoInt.h" @@ -329,7 +331,6 @@ static void DrZ80_irq_callback() { drZ80.Z80_IRQ = 0; // lower irq when accepted } - #endif // z80 functionality wrappers @@ -353,7 +354,6 @@ PICO_INTERNAL void z80_init(void) mz80SetContext(&z80); #elif defined(_USE_DRZ80) - memset(&drZ80, 0, sizeof(struct DrZ80)); drZ80.z80_rebasePC=DrZ80_rebasePC; drZ80.z80_rebaseSP=DrZ80_rebaseSP; @@ -364,6 +364,14 @@ PICO_INTERNAL void z80_init(void) drZ80.z80_in =DrZ80_in; drZ80.z80_out =DrZ80_out; drZ80.z80_irq_callback=DrZ80_irq_callback; + +#elif defined(_USE_CZ80) + memset(&CZ80, 0, sizeof(CZ80)); + Cz80_Init(&CZ80); + Cz80_Set_Fetch(&CZ80, 0x0000, 0x1fff, (UINT32)Pico.zram); // main RAM + Cz80_Set_Fetch(&CZ80, 0x2000, 0x3fff, (UINT32)Pico.zram - 0x2000); // mirror + Cz80_Set_ReadB(&CZ80, (UINT8 (*)(UINT32 address))z80_read); + Cz80_Set_WriteB(&CZ80, z80_write); #endif } @@ -380,6 +388,8 @@ PICO_INTERNAL void z80_reset(void) drZ80.Z80IM = 0; // 1? drZ80.Z80PC = drZ80.z80_rebasePC(0); drZ80.Z80SP = drZ80.z80_rebaseSP(0x2000); // 0xf000 ? +#elif defined(_USE_CZ80) + Cz80_Reset(&CZ80); #endif Pico.m.z80_fakeval = 0; // for faking when Z80 is disabled } @@ -398,6 +408,8 @@ PICO_INTERNAL void z80_int(void) #elif defined(_USE_DRZ80) drZ80.z80irqvector = 0xFF; // default IRQ vector RST opcode drZ80.Z80_IRQ = 1; +#elif defined(_USE_CZ80) + Cz80_Set_IRQ(&CZ80, 0, HOLD_LINE); #endif } @@ -410,6 +422,8 @@ PICO_INTERNAL int z80_run(int cycles) return mz80GetElapsedTicks(0) - ticks_pre; #elif defined(_USE_DRZ80) return cycles - DrZ80Run(&drZ80, cycles); +#elif defined(_USE_CZ80) + return Cz80_Exec(&CZ80, cycles); #else return cycles; #endif @@ -427,13 +441,17 @@ PICO_INTERNAL void z80_pack(unsigned char *data) drZ80.Z80PC = drZ80.z80_rebasePC(drZ80.Z80PC-drZ80.Z80PC_BASE); drZ80.Z80SP = drZ80.z80_rebaseSP(drZ80.Z80SP-drZ80.Z80SP_BASE); memcpy(data+4, &drZ80, 0x54); +#elif defined(_USE_CZ80) + *(int *)data = 0x00007a43; // "Cz" + memcpy(data+4, &CZ80, (INT32)&CZ80.BasePC - (INT32)&CZ80); + printf("size: %i (%x)\n", (INT32)&CZ80.BasePC - (INT32)&CZ80, (INT32)&CZ80.BasePC - (INT32)&CZ80); // FIXME rm #endif } PICO_INTERNAL void z80_unpack(unsigned char *data) { #if defined(_USE_MZ80) - if(*(int *)data == 0x00005A6D) { // "mZ" save? + if (*(int *)data == 0x00005A6D) { // "mZ" save? struct mz80context mz80; mz80GetContext(&mz80); memcpy(&mz80.z80clockticks, data+4, sizeof(mz80)-5*4); @@ -443,7 +461,7 @@ PICO_INTERNAL void z80_unpack(unsigned char *data) z80_int(); } #elif defined(_USE_DRZ80) - if(*(int *)data == 0x015A7244) { // "DrZ" v1 save? + if (*(int *)data == 0x015A7244) { // "DrZ" v1 save? memcpy(&drZ80, data+4, 0x54); // update bases drZ80.Z80PC = drZ80.z80_rebasePC(drZ80.Z80PC-drZ80.Z80PC_BASE); @@ -453,6 +471,13 @@ PICO_INTERNAL void z80_unpack(unsigned char *data) drZ80.Z80IM = 1; z80_int(); // try to goto int handler, maybe we won't execute trash there? } +#elif defined(_USE_CZ80) + if (*(int *)data == 0x00007a43) // "Cz" save? + memcpy(&CZ80, data+4, (INT32)&CZ80.BasePC - (INT32)&CZ80); + else { + z80_reset(); + z80_int(); + } #endif } @@ -468,6 +493,8 @@ PICO_INTERNAL void z80_debug(char *dstr) { #if defined(_USE_DRZ80) sprintf(dstr, "Z80 state: PC: %04x SP: %04x\n", drZ80.Z80PC-drZ80.Z80PC_BASE, drZ80.Z80SP-drZ80.Z80SP_BASE); +#elif defined(_USE_CZ80) + sprintf(dstr, "Z80 state: PC: %04x SP: %04x\n", CZ80.PC - CZ80.BasePC, CZ80.SP.W); #endif } #endif diff --git a/cpu/cz80/cz80.c b/cpu/cz80/cz80.c new file mode 100644 index 0000000..bcff740 --- /dev/null +++ b/cpu/cz80/cz80.c @@ -0,0 +1,460 @@ +/****************************************************************************** + * + * CZ80 (Z80 CPU emulator) version 0.9 + * Compiled with Dev-C++ + * Copyright 2004-2005 Stéphane Dallongeville + * + * (Modified by NJ) + * + *****************************************************************************/ + +#include +#include +#include +#include "cz80.h" + +#ifndef ALIGN_DATA +#define ALIGN_DATA __attribute__((aligned(4))) +#endif + +#define CF 0x01 +#define NF 0x02 +#define PF 0x04 +#define VF PF +#define XF 0x08 +#define HF 0x10 +#define YF 0x20 +#define ZF 0x40 +#define SF 0x80 + + +/****************************************************************************** + ƒ}ƒNƒ +******************************************************************************/ + +#include "cz80macro.h" + + +/****************************************************************************** + ƒOƒ[ƒoƒ‹\‘¢‘Ì +******************************************************************************/ + +cz80_struc ALIGN_DATA CZ80; + + +/****************************************************************************** + ƒ[ƒJƒ‹•Ï” +******************************************************************************/ + +static UINT8 ALIGN_DATA cz80_bad_address[1 << CZ80_FETCH_SFT]; + +static UINT8 ALIGN_DATA SZ[256]; +static UINT8 ALIGN_DATA SZP[256]; +static UINT8 ALIGN_DATA SZ_BIT[256]; +static UINT8 ALIGN_DATA SZHV_inc[256]; +static UINT8 ALIGN_DATA SZHV_dec[256]; +#if CZ80_BIG_FLAGS_ARRAY +static UINT8 ALIGN_DATA SZHVC_add[2*256*256]; +static UINT8 ALIGN_DATA SZHVC_sub[2*256*256]; +#endif + + +/****************************************************************************** + ƒ[ƒJƒ‹ŠÖ” +******************************************************************************/ + +/*-------------------------------------------------------- + Š„‚荞‚݃R[ƒ‹ƒoƒbƒN +--------------------------------------------------------*/ + +static INT32 Cz80_Interrupt_Callback(INT32 line) +{ + return 0xff; +} + + +/****************************************************************************** + CZ80ƒCƒ“ƒ^ƒtƒF[ƒXŠÖ” +******************************************************************************/ + +/*-------------------------------------------------------- + CPU‰Šú‰» +--------------------------------------------------------*/ + +void Cz80_Init(cz80_struc *CPU) +{ + UINT32 i, j, p; +#if CZ80_BIG_FLAGS_ARRAY + int oldval, newval, val; + UINT8 *padd, *padc, *psub, *psbc; +#endif + + memset(CPU, 0, sizeof(cz80_struc)); + + memset(cz80_bad_address, 0xff, sizeof(cz80_bad_address)); + + for (i = 0; i < CZ80_FETCH_BANK; i++) + { + CPU->Fetch[i] = (UINT32)cz80_bad_address; +#if CZ80_ENCRYPTED_ROM + CPU->OPFetch[i] = 0; +#endif + } + + // flags tables initialisation + for (i = 0; i < 256; i++) + { + SZ[i] = i & (SF | YF | XF); + if (!i) SZ[i] |= ZF; + + SZ_BIT[i] = i & (SF | YF | XF); + if (!i) SZ_BIT[i] |= ZF | PF; + + for (j = 0, p = 0; j < 8; j++) if (i & (1 << j)) p++; + SZP[i] = SZ[i]; + if (!(p & 1)) SZP[i] |= PF; + + SZHV_inc[i] = SZ[i]; + if(i == 0x80) SZHV_inc[i] |= VF; + if((i & 0x0f) == 0x00) SZHV_inc[i] |= HF; + + SZHV_dec[i] = SZ[i] | NF; + if (i == 0x7f) SZHV_dec[i] |= VF; + if ((i & 0x0f) == 0x0f) SZHV_dec[i] |= HF; + } + +#if CZ80_BIG_FLAGS_ARRAY + padd = &SZHVC_add[ 0*256]; + padc = &SZHVC_add[256*256]; + psub = &SZHVC_sub[ 0*256]; + psbc = &SZHVC_sub[256*256]; + + for (oldval = 0; oldval < 256; oldval++) + { + for (newval = 0; newval < 256; newval++) + { + /* add or adc w/o carry set */ + val = newval - oldval; + *padd = (newval) ? ((newval & 0x80) ? SF : 0) : ZF; + *padd |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */ + if ((newval & 0x0f) < (oldval & 0x0f)) *padd |= HF; + if (newval < oldval ) *padd |= CF; + if ((val ^ oldval ^ 0x80) & (val ^ newval) & 0x80) *padd |= VF; + padd++; + + /* adc with carry set */ + val = newval - oldval - 1; + *padc = (newval) ? ((newval & 0x80) ? SF : 0) : ZF; + *padc |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */ + if ((newval & 0x0f) <= (oldval & 0x0f)) *padc |= HF; + if (newval <= oldval) *padc |= CF; + if ((val ^ oldval ^ 0x80) & (val ^ newval) & 0x80) *padc |= VF; + padc++; + + /* cp, sub or sbc w/o carry set */ + val = oldval - newval; + *psub = NF | ((newval) ? ((newval & 0x80) ? SF : 0) : ZF); + *psub |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */ + if ((newval & 0x0f) > (oldval & 0x0f)) *psub |= HF; + if (newval > oldval) *psub |= CF; + if ((val^oldval) & (oldval^newval) & 0x80) *psub |= VF; + psub++; + + /* sbc with carry set */ + val = oldval - newval - 1; + *psbc = NF | ((newval) ? ((newval & 0x80) ? SF : 0) : ZF); + *psbc |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */ + if ((newval & 0x0f) >= (oldval & 0x0f)) *psbc |= HF; + if (newval >= oldval) *psbc |= CF; + if ((val ^ oldval) & (oldval^newval) & 0x80) *psbc |= VF; + psbc++; + } + } +#endif + + CPU->pzR8[0] = &zB; + CPU->pzR8[1] = &zC; + CPU->pzR8[2] = &zD; + CPU->pzR8[3] = &zE; + CPU->pzR8[4] = &zH; + CPU->pzR8[5] = &zL; + CPU->pzR8[6] = &zF; // ˆ—‚Ì“s‡ãAA‚Æ“ü‚ê‘Ö‚¦ + CPU->pzR8[7] = &zA; // ˆ—‚Ì“s‡ãAF‚Æ“ü‚ê‘Ö‚¦ + + CPU->pzR16[0] = pzBC; + CPU->pzR16[1] = pzDE; + CPU->pzR16[2] = pzHL; + CPU->pzR16[3] = pzAF; + + zIX = zIY = 0xffff; + zF = ZF; + + CPU->Interrupt_Callback = Cz80_Interrupt_Callback; +} + + +/*-------------------------------------------------------- + CPUƒŠƒZƒbƒg +--------------------------------------------------------*/ + +void Cz80_Reset(cz80_struc *CPU) +{ + memset(CPU, 0, (INT32)&CPU->BasePC - (INT32)CPU); + Cz80_Set_Reg(CPU, CZ80_PC, 0); +} + + +/*-------------------------------------------------------- + CPUŽÀs +--------------------------------------------------------*/ + +INT32 Cz80_Exec(cz80_struc *CPU, INT32 cycles) +{ +#if CZ80_USE_JUMPTABLE +#include "cz80jmp.c" +#endif + + UINT32 PC; +#if CZ80_ENCRYPTED_ROM + INT32 OPBase; +#endif + UINT32 Opcode; + UINT32 adr = 0; + UINT32 res; + UINT32 val; + int afterEI = 0; + + PC = CPU->PC; +#if CZ80_ENCRYPTED_ROM + OPBase = CPU->OPBase; +#endif + CPU->ICount = cycles - CPU->ExtraCycles; + CPU->ExtraCycles = 0; + + if (!CPU->HaltState) + { +Cz80_Exec: + if (CPU->ICount > 0) + { + union16 *data = pzHL; + Opcode = READ_OP(); +#if CZ80_EMULATE_R_EXACTLY + zR++; +#endif + #include "cz80_op.c" + } + + if (afterEI) + { + afterEI = 0; +Cz80_Check_Interrupt: + CHECK_INT + goto Cz80_Exec; + } + } + else CPU->ICount = 0; + +Cz80_Exec_End: + CPU->PC = PC; +#if CZ80_ENCRYPTED_ROM + CPU->OPBase = OPBase; +#endif + cycles -= CPU->ICount; +#if !CZ80_EMULATE_R_EXACTLY + zR = (zR + (cycles >> 2)) & 0x7f; +#endif + + return cycles; +} + + +/*-------------------------------------------------------- + Š„‚荞‚ݏˆ— +--------------------------------------------------------*/ + +void Cz80_Set_IRQ(cz80_struc *CPU, INT32 line, INT32 state) +{ + if (line == IRQ_LINE_NMI) + { + zIFF1 = 0; + CPU->ExtraCycles += 11; + CPU->HaltState = 0; + PUSH_16(CPU->PC - CPU->BasePC) + Cz80_Set_Reg(CPU, CZ80_PC, 0x66); + } + else + { + CPU->IRQState = state; + + if (state != CLEAR_LINE) + { + UINT32 PC = CPU->PC; +#if CZ80_ENCRYPTED_ROM + INT32 OPBase = CPU->OPBase; +#endif + + CPU->IRQLine = line; + CHECK_INT + CPU->PC = PC; +#if CZ80_ENCRYPTED_ROM + CPU->OPBase = OPBase; +#endif + } + } +} + + +/*-------------------------------------------------------- + ƒŒƒWƒXƒ^Žæ“¾ +--------------------------------------------------------*/ + +UINT32 Cz80_Get_Reg(cz80_struc *CPU, INT32 regnum) +{ + switch (regnum) + { + case CZ80_PC: return (CPU->PC - CPU->BasePC); + case CZ80_SP: return zSP; + case CZ80_AF: return zAF; + case CZ80_BC: return zBC; + case CZ80_DE: return zDE; + case CZ80_HL: return zHL; + case CZ80_IX: return zIX; + case CZ80_IY: return zIY; + case CZ80_AF2: return zAF2; + case CZ80_BC2: return zBC2; + case CZ80_DE2: return zDE2; + case CZ80_HL2: return zHL2; + case CZ80_R: return zR; + case CZ80_I: return zI; + case CZ80_IM: return zIM; + case CZ80_IFF1: return zIFF1; + case CZ80_IFF2: return zIFF2; + case CZ80_HALT: return CPU->HaltState; + case CZ80_IRQ: return CPU->IRQState; + default: return 0; + } +} + + +/*-------------------------------------------------------- + ƒŒƒWƒXƒ^Ý’è +--------------------------------------------------------*/ + +void Cz80_Set_Reg(cz80_struc *CPU, INT32 regnum, UINT32 val) +{ + switch (regnum) + { + case CZ80_PC: + CPU->BasePC = CPU->Fetch[val >> CZ80_FETCH_SFT]; +#if CZ80_ENCRYPTED_ROM + CPU->OPBase = CPU->OPFetch[val >> CZ80_FETCH_SFT]; +#endif + CPU->PC = val + CPU->BasePC; + break; + + case CZ80_SP: zSP = val; break; + case CZ80_AF: zAF = val; break; + case CZ80_BC: zBC = val; break; + case CZ80_DE: zDE = val; break; + case CZ80_HL: zHL = val; break; + case CZ80_IX: zIX = val; break; + case CZ80_IY: zIY = val; break; + case CZ80_AF2: zAF2 = val; break; + case CZ80_BC2: zBC2 = val; break; + case CZ80_DE2: zDE2 = val; break; + case CZ80_HL2: zHL2 = val; break; + case CZ80_R: zR = val; break; + case CZ80_I: zI = val; break; + case CZ80_IM: zIM = val; break; + case CZ80_IFF1: zIFF1 = val; break; + case CZ80_IFF2: zIFF2 = val; break; + case CZ80_HALT: CPU->HaltState = val; break; + case CZ80_IRQ: CPU->IRQState = val; break; + default: break; + } +} + + +/*-------------------------------------------------------- + ƒtƒFƒbƒ`ƒAƒhƒŒƒXÝ’è +--------------------------------------------------------*/ + +void Cz80_Set_Fetch(cz80_struc *CPU, UINT32 low_adr, UINT32 high_adr, UINT32 fetch_adr) +{ + int i, j; + + i = low_adr >> CZ80_FETCH_SFT; + j = high_adr >> CZ80_FETCH_SFT; + fetch_adr -= i << CZ80_FETCH_SFT; + + while (i <= j) + { + CPU->Fetch[i] = fetch_adr; +#if CZ80_ENCRYPTED_ROM + CPU->OPFetch[i] = 0; +#endif + i++; + } +} + + +/*-------------------------------------------------------- + ƒtƒFƒbƒ`ƒAƒhƒŒƒXÝ’è (ˆÃ†‰»ROM‘Ήž) +--------------------------------------------------------*/ + +#if CZ80_ENCRYPTED_ROM +void Cz80_Set_Encrypt_Range(cz80_struc *CPU, UINT32 low_adr, UINT32 high_adr, UINT32 decrypted_rom) +{ + int i, j; + + i = low_adr >> CZ80_FETCH_SFT; + j = high_adr >> CZ80_FETCH_SFT; + decrypted_rom -= i << CZ80_FETCH_SFT; + + while (i <= j) + { + CPU->OPFetch[i] = (INT32)decrypted_rom - (INT32)CPU->Fetch[i]; + i++; + } +} +#endif + + +/*-------------------------------------------------------- + ƒƒ‚ƒŠƒŠ[ƒh/ƒ‰ƒCƒgŠÖ”Ý’è +--------------------------------------------------------*/ + +void Cz80_Set_ReadB(cz80_struc *CPU, UINT8 (*Func)(UINT32 address)) +{ + CPU->Read_Byte = Func; +} + +void Cz80_Set_WriteB(cz80_struc *CPU, void (*Func)(UINT32 address, UINT8 data)) +{ + CPU->Write_Byte = Func; +} + + +/*-------------------------------------------------------- + ƒ|[ƒgƒŠ[ƒh/ƒ‰ƒCƒgŠÖ”Ý’è +--------------------------------------------------------*/ + +void Cz80_Set_INPort(cz80_struc *CPU, UINT8 (*Func)(UINT16 port)) +{ + CPU->IN_Port = Func; +} + +void Cz80_Set_OUTPort(cz80_struc *CPU, void (*Func)(UINT16 port, UINT8 value)) +{ + CPU->OUT_Port = Func; +} + + +/*-------------------------------------------------------- + ƒR[ƒ‹ƒoƒbƒNŠÖ”Ý’è +--------------------------------------------------------*/ + +void Cz80_Set_IRQ_Callback(cz80_struc *CPU, INT32 (*Func)(INT32 irqline)) +{ + CPU->Interrupt_Callback = Func; +} diff --git a/cpu/cz80/cz80.h b/cpu/cz80/cz80.h new file mode 100644 index 0000000..a5da31d --- /dev/null +++ b/cpu/cz80/cz80.h @@ -0,0 +1,303 @@ +/****************************************************************************** + * + * CZ80 (Z80 CPU emulator) version 0.9 + * Compiled with Dev-C++ + * Copyright 2004-2005 Stéphane Dallongeville + * + * (Modified by NJ) + * + *****************************************************************************/ + +#ifndef CZ80_H +#define CZ80_H + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************/ +/* Compiler dependant defines */ +/******************************/ + +#ifndef UINT8 +#define UINT8 unsigned char +#endif + +#ifndef INT8 +#define INT8 char +#endif + +#ifndef UINT16 +#define UINT16 unsigned short +#endif + +#ifndef INT16 +#define INT16 short +#endif + +#ifndef UINT32 +#define UINT32 unsigned int +#endif + +#ifndef INT32 +#define INT32 int +#endif + +/*************************************/ +/* Z80 core Structures & definitions */ +/*************************************/ + +#define CZ80_FETCH_BITS 4 // [4-12] default = 8 + +#define CZ80_FETCH_SFT (16 - CZ80_FETCH_BITS) +#define CZ80_FETCH_BANK (1 << CZ80_FETCH_BITS) + +#define CZ80_LITTLE_ENDIAN 1 +#define CZ80_USE_JUMPTABLE 1 +#define CZ80_BIG_FLAGS_ARRAY 1 +//#ifdef BUILD_CPS1PSP +//#define CZ80_ENCRYPTED_ROM 1 +//#else +#define CZ80_ENCRYPTED_ROM 0 +//#endif +#define CZ80_EMULATE_R_EXACTLY 0 + +#define zR8(A) (*CPU->pzR8[A]) +#define zR16(A) (CPU->pzR16[A]->W) + +#define pzAF &(CPU->AF) +#define zAF CPU->AF.W +#define zlAF CPU->AF.B.L +#define zhAF CPU->AF.B.H +#define zA zhAF +#define zF zlAF + +#define pzBC &(CPU->BC) +#define zBC CPU->BC.W +#define zlBC CPU->BC.B.L +#define zhBC CPU->BC.B.H +#define zB zhBC +#define zC zlBC + +#define pzDE &(CPU->DE) +#define zDE CPU->DE.W +#define zlDE CPU->DE.B.L +#define zhDE CPU->DE.B.H +#define zD zhDE +#define zE zlDE + +#define pzHL &(CPU->HL) +#define zHL CPU->HL.W +#define zlHL CPU->HL.B.L +#define zhHL CPU->HL.B.H +#define zH zhHL +#define zL zlHL + +#define zAF2 CPU->AF2.W +#define zlAF2 CPU->AF2.B.L +#define zhAF2 CPU->AF2.B.H +#define zA2 zhAF2 +#define zF2 zlAF2 + +#define zBC2 CPU->BC2.W +#define zDE2 CPU->DE2.W +#define zHL2 CPU->HL2.W + +#define pzIX &(CPU->IX) +#define zIX CPU->IX.W +#define zlIX CPU->IX.B.L +#define zhIX CPU->IX.B.H + +#define pzIY &(CPU->IY) +#define zIY CPU->IY.W +#define zlIY CPU->IY.B.L +#define zhIY CPU->IY.B.H + +#define pzSP &(CPU->SP) +#define zSP CPU->SP.W +#define zlSP CPU->SP.B.L +#define zhSP CPU->SP.B.H + +#define zRealPC (PC - CPU->BasePC) +#define zPC PC + +#define zI CPU->I +#define zIM CPU->IM + +#define zwR CPU->R.W +#define zR1 CPU->R.B.L +#define zR2 CPU->R.B.H +#define zR zR1 + +#define zIFF CPU->IFF.W +#define zIFF1 CPU->IFF.B.L +#define zIFF2 CPU->IFF.B.H + +#define CZ80_SF_SFT 7 +#define CZ80_ZF_SFT 6 +#define CZ80_YF_SFT 5 +#define CZ80_HF_SFT 4 +#define CZ80_XF_SFT 3 +#define CZ80_PF_SFT 2 +#define CZ80_VF_SFT 2 +#define CZ80_NF_SFT 1 +#define CZ80_CF_SFT 0 + +#define CZ80_SF (1 << CZ80_SF_SFT) +#define CZ80_ZF (1 << CZ80_ZF_SFT) +#define CZ80_YF (1 << CZ80_YF_SFT) +#define CZ80_HF (1 << CZ80_HF_SFT) +#define CZ80_XF (1 << CZ80_XF_SFT) +#define CZ80_PF (1 << CZ80_PF_SFT) +#define CZ80_VF (1 << CZ80_VF_SFT) +#define CZ80_NF (1 << CZ80_NF_SFT) +#define CZ80_CF (1 << CZ80_CF_SFT) + +#define CZ80_IFF_SFT CZ80_PF_SFT +#define CZ80_IFF CZ80_PF + +#ifndef IRQ_LINE_STATE +#define IRQ_LINE_STATE +#define CLEAR_LINE 0 /* clear (a fired, held or pulsed) line */ +#define ASSERT_LINE 1 /* assert an interrupt immediately */ +#define HOLD_LINE 2 /* hold interrupt line until acknowledged */ +#define PULSE_LINE 3 /* pulse interrupt line for one instruction */ +#define IRQ_LINE_NMI 127 /* IRQ line for NMIs */ +#endif + +enum +{ + CZ80_PC = 1, + CZ80_SP, + CZ80_AF, + CZ80_BC, + CZ80_DE, + CZ80_HL, + CZ80_IX, + CZ80_IY, + CZ80_AF2, + CZ80_BC2, + CZ80_DE2, + CZ80_HL2, + CZ80_R, + CZ80_I, + CZ80_IM, + CZ80_IFF1, + CZ80_IFF2, + CZ80_HALT, + CZ80_IRQ +}; + +typedef union +{ + struct + { +#if CZ80_LITTLE_ENDIAN + UINT8 L; + UINT8 H; +#else + UINT8 H; + UINT8 L; +#endif + } B; + UINT16 W; +} union16; + +typedef struct cz80_t +{ + union + { + UINT8 r8[8]; + union16 r16[4]; + struct + { + union16 BC; + union16 DE; + union16 HL; + union16 AF; + }; + }; + + union16 IX; + union16 IY; + union16 SP; + UINT32 PC; + + union16 BC2; + union16 DE2; + union16 HL2; + union16 AF2; + + union16 R; + union16 IFF; + + UINT8 I; + UINT8 IM; + UINT8 HaltState; + UINT8 dummy; + + INT32 IRQLine; + INT32 IRQState; + INT32 ICount; + INT32 ExtraCycles; + + UINT32 BasePC; + UINT32 Fetch[CZ80_FETCH_BANK]; +#if CZ80_ENCRYPTED_ROM + INT32 OPBase; + INT32 OPFetch[CZ80_FETCH_BANK]; +#endif + + UINT8 *pzR8[8]; + union16 *pzR16[4]; + + UINT8 (*Read_Byte)(UINT32 address); + void (*Write_Byte)(UINT32 address, UINT8 data); + + UINT8 (*IN_Port)(UINT16 port); + void (*OUT_Port)(UINT16 port, UINT8 value); + + INT32 (*Interrupt_Callback)(INT32 irqline); + +} cz80_struc; + + +/*************************/ +/* Publics Z80 variables */ +/*************************/ + +extern cz80_struc CZ80; + +/*************************/ +/* Publics Z80 functions */ +/*************************/ + +void Cz80_Init(cz80_struc *CPU); + +void Cz80_Reset(cz80_struc *CPU); + +INT32 Cz80_Exec(cz80_struc *CPU, INT32 cycles); + +void Cz80_Set_IRQ(cz80_struc *CPU, INT32 line, INT32 state); + +UINT32 Cz80_Get_Reg(cz80_struc *CPU, INT32 regnum); +void Cz80_Set_Reg(cz80_struc *CPU, INT32 regnum, UINT32 value); + +void Cz80_Set_Fetch(cz80_struc *CPU, UINT32 low_adr, UINT32 high_adr, UINT32 fetch_adr); +#if CZ80_ENCRYPTED_ROM +void Cz80_Set_Encrypt_Range(cz80_struc *CPU, UINT32 low_adr, UINT32 high_adr, UINT32 decrypted_rom); +#endif + +void Cz80_Set_ReadB(cz80_struc *CPU, UINT8 (*Func)(UINT32 address)); +void Cz80_Set_WriteB(cz80_struc *CPU, void (*Func)(UINT32 address, UINT8 data)); + +void Cz80_Set_INPort(cz80_struc *CPU, UINT8 (*Func)(UINT16 port)); +void Cz80_Set_OUTPort(cz80_struc *CPU, void (*Func)(UINT16 port, UINT8 value)); + +void Cz80_Set_IRQ_Callback(cz80_struc *CPU, INT32 (*Func)(INT32 irqline)); + +#ifdef __cplusplus +}; +#endif + +#endif /* CZ80_H */ diff --git a/cpu/cz80/cz80_op.c b/cpu/cz80/cz80_op.c new file mode 100644 index 0000000..ed13c9e --- /dev/null +++ b/cpu/cz80/cz80_op.c @@ -0,0 +1,1145 @@ +/****************************************************************************** + * + * CZ80 opcode include source file + * CZ80 emulator version 0.9 + * Copyright 2004-2005 Stéphane Dallongeville + * + * (Modified by NJ) + * + *****************************************************************************/ + +#if CZ80_USE_JUMPTABLE + goto *JumpTable[Opcode]; +#else +switch (Opcode) +{ +#endif + +/*----------------------------------------- + NOP +-----------------------------------------*/ + + OP(0x00): // NOP + +/*----------------------------------------- + LD r8 (same register) +-----------------------------------------*/ + + OP(0x40): // LD B,B + OP(0x49): // LD C,C + OP(0x52): // LD D,D + OP(0x5b): // LD E,E + OP(0x64): // LD H,H + OP(0x6d): // LD L,L + OP(0x7f): // LD A,A + RET(4) + +/*----------------------------------------- + LD r8 +-----------------------------------------*/ + + OP(0x41): // LD B,C + OP(0x42): // LD B,D + OP(0x43): // LD B,E + OP(0x44): // LD B,H + OP(0x45): // LD B,L + OP(0x47): // LD B,A + + OP(0x48): // LD C,B + OP(0x4a): // LD C,D + OP(0x4b): // LD C,E + OP(0x4c): // LD C,H + OP(0x4d): // LD C,L + OP(0x4f): // LD C,A + + OP(0x50): // LD D,B + OP(0x51): // LD D,C + OP(0x53): // LD D,E + OP(0x54): // LD D,H + OP(0x55): // LD D,L + OP(0x57): // LD D,A + + OP(0x58): // LD E,B + OP(0x59): // LD E,C + OP(0x5a): // LD E,D + OP(0x5c): // LD E,H + OP(0x5d): // LD E,L + OP(0x5f): // LD E,A + + OP(0x60): // LD H,B + OP(0x61): // LD H,C + OP(0x62): // LD H,D + OP(0x63): // LD H,E + OP(0x65): // LD H,L + OP(0x67): // LD H,A + + OP(0x68): // LD L,B + OP(0x69): // LD L,C + OP(0x6a): // LD L,D + OP(0x6b): // LD L,E + OP(0x6c): // LD L,H + OP(0x6f): // LD L,A + + OP(0x78): // LD A,B + OP(0x79): // LD A,C + OP(0x7a): // LD A,D + OP(0x7b): // LD A,E + OP(0x7c): // LD A,H + OP(0x7d): // LD A,L +OP_LD_R_R: + zR8((Opcode >> 3) & 7) = zR8(Opcode & 7); + RET(4) + + OP(0x06): // LD B,#imm + OP(0x0e): // LD C,#imm + OP(0x16): // LD D,#imm + OP(0x1e): // LD E,#imm + OP(0x26): // LD H,#imm + OP(0x2e): // LD L,#imm + OP(0x3e): // LD A,#imm +OP_LD_R_imm: + zR8(Opcode >> 3) = READ_ARG(); + RET(7) + + OP(0x46): // LD B,(HL) + OP(0x4e): // LD C,(HL) + OP(0x56): // LD D,(HL) + OP(0x5e): // LD E,(HL) + OP(0x66): // LD H,(HL) + OP(0x6e): // LD L,(HL) + OP(0x7e): // LD A,(HL) + zR8((Opcode >> 3) & 7) = READ_MEM8(zHL); + RET(7) + + OP(0x70): // LD (HL),B + OP(0x71): // LD (HL),C + OP(0x72): // LD (HL),D + OP(0x73): // LD (HL),E + OP(0x74): // LD (HL),H + OP(0x75): // LD (HL),L + OP(0x77): // LD (HL),A + WRITE_MEM8(zHL, zR8(Opcode & 7)); + RET(7) + + OP(0x36): // LD (HL), #imm + WRITE_MEM8(zHL, READ_ARG()); + RET(10) + + OP(0x0a): // LD A,(BC) +OP_LOAD_A_mBC: + adr = zBC; + goto OP_LOAD_A_mxx; + + OP(0x1a): // LD A,(DE) +OP_LOAD_A_mDE: + adr = zDE; + +OP_LOAD_A_mxx: + zA = READ_MEM8(adr); + RET(7) + + OP(0x3a): // LD A,(nn) +OP_LOAD_A_mNN: + adr = READ_ARG16(); + zA = READ_MEM8(adr); + RET(13) + + OP(0x02): // LD (BC),A +OP_LOAD_mBC_A: + adr = zBC; + goto OP_LOAD_mxx_A; + + OP(0x12): // LD (DE),A +OP_LOAD_mDE_A: + adr = zDE; + +OP_LOAD_mxx_A: + WRITE_MEM8(adr, zA); + RET(7) + + OP(0x32): // LD (nn),A +OP_LOAD_mNN_A: + adr = READ_ARG16(); + WRITE_MEM8(adr, zA); + RET(13) + +/*----------------------------------------- + LD r16 +-----------------------------------------*/ + + OP(0x01): // LD BC,nn + OP(0x11): // LD DE,nn + OP(0x21): // LD HL,nn +OP_LOAD_RR_imm16: + zR16(Opcode >> 4) = READ_ARG16(); + RET(10) + + OP(0x31): // LD SP,nn +OP_LOAD_SP_imm16: + zSP = READ_ARG16(); + RET(10) + + OP(0xf9): // LD SP,HL +OP_LD_SP_xx: + zSP = data->W; + RET(6) + + OP(0x2a): // LD HL,(nn) +OP_LD_xx_mNN: + adr = READ_ARG16(); + data->W = READ_MEM16(adr); + RET(16) + + OP(0x22): // LD (nn),HL +OP_LD_mNN_xx: + adr = READ_ARG16(); + WRITE_MEM16(adr, data->W); + RET(16) + +/*----------------------------------------- + POP +-----------------------------------------*/ + + OP(0xc1): // POP BC + OP(0xd1): // POP DE + OP(0xf1): // POP AF +OP_POP_RR: + data = CPU->pzR16[(Opcode >> 4) & 3]; + + OP(0xe1): // POP HL +OP_POP: + POP_16(data->W) + RET(10) + +/*----------------------------------------- + PUSH +-----------------------------------------*/ + + OP(0xc5): // PUSH BC + OP(0xd5): // PUSH DE + OP(0xf5): // PUSH AF +OP_PUSH_RR: + data = CPU->pzR16[(Opcode >> 4) & 3]; + + OP(0xe5): // PUSH HL +OP_PUSH: + PUSH_16(data->W); + RET(11) + +/*----------------------------------------- + EX +-----------------------------------------*/ + + OP(0x08): // EX AF,AF' +OP_EX_AF_AF2: + res = zAF; + zAF = zAF2; + zAF2 = res; + RET(4) + + OP(0xeb): // EX DE,HL +OP_EX_DE_HL: + res = zDE; + zDE = zHL; + zHL = res; + RET(4) + + OP(0xd9): // EXX +OP_EXX: + res = zBC; + zBC = zBC2; + zBC2 = res; + res = zDE; + zDE = zDE2; + zDE2 = res; + res = zHL; + zHL = zHL2; + zHL2 = res; + RET(4) + + OP(0xe3): // EX HL,(SP) +OP_EX_xx_mSP: + adr = zSP; + res = data->W; + data->W = READ_MEM16(adr); + WRITE_MEM16(adr, res); + RET(19) + +/*----------------------------------------- + INC r8 +-----------------------------------------*/ + + OP(0x04): // INC B + OP(0x0c): // INC C + OP(0x14): // INC D + OP(0x1c): // INC E + OP(0x24): // INC H + OP(0x2c): // INC L + OP(0x3c): // INC A +OP_INC_R: + zR8(Opcode >> 3)++; + zF = (zF & CF) | SZHV_inc[zR8(Opcode >> 3)]; + RET(4) + + OP(0x34): // INC (HL) + adr = zHL; + +OP_INC_m: + res = READ_MEM8(adr); + res = (res + 1) & 0xff; + zF = (zF & CF) | SZHV_inc[res]; + WRITE_MEM8(adr, res); + RET(11) + +/*----------------------------------------- + DEC r8 +-----------------------------------------*/ + + OP(0x05): // DEC B + OP(0x0d): // DEC C + OP(0x15): // DEC D + OP(0x1d): // DEC E + OP(0x25): // DEC H + OP(0x2d): // DEC L + OP(0x3d): // DEC A +OP_DEC_R: + zR8(Opcode >> 3)--; + zF = (zF & CF) | SZHV_dec[zR8(Opcode >> 3)]; + RET(4) + + OP(0x35): // DEC (HL) + adr = zHL; + +OP_DEC_m: + res = READ_MEM8(adr); + res = (res - 1) & 0xff; + zF = (zF & CF) | SZHV_dec[res]; + WRITE_MEM8(adr, res); + RET(11) + +/*----------------------------------------- + ADD r8 +-----------------------------------------*/ + + OP(0x86): // ADD A,(HL) + val = READ_MEM8(zHL); + USE_CYCLES(3) + goto OP_ADD; + + OP(0xc6): // ADD A,n +OP_ADD_imm: + val = READ_ARG(); + USE_CYCLES(3) + goto OP_ADD; + + OP(0x80): // ADD A,B + OP(0x81): // ADD A,C + OP(0x82): // ADD A,D + OP(0x83): // ADD A,E + OP(0x84): // ADD A,H + OP(0x85): // ADD A,L + OP(0x87): // ADD A,A +OP_ADD_R: + val = zR8(Opcode & 7); + +OP_ADD: +#if CZ80_BIG_FLAGS_ARRAY + { + UINT16 A = zA; + res = (UINT8)(A + val); + zF = SZHVC_add[(A << 8) | res]; + zA = res; + } +#else + res = zA + val; + zF = SZ[(UINT8)res] | ((res >> 8) & CF) | + ((zA ^ res ^ val) & HF) | + (((val ^ zA ^ 0x80) & (val ^ res) & 0x80) >> 5); + zA = res; +#endif + RET(4) + +/*----------------------------------------- + ADC r8 +-----------------------------------------*/ + + OP(0x8e): // ADC A,(HL) + val = READ_MEM8(zHL); + USE_CYCLES(3) + goto OP_ADC; + + OP(0xce): // ADC A,n +OP_ADC_imm: + val = READ_ARG(); + USE_CYCLES(3) + goto OP_ADC; + + OP(0x88): // ADC A,B + OP(0x89): // ADC A,C + OP(0x8a): // ADC A,D + OP(0x8b): // ADC A,E + OP(0x8c): // ADC A,H + OP(0x8d): // ADC A,L + OP(0x8f): // ADC A,A +OP_ADC_R: + val = zR8(Opcode & 7); + +OP_ADC: +#if CZ80_BIG_FLAGS_ARRAY + { + UINT8 A = zA; + UINT8 c = zF & CF; + res = (UINT8)(A + val + c); + zF = SZHVC_add[(c << 16) | (A << 8) | res]; + zA = res; + } +#else + res = zA + val + (zF & CF); + zF = SZ[res & 0xff] | ((res >> 8) & CF) | + ((zA ^ res ^ val) & HF) | + (((val ^ zA ^ 0x80) & (val ^ res) & 0x80) >> 5); + zA = res; +#endif + RET(4) + +/*----------------------------------------- + SUB r8 +-----------------------------------------*/ + + OP(0x96): // SUB (HL) + val = READ_MEM8(zHL); + USE_CYCLES(3) + goto OP_SUB; + + OP(0xd6): // SUB A,n +OP_SUB_imm: + val = READ_ARG(); + USE_CYCLES(3) + goto OP_SUB; + + OP(0x90): // SUB B + OP(0x91): // SUB C + OP(0x92): // SUB D + OP(0x93): // SUB E + OP(0x94): // SUB H + OP(0x95): // SUB L + OP(0x97): // SUB A +OP_SUB_R: + val = zR8(Opcode & 7); + +OP_SUB: +#if CZ80_BIG_FLAGS_ARRAY + { + UINT8 A = zA; + res = (UINT8)(A - val); + zF = SZHVC_sub[(A << 8) | res]; + zA = res; + } +#else + res = zA - val; + zF = SZ[res & 0xff] | ((res >> 8) & CF) | NF | + ((zA ^ res ^ val) & HF) | + (((val ^ zA) & (zA ^ res) & 0x80) >> 5); + zA = res; +#endif + RET(4) + +/*----------------------------------------- + SBC r8 +-----------------------------------------*/ + + OP(0x9e): // SBC A,(HL) + val = READ_MEM8(zHL); + USE_CYCLES(3) + goto OP_SBC; + + OP(0xde): // SBC A,n +OP_SBC_imm: + val = READ_ARG(); + USE_CYCLES(3) + goto OP_SBC; + + OP(0x98): // SBC A,B + OP(0x99): // SBC A,C + OP(0x9a): // SBC A,D + OP(0x9b): // SBC A,E + OP(0x9c): // SBC A,H + OP(0x9d): // SBC A,L + OP(0x9f): // SBC A,A +OP_SBC_R: + val = zR8(Opcode & 7); + +OP_SBC: +#if CZ80_BIG_FLAGS_ARRAY + { + UINT8 A = zA; + UINT8 c = zF & CF; + res = (UINT8)(A - val - c); + zF = SZHVC_sub[(c << 16) | (A << 8) | res]; + zA = res; + } +#else + res = zA - val - (zF & CF); + zF = SZ[res & 0xff] | ((res >> 8) & CF) | NF | + ((zA ^ res ^ val) & HF) | + (((val ^ zA) & (zA ^ res) & 0x80) >> 5); + zA = res; +#endif + RET(4) + +/*----------------------------------------- + CP r8 +-----------------------------------------*/ + + OP(0xbe): // CP (HL) + val = READ_MEM8(zHL); + USE_CYCLES(3) + goto OP_CP; + + OP(0xfe): // CP n +OP_CP_imm: + val = READ_ARG(); + USE_CYCLES(3) + goto OP_CP; + + OP(0xb8): // CP B + OP(0xb9): // CP C + OP(0xba): // CP D + OP(0xbb): // CP E + OP(0xbc): // CP H + OP(0xbd): // CP L + OP(0xbf): // CP A +OP_CP_R: + val = zR8(Opcode & 7); + +OP_CP: +#if CZ80_BIG_FLAGS_ARRAY + { + UINT8 A = zA; + res = (UINT8)(A - val); + zF = (SZHVC_sub[(A << 8) | res] & ~(YF | XF)) | + (val & (YF | XF)); + } +#else + res = zA - val; + zF = (SZ[res & 0xff] & (SF | ZF)) | + (val & (YF | XF)) | ((res >> 8) & CF) | NF | + ((zA ^ res ^ val) & HF) | + (((val ^ zA) & (zA ^ res) >> 5) & VF); +#endif + RET(4) + +/*----------------------------------------- + AND r8 +-----------------------------------------*/ + + OP(0xa6): // AND (HL) + val = READ_MEM8(zHL); + USE_CYCLES(3) + goto OP_AND; + + OP(0xe6): // AND A,n +OP_AND_imm: + val = READ_ARG(); + USE_CYCLES(3) + goto OP_AND; + + OP(0xa0): // AND B + OP(0xa1): // AND C + OP(0xa2): // AND D + OP(0xa3): // AND E + OP(0xa4): // AND H + OP(0xa5): // AND L + OP(0xa7): // AND A +OP_AND_R: + val = zR8(Opcode & 7); + +OP_AND: + zA &= val; + zF = SZP[zA] | HF; + RET(4) + +/*----------------------------------------- + XOR r8 +-----------------------------------------*/ + + OP(0xae): // XOR (HL) + val = READ_MEM8(zHL); + USE_CYCLES(3) + goto OP_XOR; + + OP(0xee): // XOR A,n +OP_XOR_imm: + val = READ_ARG(); + USE_CYCLES(3) + goto OP_XOR; + + OP(0xa8): // XOR B + OP(0xa9): // XOR C + OP(0xaa): // XOR D + OP(0xab): // XOR E + OP(0xac): // XOR H + OP(0xad): // XOR L + OP(0xaf): // XOR A +OP_XOR_R: + val = zR8(Opcode & 7); + +OP_XOR: + zA ^= val; + zF = SZP[zA]; + RET(4) + +/*----------------------------------------- + OR r8 +-----------------------------------------*/ + + OP(0xb6): // OR (HL) + val = READ_MEM8(zHL); + USE_CYCLES(3) + goto OP_OR; + + OP(0xf6): // OR A,n +OP_OR_imm: + val = READ_ARG(); + USE_CYCLES(3) + goto OP_OR; + + OP(0xb0): // OR B + OP(0xb1): // OR C + OP(0xb2): // OR D + OP(0xb3): // OR E + OP(0xb4): // OR H + OP(0xb5): // OR L + OP(0xb7): // OR A +OP_OR_R: + val = zR8(Opcode & 7); + +OP_OR: + zA |= val; + zF = SZP[zA]; + RET(4) + +/*----------------------------------------- + MISC ARITHMETIC & CPU CONTROL +-----------------------------------------*/ + + OP(0x27): // DAA +OP_DAA: + { + UINT8 F; + UINT8 cf, nf, hf, lo, hi, diff; + + F = zF; + cf = F & CF; + nf = F & NF; + hf = F & HF; + lo = zA & 0x0f; + hi = zA >> 4; + + if (cf) + { + diff = (lo <= 9 && !hf) ? 0x60 : 0x66; + } + else + { + if (lo >= 10) + { + diff = hi <= 8 ? 0x06 : 0x66; + } + else + { + if (hi >= 10) + { + diff = hf ? 0x66 : 0x60; + } + else + { + diff = hf ? 0x06 : 0x00; + } + } + } + if (nf) zA -= diff; + else zA += diff; + + F = SZP[zA] | (F & NF); + if (cf || (lo <= 9 ? hi >= 10 : hi >= 9)) F |= CF; + if (nf ? hf && lo <= 5 : lo >= 10) F |= HF; + zF = F; + RET(4) + } + + OP(0x2f): // CPL +OP_CPL: + zA ^= 0xff; + zF = (zF & (SF | ZF | PF | CF)) | HF | NF | (zA & (YF | XF)); + RET(4) + + OP(0x37): // SCF +OP_SCF: + zF = (zF & (SF | ZF | PF)) | CF | (zA & (YF | XF)); + RET(4) + + OP(0x3f): // CCF +OP_CCF: + zF = ((zF & (SF | ZF | PF | CF)) | ((zF & CF) << 4) | (zA & (YF | XF))) ^ CF; + RET(4) + + OP(0x76): // HALT +OP_HALT: + CPU->HaltState = 1; + CPU->ICount = 0; + goto Cz80_Check_Interrupt; + + OP(0xf3): // DI +OP_DI: + zIFF = 0; + RET(4) + + OP(0xfb): // EI +OP_EI: + USE_CYCLES(4) + if (!zIFF1) + { + zIFF1 = zIFF2 = (1 << 2); + while (GET_OP() == 0xfb) + { + USE_CYCLES(4) + PC++; +#if CZ80_EMULATE_R_EXACTLY + zR++; +#endif + } + if (CPU->IRQState) + { + afterEI = 1; + } + if (CPU->ICount <= 0) + { + CPU->ICount = 1; + } + } + else zIFF2 = (1 << 2); + goto Cz80_Exec; + +/*----------------------------------------- + INC r16 +-----------------------------------------*/ + + OP(0x03): // INC BC +OP_INC_BC: + zBC++; + RET(6) + + OP(0x13): // INC DE +OP_INC_DE: + zDE++; + RET(6) + + OP(0x23): // INC HL +OP_INC_xx: + data->W++; + RET(6) + + OP(0x33): // INC SP +OP_INC_SP: + zSP++; + RET(6) + +/*----------------------------------------- + DEC r16 +-----------------------------------------*/ + + OP(0x0b): // DEC BC +OP_DEC_BC: + zBC--; + RET(6) + + OP(0x1b): // DEC DE +OP_DEC_DE: + zDE--; + RET(6) + + OP(0x2b): // DEC HL +OP_DEC_xx: + data->W--; + RET(6) + + OP(0x3b): // DEC SP +OP_DEC_SP: + zSP--; + RET(6) + +/*----------------------------------------- + ADD r16 +-----------------------------------------*/ + + OP(0x39): // ADD xx,SP +OP_ADD16_xx_SP: + val = zSP; + goto OP_ADD16; + + OP(0x29): // ADD xx,xx +OP_ADD16_xx_xx: + val = data->W; + goto OP_ADD16; + + OP(0x09): // ADD xx,BC +OP_ADD16_xx_BC: + val = zBC; + goto OP_ADD16; + + OP(0x19): // ADD xx,DE +OP_ADD16_xx_DE: + val = zDE; + +OP_ADD16: + res = data->W + val; + zF = (zF & (SF | ZF | VF)) | + (((data->W ^ res ^ val) >> 8) & HF) | + ((res >> 16) & CF) | ((res >> 8) & (YF | XF)); + data->W = (UINT16)res; + RET(11) + +/*----------------------------------------- + ROTATE +-----------------------------------------*/ + + { + UINT8 A; + UINT8 F; + + OP(0x07): // RLCA +OP_RLCA: + A = zA; + zA = (A << 1) | (A >> 7); + zF = (zF & (SF | ZF | PF)) | (zA & (YF | XF | CF)); + RET(4) + + OP(0x0f): // RRCA +OP_RRCA: + A = zA; + F = zF; + F = (F & (SF | ZF | PF)) | (A & CF); + zA = (A >> 1) | (A << 7); + zF = F | (zA & (YF | XF)); + RET(4) + + OP(0x17): // RLA +OP_RLA: + A = zA; + F = zF; + zA = (A << 1) | (F & CF); + zF = (F & (SF | ZF | PF)) | (A >> 7) | (zA & (YF | XF)); + RET(4) + + OP(0x1f): // RRA +OP_RRA: + A = zA; + F = zF; + zA = (A >> 1) | (F << 7); + zF = (F & (SF | ZF | PF)) | (A & CF) | (zA & (YF | XF)); + RET(4) + } + +/*----------------------------------------- + JP +-----------------------------------------*/ + + OP(0xc3): // JP nn +OP_JP: + res = READ_ARG16(); + SET_PC(res); + RET(10) + + OP(0xc2): // JP NZ,nn +OP_JP_NZ: + if (!(zF & ZF)) goto OP_JP; + PC += 2; + RET(10) + + OP(0xca): // JP Z,nn +OP_JP_Z: + if (zF & ZF) goto OP_JP; + PC += 2; + RET(10) + + OP(0xd2): // JP NC,nn +OP_JP_NC: + if (!(zF & CF)) goto OP_JP; + PC += 2; + RET(10) + + OP(0xda): // JP C,nn +OP_JP_C: + if (zF & CF) goto OP_JP; + PC += 2; + RET(10) + + OP(0xe2): // JP PO,nn +OP_JP_PO: + if (!(zF & VF)) goto OP_JP; + PC += 2; + RET(10) + + OP(0xea): // JP PE,nn +OP_JP_PE: + if (zF & VF) goto OP_JP; + PC += 2; + RET(10) + + OP(0xf2): // JP P,nn +OP_JP_P: + if (!(zF & SF)) goto OP_JP; + PC += 2; + RET(10) + + OP(0xfa): // JP M,nn +OP_JP_M: + if (zF & SF) goto OP_JP; + PC += 2; + RET(10) + + OP(0xe9): // JP (xx) +OP_JP_xx: + res = data->W; + SET_PC(res); + RET(4) + +/*----------------------------------------- + JR +-----------------------------------------*/ + + OP(0x10): // DJNZ n +OP_DJNZ: + USE_CYCLES(1) + if (--zB) goto OP_JR; + PC++; + RET(7) + + OP(0x18): // JR n +OP_JR: + adr = (INT8)READ_ARG(); + PC += adr; + RET(12) + + OP(0x20): // JR NZ,n +OP_JR_NZ: + if (!(zF & ZF)) goto OP_JR; + PC++; + RET(7) + + OP(0x28): // JR Z,n +OP_JR_Z: + if (zF & ZF) goto OP_JR; + PC++; + RET(7) + + OP(0x38): // JR C,n +OP_JR_C: + if (zF & CF) goto OP_JR; + PC++; + RET(7) + + OP(0x30): // JR NC,n +OP_JR_NC: + if (!(zF & CF)) goto OP_JR; + PC++; + RET(7) + +/*----------------------------------------- + CALL +-----------------------------------------*/ + + OP(0xcd): // CALL nn +OP_CALL: + res = READ_ARG16(); + val = zRealPC; + PUSH_16(val); + SET_PC(res); + RET(17) + + OP(0xc4): // CALL NZ,nn +OP_CALL_NZ: + if (!(zF & ZF)) goto OP_CALL; + PC += 2; + RET(10) + + OP(0xcc): // CALL Z,nn +OP_CALL_Z: + if (zF & ZF) goto OP_CALL; + PC += 2; + RET(10) + + OP(0xd4): // CALL NC,nn +OP_CALL_NC: + if (!(zF & CF)) goto OP_CALL; + PC += 2; + RET(10) + + OP(0xdc): // CALL C,nn +OP_CALL_C: + if (zF & CF) goto OP_CALL; + PC += 2; + RET(10) + + OP(0xe4): // CALL PO,nn +OP_CALL_PO: + if (!(zF & VF)) goto OP_CALL; + PC += 2; + RET(10) + + OP(0xec): // CALL PE,nn +OP_CALL_PE: + if (zF & VF) goto OP_CALL; + PC += 2; + RET(10) + + OP(0xf4): // CALL P,nn +OP_CALL_P: + if (!(zF & SF)) goto OP_CALL; + PC += 2; + RET(10) + + OP(0xfc): // CALL M,nn +OP_CALL_M: + if (zF & SF) goto OP_CALL; + PC += 2; + RET(10) + +/*----------------------------------------- + RET +-----------------------------------------*/ + +OP_RET_COND: + USE_CYCLES(1) + + OP(0xc9): // RET +OP_RET: + POP_16(res); + SET_PC(res); + RET(10) + + OP(0xc0): // RET NZ +OP_RET_NZ: + if (!(zF & ZF)) goto OP_RET_COND; + RET(5) + + OP(0xc8): // RET Z +OP_RET_Z: + if (zF & ZF) goto OP_RET_COND; + RET(5) + + OP(0xd0): // RET NC +OP_RET_NC: + if (!(zF & CF)) goto OP_RET_COND; + RET(5) + + OP(0xd8): // RET C +OP_RET_C: + if (zF & CF) goto OP_RET_COND; + RET(5) + + OP(0xe0): // RET PO +OP_RET_PO: + if (!(zF & VF)) goto OP_RET_COND; + RET(5) + + OP(0xe8): // RET PE +OP_RET_PE: + if (zF & VF) goto OP_RET_COND; + RET(5) + + OP(0xf0): // RET P +OP_RET_P: + if (!(zF & SF)) goto OP_RET_COND; + RET(5) + + OP(0xf8): // RET M +OP_RET_M: + if (zF & SF) goto OP_RET_COND; + RET(5) + +/*----------------------------------------- + RST +-----------------------------------------*/ + + OP(0xc7): // RST 0 + OP(0xcf): // RST 1 + OP(0xd7): // RST 2 + OP(0xdf): // RST 3 + OP(0xe7): // RST 4 + OP(0xef): // RST 5 + OP(0xf7): // RST 6 + OP(0xff): // RST 7 +OP_RST: + res = zRealPC; + PUSH_16(res); + res = Opcode & 0x38; + SET_PC(res); + RET(11) + +/*----------------------------------------- + OUT +-----------------------------------------*/ + + OP(0xd3): // OUT (n),A +OP_OUT_mN_A: + adr = (zA << 8) | READ_ARG(); + OUT(adr, zA); + RET(11) + +/*----------------------------------------- + IN +-----------------------------------------*/ + + OP(0xdb): // IN A,(n) +OP_IN_A_mN: + adr = (zA << 8) | READ_ARG(); + zA = IN(adr); + RET(11) + +/*----------------------------------------- + PREFIX +-----------------------------------------*/ + + OP(0xcb): // CB prefix (BIT & SHIFT INSTRUCTIONS) + { + UINT8 src; + UINT8 res; + + Opcode = READ_OP(); +#if CZ80_EMULATE_R_EXACTLY + zR++; +#endif + #include "cz80_opCB.c" + } + + OP(0xed): // ED prefix +ED_PREFIX: + USE_CYCLES(4) + Opcode = READ_OP(); +#if CZ80_EMULATE_R_EXACTLY + zR++; +#endif + #include "cz80_opED.c" + + OP(0xdd): // DD prefix (IX) +DD_PREFIX: + data = pzIX; + goto XY_PREFIX; + + OP(0xfd): // FD prefix (IY) +FD_PREFIX: + data = pzIY; + +XY_PREFIX: + USE_CYCLES(4) + Opcode = READ_OP(); +#if CZ80_EMULATE_R_EXACTLY + zR++; +#endif + #include "cz80_opXY.c" + +#if !CZ80_USE_JUMPTABLE +} +#endif diff --git a/cpu/cz80/cz80_opCB.c b/cpu/cz80/cz80_opCB.c new file mode 100644 index 0000000..58a78c5 --- /dev/null +++ b/cpu/cz80/cz80_opCB.c @@ -0,0 +1,470 @@ +/****************************************************************************** + * + * CZ80 CB opcode include source file + * CZ80 emulator version 0.9 + * Copyright 2004-2005 Stéphane Dallongeville + * + * (Modified by NJ) + * + *****************************************************************************/ + +#if CZ80_USE_JUMPTABLE + goto *JumpTableCB[Opcode]; +#else +switch (Opcode) +{ +#endif + +/*----------------------------------------- + RLC +-----------------------------------------*/ + + OPCB(0x00): // RLC B + OPCB(0x01): // RLC C + OPCB(0x02): // RLC D + OPCB(0x03): // RLC E + OPCB(0x04): // RLC H + OPCB(0x05): // RLC L + OPCB(0x07): // RLC A + src = zR8(Opcode); + res = (src << 1) | (src >> 7); + zF = SZP[res] | (src >> 7); + zR8(Opcode) = res; + RET(8) + + OPCB(0x06): // RLC (HL) + adr = zHL; + src = READ_MEM8(adr); + res = (src << 1) | (src >> 7); + zF = SZP[res] | (src >> 7); + WRITE_MEM8(adr, res); + RET(15) + +/*----------------------------------------- + RRC +-----------------------------------------*/ + + OPCB(0x08): // RRC B + OPCB(0x09): // RRC C + OPCB(0x0a): // RRC D + OPCB(0x0b): // RRC E + OPCB(0x0c): // RRC H + OPCB(0x0d): // RRC L + OPCB(0x0f): // RRC A + src = zR8(Opcode & 7); + res = (src >> 1) | (src << 7); + zF = SZP[res] | (src & CF); + zR8(Opcode & 7) = res; + RET(8) + + OPCB(0x0e): // RRC (HL) + adr = zHL; + src = READ_MEM8(adr); + res = (src >> 1) | (src << 7); + zF = SZP[res] | (src & CF); + WRITE_MEM8(adr, res); + RET(15) + +/*----------------------------------------- + RL +-----------------------------------------*/ + + OPCB(0x10): // RL B + OPCB(0x11): // RL C + OPCB(0x12): // RL D + OPCB(0x13): // RL E + OPCB(0x14): // RL H + OPCB(0x15): // RL L + OPCB(0x17): // RL A + src = zR8(Opcode & 7); + res = (src << 1) | (zF & CF); + zF = SZP[res] | (src >> 7); + zR8(Opcode & 7) = res; + RET(8) + + OPCB(0x16): // RL (HL) + adr = zHL; + src = READ_MEM8(adr); + res = (src << 1) | (zF & CF); + zF = SZP[res] | (src >> 7); + WRITE_MEM8(adr, res); + RET(15) + +/*----------------------------------------- + RR +-----------------------------------------*/ + + OPCB(0x18): // RR B + OPCB(0x19): // RR C + OPCB(0x1a): // RR D + OPCB(0x1b): // RR E + OPCB(0x1c): // RR H + OPCB(0x1d): // RR L + OPCB(0x1f): // RR A + src = zR8(Opcode & 7); + res = (src >> 1) | (zF << 7); + zF = SZP[res] | (src & CF); + zR8(Opcode & 7) = res; + RET(8) + + OPCB(0x1e): // RR (HL) + adr = zHL; + src = READ_MEM8(adr); + res = (src >> 1) | (zF << 7); + zF = SZP[res] | (src & CF); + WRITE_MEM8(adr, res); + RET(15) + +/*----------------------------------------- + SLA +-----------------------------------------*/ + + OPCB(0x20): // SLA B + OPCB(0x21): // SLA C + OPCB(0x22): // SLA D + OPCB(0x23): // SLA E + OPCB(0x24): // SLA H + OPCB(0x25): // SLA L + OPCB(0x27): // SLA A + src = zR8(Opcode & 7); + res = src << 1; + zF = SZP[res] | (src >> 7); + zR8(Opcode & 7) = res; + RET(8) + + OPCB(0x26): // SLA (HL) + adr = zHL; + src = READ_MEM8(adr); + res = src << 1; + zF = SZP[res] | (src >> 7); + WRITE_MEM8(adr, res); + RET(15) + +/*----------------------------------------- + SRA +-----------------------------------------*/ + + OPCB(0x28): // SRA B + OPCB(0x29): // SRA C + OPCB(0x2a): // SRA D + OPCB(0x2b): // SRA E + OPCB(0x2c): // SRA H + OPCB(0x2d): // SRA L + OPCB(0x2f): // SRA A + src = zR8(Opcode & 7); + res = (src >> 1) | (src & 0x80); + zF = SZP[res] | (src & CF); + zR8(Opcode & 7) = res; + RET(8) + + OPCB(0x2e): // SRA (HL) + adr = zHL; + src = READ_MEM8(adr); + res = (src >> 1) | (src & 0x80); + zF = SZP[res] | (src & CF); + WRITE_MEM8(adr, res); + RET(15) + +/*----------------------------------------- + SLL +-----------------------------------------*/ + + OPCB(0x30): // SLL B + OPCB(0x31): // SLL C + OPCB(0x32): // SLL D + OPCB(0x33): // SLL E + OPCB(0x34): // SLL H + OPCB(0x35): // SLL L + OPCB(0x37): // SLL A + src = zR8(Opcode & 7); + res = (src << 1) | 0x01; + zF = SZP[res] | (src >> 7); + zR8(Opcode & 7) = res; + RET(8) + + OPCB(0x36): // SLL (HL) + adr = zHL; + src = READ_MEM8(adr); + res = (src << 1) | 0x01; + zF = SZP[res] | (src >> 7); + WRITE_MEM8(adr, res); + RET(15) + +/*----------------------------------------- + SRL +-----------------------------------------*/ + + OPCB(0x38): // SRL B + OPCB(0x39): // SRL C + OPCB(0x3a): // SRL D + OPCB(0x3b): // SRL E + OPCB(0x3c): // SRL H + OPCB(0x3d): // SRL L + OPCB(0x3f): // SRL A + src = zR8(Opcode & 7); + res = src >> 1; + zF = SZP[res] | (src & CF); + zR8(Opcode & 7) = res; + RET(8) + + OPCB(0x3e): // SRL (HL) + adr = zHL; + src = READ_MEM8(adr); + res = src >> 1; + zF = SZP[res] | (src & CF); + WRITE_MEM8(adr, res); + RET(15) + +/*----------------------------------------- + BIT +-----------------------------------------*/ + + OPCB(0x40): // BIT 0,B + OPCB(0x41): // BIT 0,C + OPCB(0x42): // BIT 0,D + OPCB(0x43): // BIT 0,E + OPCB(0x44): // BIT 0,H + OPCB(0x45): // BIT 0,L + OPCB(0x47): // BIT 0,A + + OPCB(0x48): // BIT 1,B + OPCB(0x49): // BIT 1,C + OPCB(0x4a): // BIT 1,D + OPCB(0x4b): // BIT 1,E + OPCB(0x4c): // BIT 1,H + OPCB(0x4d): // BIT 1,L + OPCB(0x4f): // BIT 1,A + + OPCB(0x50): // BIT 2,B + OPCB(0x51): // BIT 2,C + OPCB(0x52): // BIT 2,D + OPCB(0x53): // BIT 2,E + OPCB(0x54): // BIT 2,H + OPCB(0x55): // BIT 2,L + OPCB(0x57): // BIT 2,A + + OPCB(0x58): // BIT 3,B + OPCB(0x59): // BIT 3,C + OPCB(0x5a): // BIT 3,D + OPCB(0x5b): // BIT 3,E + OPCB(0x5c): // BIT 3,H + OPCB(0x5d): // BIT 3,L + OPCB(0x5f): // BIT 3,A + + OPCB(0x60): // BIT 4,B + OPCB(0x61): // BIT 4,C + OPCB(0x62): // BIT 4,D + OPCB(0x63): // BIT 4,E + OPCB(0x64): // BIT 4,H + OPCB(0x65): // BIT 4,L + OPCB(0x67): // BIT 4,A + + OPCB(0x68): // BIT 5,B + OPCB(0x69): // BIT 5,C + OPCB(0x6a): // BIT 5,D + OPCB(0x6b): // BIT 5,E + OPCB(0x6c): // BIT 5,H + OPCB(0x6d): // BIT 5,L + OPCB(0x6f): // BIT 5,A + + OPCB(0x70): // BIT 6,B + OPCB(0x71): // BIT 6,C + OPCB(0x72): // BIT 6,D + OPCB(0x73): // BIT 6,E + OPCB(0x74): // BIT 6,H + OPCB(0x75): // BIT 6,L + OPCB(0x77): // BIT 6,A + + OPCB(0x78): // BIT 7,B + OPCB(0x79): // BIT 7,C + OPCB(0x7a): // BIT 7,D + OPCB(0x7b): // BIT 7,E + OPCB(0x7c): // BIT 7,H + OPCB(0x7d): // BIT 7,L + OPCB(0x7f): // BIT 7,A + zF = (zF & CF) | HF | SZ_BIT[zR8(Opcode & 7) & (1 << ((Opcode >> 3) & 7))]; + RET(8) + + OPCB(0x46): // BIT 0,(HL) + OPCB(0x4e): // BIT 1,(HL) + OPCB(0x56): // BIT 2,(HL) + OPCB(0x5e): // BIT 3,(HL) + OPCB(0x66): // BIT 4,(HL) + OPCB(0x6e): // BIT 5,(HL) + OPCB(0x76): // BIT 6,(HL) + OPCB(0x7e): // BIT 7,(HL) + src = READ_MEM8(zHL); + zF = (zF & CF) | HF | SZ_BIT[src & (1 << ((Opcode >> 3) & 7))]; + RET(12) + +/*----------------------------------------- + RES +-----------------------------------------*/ + + OPCB(0x80): // RES 0,B + OPCB(0x81): // RES 0,C + OPCB(0x82): // RES 0,D + OPCB(0x83): // RES 0,E + OPCB(0x84): // RES 0,H + OPCB(0x85): // RES 0,L + OPCB(0x87): // RES 0,A + + OPCB(0x88): // RES 1,B + OPCB(0x89): // RES 1,C + OPCB(0x8a): // RES 1,D + OPCB(0x8b): // RES 1,E + OPCB(0x8c): // RES 1,H + OPCB(0x8d): // RES 1,L + OPCB(0x8f): // RES 1,A + + OPCB(0x90): // RES 2,B + OPCB(0x91): // RES 2,C + OPCB(0x92): // RES 2,D + OPCB(0x93): // RES 2,E + OPCB(0x94): // RES 2,H + OPCB(0x95): // RES 2,L + OPCB(0x97): // RES 2,A + + OPCB(0x98): // RES 3,B + OPCB(0x99): // RES 3,C + OPCB(0x9a): // RES 3,D + OPCB(0x9b): // RES 3,E + OPCB(0x9c): // RES 3,H + OPCB(0x9d): // RES 3,L + OPCB(0x9f): // RES 3,A + + OPCB(0xa0): // RES 4,B + OPCB(0xa1): // RES 4,C + OPCB(0xa2): // RES 4,D + OPCB(0xa3): // RES 4,E + OPCB(0xa4): // RES 4,H + OPCB(0xa5): // RES 4,L + OPCB(0xa7): // RES 4,A + + OPCB(0xa8): // RES 5,B + OPCB(0xa9): // RES 5,C + OPCB(0xaa): // RES 5,D + OPCB(0xab): // RES 5,E + OPCB(0xac): // RES 5,H + OPCB(0xad): // RES 5,L + OPCB(0xaf): // RES 5,A + + OPCB(0xb0): // RES 6,B + OPCB(0xb1): // RES 6,C + OPCB(0xb2): // RES 6,D + OPCB(0xb3): // RES 6,E + OPCB(0xb4): // RES 6,H + OPCB(0xb5): // RES 6,L + OPCB(0xb7): // RES 6,A + + OPCB(0xb8): // RES 7,B + OPCB(0xb9): // RES 7,C + OPCB(0xba): // RES 7,D + OPCB(0xbb): // RES 7,E + OPCB(0xbc): // RES 7,H + OPCB(0xbd): // RES 7,L + OPCB(0xbf): // RES 7,A + zR8(Opcode & 7) &= ~(1 << ((Opcode >> 3) & 7)); + RET(8) + + OPCB(0x86): // RES 0,(HL) + OPCB(0x8e): // RES 1,(HL) + OPCB(0x96): // RES 2,(HL) + OPCB(0x9e): // RES 3,(HL) + OPCB(0xa6): // RES 4,(HL) + OPCB(0xae): // RES 5,(HL) + OPCB(0xb6): // RES 6,(HL) + OPCB(0xbe): // RES 7,(HL) + adr = zHL; + res = READ_MEM8(adr); + res &= ~(1 << ((Opcode >> 3) & 7)); + WRITE_MEM8(adr, res); + RET(15) + +/*----------------------------------------- + SET +-----------------------------------------*/ + + OPCB(0xc0): // SET 0,B + OPCB(0xc1): // SET 0,C + OPCB(0xc2): // SET 0,D + OPCB(0xc3): // SET 0,E + OPCB(0xc4): // SET 0,H + OPCB(0xc5): // SET 0,L + OPCB(0xc7): // SET 0,A + + OPCB(0xc8): // SET 1,B + OPCB(0xc9): // SET 1,C + OPCB(0xca): // SET 1,D + OPCB(0xcb): // SET 1,E + OPCB(0xcc): // SET 1,H + OPCB(0xcd): // SET 1,L + OPCB(0xcf): // SET 1,A + + OPCB(0xd0): // SET 2,B + OPCB(0xd1): // SET 2,C + OPCB(0xd2): // SET 2,D + OPCB(0xd3): // SET 2,E + OPCB(0xd4): // SET 2,H + OPCB(0xd5): // SET 2,L + OPCB(0xd7): // SET 2,A + + OPCB(0xd8): // SET 3,B + OPCB(0xd9): // SET 3,C + OPCB(0xda): // SET 3,D + OPCB(0xdb): // SET 3,E + OPCB(0xdc): // SET 3,H + OPCB(0xdd): // SET 3,L + OPCB(0xdf): // SET 3,A + + OPCB(0xe0): // SET 4,B + OPCB(0xe1): // SET 4,C + OPCB(0xe2): // SET 4,D + OPCB(0xe3): // SET 4,E + OPCB(0xe4): // SET 4,H + OPCB(0xe5): // SET 4,L + OPCB(0xe7): // SET 4,A + + OPCB(0xe8): // SET 5,B + OPCB(0xe9): // SET 5,C + OPCB(0xea): // SET 5,D + OPCB(0xeb): // SET 5,E + OPCB(0xec): // SET 5,H + OPCB(0xed): // SET 5,L + OPCB(0xef): // SET 5,A + + OPCB(0xf0): // SET 6,B + OPCB(0xf1): // SET 6,C + OPCB(0xf2): // SET 6,D + OPCB(0xf3): // SET 6,E + OPCB(0xf4): // SET 6,H + OPCB(0xf5): // SET 6,L + OPCB(0xf7): // SET 6,A + + OPCB(0xf8): // SET 7,B + OPCB(0xf9): // SET 7,C + OPCB(0xfa): // SET 7,D + OPCB(0xfb): // SET 7,E + OPCB(0xfc): // SET 7,H + OPCB(0xfd): // SET 7,L + OPCB(0xff): // SET 7,A + zR8(Opcode & 7) |= 1 << ((Opcode >> 3) & 7); + RET(8) + + OPCB(0xc6): // SET 0,(HL) + OPCB(0xce): // SET 1,(HL) + OPCB(0xd6): // SET 2,(HL) + OPCB(0xde): // SET 3,(HL) + OPCB(0xe6): // SET 4,(HL) + OPCB(0xee): // SET 5,(HL) + OPCB(0xf6): // SET 6,(HL) + OPCB(0xfe): // SET 7,(HL) + adr = zHL; + res = READ_MEM8(adr); + res |= 1 << ((Opcode >> 3) & 7); + WRITE_MEM8(adr, res); + RET(15) + +#if !CZ80_USE_JUMPTABLE +} +#endif diff --git a/cpu/cz80/cz80_opED.c b/cpu/cz80/cz80_opED.c new file mode 100644 index 0000000..c3b7ec6 --- /dev/null +++ b/cpu/cz80/cz80_opED.c @@ -0,0 +1,731 @@ +/****************************************************************************** + * + * CZ80 ED opcode include source file + * CZ80 emulator version 0.9 + * Copyright 2004-2005 Stéphane Dallongeville + * + * (Modified by NJ) + * + *****************************************************************************/ + +#if CZ80_USE_JUMPTABLE + goto *JumpTableED[Opcode]; +#else +switch (Opcode) +{ +#endif + +/*----------------------------------------- + ILLEGAL +-----------------------------------------*/ + + OPED(0x00): + OPED(0x01): + OPED(0x02): + OPED(0x03): + OPED(0x04): + OPED(0x05): + OPED(0x06): + OPED(0x07): + OPED(0x08): + OPED(0x09): + OPED(0x0a): + OPED(0x0b): + OPED(0x0c): + OPED(0x0d): + OPED(0x0e): + OPED(0x0f): + + OPED(0x10): + OPED(0x11): + OPED(0x12): + OPED(0x13): + OPED(0x14): + OPED(0x15): + OPED(0x16): + OPED(0x17): + OPED(0x18): + OPED(0x19): + OPED(0x1a): + OPED(0x1b): + OPED(0x1c): + OPED(0x1d): + OPED(0x1e): + OPED(0x1f): + + OPED(0x20): + OPED(0x21): + OPED(0x22): + OPED(0x23): + OPED(0x24): + OPED(0x25): + OPED(0x26): + OPED(0x27): + OPED(0x28): + OPED(0x29): + OPED(0x2a): + OPED(0x2b): + OPED(0x2c): + OPED(0x2d): + OPED(0x2e): + OPED(0x2f): + + OPED(0x30): + OPED(0x31): + OPED(0x32): + OPED(0x33): + OPED(0x34): + OPED(0x35): + OPED(0x36): + OPED(0x37): + OPED(0x38): + OPED(0x39): + OPED(0x3a): + OPED(0x3b): + OPED(0x3c): + OPED(0x3d): + OPED(0x3e): + OPED(0x3f): + + OPED(0x77): + OPED(0x7f): + + OPED(0x80): + OPED(0x81): + OPED(0x82): + OPED(0x83): + OPED(0x84): + OPED(0x85): + OPED(0x86): + OPED(0x87): + OPED(0x88): + OPED(0x89): + OPED(0x8a): + OPED(0x8b): + OPED(0x8c): + OPED(0x8d): + OPED(0x8e): + OPED(0x8f): + + OPED(0x90): + OPED(0x91): + OPED(0x92): + OPED(0x93): + OPED(0x94): + OPED(0x95): + OPED(0x96): + OPED(0x97): + OPED(0x98): + OPED(0x99): + OPED(0x9a): + OPED(0x9b): + OPED(0x9c): + OPED(0x9d): + OPED(0x9e): + OPED(0x9f): + + OPED(0xa4): + OPED(0xa5): + OPED(0xa6): + OPED(0xa7): + + OPED(0xac): + OPED(0xad): + OPED(0xae): + OPED(0xaf): + + OPED(0xb4): + OPED(0xb5): + OPED(0xb6): + OPED(0xb7): + + OPED(0xbc): + OPED(0xbd): + OPED(0xbe): + OPED(0xbf): + + OPED(0xc0): + OPED(0xc1): + OPED(0xc2): + OPED(0xc3): + OPED(0xc4): + OPED(0xc5): + OPED(0xc6): + OPED(0xc7): + OPED(0xc8): + OPED(0xc9): + OPED(0xca): + OPED(0xcb): + OPED(0xcc): + OPED(0xcd): + OPED(0xce): + OPED(0xcf): + + OPED(0xd0): + OPED(0xd1): + OPED(0xd2): + OPED(0xd3): + OPED(0xd4): + OPED(0xd5): + OPED(0xd6): + OPED(0xd7): + OPED(0xd8): + OPED(0xd9): + OPED(0xda): + OPED(0xdb): + OPED(0xdc): + OPED(0xdd): + OPED(0xde): + OPED(0xdf): + + OPED(0xe0): + OPED(0xe1): + OPED(0xe2): + OPED(0xe3): + OPED(0xe4): + OPED(0xe5): + OPED(0xe6): + OPED(0xe7): + OPED(0xe8): + OPED(0xe9): + OPED(0xea): + OPED(0xeb): + OPED(0xec): + OPED(0xed): + OPED(0xee): + OPED(0xef): + + OPED(0xf0): + OPED(0xf1): + OPED(0xf2): + OPED(0xf3): + OPED(0xf4): + OPED(0xf5): + OPED(0xf6): + OPED(0xf7): + OPED(0xf8): + OPED(0xf9): + OPED(0xfa): + OPED(0xfb): + OPED(0xfc): + OPED(0xfd): + OPED(0xfe): + OPED(0xff): + RET(4) + +/*----------------------------------------- + LD r8 +-----------------------------------------*/ + + OPED(0x47): // LD I,A + zI = zA; + RET(5) + + OPED(0x4f): // LD R,A +#if CZ80_EMULATE_R_EXACTLY + zR = zA; +#else + zR = zA - ((cycles - CPU->ICount) >> 2); +#endif + zR2 = zA & 0x80; + RET(5) + + OPED(0x57): // LD A,I + zA = zI; + zF = (zF & CF) | SZ[zA] | zIFF2; + RET(5) + + OPED(0x5f): // LD A,R +#if CZ80_EMULATE_R_EXACTLY + zA = (zR & 0x7f) | zR2; +#else + zA = ((zR + ((cycles - CPU->ICount) >> 2)) & 0x7f) | zR2; +#endif + zF = (zF & CF) | SZ[zA] | zIFF2; + RET(5) + +/*----------------------------------------- + LD r16 +-----------------------------------------*/ + + OPED(0x43): // LD (w),BC + data = pzBC; + goto OP_LD_mNN_xx; + + OPED(0x53): // LD (w),DE + data = pzDE; + goto OP_LD_mNN_xx; + + OPED(0x63): // LD (w),HL + data = pzHL; + goto OP_LD_mNN_xx; + + OPED(0x73): // LD (w),SP + data = pzSP; + goto OP_LD_mNN_xx; + + OPED(0x4b): // LD BC,(w) + data = pzBC; + goto OP_LD_xx_mNN; + + OPED(0x5b): // LD DE,(w) + data = pzDE; + goto OP_LD_xx_mNN; + + OPED(0x6b): // LD HL,(w) + data = pzHL; + goto OP_LD_xx_mNN; + + OPED(0x7b): // LD SP,(w) + data = pzSP; + goto OP_LD_xx_mNN; + +/*----------------------------------------- + NEG +-----------------------------------------*/ + + OPED(0x44): // NEG + OPED(0x4c): // NEG + OPED(0x54): // NEG + OPED(0x5c): // NEG + OPED(0x64): // NEG + OPED(0x6c): // NEG + OPED(0x74): // NEG + OPED(0x7c): // NEG + val = zA; + zA = 0; + goto OP_SUB; + +/*----------------------------------------- + RRD +-----------------------------------------*/ + + OPED(0x67): // RRD (HL) + adr = zHL; + val = READ_MEM8(adr); + WRITE_MEM8(adr, (val >> 4) | (zA << 4)); + zA = (zA & 0xf0) | (val & 0x0f); + zF = (zF & CF) | SZP[zA]; + RET(14) + +/*----------------------------------------- + RLD +-----------------------------------------*/ + + OPED(0x6f): // RLD (HL) + adr = zHL; + val = READ_MEM8(adr); + WRITE_MEM8(adr, (val << 4) | (zA & 0x0f)); + zA = (zA & 0xf0) | (val >> 4); + zF = (zF & CF) | SZP[zA]; + RET(14) + +/*----------------------------------------- + ADC 16 +-----------------------------------------*/ + + OPED(0x7a): // ADC HL,SP + val = zSP; + goto OP_ADC16; + + OPED(0x4a): // ADC HL,BC + OPED(0x5a): // ADC HL,DE + OPED(0x6a): // ADC HL,HL + val = zR16((Opcode >> 4) & 3); + +OP_ADC16: + res = zHL + val + (zF & CF); + zF = (((zHL ^ res ^ val) >> 8) & HF) | + ((res >> 16) & CF) | + ((res >> 8) & (SF | YF | XF)) | + ((res & 0xffff) ? 0 : ZF) | + (((val ^ zHL ^ 0x8000) & (val ^ res) & 0x8000) >> 13); + zHL = (UINT16)res; + RET(11) + +/*----------------------------------------- + SBC 16 +-----------------------------------------*/ + + OPED(0x72): // SBC HL,SP + val = zSP; + goto OP_SBC16; + + OPED(0x42): // SBC HL,BC + OPED(0x52): // SBC HL,DE + OPED(0x62): // SBC HL,HL + val = zR16((Opcode >> 4) & 3); + +OP_SBC16: + res = zHL - val - (zF & CF); + zF = (((zHL ^ res ^ val) >> 8) & HF) | NF | + ((res >> 16) & CF) | + ((res >> 8) & (SF | YF | XF)) | + ((res & 0xffff) ? 0 : ZF) | + (((val ^ zHL) & (zHL ^ res) & 0x8000) >> 13); + zHL = (UINT16)res; + RET(11) + +/*----------------------------------------- + IN +-----------------------------------------*/ + + OPED(0x40): // IN B,(C) + OPED(0x48): // IN C,(C) + OPED(0x50): // IN D,(C) + OPED(0x58): // IN E,(C) + OPED(0x60): // IN H,(C) + OPED(0x68): // IN L,(C) + OPED(0x78): // IN E,(C) + res = IN(zBC); + zR8((Opcode >> 3) & 7) = res; + zF = (zF & CF) | SZP[res]; + RET(8) + + OPED(0x70): // IN 0,(C) + res = IN(zBC); + zF = (zF & CF) | SZP[res]; + RET(8) + +/*----------------------------------------- + OUT +-----------------------------------------*/ + + OPED(0x51): // OUT (C),D + OPED(0x41): // OUT (C),B + OPED(0x49): // OUT (C),C + OPED(0x59): // OUT (C),E + OPED(0x61): // OUT (C),H + OPED(0x69): // OUT (C),L + OPED(0x79): // OUT (C),E + res = zR8((Opcode >> 3) & 7); + OUT(zBC, res); + RET(8) + + OPED(0x71): // OUT (C),0 + OUT(zBC, 0); + RET(8) + +/*----------------------------------------- + RETN +-----------------------------------------*/ + + OPED(0x45): // RETN; + OPED(0x55): // RETN; + OPED(0x65): // RETN; + OPED(0x75): // RETN; + POP_16(res); + SET_PC(res); + if (!zIFF1 && zIFF2) + { + zIFF1 = (1 << 2); + if (CPU->IRQState) + { + USE_CYCLES(10) + goto Cz80_Check_Interrupt; + } + } + else zIFF1 = zIFF2; + RET(10) + +/*----------------------------------------- + RETI +-----------------------------------------*/ + + OPED(0x4d): // RETI + OPED(0x5d): // RETI + OPED(0x6d): // RETI + OPED(0x7d): // RETI + POP_16(res); + SET_PC(res); + RET(10) + +/*----------------------------------------- + IM +-----------------------------------------*/ + + OPED(0x46): // IM 0 + OPED(0x4e): // IM 0 + OPED(0x66): // IM 0 + OPED(0x6e): // IM 0 + zIM = 0; + RET(4) + + OPED(0x56): // IM 1 + OPED(0x76): // IM 1 + zIM = 1; + RET(4) + + OPED(0x5e): // IM 2 + OPED(0x7e): // IM 2 + zIM = 2; + RET(4) + + { + UINT8 val; + UINT8 res; + UINT8 F; + +/*----------------------------------------- + LDI/LDD +-----------------------------------------*/ + + OPED(0xa0): // LDI + val = READ_MEM8(zHL++); + WRITE_MEM8(zDE++, val); + goto OP_LDX; + + OPED(0xa8): // LDD + val = READ_MEM8(zHL--); + WRITE_MEM8(zDE--, val); + +OP_LDX: + F = zF & (SF | ZF | CF); + if ((zA + val) & 0x02) F |= YF; + if ((zA + val) & 0x08) F |= XF; + if (--zBC) F |= VF; + zF = F; + RET(12) + +/*----------------------------------------- + LDIR/LDDR +-----------------------------------------*/ + + OPED(0xb0): // LDIR + do + { + val = READ_MEM8(zHL++); + WRITE_MEM8(zDE++, val); + zBC--; + USE_CYCLES(17) + } while (zBC && (CPU->ICount > 0)); + goto OP_LDXR; + + OPED(0xb8): // LDDR + do + { + val = READ_MEM8(zHL--); + WRITE_MEM8(zDE--, val); + zBC--; + USE_CYCLES(17) + } while (zBC && (CPU->ICount > 0)); + +OP_LDXR: + F = zF & (SF | ZF | CF); + if ((zA + val) & 0x02) F |= YF; + if ((zA + val) & 0x08) F |= XF; + if (zBC) + { + zF = F | VF; + PC -= 2; +#if CZ80_EMULATE_R_EXACTLY + zR--; +#endif + goto Cz80_Exec_End; + } + zF = F; + ADD_CYCLES(5) + goto Cz80_Exec; + +/*----------------------------------------- + CPI/CPD +-----------------------------------------*/ + + OPED(0xa1): // CPI + val = READ_MEM8(zHL++); + goto OP_CPX; + + OPED(0xa9): // CPD + val = READ_MEM8(zHL--); + +OP_CPX: + res = zA - val; + F = (zF & CF) | (SZ[res] & ~(YF | XF)) | ((zA ^ val ^ res) & HF) | NF; + if (F & HF) res--; + if (res & 0x02) F |= YF; + if (res & 0x08) F |= XF; + if (--zBC) F |= VF; + zF = F; + RET(12) + +/*----------------------------------------- + CPIR/CPDR +-----------------------------------------*/ + + OPED(0xb1): // CPIR + do + { + val = READ_MEM8(zHL++); + res = zA - val; + zBC--; + F = (zF & CF) | (SZ[res] & ~(YF | XF)) | ((zA ^ val ^ res) & HF) | NF; + if (F & HF) res--; + if (res & 0x02) F |= YF; + if (res & 0x08) F |= XF; + if (zBC) F |= VF; + zF = F; + USE_CYCLES(17) + } while (zBC && !(F & ZF) && (CPU->ICount > 0)); + goto OP_CPXR; + + OPED(0xb9): // CPDR + do + { + val = READ_MEM8(zHL--); + res = zA - val; + zBC--; + F = (zF & CF) | (SZ[res] & ~(YF | XF)) | ((zA ^ val ^ res) & HF) | NF; + if (F & HF) res--; + if (res & 0x02) F |= YF; + if (res & 0x08) F |= XF; + if (zBC) F |= VF; + zF = F; + USE_CYCLES(17) + } while (zBC && !(F & ZF) && (CPU->ICount > 0)); + +OP_CPXR: + if (zBC && !(F & ZF)) + { + PC -= 2; +#if CZ80_EMULATE_R_EXACTLY + zR--; +#endif + goto Cz80_Exec_End; + } + ADD_CYCLES(5) + goto Cz80_Exec; + +/*----------------------------------------- + INI/IND +-----------------------------------------*/ + + OPED(0xa2): // INI + val = IN(zBC); + zB--; + WRITE_MEM8(zHL++, val); + goto OP_INX; + + OPED(0xaa): // IND + val = IN(zBC); + zB--; + WRITE_MEM8(zHL--, val); + +OP_INX: + F = SZ[zB]; + res = ((UINT32)(zC - 1) & 0xff) + (UINT32)val; + if (val & SF) F |= NF; + if (res & 0x100) F |= HF | CF; + F |= SZP[(UINT8)(res & 0x07) ^ zB] & PF; + zF = F; + RET(12) + +/*----------------------------------------- + INIR/INDR +-----------------------------------------*/ + + OPED(0xb2): // INIR + do + { + val = IN(zBC); + zB--; + WRITE_MEM8(zHL++, val); + USE_CYCLES(17) + } while (zB && (CPU->ICount > 0)); + goto OP_INXR; + + OPED(0xba): // INDR + do + { + val = IN(zBC); + zB--; + WRITE_MEM8(zHL--, val); + USE_CYCLES(17) + } while (zB && (CPU->ICount > 0)); + +OP_INXR: + F = SZ[zB]; + res = ((UINT32)(zC - 1) & 0xff) + (UINT32)val; + if (val & SF) F |= NF; + if (res & 0x100) F |= HF | CF; + F |= SZP[(UINT8)(res & 0x07) ^ zB] & PF; + zF = F; + if (zB) + { + PC -= 2; +#if CZ80_EMULATE_R_EXACTLY + zR--; +#endif + goto Cz80_Exec_End; + } + ADD_CYCLES(5); + goto Cz80_Exec; + +/*----------------------------------------- + OUTI/OUTD +-----------------------------------------*/ + + OPED(0xa3): // OUTI + val = READ_MEM8(zHL++); + zB--; + OUT(zBC, val); + goto OP_OUTX; + + OPED(0xab): // OUTD + val = READ_MEM8(zHL--); + zB--; + OUT(zBC, val); + +OP_OUTX: + F = SZ[zB]; + res = (UINT32)zL + (UINT32)val; + if (val & SF) F |= NF; + if (res & 0x100) F |= HF | CF; + F |= SZP[(UINT8)(res & 0x07) - zB] & PF; + zF = F; + RET(12) + +/*----------------------------------------- + OTIR/OTDR +-----------------------------------------*/ + + OPED(0xb3): // OTIR + do + { + val = READ_MEM8(zHL++); + zB--; + OUT(zBC, val); + USE_CYCLES(17) + } while (zB && (CPU->ICount > 0)); + goto OP_OTXR; + + OPED(0xbb): // OTDR + do + { + val = READ_MEM8(zHL--); + zB--; + OUT(zBC, val); + USE_CYCLES(17) + } while (zB && (CPU->ICount > 0)); + +OP_OTXR: + F = SZ[zB]; + res = (UINT32)zL + (UINT32)val; + if (val & SF) F |= NF; + if (res & 0x100) F |= HF | CF; + F |= SZP[(UINT8)(res & 0x07) - zB] & PF; + zF = F; + if (zB) + { + PC -= 2; +#if CZ80_EMULATE_R_EXACTLY + zR--; +#endif + goto Cz80_Exec_End; + } + ADD_CYCLES(5) + goto Cz80_Exec; + } + +#if !CZ80_USE_JUMPTABLE +} +#endif diff --git a/cpu/cz80/cz80_opXY.c b/cpu/cz80/cz80_opXY.c new file mode 100644 index 0000000..b02e401 --- /dev/null +++ b/cpu/cz80/cz80_opXY.c @@ -0,0 +1,786 @@ +/****************************************************************************** + * + * CZ80 XY opcode include source file + * CZ80 emulator version 0.9 + * Copyright 2004-2005 Stéphane Dallongeville + * + * (Modified by NJ) + * + *****************************************************************************/ + +#if CZ80_USE_JUMPTABLE + goto *JumpTableXY[Opcode]; +#else +switch (Opcode) +{ +#endif + +/*----------------------------------------- + NOP +-----------------------------------------*/ + + OPXY(0x00): // NOP + +/*----------------------------------------- + LD r8 (same register) +-----------------------------------------*/ + + OPXY(0x40): // LD B,B + OPXY(0x49): // LD C,C + OPXY(0x52): // LD D,D + OPXY(0x5b): // LD E,E + OPXY(0x64): // LD H,H + OPXY(0x6d): // LD L,L + OPXY(0x7f): // LD A,A + RET(4) + +/*----------------------------------------- + LD r8 +-----------------------------------------*/ + + OPXY(0x41): // LD B,C + OPXY(0x42): // LD B,D + OPXY(0x43): // LD B,E + OPXY(0x47): // LD B,A + + OPXY(0x48): // LD C,B + OPXY(0x4a): // LD C,D + OPXY(0x4b): // LD C,E + OPXY(0x4f): // LD C,A + + OPXY(0x50): // LD D,B + OPXY(0x51): // LD D,C + OPXY(0x53): // LD D,E + OPXY(0x57): // LD D,A + + OPXY(0x58): // LD E,B + OPXY(0x59): // LD E,C + OPXY(0x5a): // LD E,D + OPXY(0x5f): // LD E,A + + OPXY(0x78): // LD A,B + OPXY(0x79): // LD A,C + OPXY(0x7a): // LD A,D + OPXY(0x7b): // LD A,E + goto OP_LD_R_R; + + OPXY(0x44): // LD B,HX + OPXY(0x4c): // LD C,HX + OPXY(0x54): // LD D,HX + OPXY(0x5c): // LD E,HX + OPXY(0x7c): // LD A,HX + zR8((Opcode >> 3) & 7) = data->B.H; + RET(5) + + OPXY(0x45): // LD B,LX + OPXY(0x4d): // LD C,LX + OPXY(0x55): // LD D,LX + OPXY(0x5d): // LD E,LX + OPXY(0x7d): // LD A,LX + zR8((Opcode >> 3) & 7) = data->B.L; + RET(5) + + OPXY(0x60): // LD HX,B + OPXY(0x61): // LD HX,C + OPXY(0x62): // LD HX,D + OPXY(0x63): // LD HX,E + OPXY(0x67): // LD HX,A + data->B.H = zR8(Opcode & 7); + RET(5) + + OPXY(0x68): // LD LX,B + OPXY(0x69): // LD LX,C + OPXY(0x6a): // LD LX,D + OPXY(0x6b): // LD LX,E + OPXY(0x6f): // LD LX,A + data->B.L = zR8(Opcode & 7); + RET(5) + + OPXY(0x65): // LD HX,LX + data->B.H = data->B.L; + RET(5) + + OPXY(0x6c): // LD LX,HX + data->B.L = data->B.H; + RET(5) + + OPXY(0x06): // LD B,#imm + OPXY(0x0e): // LD C,#imm + OPXY(0x16): // LD D,#imm + OPXY(0x1e): // LD E,#imm + OPXY(0x3e): // LD A,#imm + goto OP_LD_R_imm; + + OPXY(0x26): // LD HX,#imm + data->B.H = READ_ARG(); + RET(5) + + OPXY(0x2e): // LD LX,#imm + data->B.L = READ_ARG(); + RET(5) + + OPXY(0x0a): // LD A,(BC) + goto OP_LOAD_A_mBC; + + OPXY(0x1a): // LD A,(DE) + goto OP_LOAD_A_mDE; + + OPXY(0x3a): // LD A,(nn) + goto OP_LOAD_A_mNN; + + OPXY(0x02): // LD (BC),A + goto OP_LOAD_mBC_A; + + OPXY(0x12): // LD (DE),A + goto OP_LOAD_mDE_A; + + OPXY(0x32): // LD (nn),A + goto OP_LOAD_mNN_A; + + OPXY(0x46): // LD B,(IX+o) + OPXY(0x4e): // LD C,(IX+o) + OPXY(0x56): // LD D,(IX+o) + OPXY(0x5e): // LD E,(IX+o) + OPXY(0x66): // LD H,(IX+o) + OPXY(0x6e): // LD L,(IX+o) + OPXY(0x7e): // LD A,(IX+o) + adr = data->W + (INT8)READ_ARG(); + zR8((Opcode >> 3) & 7) = READ_MEM8(adr); + RET(15) + + OPXY(0x70): // LD (IX+o),B + OPXY(0x71): // LD (IX+o),C + OPXY(0x72): // LD (IX+o),D + OPXY(0x73): // LD (IX+o),E + OPXY(0x74): // LD (IX+o),H + OPXY(0x75): // LD (IX+o),L + OPXY(0x77): // LD (IX+o),A + adr = data->W + (INT8)READ_ARG(); + WRITE_MEM8(adr, zR8(Opcode & 7)); + RET(15) + + OPXY(0x36): // LD (IX+o),#imm + adr = data->W + (INT8)READ_ARG(); + WRITE_MEM8(adr, READ_ARG()); + RET(15) + +/*----------------------------------------- + LD r16 +-----------------------------------------*/ + + OPXY(0x01): // LD BC,nn + OPXY(0x11): // LD DE,nn + goto OP_LOAD_RR_imm16; + + OPXY(0x21): // LD IX,nn + data->W = READ_ARG16(); + RET(10) + + OPXY(0x31): // LD SP,nn + goto OP_LOAD_SP_imm16; + + OPXY(0x2a): // LD IX,(w) + goto OP_LD_xx_mNN; + + OPXY(0x22): // LD (w),IX + goto OP_LD_mNN_xx; + + OPXY(0xf9): // LD SP,IX + goto OP_LD_SP_xx; + +/*----------------------------------------- + POP +-----------------------------------------*/ + + OPXY(0xc1): // POP BC + OPXY(0xd1): // POP DE + OPXY(0xf1): // POP AF + goto OP_POP_RR; + + OPXY(0xe1): // POP IX + goto OP_POP; + +/*----------------------------------------- + PUSH +-----------------------------------------*/ + + OPXY(0xc5): // PUSH BC + OPXY(0xd5): // PUSH DE + OPXY(0xf5): // PUSH AF + goto OP_PUSH_RR; + + OPXY(0xe5): // PUSH IX + goto OP_PUSH; + +/*----------------------------------------- + EX +-----------------------------------------*/ + + OPXY(0x08): // EX AF,AF' + goto OP_EX_AF_AF2; + + OPXY(0xeb): // EX DE,HL + goto OP_EX_DE_HL; + + OPXY(0xd9): // EXX + goto OP_EXX; + + OPXY(0xe3): // EX (SP),IX + goto OP_EX_xx_mSP; + +/*----------------------------------------- + INC r8 +-----------------------------------------*/ + + OPXY(0x04): // INC B + OPXY(0x0c): // INC C + OPXY(0x14): // INC D + OPXY(0x1c): // INC E + OPXY(0x3c): // INC A + goto OP_INC_R; + + OPXY(0x24): // INC HX + data->B.H++; + zF = (zF & CF) | SZHV_inc[data->B.H]; + RET(5) + + OPXY(0x2c): // INC LX + data->B.L++; + zF = (zF & CF) | SZHV_inc[data->B.L]; + RET(5) + + OPXY(0x34): // INC (IX+o) + adr = data->W + (INT8)READ_ARG(); + USE_CYCLES(8) + goto OP_INC_m; + +/*----------------------------------------- + DEC r8 +-----------------------------------------*/ + + OPXY(0x05): // DEC B + OPXY(0x0d): // DEC C + OPXY(0x15): // DEC D + OPXY(0x1d): // DEC E + OPXY(0x3d): // DEC A + goto OP_DEC_R; + + OPXY(0x25): // DEC HX + data->B.H--; + zF = (zF & CF) | SZHV_dec[data->B.H]; + RET(5) + + OPXY(0x2d): // DEC LX + data->B.L--; + zF = (zF & CF) | SZHV_dec[data->B.L]; + RET(5) + + OPXY(0x35): // DEC (IX+o) + adr = data->W + (INT8)READ_ARG(); + USE_CYCLES(8) + goto OP_DEC_m; + +/*----------------------------------------- + ADD r8 +-----------------------------------------*/ + + OPXY(0x80): // ADD A,B + OPXY(0x81): // ADD A,C + OPXY(0x82): // ADD A,D + OPXY(0x83): // ADD A,E + OPXY(0x87): // ADD A,A + goto OP_ADD_R; + + OPXY(0xc6): // ADD A,n + goto OP_ADD_imm; + + OPXY(0x84): // ADD A,HX + val = data->B.H; + USE_CYCLES(1) + goto OP_ADD; + + OPXY(0x85): // ADD A,LX + val = data->B.L; + USE_CYCLES(1) + goto OP_ADD; + + OPXY(0x86): // ADD A,(IX+o) + adr = data->W + (INT8)READ_ARG(); + val = READ_MEM8(adr); + USE_CYCLES(11) + goto OP_ADD; + +/*----------------------------------------- + ADC r8 +-----------------------------------------*/ + + OPXY(0x88): // ADC A,B + OPXY(0x89): // ADC A,C + OPXY(0x8a): // ADC A,D + OPXY(0x8b): // ADC A,E + OPXY(0x8f): // ADC A,A + goto OP_ADC_R; + + OPXY(0xce): // ADC A,n + goto OP_ADC_imm; + + OPXY(0x8c): // ADC A,HX + val = data->B.H; + USE_CYCLES(1) + goto OP_ADC; + + OPXY(0x8d): // ADC A,LX + val = data->B.L; + USE_CYCLES(1) + goto OP_ADC; + + OPXY(0x8e): // ADC A,(IX+o) + adr = data->W + (INT8)READ_ARG(); + val = READ_MEM8(adr); + USE_CYCLES(11) + goto OP_ADC; + +/*----------------------------------------- + SUB r8 +-----------------------------------------*/ + + OPXY(0x90): // SUB B + OPXY(0x91): // SUB C + OPXY(0x92): // SUB D + OPXY(0x93): // SUB E + OPXY(0x97): // SUB A + goto OP_SUB_R; + + OPXY(0xd6): // SUB A,n + goto OP_SUB_imm; + + OPXY(0x94): // SUB HX + val = data->B.H; + USE_CYCLES(1) + goto OP_SUB; + + OPXY(0x95): // SUB LX + val = data->B.L; + USE_CYCLES(1) + goto OP_SUB; + + OPXY(0x96): // SUB (IX+o) + adr = data->W + (INT8)READ_ARG(); + val = READ_MEM8(adr); + USE_CYCLES(11) + goto OP_SUB; + +/*----------------------------------------- + SBC r8 +-----------------------------------------*/ + + OPXY(0x98): // SBC A,B + OPXY(0x99): // SBC A,C + OPXY(0x9a): // SBC A,D + OPXY(0x9b): // SBC A,E + OPXY(0x9f): // SBC A,A + goto OP_SBC_R; + + OPXY(0xde): // SBC A,n + goto OP_SBC_imm; + + OPXY(0x9c): // SBC A,HX + val = data->B.H; + USE_CYCLES(1) + goto OP_SBC; + + OPXY(0x9d): // SBC A,LX + val = data->B.L; + USE_CYCLES(1) + goto OP_SBC; + + OPXY(0x9e): // SBC A,(IX+o) + adr = data->W + (INT8)READ_ARG(); + val = READ_MEM8(adr); + USE_CYCLES(11) + goto OP_SBC; + +/*----------------------------------------- + CP r8 +-----------------------------------------*/ + + OPXY(0xb8): // CP B + OPXY(0xb9): // CP C + OPXY(0xba): // CP D + OPXY(0xbb): // CP E + OPXY(0xbf): // CP A + goto OP_CP_R; + + OPXY(0xfe): // CP n + goto OP_CP_imm; + + OPXY(0xbc): // CP HX + val = data->B.H; + USE_CYCLES(1) + goto OP_CP; + + OPXY(0xbd): // CP LX + val = data->B.L; + USE_CYCLES(1) + goto OP_CP; + + OPXY(0xbe): // CP (IX+o) + adr = data->W + (INT8)READ_ARG(); + val = READ_MEM8(adr); + USE_CYCLES(11) + goto OP_CP; + +/*----------------------------------------- + AND r8 +-----------------------------------------*/ + + OPXY(0xa0): // AND B + OPXY(0xa1): // AND C + OPXY(0xa2): // AND D + OPXY(0xa3): // AND E + OPXY(0xa7): // AND A + goto OP_AND_R; + + OPXY(0xe6): // AND A,n + goto OP_AND_imm; + + OPXY(0xa4): // AND HX + val = data->B.H; + USE_CYCLES(1) + goto OP_AND; + + OPXY(0xa5): // AND LX + val = data->B.L; + USE_CYCLES(1) + goto OP_AND; + + OPXY(0xa6): // AND (IX+o) + adr = data->W + (INT8)READ_ARG(); + val = READ_MEM8(adr); + USE_CYCLES(11) + goto OP_AND; + +/*----------------------------------------- + XOR r8 +-----------------------------------------*/ + + OPXY(0xa8): // XOR B + OPXY(0xa9): // XOR C + OPXY(0xaa): // XOR D + OPXY(0xab): // XOR E + OPXY(0xaf): // XOR A + goto OP_XOR_R; + + OPXY(0xee): // XOR A,n + goto OP_XOR_imm; + + OPXY(0xac): // XOR HX + val = data->B.H; + USE_CYCLES(1) + goto OP_XOR; + + OPXY(0xad): // XOR LX + val = data->B.L; + USE_CYCLES(1) + goto OP_XOR; + + OPXY(0xae): // XOR (IX+o) + adr = data->W + (INT8)READ_ARG(); + val = READ_MEM8(adr); + USE_CYCLES(11) + goto OP_XOR; + +/*----------------------------------------- + OR r8 +-----------------------------------------*/ + + OPXY(0xb0): // OR B + OPXY(0xb1): // OR C + OPXY(0xb2): // OR D + OPXY(0xb3): // OR E + OPXY(0xb7): // OR A + goto OP_OR_R; + + OPXY(0xf6): // OR A,n + goto OP_OR_imm; + + OPXY(0xb4): // OR HX + val = data->B.H; + USE_CYCLES(1) + goto OP_OR; + + OPXY(0xb5): // OR LX + val = data->B.L; + USE_CYCLES(1) + goto OP_OR; + + OPXY(0xb6): // OR (IX+o) + adr = data->W + (INT8)READ_ARG(); + val = READ_MEM8(adr); + USE_CYCLES(11) + goto OP_OR; + +/*----------------------------------------- + MISC ARITHMETIC & CPU CONTROL +-----------------------------------------*/ + + OPXY(0x27): // DAA + goto OP_DAA; + + OPXY(0x2f): // CPL + goto OP_CPL; + + OPXY(0x37): // SCF + goto OP_SCF; + + OPXY(0x3f): // CCF + goto OP_CCF; + + OPXY(0x76): // HALT + goto OP_HALT; + + OPXY(0xf3): // DI + goto OP_DI; + + OPXY(0xfb): // EI + goto OP_EI; + +/*----------------------------------------- + INC r16 +-----------------------------------------*/ + + OPXY(0x03): // INC BC + goto OP_INC_BC; + + OPXY(0x13): // INC DE + goto OP_INC_DE; + + OPXY(0x23): // INC IX + goto OP_INC_xx; + + OPXY(0x33): // INC SP + goto OP_INC_SP; + +/*----------------------------------------- + DEC r16 +-----------------------------------------*/ + + OPXY(0x0b): // DEC BC + goto OP_DEC_BC; + + OPXY(0x1b): // DEC DE + goto OP_DEC_DE; + + OPXY(0x2b): // DEC IX + goto OP_DEC_xx; + + OPXY(0x3b): // DEC SP + goto OP_DEC_SP; + +/*----------------------------------------- + ADD r16 +-----------------------------------------*/ + + OPXY(0x09): // ADD IX,BC + goto OP_ADD16_xx_BC; + + OPXY(0x19): // ADD IX,DE + goto OP_ADD16_xx_DE; + + OPXY(0x29): // ADD IX,IX + goto OP_ADD16_xx_xx; + + OPXY(0x39): // ADD IX,SP + goto OP_ADD16_xx_SP; + +/*----------------------------------------- + ROTATE +-----------------------------------------*/ + + OPXY(0x07): // RLCA + goto OP_RLCA; + + OPXY(0x0f): // RRCA + goto OP_RRCA; + + OPXY(0x17): // RLA + goto OP_RLA; + + OPXY(0x1f): // RRA + goto OP_RRA; + +/*----------------------------------------- + JP +-----------------------------------------*/ + + OPXY(0xc3): // JP nn + goto OP_JP; + + OPXY(0xe9): // JP (IX) + goto OP_JP_xx; + + OPXY(0xc2): // JP NZ,nn + goto OP_JP_NZ; + + OPXY(0xca): // JP Z,nn + goto OP_JP_Z; + + OPXY(0xd2): // JP NC,nn + goto OP_JP_NC; + + OPXY(0xda): // JP C,nn + goto OP_JP_C; + + OPXY(0xe2): // JP PO,nn + goto OP_JP_PO; + + OPXY(0xea): // JP PE,nn + goto OP_JP_PE; + + OPXY(0xf2): // JP P,nn + goto OP_JP_P; + + OPXY(0xfa): // JP M,nn + goto OP_JP_M; + +/*----------------------------------------- + JR +-----------------------------------------*/ + + OPXY(0x10): // DJNZ n + goto OP_DJNZ; + + OPXY(0x18): // JR n + goto OP_JR; + + OPXY(0x20): // JR NZ,n + goto OP_JR_NZ; + + OPXY(0x28): // JR Z,n + goto OP_JR_Z; + + OPXY(0x30): // JR NC,n + goto OP_JR_NC; + + OPXY(0x38): // JR C,n + goto OP_JR_C; + +/*----------------------------------------- + CALL +-----------------------------------------*/ + + OPXY(0xcd): // CALL nn + goto OP_CALL; + + OPXY(0xc4): // CALL NZ,nn + goto OP_CALL_NZ; + + OPXY(0xcc): // CALL Z,nn + goto OP_CALL_Z; + + OPXY(0xd4): // CALL NC,nn + goto OP_CALL_NC; + + OPXY(0xdc): // CALL C,nn + goto OP_CALL_C; + + OPXY(0xe4): // CALL PO,nn + goto OP_CALL_PO; + + OPXY(0xec): // CALL PE,nn + goto OP_CALL_PE; + + OPXY(0xf4): // CALL P,nn + goto OP_CALL_P; + + OPXY(0xfc): // CALL M,nn + goto OP_CALL_M; + +/*----------------------------------------- + RET +-----------------------------------------*/ + + OPXY(0xc9): // RET + goto OP_RET; + + OPXY(0xc0): // RET NZ + goto OP_RET_NZ; + + OPXY(0xc8): // RET Z + goto OP_RET_Z; + + OPXY(0xd0): // RET NC + goto OP_RET_NC; + + OPXY(0xd8): // RET C + goto OP_RET_C; + + OPXY(0xe0): // RET PO + goto OP_RET_PO; + + OPXY(0xe8): // RET PE + goto OP_RET_PE; + + OPXY(0xf0): // RET P + goto OP_RET_P; + + OPXY(0xf8): // RET M + goto OP_RET_M; + +/*----------------------------------------- + RST +-----------------------------------------*/ + + OPXY(0xc7): // RST 0 + OPXY(0xcf): // RST 1 + OPXY(0xd7): // RST 2 + OPXY(0xdf): // RST 3 + OPXY(0xe7): // RST 4 + OPXY(0xef): // RST 5 + OPXY(0xf7): // RST 6 + OPXY(0xff): // RST 7 + goto OP_RST; + +/*----------------------------------------- + OUT +-----------------------------------------*/ + + OPXY(0xd3): // OUT (n),A + goto OP_OUT_mN_A; + +/*----------------------------------------- + IN +-----------------------------------------*/ + + OPXY(0xdb): // IN A,(n) + goto OP_IN_A_mN; + +/*----------------------------------------- + PREFIX +-----------------------------------------*/ + + OPXY(0xcb): // XYCB prefix (BIT & SHIFT INSTRUCTIONS) + { + UINT8 src; + UINT8 res; + + adr = data->W + (INT8)READ_ARG(); + Opcode = READ_ARG(); +#if CZ80_EMULATE_R_EXACTLY + zR++; +#endif + #include "cz80_opXYCB.c" + } + + OPXY(0xed): // ED prefix + goto ED_PREFIX; + + OPXY(0xdd): // DD prefix (IX) + goto DD_PREFIX; + + OPXY(0xfd): // FD prefix (IY) + goto FD_PREFIX; + +#if !CZ80_USE_JUMPTABLE +} +#endif diff --git a/cpu/cz80/cz80_opXYCB.c b/cpu/cz80/cz80_opXYCB.c new file mode 100644 index 0000000..b706580 --- /dev/null +++ b/cpu/cz80/cz80_opXYCB.c @@ -0,0 +1,474 @@ +/****************************************************************************** + * + * CZ80 XYCB opcode include source file + * CZ80 emulator version 0.9 + * Copyright 2004-2005 Stéphane Dallongeville + * + * (Modified by NJ) + * + *****************************************************************************/ + +#if CZ80_USE_JUMPTABLE + goto *JumpTableXYCB[Opcode]; +#else +switch (Opcode) +{ +#endif + +/*----------------------------------------- + RLC +-----------------------------------------*/ + + OPXYCB(0x00): // RLC (Ix+d), B + OPXYCB(0x01): // RLC (Ix+d), C + OPXYCB(0x02): // RLC (Ix+d), D + OPXYCB(0x03): // RLC (Ix+d), E + OPXYCB(0x04): // RLC (Ix+d), H + OPXYCB(0x05): // RLC (Ix+d), L + OPXYCB(0x07): // RLC (Ix+d), A + src = READ_MEM8(adr); + res = ((src << 1) | (src >> 7)) & 0xff; + zF = SZP[res] | (src >> 7); + zR8(Opcode) = res; + WRITE_MEM8(adr, res); + RET(19) + + OPXYCB(0x06): // RLC (Ix+d) + src = READ_MEM8(adr); + res = ((src << 1) | (src >> 7)) & 0xff; + zF = SZP[res] | (src >> 7); + WRITE_MEM8(adr, res); + RET(19) + +/*----------------------------------------- + RRC +-----------------------------------------*/ + + OPXYCB(0x08): // RRC (Ix+d), B + OPXYCB(0x09): // RRC (Ix+d), C + OPXYCB(0x0a): // RRC (Ix+d), D + OPXYCB(0x0b): // RRC (Ix+d), E + OPXYCB(0x0c): // RRC (Ix+d), H + OPXYCB(0x0d): // RRC (Ix+d), L + OPXYCB(0x0f): // RRC (Ix+d), A + src = READ_MEM8(adr); + res = ((src >> 1) | (src << 7)) & 0xff; + zF = SZP[res] | (src & CF); + zR8(Opcode & 7) = res; + WRITE_MEM8(adr, res); + RET(19) + + OPXYCB(0x0e): // RRC (Ix+d) + src = READ_MEM8(adr); + res = ((src >> 1) | (src << 7)) & 0xff; + zF = SZP[res] | (src & CF); + WRITE_MEM8(adr, res); + RET(19) + +/*----------------------------------------- + RL +-----------------------------------------*/ + + OPXYCB(0x10): // RL (Ix+d), B + OPXYCB(0x11): // RL (Ix+d), C + OPXYCB(0x12): // RL (Ix+d), D + OPXYCB(0x13): // RL (Ix+d), E + OPXYCB(0x14): // RL (Ix+d), H + OPXYCB(0x15): // RL (Ix+d), L + OPXYCB(0x17): // RL (Ix+d), A + src = READ_MEM8(adr); + res = ((src << 1) | (zF & CF)) & 0xff; + zF = SZP[res] | (src >> 7); + zR8(Opcode & 7) = res; + WRITE_MEM8(adr, res); + RET(19) + + OPXYCB(0x16): // RL (Ix+d) + src = READ_MEM8(adr); + res = ((src << 1) | (zF & CF)) & 0xff; + zF = SZP[res] | (src >> 7); + WRITE_MEM8(adr, res); + RET(19) + +/*----------------------------------------- + RR +-----------------------------------------*/ + + OPXYCB(0x18): // RR (Ix+d), B + OPXYCB(0x19): // RR (Ix+d), C + OPXYCB(0x1a): // RR (Ix+d), D + OPXYCB(0x1b): // RR (Ix+d), E + OPXYCB(0x1c): // RR (Ix+d), H + OPXYCB(0x1d): // RR (Ix+d), L + OPXYCB(0x1f): // RR (Ix+d), A + src = READ_MEM8(adr); + res = ((src >> 1) | (zF << 7)) & 0xff; + zF = SZP[res] | (src & CF); + zR8(Opcode & 7) = res; + WRITE_MEM8(adr, res); + RET(19) + + OPXYCB(0x1e): // RR (Ix+d) + src = READ_MEM8(adr); + res = ((src >> 1) | (zF << 7)) & 0xff; + zF = SZP[res] | (src & CF); + WRITE_MEM8(adr, res); + RET(19) + +/*----------------------------------------- + SLA +-----------------------------------------*/ + + OPXYCB(0x20): // SLA (Ix+d), B + OPXYCB(0x21): // SLA (Ix+d), C + OPXYCB(0x22): // SLA (Ix+d), D + OPXYCB(0x23): // SLA (Ix+d), E + OPXYCB(0x24): // SLA (Ix+d), H + OPXYCB(0x25): // SLA (Ix+d), L + OPXYCB(0x27): // SLA (Ix+d), A + src = READ_MEM8(adr); + res = (src << 1) & 0xff; + zF = SZP[res] | (src >> 7); + zR8(Opcode & 7) = res; + WRITE_MEM8(adr, res); + RET(19) + + OPXYCB(0x26): // SLA (Ix+d) + src = READ_MEM8(adr); + res = (src << 1) & 0xff; + zF = SZP[res] | (src >> 7); + WRITE_MEM8(adr, res); + RET(19) + +/*----------------------------------------- + SRA +-----------------------------------------*/ + + OPXYCB(0x28): // SRA (Ix+d), B + OPXYCB(0x29): // SRA (Ix+d), C + OPXYCB(0x2a): // SRA (Ix+d), D + OPXYCB(0x2b): // SRA (Ix+d), E + OPXYCB(0x2c): // SRA (Ix+d), H + OPXYCB(0x2d): // SRA (Ix+d), L + OPXYCB(0x2f): // SRA (Ix+d), A + src = READ_MEM8(adr); + res = ((src >> 1) | (src & 0x80)) & 0xff; + zF = SZP[res] | (src & CF); + zR8(Opcode & 7) = res; + WRITE_MEM8(adr, res); + RET(19) + + OPXYCB(0x2e): // SRA (Ix+d) + src = READ_MEM8(adr); + res = ((src >> 1) | (src & 0x80)) & 0xff; + zF = SZP[res] | (src & CF); + WRITE_MEM8(adr, res); + RET(19) + +/*----------------------------------------- + SLL +-----------------------------------------*/ + + OPXYCB(0x30): // SLL (Ix+d), B + OPXYCB(0x31): // SLL (Ix+d), C + OPXYCB(0x32): // SLL (Ix+d), D + OPXYCB(0x33): // SLL (Ix+d), E + OPXYCB(0x34): // SLL (Ix+d), H + OPXYCB(0x35): // SLL (Ix+d), L + OPXYCB(0x37): // SLL (Ix+d), A + src = READ_MEM8(adr); + res = ((src << 1) | 0x01) & 0xff; + zF = SZP[res] | (src >> 7); + zR8(Opcode & 7) = res; + WRITE_MEM8(adr, res); + RET(19) + + OPXYCB(0x36): // SLL (Ix+d) + src = READ_MEM8(adr); + res = ((src << 1) | 0x01) & 0xff; + zF = SZP[res] | (src >> 7); + WRITE_MEM8(adr, res); + RET(19) + +/*----------------------------------------- + SRL +-----------------------------------------*/ + + OPXYCB(0x38): // SRL (Ix+d), B + OPXYCB(0x39): // SRL (Ix+d), C + OPXYCB(0x3a): // SRL (Ix+d), D + OPXYCB(0x3b): // SRL (Ix+d), E + OPXYCB(0x3c): // SRL (Ix+d), H + OPXYCB(0x3d): // SRL (Ix+d), L + OPXYCB(0x3f): // SRL (Ix+d), A + src = READ_MEM8(adr); + res = (src >> 1) & 0xff; + zF = SZP[res] | (src & CF); + zR8(Opcode & 7) = res; + WRITE_MEM8(adr, res); + RET(19) + + OPXYCB(0x3e): // SRL (Ix+d) + src = READ_MEM8(adr); + res = (src >> 1) & 0xff; + zF = SZP[res] | (src & CF); + WRITE_MEM8(adr, res); + RET(19) + +/*----------------------------------------- + BIT +-----------------------------------------*/ + + OPXYCB(0x40): // BIT 0,(Ix+d) + OPXYCB(0x41): // BIT 0,(Ix+d) + OPXYCB(0x42): // BIT 0,(Ix+d) + OPXYCB(0x43): // BIT 0,(Ix+d) + OPXYCB(0x44): // BIT 0,(Ix+d) + OPXYCB(0x45): // BIT 0,(Ix+d) + OPXYCB(0x47): // BIT 0,(Ix+d) + + OPXYCB(0x48): // BIT 1,(Ix+d) + OPXYCB(0x49): // BIT 1,(Ix+d) + OPXYCB(0x4a): // BIT 1,(Ix+d) + OPXYCB(0x4b): // BIT 1,(Ix+d) + OPXYCB(0x4c): // BIT 1,(Ix+d) + OPXYCB(0x4d): // BIT 1,(Ix+d) + OPXYCB(0x4f): // BIT 1,(Ix+d) + + OPXYCB(0x50): // BIT 2,(Ix+d) + OPXYCB(0x51): // BIT 2,(Ix+d) + OPXYCB(0x52): // BIT 2,(Ix+d) + OPXYCB(0x53): // BIT 2,(Ix+d) + OPXYCB(0x54): // BIT 2,(Ix+d) + OPXYCB(0x55): // BIT 2,(Ix+d) + OPXYCB(0x57): // BIT 2,(Ix+d) + + OPXYCB(0x58): // BIT 3,(Ix+d) + OPXYCB(0x59): // BIT 3,(Ix+d) + OPXYCB(0x5a): // BIT 3,(Ix+d) + OPXYCB(0x5b): // BIT 3,(Ix+d) + OPXYCB(0x5c): // BIT 3,(Ix+d) + OPXYCB(0x5d): // BIT 3,(Ix+d) + OPXYCB(0x5f): // BIT 3,(Ix+d) + + OPXYCB(0x60): // BIT 4,(Ix+d) + OPXYCB(0x61): // BIT 4,(Ix+d) + OPXYCB(0x62): // BIT 4,(Ix+d) + OPXYCB(0x63): // BIT 4,(Ix+d) + OPXYCB(0x64): // BIT 4,(Ix+d) + OPXYCB(0x65): // BIT 4,(Ix+d) + OPXYCB(0x67): // BIT 4,(Ix+d) + + OPXYCB(0x68): // BIT 5,(Ix+d) + OPXYCB(0x69): // BIT 5,(Ix+d) + OPXYCB(0x6a): // BIT 5,(Ix+d) + OPXYCB(0x6b): // BIT 5,(Ix+d) + OPXYCB(0x6c): // BIT 5,(Ix+d) + OPXYCB(0x6d): // BIT 5,(Ix+d) + OPXYCB(0x6f): // BIT 5,(Ix+d) + + OPXYCB(0x70): // BIT 6,(Ix+d) + OPXYCB(0x71): // BIT 6,(Ix+d) + OPXYCB(0x72): // BIT 6,(Ix+d) + OPXYCB(0x73): // BIT 6,(Ix+d) + OPXYCB(0x74): // BIT 6,(Ix+d) + OPXYCB(0x75): // BIT 6,(Ix+d) + OPXYCB(0x77): // BIT 6,(Ix+d) + + OPXYCB(0x78): // BIT 7,(Ix+d) + OPXYCB(0x79): // BIT 7,(Ix+d) + OPXYCB(0x7a): // BIT 7,(Ix+d) + OPXYCB(0x7b): // BIT 7,(Ix+d) + OPXYCB(0x7c): // BIT 7,(Ix+d) + OPXYCB(0x7d): // BIT 7,(Ix+d) + OPXYCB(0x7f): // BIT 7,(Ix+d) + + OPXYCB(0x46): // BIT 0,(Ix+d) + OPXYCB(0x4e): // BIT 1,(Ix+d) + OPXYCB(0x56): // BIT 2,(Ix+d) + OPXYCB(0x5e): // BIT 3,(Ix+d) + OPXYCB(0x66): // BIT 4,(Ix+d) + OPXYCB(0x6e): // BIT 5,(Ix+d) + OPXYCB(0x76): // BIT 6,(Ix+d) + OPXYCB(0x7e): // BIT 7,(Ix+d) + src = READ_MEM8(adr); + zF = (zF & CF) | HF | + (SZ_BIT[src & (1 << ((Opcode >> 3) & 7))] & ~(YF | XF)) | + ((adr >> 8) & (YF | XF)); + RET(16) + +/*----------------------------------------- + RES +-----------------------------------------*/ + + OPXYCB(0x80): // RES 0,(Ix+d),B + OPXYCB(0x81): // RES 0,(Ix+d),C + OPXYCB(0x82): // RES 0,(Ix+d),D + OPXYCB(0x83): // RES 0,(Ix+d),E + OPXYCB(0x84): // RES 0,(Ix+d),H + OPXYCB(0x85): // RES 0,(Ix+d),L + OPXYCB(0x87): // RES 0,(Ix+d),A + + OPXYCB(0x88): // RES 1,(Ix+d),B + OPXYCB(0x89): // RES 1,(Ix+d),C + OPXYCB(0x8a): // RES 1,(Ix+d),D + OPXYCB(0x8b): // RES 1,(Ix+d),E + OPXYCB(0x8c): // RES 1,(Ix+d),H + OPXYCB(0x8d): // RES 1,(Ix+d),L + OPXYCB(0x8f): // RES 1,(Ix+d),A + + OPXYCB(0x90): // RES 2,(Ix+d),B + OPXYCB(0x91): // RES 2,(Ix+d),C + OPXYCB(0x92): // RES 2,(Ix+d),D + OPXYCB(0x93): // RES 2,(Ix+d),E + OPXYCB(0x94): // RES 2,(Ix+d),H + OPXYCB(0x95): // RES 2,(Ix+d),L + OPXYCB(0x97): // RES 2,(Ix+d),A + + OPXYCB(0x98): // RES 3,(Ix+d),B + OPXYCB(0x99): // RES 3,(Ix+d),C + OPXYCB(0x9a): // RES 3,(Ix+d),D + OPXYCB(0x9b): // RES 3,(Ix+d),E + OPXYCB(0x9c): // RES 3,(Ix+d),H + OPXYCB(0x9d): // RES 3,(Ix+d),L + OPXYCB(0x9f): // RES 3,(Ix+d),A + + OPXYCB(0xa0): // RES 4,(Ix+d),B + OPXYCB(0xa1): // RES 4,(Ix+d),C + OPXYCB(0xa2): // RES 4,(Ix+d),D + OPXYCB(0xa3): // RES 4,(Ix+d),E + OPXYCB(0xa4): // RES 4,(Ix+d),H + OPXYCB(0xa5): // RES 4,(Ix+d),L + OPXYCB(0xa7): // RES 4,(Ix+d),A + + OPXYCB(0xa8): // RES 5,(Ix+d),B + OPXYCB(0xa9): // RES 5,(Ix+d),C + OPXYCB(0xaa): // RES 5,(Ix+d),D + OPXYCB(0xab): // RES 5,(Ix+d),E + OPXYCB(0xac): // RES 5,(Ix+d),H + OPXYCB(0xad): // RES 5,(Ix+d),L + OPXYCB(0xaf): // RES 5,(Ix+d),A + + OPXYCB(0xb0): // RES 6,(Ix+d),B + OPXYCB(0xb1): // RES 6,(Ix+d),C + OPXYCB(0xb2): // RES 6,(Ix+d),D + OPXYCB(0xb3): // RES 6,(Ix+d),E + OPXYCB(0xb4): // RES 6,(Ix+d),H + OPXYCB(0xb5): // RES 6,(Ix+d),L + OPXYCB(0xb7): // RES 6,(Ix+d),A + + OPXYCB(0xb8): // RES 7,(Ix+d),B + OPXYCB(0xb9): // RES 7,(Ix+d),C + OPXYCB(0xba): // RES 7,(Ix+d),D + OPXYCB(0xbb): // RES 7,(Ix+d),E + OPXYCB(0xbc): // RES 7,(Ix+d),H + OPXYCB(0xbd): // RES 7,(Ix+d),L + OPXYCB(0xbf): // RES 7,(Ix+d),A + res = READ_MEM8(adr); + res &= ~(1 << ((Opcode >> 3) & 7)); + zR8(Opcode & 7) = res; + WRITE_MEM8(adr, res); + RET(19) + + OPXYCB(0x86): // RES 0,(Ix+d) + OPXYCB(0x8e): // RES 1,(Ix+d) + OPXYCB(0x96): // RES 2,(Ix+d) + OPXYCB(0x9e): // RES 3,(Ix+d) + OPXYCB(0xa6): // RES 4,(Ix+d) + OPXYCB(0xae): // RES 5,(Ix+d) + OPXYCB(0xb6): // RES 6,(Ix+d) + OPXYCB(0xbe): // RES 7,(Ix+d) + res = READ_MEM8(adr); + res &= ~(1 << ((Opcode >> 3) & 7)); + WRITE_MEM8(adr, res); + RET(19) + +/*----------------------------------------- + SET +-----------------------------------------*/ + + OPXYCB(0xc0): // SET 0,(Ix+d),B + OPXYCB(0xc1): // SET 0,(Ix+d),C + OPXYCB(0xc2): // SET 0,(Ix+d),D + OPXYCB(0xc3): // SET 0,(Ix+d),E + OPXYCB(0xc4): // SET 0,(Ix+d),H + OPXYCB(0xc5): // SET 0,(Ix+d),L + OPXYCB(0xc7): // SET 0,(Ix+d),A + + OPXYCB(0xc8): // SET 1,(Ix+d),B + OPXYCB(0xc9): // SET 1,(Ix+d),C + OPXYCB(0xca): // SET 1,(Ix+d),D + OPXYCB(0xcb): // SET 1,(Ix+d),E + OPXYCB(0xcc): // SET 1,(Ix+d),H + OPXYCB(0xcd): // SET 1,(Ix+d),L + OPXYCB(0xcf): // SET 1,(Ix+d),A + + OPXYCB(0xd0): // SET 2,(Ix+d),B + OPXYCB(0xd1): // SET 2,(Ix+d),C + OPXYCB(0xd2): // SET 2,(Ix+d),D + OPXYCB(0xd3): // SET 2,(Ix+d),E + OPXYCB(0xd4): // SET 2,(Ix+d),H + OPXYCB(0xd5): // SET 2,(Ix+d),L + OPXYCB(0xd7): // SET 2,(Ix+d),A + + OPXYCB(0xd8): // SET 3,(Ix+d),B + OPXYCB(0xd9): // SET 3,(Ix+d),C + OPXYCB(0xda): // SET 3,(Ix+d),D + OPXYCB(0xdb): // SET 3,(Ix+d),E + OPXYCB(0xdc): // SET 3,(Ix+d),H + OPXYCB(0xdd): // SET 3,(Ix+d),L + OPXYCB(0xdf): // SET 3,(Ix+d),A + + OPXYCB(0xe0): // SET 4,(Ix+d),B + OPXYCB(0xe1): // SET 4,(Ix+d),C + OPXYCB(0xe2): // SET 4,(Ix+d),D + OPXYCB(0xe3): // SET 4,(Ix+d),E + OPXYCB(0xe4): // SET 4,(Ix+d),H + OPXYCB(0xe5): // SET 4,(Ix+d),L + OPXYCB(0xe7): // SET 4,(Ix+d),A + + OPXYCB(0xe8): // SET 5,(Ix+d),B + OPXYCB(0xe9): // SET 5,(Ix+d),C + OPXYCB(0xea): // SET 5,(Ix+d),D + OPXYCB(0xeb): // SET 5,(Ix+d),E + OPXYCB(0xec): // SET 5,(Ix+d),H + OPXYCB(0xed): // SET 5,(Ix+d),L + OPXYCB(0xef): // SET 5,(Ix+d),A + + OPXYCB(0xf0): // SET 6,(Ix+d),B + OPXYCB(0xf1): // SET 6,(Ix+d),C + OPXYCB(0xf2): // SET 6,(Ix+d),D + OPXYCB(0xf3): // SET 6,(Ix+d),E + OPXYCB(0xf4): // SET 6,(Ix+d),H + OPXYCB(0xf5): // SET 6,(Ix+d),L + OPXYCB(0xf7): // SET 6,(Ix+d),A + + OPXYCB(0xf8): // SET 7,(Ix+d),B + OPXYCB(0xf9): // SET 7,(Ix+d),C + OPXYCB(0xfa): // SET 7,(Ix+d),D + OPXYCB(0xfb): // SET 7,(Ix+d),E + OPXYCB(0xfc): // SET 7,(Ix+d),H + OPXYCB(0xfd): // SET 7,(Ix+d),L + OPXYCB(0xff): // SET 7,(Ix+d),A + res = READ_MEM8(adr); + res |= 1 << ((Opcode >> 3) & 7); + zR8(Opcode & 7) = res; + WRITE_MEM8(adr, res); + RET(19) + + OPXYCB(0xc6): // SET 0,(Ix+d) + OPXYCB(0xce): // SET 1,(Ix+d) + OPXYCB(0xd6): // SET 2,(Ix+d) + OPXYCB(0xde): // SET 3,(Ix+d) + OPXYCB(0xe6): // SET 4,(Ix+d) + OPXYCB(0xee): // SET 5,(Ix+d) + OPXYCB(0xf6): // SET 6,(Ix+d) + OPXYCB(0xfe): // SET 7,(Ix+d) + res = READ_MEM8(adr); + res |= 1 << ((Opcode >> 3) & 7); + WRITE_MEM8(adr, res); + RET(19) + +#if !CZ80_USE_JUMPTABLE +} +#endif diff --git a/cpu/cz80/cz80jmp.c b/cpu/cz80/cz80jmp.c new file mode 100644 index 0000000..0100772 --- /dev/null +++ b/cpu/cz80/cz80jmp.c @@ -0,0 +1,422 @@ +/****************************************************************************** + + cz80jmp.c + + CZ80 opcodeƒWƒƒƒ“ƒvƒe[ƒuƒ‹ + +******************************************************************************/ + +static const void ALIGN_DATA *JumpTable[0x100] = +{ + &&OP0x00, &&OP0x01, &&OP0x02, &&OP0x03, + &&OP0x04, &&OP0x05, &&OP0x06, &&OP0x07, + &&OP0x08, &&OP0x09, &&OP0x0a, &&OP0x0b, + &&OP0x0c, &&OP0x0d, &&OP0x0e, &&OP0x0f, + + &&OP0x10, &&OP0x11, &&OP0x12, &&OP0x13, + &&OP0x14, &&OP0x15, &&OP0x16, &&OP0x17, + &&OP0x18, &&OP0x19, &&OP0x1a, &&OP0x1b, + &&OP0x1c, &&OP0x1d, &&OP0x1e, &&OP0x1f, + + &&OP0x20, &&OP0x21, &&OP0x22, &&OP0x23, + &&OP0x24, &&OP0x25, &&OP0x26, &&OP0x27, + &&OP0x28, &&OP0x29, &&OP0x2a, &&OP0x2b, + &&OP0x2c, &&OP0x2d, &&OP0x2e, &&OP0x2f, + + &&OP0x30, &&OP0x31, &&OP0x32, &&OP0x33, + &&OP0x34, &&OP0x35, &&OP0x36, &&OP0x37, + &&OP0x38, &&OP0x39, &&OP0x3a, &&OP0x3b, + &&OP0x3c, &&OP0x3d, &&OP0x3e, &&OP0x3f, + + &&OP0x40, &&OP0x41, &&OP0x42, &&OP0x43, + &&OP0x44, &&OP0x45, &&OP0x46, &&OP0x47, + &&OP0x48, &&OP0x49, &&OP0x4a, &&OP0x4b, + &&OP0x4c, &&OP0x4d, &&OP0x4e, &&OP0x4f, + + &&OP0x50, &&OP0x51, &&OP0x52, &&OP0x53, + &&OP0x54, &&OP0x55, &&OP0x56, &&OP0x57, + &&OP0x58, &&OP0x59, &&OP0x5a, &&OP0x5b, + &&OP0x5c, &&OP0x5d, &&OP0x5e, &&OP0x5f, + + &&OP0x60, &&OP0x61, &&OP0x62, &&OP0x63, + &&OP0x64, &&OP0x65, &&OP0x66, &&OP0x67, + &&OP0x68, &&OP0x69, &&OP0x6a, &&OP0x6b, + &&OP0x6c, &&OP0x6d, &&OP0x6e, &&OP0x6f, + + &&OP0x70, &&OP0x71, &&OP0x72, &&OP0x73, + &&OP0x74, &&OP0x75, &&OP0x76, &&OP0x77, + &&OP0x78, &&OP0x79, &&OP0x7a, &&OP0x7b, + &&OP0x7c, &&OP0x7d, &&OP0x7e, &&OP0x7f, + + &&OP0x80, &&OP0x81, &&OP0x82, &&OP0x83, + &&OP0x84, &&OP0x85, &&OP0x86, &&OP0x87, + &&OP0x88, &&OP0x89, &&OP0x8a, &&OP0x8b, + &&OP0x8c, &&OP0x8d, &&OP0x8e, &&OP0x8f, + + &&OP0x90, &&OP0x91, &&OP0x92, &&OP0x93, + &&OP0x94, &&OP0x95, &&OP0x96, &&OP0x97, + &&OP0x98, &&OP0x99, &&OP0x9a, &&OP0x9b, + &&OP0x9c, &&OP0x9d, &&OP0x9e, &&OP0x9f, + + &&OP0xa0, &&OP0xa1, &&OP0xa2, &&OP0xa3, + &&OP0xa4, &&OP0xa5, &&OP0xa6, &&OP0xa7, + &&OP0xa8, &&OP0xa9, &&OP0xaa, &&OP0xab, + &&OP0xac, &&OP0xad, &&OP0xae, &&OP0xaf, + + &&OP0xb0, &&OP0xb1, &&OP0xb2, &&OP0xb3, + &&OP0xb4, &&OP0xb5, &&OP0xb6, &&OP0xb7, + &&OP0xb8, &&OP0xb9, &&OP0xba, &&OP0xbb, + &&OP0xbc, &&OP0xbd, &&OP0xbe, &&OP0xbf, + + &&OP0xc0, &&OP0xc1, &&OP0xc2, &&OP0xc3, + &&OP0xc4, &&OP0xc5, &&OP0xc6, &&OP0xc7, + &&OP0xc8, &&OP0xc9, &&OP0xca, &&OP0xcb, + &&OP0xcc, &&OP0xcd, &&OP0xce, &&OP0xcf, + + &&OP0xd0, &&OP0xd1, &&OP0xd2, &&OP0xd3, + &&OP0xd4, &&OP0xd5, &&OP0xd6, &&OP0xd7, + &&OP0xd8, &&OP0xd9, &&OP0xda, &&OP0xdb, + &&OP0xdc, &&OP0xdd, &&OP0xde, &&OP0xdf, + + &&OP0xe0, &&OP0xe1, &&OP0xe2, &&OP0xe3, + &&OP0xe4, &&OP0xe5, &&OP0xe6, &&OP0xe7, + &&OP0xe8, &&OP0xe9, &&OP0xea, &&OP0xeb, + &&OP0xec, &&OP0xed, &&OP0xee, &&OP0xef, + + &&OP0xf0, &&OP0xf1, &&OP0xf2, &&OP0xf3, + &&OP0xf4, &&OP0xf5, &&OP0xf6, &&OP0xf7, + &&OP0xf8, &&OP0xf9, &&OP0xfa, &&OP0xfb, + &&OP0xfc, &&OP0xfd, &&OP0xfe, &&OP0xff +}; + +static const void ALIGN_DATA *JumpTableCB[0x100] = +{ + &&OPCB0x00, &&OPCB0x01, &&OPCB0x02, &&OPCB0x03, + &&OPCB0x04, &&OPCB0x05, &&OPCB0x06, &&OPCB0x07, + &&OPCB0x08, &&OPCB0x09, &&OPCB0x0a, &&OPCB0x0b, + &&OPCB0x0c, &&OPCB0x0d, &&OPCB0x0e, &&OPCB0x0f, + + &&OPCB0x10, &&OPCB0x11, &&OPCB0x12, &&OPCB0x13, + &&OPCB0x14, &&OPCB0x15, &&OPCB0x16, &&OPCB0x17, + &&OPCB0x18, &&OPCB0x19, &&OPCB0x1a, &&OPCB0x1b, + &&OPCB0x1c, &&OPCB0x1d, &&OPCB0x1e, &&OPCB0x1f, + + &&OPCB0x20, &&OPCB0x21, &&OPCB0x22, &&OPCB0x23, + &&OPCB0x24, &&OPCB0x25, &&OPCB0x26, &&OPCB0x27, + &&OPCB0x28, &&OPCB0x29, &&OPCB0x2a, &&OPCB0x2b, + &&OPCB0x2c, &&OPCB0x2d, &&OPCB0x2e, &&OPCB0x2f, + + &&OPCB0x30, &&OPCB0x31, &&OPCB0x32, &&OPCB0x33, + &&OPCB0x34, &&OPCB0x35, &&OPCB0x36, &&OPCB0x37, + &&OPCB0x38, &&OPCB0x39, &&OPCB0x3a, &&OPCB0x3b, + &&OPCB0x3c, &&OPCB0x3d, &&OPCB0x3e, &&OPCB0x3f, + + &&OPCB0x40, &&OPCB0x41, &&OPCB0x42, &&OPCB0x43, + &&OPCB0x44, &&OPCB0x45, &&OPCB0x46, &&OPCB0x47, + &&OPCB0x48, &&OPCB0x49, &&OPCB0x4a, &&OPCB0x4b, + &&OPCB0x4c, &&OPCB0x4d, &&OPCB0x4e, &&OPCB0x4f, + + &&OPCB0x50, &&OPCB0x51, &&OPCB0x52, &&OPCB0x53, + &&OPCB0x54, &&OPCB0x55, &&OPCB0x56, &&OPCB0x57, + &&OPCB0x58, &&OPCB0x59, &&OPCB0x5a, &&OPCB0x5b, + &&OPCB0x5c, &&OPCB0x5d, &&OPCB0x5e, &&OPCB0x5f, + + &&OPCB0x60, &&OPCB0x61, &&OPCB0x62, &&OPCB0x63, + &&OPCB0x64, &&OPCB0x65, &&OPCB0x66, &&OPCB0x67, + &&OPCB0x68, &&OPCB0x69, &&OPCB0x6a, &&OPCB0x6b, + &&OPCB0x6c, &&OPCB0x6d, &&OPCB0x6e, &&OPCB0x6f, + + &&OPCB0x70, &&OPCB0x71, &&OPCB0x72, &&OPCB0x73, + &&OPCB0x74, &&OPCB0x75, &&OPCB0x76, &&OPCB0x77, + &&OPCB0x78, &&OPCB0x79, &&OPCB0x7a, &&OPCB0x7b, + &&OPCB0x7c, &&OPCB0x7d, &&OPCB0x7e, &&OPCB0x7f, + + &&OPCB0x80, &&OPCB0x81, &&OPCB0x82, &&OPCB0x83, + &&OPCB0x84, &&OPCB0x85, &&OPCB0x86, &&OPCB0x87, + &&OPCB0x88, &&OPCB0x89, &&OPCB0x8a, &&OPCB0x8b, + &&OPCB0x8c, &&OPCB0x8d, &&OPCB0x8e, &&OPCB0x8f, + + &&OPCB0x90, &&OPCB0x91, &&OPCB0x92, &&OPCB0x93, + &&OPCB0x94, &&OPCB0x95, &&OPCB0x96, &&OPCB0x97, + &&OPCB0x98, &&OPCB0x99, &&OPCB0x9a, &&OPCB0x9b, + &&OPCB0x9c, &&OPCB0x9d, &&OPCB0x9e, &&OPCB0x9f, + + &&OPCB0xa0, &&OPCB0xa1, &&OPCB0xa2, &&OPCB0xa3, + &&OPCB0xa4, &&OPCB0xa5, &&OPCB0xa6, &&OPCB0xa7, + &&OPCB0xa8, &&OPCB0xa9, &&OPCB0xaa, &&OPCB0xab, + &&OPCB0xac, &&OPCB0xad, &&OPCB0xae, &&OPCB0xaf, + + &&OPCB0xb0, &&OPCB0xb1, &&OPCB0xb2, &&OPCB0xb3, + &&OPCB0xb4, &&OPCB0xb5, &&OPCB0xb6, &&OPCB0xb7, + &&OPCB0xb8, &&OPCB0xb9, &&OPCB0xba, &&OPCB0xbb, + &&OPCB0xbc, &&OPCB0xbd, &&OPCB0xbe, &&OPCB0xbf, + + &&OPCB0xc0, &&OPCB0xc1, &&OPCB0xc2, &&OPCB0xc3, + &&OPCB0xc4, &&OPCB0xc5, &&OPCB0xc6, &&OPCB0xc7, + &&OPCB0xc8, &&OPCB0xc9, &&OPCB0xca, &&OPCB0xcb, + &&OPCB0xcc, &&OPCB0xcd, &&OPCB0xce, &&OPCB0xcf, + + &&OPCB0xd0, &&OPCB0xd1, &&OPCB0xd2, &&OPCB0xd3, + &&OPCB0xd4, &&OPCB0xd5, &&OPCB0xd6, &&OPCB0xd7, + &&OPCB0xd8, &&OPCB0xd9, &&OPCB0xda, &&OPCB0xdb, + &&OPCB0xdc, &&OPCB0xdd, &&OPCB0xde, &&OPCB0xdf, + + &&OPCB0xe0, &&OPCB0xe1, &&OPCB0xe2, &&OPCB0xe3, + &&OPCB0xe4, &&OPCB0xe5, &&OPCB0xe6, &&OPCB0xe7, + &&OPCB0xe8, &&OPCB0xe9, &&OPCB0xea, &&OPCB0xeb, + &&OPCB0xec, &&OPCB0xed, &&OPCB0xee, &&OPCB0xef, + + &&OPCB0xf0, &&OPCB0xf1, &&OPCB0xf2, &&OPCB0xf3, + &&OPCB0xf4, &&OPCB0xf5, &&OPCB0xf6, &&OPCB0xf7, + &&OPCB0xf8, &&OPCB0xf9, &&OPCB0xfa, &&OPCB0xfb, + &&OPCB0xfc, &&OPCB0xfd, &&OPCB0xfe, &&OPCB0xff +}; + +static const void ALIGN_DATA *JumpTableED[0x100] = +{ + &&OPED0x00, &&OPED0x01, &&OPED0x02, &&OPED0x03, + &&OPED0x04, &&OPED0x05, &&OPED0x06, &&OPED0x07, + &&OPED0x08, &&OPED0x09, &&OPED0x0a, &&OPED0x0b, + &&OPED0x0c, &&OPED0x0d, &&OPED0x0e, &&OPED0x0f, + + &&OPED0x10, &&OPED0x11, &&OPED0x12, &&OPED0x13, + &&OPED0x14, &&OPED0x15, &&OPED0x16, &&OPED0x17, + &&OPED0x18, &&OPED0x19, &&OPED0x1a, &&OPED0x1b, + &&OPED0x1c, &&OPED0x1d, &&OPED0x1e, &&OPED0x1f, + + &&OPED0x20, &&OPED0x21, &&OPED0x22, &&OPED0x23, + &&OPED0x24, &&OPED0x25, &&OPED0x26, &&OPED0x27, + &&OPED0x28, &&OPED0x29, &&OPED0x2a, &&OPED0x2b, + &&OPED0x2c, &&OPED0x2d, &&OPED0x2e, &&OPED0x2f, + + &&OPED0x30, &&OPED0x31, &&OPED0x32, &&OPED0x33, + &&OPED0x34, &&OPED0x35, &&OPED0x36, &&OPED0x37, + &&OPED0x38, &&OPED0x39, &&OPED0x3a, &&OPED0x3b, + &&OPED0x3c, &&OPED0x3d, &&OPED0x3e, &&OPED0x3f, + + &&OPED0x40, &&OPED0x41, &&OPED0x42, &&OPED0x43, + &&OPED0x44, &&OPED0x45, &&OPED0x46, &&OPED0x47, + &&OPED0x48, &&OPED0x49, &&OPED0x4a, &&OPED0x4b, + &&OPED0x4c, &&OPED0x4d, &&OPED0x4e, &&OPED0x4f, + + &&OPED0x50, &&OPED0x51, &&OPED0x52, &&OPED0x53, + &&OPED0x54, &&OPED0x55, &&OPED0x56, &&OPED0x57, + &&OPED0x58, &&OPED0x59, &&OPED0x5a, &&OPED0x5b, + &&OPED0x5c, &&OPED0x5d, &&OPED0x5e, &&OPED0x5f, + + &&OPED0x60, &&OPED0x61, &&OPED0x62, &&OPED0x63, + &&OPED0x64, &&OPED0x65, &&OPED0x66, &&OPED0x67, + &&OPED0x68, &&OPED0x69, &&OPED0x6a, &&OPED0x6b, + &&OPED0x6c, &&OPED0x6d, &&OPED0x6e, &&OPED0x6f, + + &&OPED0x70, &&OPED0x71, &&OPED0x72, &&OPED0x73, + &&OPED0x74, &&OPED0x75, &&OPED0x76, &&OPED0x77, + &&OPED0x78, &&OPED0x79, &&OPED0x7a, &&OPED0x7b, + &&OPED0x7c, &&OPED0x7d, &&OPED0x7e, &&OPED0x7f, + + &&OPED0x80, &&OPED0x81, &&OPED0x82, &&OPED0x83, + &&OPED0x84, &&OPED0x85, &&OPED0x86, &&OPED0x87, + &&OPED0x88, &&OPED0x89, &&OPED0x8a, &&OPED0x8b, + &&OPED0x8c, &&OPED0x8d, &&OPED0x8e, &&OPED0x8f, + + &&OPED0x90, &&OPED0x91, &&OPED0x92, &&OPED0x93, + &&OPED0x94, &&OPED0x95, &&OPED0x96, &&OPED0x97, + &&OPED0x98, &&OPED0x99, &&OPED0x9a, &&OPED0x9b, + &&OPED0x9c, &&OPED0x9d, &&OPED0x9e, &&OPED0x9f, + + &&OPED0xa0, &&OPED0xa1, &&OPED0xa2, &&OPED0xa3, + &&OPED0xa4, &&OPED0xa5, &&OPED0xa6, &&OPED0xa7, + &&OPED0xa8, &&OPED0xa9, &&OPED0xaa, &&OPED0xab, + &&OPED0xac, &&OPED0xad, &&OPED0xae, &&OPED0xaf, + + &&OPED0xb0, &&OPED0xb1, &&OPED0xb2, &&OPED0xb3, + &&OPED0xb4, &&OPED0xb5, &&OPED0xb6, &&OPED0xb7, + &&OPED0xb8, &&OPED0xb9, &&OPED0xba, &&OPED0xbb, + &&OPED0xbc, &&OPED0xbd, &&OPED0xbe, &&OPED0xbf, + + &&OPED0xc0, &&OPED0xc1, &&OPED0xc2, &&OPED0xc3, + &&OPED0xc4, &&OPED0xc5, &&OPED0xc6, &&OPED0xc7, + &&OPED0xc8, &&OPED0xc9, &&OPED0xca, &&OPED0xcb, + &&OPED0xcc, &&OPED0xcd, &&OPED0xce, &&OPED0xcf, + + &&OPED0xd0, &&OPED0xd1, &&OPED0xd2, &&OPED0xd3, + &&OPED0xd4, &&OPED0xd5, &&OPED0xd6, &&OPED0xd7, + &&OPED0xd8, &&OPED0xd9, &&OPED0xda, &&OPED0xdb, + &&OPED0xdc, &&OPED0xdd, &&OPED0xde, &&OPED0xdf, + + &&OPED0xe0, &&OPED0xe1, &&OPED0xe2, &&OPED0xe3, + &&OPED0xe4, &&OPED0xe5, &&OPED0xe6, &&OPED0xe7, + &&OPED0xe8, &&OPED0xe9, &&OPED0xea, &&OPED0xeb, + &&OPED0xec, &&OPED0xed, &&OPED0xee, &&OPED0xef, + + &&OPED0xf0, &&OPED0xf1, &&OPED0xf2, &&OPED0xf3, + &&OPED0xf4, &&OPED0xf5, &&OPED0xf6, &&OPED0xf7, + &&OPED0xf8, &&OPED0xf9, &&OPED0xfa, &&OPED0xfb, + &&OPED0xfc, &&OPED0xfd, &&OPED0xfe, &&OPED0xff +}; + +static const void ALIGN_DATA *JumpTableXY[0x100] = +{ + &&OPXY0x00, &&OPXY0x01, &&OPXY0x02, &&OPXY0x03, + &&OPXY0x04, &&OPXY0x05, &&OPXY0x06, &&OPXY0x07, + &&OPXY0x08, &&OPXY0x09, &&OPXY0x0a, &&OPXY0x0b, + &&OPXY0x0c, &&OPXY0x0d, &&OPXY0x0e, &&OPXY0x0f, + + &&OPXY0x10, &&OPXY0x11, &&OPXY0x12, &&OPXY0x13, + &&OPXY0x14, &&OPXY0x15, &&OPXY0x16, &&OPXY0x17, + &&OPXY0x18, &&OPXY0x19, &&OPXY0x1a, &&OPXY0x1b, + &&OPXY0x1c, &&OPXY0x1d, &&OPXY0x1e, &&OPXY0x1f, + + &&OPXY0x20, &&OPXY0x21, &&OPXY0x22, &&OPXY0x23, + &&OPXY0x24, &&OPXY0x25, &&OPXY0x26, &&OPXY0x27, + &&OPXY0x28, &&OPXY0x29, &&OPXY0x2a, &&OPXY0x2b, + &&OPXY0x2c, &&OPXY0x2d, &&OPXY0x2e, &&OPXY0x2f, + + &&OPXY0x30, &&OPXY0x31, &&OPXY0x32, &&OPXY0x33, + &&OPXY0x34, &&OPXY0x35, &&OPXY0x36, &&OPXY0x37, + &&OPXY0x38, &&OPXY0x39, &&OPXY0x3a, &&OPXY0x3b, + &&OPXY0x3c, &&OPXY0x3d, &&OPXY0x3e, &&OPXY0x3f, + + &&OPXY0x40, &&OPXY0x41, &&OPXY0x42, &&OPXY0x43, + &&OPXY0x44, &&OPXY0x45, &&OPXY0x46, &&OPXY0x47, + &&OPXY0x48, &&OPXY0x49, &&OPXY0x4a, &&OPXY0x4b, + &&OPXY0x4c, &&OPXY0x4d, &&OPXY0x4e, &&OPXY0x4f, + + &&OPXY0x50, &&OPXY0x51, &&OPXY0x52, &&OPXY0x53, + &&OPXY0x54, &&OPXY0x55, &&OPXY0x56, &&OPXY0x57, + &&OPXY0x58, &&OPXY0x59, &&OPXY0x5a, &&OPXY0x5b, + &&OPXY0x5c, &&OPXY0x5d, &&OPXY0x5e, &&OPXY0x5f, + + &&OPXY0x60, &&OPXY0x61, &&OPXY0x62, &&OPXY0x63, + &&OPXY0x64, &&OPXY0x65, &&OPXY0x66, &&OPXY0x67, + &&OPXY0x68, &&OPXY0x69, &&OPXY0x6a, &&OPXY0x6b, + &&OPXY0x6c, &&OPXY0x6d, &&OPXY0x6e, &&OPXY0x6f, + + &&OPXY0x70, &&OPXY0x71, &&OPXY0x72, &&OPXY0x73, + &&OPXY0x74, &&OPXY0x75, &&OPXY0x76, &&OPXY0x77, + &&OPXY0x78, &&OPXY0x79, &&OPXY0x7a, &&OPXY0x7b, + &&OPXY0x7c, &&OPXY0x7d, &&OPXY0x7e, &&OPXY0x7f, + + &&OPXY0x80, &&OPXY0x81, &&OPXY0x82, &&OPXY0x83, + &&OPXY0x84, &&OPXY0x85, &&OPXY0x86, &&OPXY0x87, + &&OPXY0x88, &&OPXY0x89, &&OPXY0x8a, &&OPXY0x8b, + &&OPXY0x8c, &&OPXY0x8d, &&OPXY0x8e, &&OPXY0x8f, + + &&OPXY0x90, &&OPXY0x91, &&OPXY0x92, &&OPXY0x93, + &&OPXY0x94, &&OPXY0x95, &&OPXY0x96, &&OPXY0x97, + &&OPXY0x98, &&OPXY0x99, &&OPXY0x9a, &&OPXY0x9b, + &&OPXY0x9c, &&OPXY0x9d, &&OPXY0x9e, &&OPXY0x9f, + + &&OPXY0xa0, &&OPXY0xa1, &&OPXY0xa2, &&OPXY0xa3, + &&OPXY0xa4, &&OPXY0xa5, &&OPXY0xa6, &&OPXY0xa7, + &&OPXY0xa8, &&OPXY0xa9, &&OPXY0xaa, &&OPXY0xab, + &&OPXY0xac, &&OPXY0xad, &&OPXY0xae, &&OPXY0xaf, + + &&OPXY0xb0, &&OPXY0xb1, &&OPXY0xb2, &&OPXY0xb3, + &&OPXY0xb4, &&OPXY0xb5, &&OPXY0xb6, &&OPXY0xb7, + &&OPXY0xb8, &&OPXY0xb9, &&OPXY0xba, &&OPXY0xbb, + &&OPXY0xbc, &&OPXY0xbd, &&OPXY0xbe, &&OPXY0xbf, + + &&OPXY0xc0, &&OPXY0xc1, &&OPXY0xc2, &&OPXY0xc3, + &&OPXY0xc4, &&OPXY0xc5, &&OPXY0xc6, &&OPXY0xc7, + &&OPXY0xc8, &&OPXY0xc9, &&OPXY0xca, &&OPXY0xcb, + &&OPXY0xcc, &&OPXY0xcd, &&OPXY0xce, &&OPXY0xcf, + + &&OPXY0xd0, &&OPXY0xd1, &&OPXY0xd2, &&OPXY0xd3, + &&OPXY0xd4, &&OPXY0xd5, &&OPXY0xd6, &&OPXY0xd7, + &&OPXY0xd8, &&OPXY0xd9, &&OPXY0xda, &&OPXY0xdb, + &&OPXY0xdc, &&OPXY0xdd, &&OPXY0xde, &&OPXY0xdf, + + &&OPXY0xe0, &&OPXY0xe1, &&OPXY0xe2, &&OPXY0xe3, + &&OPXY0xe4, &&OPXY0xe5, &&OPXY0xe6, &&OPXY0xe7, + &&OPXY0xe8, &&OPXY0xe9, &&OPXY0xea, &&OPXY0xeb, + &&OPXY0xec, &&OPXY0xed, &&OPXY0xee, &&OPXY0xef, + + &&OPXY0xf0, &&OPXY0xf1, &&OPXY0xf2, &&OPXY0xf3, + &&OPXY0xf4, &&OPXY0xf5, &&OPXY0xf6, &&OPXY0xf7, + &&OPXY0xf8, &&OPXY0xf9, &&OPXY0xfa, &&OPXY0xfb, + &&OPXY0xfc, &&OPXY0xfd, &&OPXY0xfe, &&OPXY0xff +}; + +static const void ALIGN_DATA *JumpTableXYCB[0x100] = +{ + &&OPXYCB0x00, &&OPXYCB0x01, &&OPXYCB0x02, &&OPXYCB0x03, + &&OPXYCB0x04, &&OPXYCB0x05, &&OPXYCB0x06, &&OPXYCB0x07, + &&OPXYCB0x08, &&OPXYCB0x09, &&OPXYCB0x0a, &&OPXYCB0x0b, + &&OPXYCB0x0c, &&OPXYCB0x0d, &&OPXYCB0x0e, &&OPXYCB0x0f, + + &&OPXYCB0x10, &&OPXYCB0x11, &&OPXYCB0x12, &&OPXYCB0x13, + &&OPXYCB0x14, &&OPXYCB0x15, &&OPXYCB0x16, &&OPXYCB0x17, + &&OPXYCB0x18, &&OPXYCB0x19, &&OPXYCB0x1a, &&OPXYCB0x1b, + &&OPXYCB0x1c, &&OPXYCB0x1d, &&OPXYCB0x1e, &&OPXYCB0x1f, + + &&OPXYCB0x20, &&OPXYCB0x21, &&OPXYCB0x22, &&OPXYCB0x23, + &&OPXYCB0x24, &&OPXYCB0x25, &&OPXYCB0x26, &&OPXYCB0x27, + &&OPXYCB0x28, &&OPXYCB0x29, &&OPXYCB0x2a, &&OPXYCB0x2b, + &&OPXYCB0x2c, &&OPXYCB0x2d, &&OPXYCB0x2e, &&OPXYCB0x2f, + + &&OPXYCB0x30, &&OPXYCB0x31, &&OPXYCB0x32, &&OPXYCB0x33, + &&OPXYCB0x34, &&OPXYCB0x35, &&OPXYCB0x36, &&OPXYCB0x37, + &&OPXYCB0x38, &&OPXYCB0x39, &&OPXYCB0x3a, &&OPXYCB0x3b, + &&OPXYCB0x3c, &&OPXYCB0x3d, &&OPXYCB0x3e, &&OPXYCB0x3f, + + &&OPXYCB0x40, &&OPXYCB0x41, &&OPXYCB0x42, &&OPXYCB0x43, + &&OPXYCB0x44, &&OPXYCB0x45, &&OPXYCB0x46, &&OPXYCB0x47, + &&OPXYCB0x48, &&OPXYCB0x49, &&OPXYCB0x4a, &&OPXYCB0x4b, + &&OPXYCB0x4c, &&OPXYCB0x4d, &&OPXYCB0x4e, &&OPXYCB0x4f, + + &&OPXYCB0x50, &&OPXYCB0x51, &&OPXYCB0x52, &&OPXYCB0x53, + &&OPXYCB0x54, &&OPXYCB0x55, &&OPXYCB0x56, &&OPXYCB0x57, + &&OPXYCB0x58, &&OPXYCB0x59, &&OPXYCB0x5a, &&OPXYCB0x5b, + &&OPXYCB0x5c, &&OPXYCB0x5d, &&OPXYCB0x5e, &&OPXYCB0x5f, + + &&OPXYCB0x60, &&OPXYCB0x61, &&OPXYCB0x62, &&OPXYCB0x63, + &&OPXYCB0x64, &&OPXYCB0x65, &&OPXYCB0x66, &&OPXYCB0x67, + &&OPXYCB0x68, &&OPXYCB0x69, &&OPXYCB0x6a, &&OPXYCB0x6b, + &&OPXYCB0x6c, &&OPXYCB0x6d, &&OPXYCB0x6e, &&OPXYCB0x6f, + + &&OPXYCB0x70, &&OPXYCB0x71, &&OPXYCB0x72, &&OPXYCB0x73, + &&OPXYCB0x74, &&OPXYCB0x75, &&OPXYCB0x76, &&OPXYCB0x77, + &&OPXYCB0x78, &&OPXYCB0x79, &&OPXYCB0x7a, &&OPXYCB0x7b, + &&OPXYCB0x7c, &&OPXYCB0x7d, &&OPXYCB0x7e, &&OPXYCB0x7f, + + &&OPXYCB0x80, &&OPXYCB0x81, &&OPXYCB0x82, &&OPXYCB0x83, + &&OPXYCB0x84, &&OPXYCB0x85, &&OPXYCB0x86, &&OPXYCB0x87, + &&OPXYCB0x88, &&OPXYCB0x89, &&OPXYCB0x8a, &&OPXYCB0x8b, + &&OPXYCB0x8c, &&OPXYCB0x8d, &&OPXYCB0x8e, &&OPXYCB0x8f, + + &&OPXYCB0x90, &&OPXYCB0x91, &&OPXYCB0x92, &&OPXYCB0x93, + &&OPXYCB0x94, &&OPXYCB0x95, &&OPXYCB0x96, &&OPXYCB0x97, + &&OPXYCB0x98, &&OPXYCB0x99, &&OPXYCB0x9a, &&OPXYCB0x9b, + &&OPXYCB0x9c, &&OPXYCB0x9d, &&OPXYCB0x9e, &&OPXYCB0x9f, + + &&OPXYCB0xa0, &&OPXYCB0xa1, &&OPXYCB0xa2, &&OPXYCB0xa3, + &&OPXYCB0xa4, &&OPXYCB0xa5, &&OPXYCB0xa6, &&OPXYCB0xa7, + &&OPXYCB0xa8, &&OPXYCB0xa9, &&OPXYCB0xaa, &&OPXYCB0xab, + &&OPXYCB0xac, &&OPXYCB0xad, &&OPXYCB0xae, &&OPXYCB0xaf, + + &&OPXYCB0xb0, &&OPXYCB0xb1, &&OPXYCB0xb2, &&OPXYCB0xb3, + &&OPXYCB0xb4, &&OPXYCB0xb5, &&OPXYCB0xb6, &&OPXYCB0xb7, + &&OPXYCB0xb8, &&OPXYCB0xb9, &&OPXYCB0xba, &&OPXYCB0xbb, + &&OPXYCB0xbc, &&OPXYCB0xbd, &&OPXYCB0xbe, &&OPXYCB0xbf, + + &&OPXYCB0xc0, &&OPXYCB0xc1, &&OPXYCB0xc2, &&OPXYCB0xc3, + &&OPXYCB0xc4, &&OPXYCB0xc5, &&OPXYCB0xc6, &&OPXYCB0xc7, + &&OPXYCB0xc8, &&OPXYCB0xc9, &&OPXYCB0xca, &&OPXYCB0xcb, + &&OPXYCB0xcc, &&OPXYCB0xcd, &&OPXYCB0xce, &&OPXYCB0xcf, + + &&OPXYCB0xd0, &&OPXYCB0xd1, &&OPXYCB0xd2, &&OPXYCB0xd3, + &&OPXYCB0xd4, &&OPXYCB0xd5, &&OPXYCB0xd6, &&OPXYCB0xd7, + &&OPXYCB0xd8, &&OPXYCB0xd9, &&OPXYCB0xda, &&OPXYCB0xdb, + &&OPXYCB0xdc, &&OPXYCB0xdd, &&OPXYCB0xde, &&OPXYCB0xdf, + + &&OPXYCB0xe0, &&OPXYCB0xe1, &&OPXYCB0xe2, &&OPXYCB0xe3, + &&OPXYCB0xe4, &&OPXYCB0xe5, &&OPXYCB0xe6, &&OPXYCB0xe7, + &&OPXYCB0xe8, &&OPXYCB0xe9, &&OPXYCB0xea, &&OPXYCB0xeb, + &&OPXYCB0xec, &&OPXYCB0xed, &&OPXYCB0xee, &&OPXYCB0xef, + + &&OPXYCB0xf0, &&OPXYCB0xf1, &&OPXYCB0xf2, &&OPXYCB0xf3, + &&OPXYCB0xf4, &&OPXYCB0xf5, &&OPXYCB0xf6, &&OPXYCB0xf7, + &&OPXYCB0xf8, &&OPXYCB0xf9, &&OPXYCB0xfa, &&OPXYCB0xfb, + &&OPXYCB0xfc, &&OPXYCB0xfd, &&OPXYCB0xfe, &&OPXYCB0xff +}; diff --git a/cpu/cz80/cz80macro.h b/cpu/cz80/cz80macro.h new file mode 100644 index 0000000..91b49ef --- /dev/null +++ b/cpu/cz80/cz80macro.h @@ -0,0 +1,113 @@ +/****************************************************************************** + + cz80macro.h + + CZ80 ŠeŽíƒ}ƒNƒ + +******************************************************************************/ + +#if CZ80_USE_JUMPTABLE +#define _SSOP(A,B) A##B +#define OP(A) _SSOP(OP,A) +#define OPCB(A) _SSOP(OPCB,A) +#define OPED(A) _SSOP(OPED,A) +#define OPXY(A) _SSOP(OPXY,A) +#define OPXYCB(A) _SSOP(OPXYCB,A) +#else +#define OP(A) case A +#define OPCB(A) case A +#define OPED(A) case A +#define OPXY(A) case A +#define OPXYCB(A) case A +#endif + +#define USE_CYCLES(A) CPU->ICount -= (A); +#define ADD_CYCLES(A) CPU->ICount += (A); + +#define RET(A) { USE_CYCLES(A) goto Cz80_Exec; } + +#if CZ80_ENCRYPTED_ROM + +#define SET_PC(A) \ + CPU->BasePC = CPU->Fetch[(A) >> CZ80_FETCH_SFT]; \ + OPBase = CPU->OPFetch[(A) >> CZ80_FETCH_SFT]; \ + PC = (A) + CPU->BasePC; + +#define GET_OP() (*(UINT8 *)(OPBase + PC)) + +#else + +#define SET_PC(A) \ + CPU->BasePC = CPU->Fetch[(A) >> CZ80_FETCH_SFT]; \ + PC = (A) + CPU->BasePC; + +#define GET_OP() (*(UINT8 *)PC) + +#endif + +#define READ_OP() GET_OP(); PC++ + +#define READ_ARG() (*(UINT8 *)PC++) +#if CZ80_LITTLE_ENDIAN +#define READ_ARG16() (*(UINT8 *)PC | (*(UINT8 *)(PC + 1) << 8)); PC += 2 +#else +#define READ_ARG16() (*(UINT8 *)(PC + 1) | (*(UINT8 *)PC << 8)); PC += 2 +#endif + +//#ifndef BUILD_CPS1PSP +//#define READ_MEM8(A) memory_region_cpu2[(A)] +//#else +#define READ_MEM8(A) CPU->Read_Byte(A) +//#endif +#if CZ80_LITTLE_ENDIAN +#define READ_MEM16(A) (READ_MEM8(A) | (READ_MEM8((A) + 1) << 8)) +#else +#define READ_MEM16(A) ((READ_MEM8(A) << 8) | READ_MEM8((A) + 1)) +#endif + +#define WRITE_MEM8(A, D) CPU->Write_Byte(A, D); +#if CZ80_LITTLE_ENDIAN +#define WRITE_MEM16(A, D) { WRITE_MEM8(A, D); WRITE_MEM8((A) + 1, (D) >> 8); } +#else +#define WRITE_MEM16(A, D) { WRITE_MEM8((A) + 1, D); WRITE_MEM8(A, (D) >> 8); } +#endif + +#define PUSH_16(A) { UINT32 sp; zSP -= 2; sp = zSP; WRITE_MEM16(sp, A); } +#define POP_16(A) { UINT32 sp; sp = zSP; A = READ_MEM16(sp); zSP = sp + 2; } + +#define IN(A) CPU->IN_Port(A) +#define OUT(A, D) CPU->OUT_Port(A, D) + +#define CHECK_INT \ + if (zIFF1) \ + { \ + UINT32 IntVect; \ + \ + if (CPU->IRQState == HOLD_LINE) \ + CPU->IRQState = CLEAR_LINE; \ + \ + CPU->HaltState = 0; \ + zIFF1 = zIFF2 = 0; \ + IntVect = CPU->Interrupt_Callback(CPU->IRQLine); \ + \ + PUSH_16(zRealPC) \ + \ + if (zIM == 2) \ + { \ + IntVect = (IntVect & 0xff) | (zI << 8); \ + PC = READ_MEM16(IntVect); \ + CPU->ExtraCycles += 17; \ + } \ + else if (zIM == 1) \ + { \ + PC = 0x38; \ + CPU->ExtraCycles += 13; \ + } \ + else \ + { \ + PC = IntVect & 0x38; \ + CPU->ExtraCycles += 13; \ + } \ + \ + SET_PC(PC) \ + } diff --git a/platform/psp/Makefile b/platform/psp/Makefile index db032d8..6aaf51b 100644 --- a/platform/psp/Makefile +++ b/platform/psp/Makefile @@ -4,7 +4,7 @@ PSPSDK = $(shell psp-config --pspsdk-path) # settings #use_musashi = 1 -use_mz80 = 1 +#use_mz80 = 1 amalgamate = 0 #profile = 1 #up = 1 @@ -69,13 +69,14 @@ ifeq "$(use_mz80)" "1" CFLAGS += -D_USE_MZ80 OBJS += ../../cpu/mz80/mz80.o else -$(error nothing here!) +CFLAGS += -D_USE_CZ80 +OBJS += ../../cpu/cz80/cz80.o endif # bg images OBJS += data/bg32.o data/bg40.o -LIBS += -lpng -lm -lpspgu -lpsppower -Wl,-Map=PicoDrive.map # -lpspaudio -lpsphprm +LIBS += -lpng -lm -lpspgu -lpsppower -Wl,-Map=PicoDrive.map -lpspaudio # target TARGET = PicoDrive diff --git a/platform/psp/emu.c b/platform/psp/emu.c index 8542a8f..df4a08e 100644 --- a/platform/psp/emu.c +++ b/platform/psp/emu.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "psp.h" #include "menu.h" @@ -20,6 +21,13 @@ #define OSD_FPS_X 420 #endif +// additional pspaudio imports, credits to crazyc +int sceAudio_38553111(unsigned short samples, unsigned short freq, char unknown); // play with conversion? +int sceAudio_5C37C0AE(void); // end play? +int sceAudio_E0727056(int volume, void *buffer); // blocking output +int sceAudioOutput2GetRestSample(); + + char romFileName[PATH_MAX]; unsigned char *PicoDraw2FB = (unsigned char *)VRAM_CACHED_STUFF + 8; // +8 to be able to skip border with 1 quadword.. int engineState; @@ -29,6 +37,8 @@ static unsigned int noticeMsgTime = 0; int reset_timing = 0; // do we need this? +static void sound_init(void); +static void sound_deinit(void); static void blit2(const char *fps, const char *notice); static void clearArea(int full); @@ -82,6 +92,8 @@ void emu_Init(void) mkdir("brm", 0777); mkdir("cfg", 0777); + sound_init(); + PicoInit(); PicoMessage = emu_msg_cb; PicoMCDopenTray = emu_msg_tray_open; @@ -111,6 +123,7 @@ void emu_Deinit(void) } PicoExit(); + sound_deinit(); } void emu_setDefaultConfig(void) @@ -462,14 +475,147 @@ static void vidResetMode(void) sceGuSync(0,0); } -/* -static void updateSound(int len) + +/* sound stuff */ +#define SOUND_DEF_BLOCK_SIZE 1024 // 1152 // 1024 +#define SOUND_BLOCK_COUNT 4 + +static short __attribute__((aligned(4))) sndBuffer[SOUND_DEF_BLOCK_SIZE*SOUND_BLOCK_COUNT*2 + 44100/50*2]; +static short *snd_playptr = NULL; +static int samples_made = 0, samples_done = 0, samples_block = SOUND_DEF_BLOCK_SIZE; +static int sound_thread_exit = 0; +static SceUID sound_sem = -1; + +static void writeSound(int len); + +static int sound_thread(SceSize args, void *argp) { + short *endptr = &sndBuffer[SOUND_DEF_BLOCK_SIZE*SOUND_BLOCK_COUNT*2]; + int ret; + + lprintf("sound_thread: started, priority %i\n", sceKernelGetThreadCurrentPriority()); + + while (!sound_thread_exit) + { + if (samples_made - samples_done < samples_block) { + // wait for data... + //lprintf("sthr: wait... (%i/%i)\n", samples_done, samples_made); + ret = sceKernelWaitSema(sound_sem, 1, 0); + //lprintf("sthr: sceKernelWaitSema: %i\n", ret); + continue; + } + + //lprintf("sthr: got data: %i\n", samples_made - samples_done); + + ret = sceAudio_E0727056(PSP_AUDIO_VOLUME_MAX, snd_playptr); + + samples_done += samples_block; + snd_playptr += samples_block; + if (snd_playptr >= endptr) + snd_playptr = sndBuffer; + if (ret) + lprintf("sthr: outf: %i; pos %i/%i\n", ret, samples_done, samples_made); + } + + lprintf("sthr: exit\n"); + sceKernelExitDeleteThread(0); + return 0; +} + +static void sound_init(void) +{ + SceUID thid; + + sound_sem = sceKernelCreateSema("sndsem", 0, 0, 1, NULL); + if (sound_sem < 0) lprintf("sceKernelCreateSema() failed: %i\n", sound_sem); + + sound_thread_exit = 0; + thid = sceKernelCreateThread("sndthread", sound_thread, 0x12, 0x10000, 0, NULL); + if (thid >= 0) + { + sceKernelStartThread(thid, 0, 0); + } + else + lprintf("sceKernelCreateThread failed: %i\n", thid); +} + +static void sound_prepare(void) +{ + static int PsndRate_old = 0, PicoOpt_old = 0, pal_old = 0; + int ret, stereo; + + samples_made = samples_done = 0; + + if (PsndRate != PsndRate_old || (PicoOpt&0x0b) != (PicoOpt_old&0x0b) || Pico.m.pal != pal_old) { + sound_rerate(Pico.m.frame_count ? 1 : 0); + } + stereo=(PicoOpt&8)>>3; + samples_block = SOUND_DEF_BLOCK_SIZE; + if (PsndRate < 44100) samples_block = SOUND_DEF_BLOCK_SIZE / 2; + if (PsndRate < 22050) samples_block = SOUND_DEF_BLOCK_SIZE / 4; + + lprintf("starting audio: %i, len: %i, stereo: %i, pal: %i, block samples: %i\n", + PsndRate, PsndLen, stereo, Pico.m.pal, samples_block); + + while (sceAudioOutput2GetRestSample() > 0) psp_msleep(100); + sceAudio_5C37C0AE(); + ret = sceAudio_38553111(samples_block/2, PsndRate, 2/*stereo ? 2 : 1*/); + lprintf("sceAudio_38553111() ret: %i\n", ret); + if (ret < 0) { + lprintf("sceAudio_38553111() failed: %i\n", ret); + sprintf(noticeMsg, "sound init failed (%i), snd disabled", ret); + noticeMsgTime = sceKernelGetSystemTimeLow(); + currentConfig.EmuOpt &= ~4; + } else { +// int ret = sceAudioSetChannelDataLen(ret, PsndLen); // a try.. +// lprintf("sceAudioSetChannelDataLen: %i\n", ret); + PicoWriteSound = writeSound; + memset32((int *)(void *)sndBuffer, 0, sizeof(sndBuffer)/4); + snd_playptr = sndBuffer; + PsndOut = sndBuffer; + PsndRate_old = PsndRate; + PicoOpt_old = PicoOpt; + pal_old = Pico.m.pal; + } +} + +static void sound_end(void) +{ + int ret; + while (sceAudioOutput2GetRestSample() > 0) psp_msleep(100); + ret = sceAudio_5C37C0AE(); + lprintf("sound_end: sceAudio_5C37C0AE ret %i\n", ret); +} + +static void sound_deinit(void) +{ + sound_thread_exit = 1; + sceKernelSignalSema(sound_sem, 1); +} + +static void writeSound(int len) +{ + int ret; + short *endptr = &sndBuffer[SOUND_DEF_BLOCK_SIZE*SOUND_BLOCK_COUNT*2]; if (PicoOpt&8) len<<=1; - // TODO.. + PsndOut += len; + if (PsndOut > endptr) { + memcpy32((int *)(void *)sndBuffer, (int *)endptr, (PsndOut - endptr + 1) / 2); + PsndOut = &sndBuffer[PsndOut - endptr]; + } + else if (PsndOut == endptr) + PsndOut = sndBuffer; // happy case + + // signal the snd thread + samples_made += len; + if (samples_made - samples_done >= samples_block) { + if (!Pico.m.scanline) lprintf("signal, %i/%i\n", samples_done, samples_made); + ret = sceKernelSignalSema(sound_sem, 1); + if (!Pico.m.scanline) lprintf("signal ret %i\n", ret); + } } -*/ + static void SkipFrame(void) { @@ -490,6 +636,7 @@ void emu_forcedFrame(void) vidResetMode(); memset32(VRAM_CACHED_STUFF, 0xe0e0e0e0, 512*8/4); // borders memset32((int *)VRAM_CACHED_STUFF + 512*232/4, 0xe0e0e0e0, 512*8/4); + memset32((int *)psp_screen + 512*264*2/4, 0, 512*8*2/4); PicoDrawSetColorFormat(-1); PicoScan = EmuScanSlow; @@ -676,7 +823,6 @@ static void simpleWait(unsigned int until) void emu_Loop(void) { - //static int PsndRate_old = 0, PicoOpt_old = 0, pal_old = 0; char fpsbuff[24]; // fps count c string unsigned int tval, tval_prev = 0, tval_thissec = 0; // timing int frames_done = 0, frames_shown = 0, oldmodes = 0; @@ -711,36 +857,10 @@ void emu_Loop(void) // prepare sound stuff PsndOut = NULL; -#if 0 // TODO if (currentConfig.EmuOpt & 4) { - int ret, snd_excess_add, stereo; - if (PsndRate != PsndRate_old || (PicoOpt&0x0b) != (PicoOpt_old&0x0b) || Pico.m.pal != pal_old) { - sound_rerate(Pico.m.frame_count ? 1 : 0); - } - stereo=(PicoOpt&8)>>3; - snd_excess_add = ((PsndRate - PsndLen*target_fps)<<16) / target_fps; - snd_cbuf_samples = (PsndRate< 0; i--, dst += 480, src += 512) menu_darken_bg(dst, src, 480, 1); @@ -1695,7 +1693,7 @@ static void menu_prepare_bg(int use_game_bg, int use_back_buff) static void menu_gfx_prepare(void) { - menu_prepare_bg(rom_data != NULL, 0); + menu_prepare_bg(rom_data != NULL); menu_draw_begin(); menu_draw_end(); diff --git a/platform/psp/psp.c b/platform/psp/psp.c index 84ab5c8..b2d0d72 100644 --- a/platform/psp/psp.c +++ b/platform/psp/psp.c @@ -32,7 +32,8 @@ static int callback_thread(SceSize args, void *argp) { int cbid; - lprintf("callback_thread started with id %i\n", sceKernelGetThreadId()); + lprintf("callback_thread started with id %i, priority %i\n", + sceKernelGetThreadId(), sceKernelGetThreadCurrentPriority()); cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL); sceKernelRegisterExitCallback(cbid); @@ -44,9 +45,10 @@ static int callback_thread(SceSize args, void *argp) void psp_init(void) { - int thid; + SceUID thid; - lprintf("entered psp_init, threadId %i\n", sceKernelGetThreadId()); + lprintf("entered psp_init, threadId %i, priority %i\n", sceKernelGetThreadId(), + sceKernelGetThreadCurrentPriority()); thid = sceKernelCreateThread("update_thread", callback_thread, 0x11, 0xFA0, 0, 0); if (thid >= 0) -- 2.39.2