diff --git a/CrabEmu.h b/CrabEmu.h index af46033..917477f 100644 --- a/CrabEmu.h +++ b/CrabEmu.h @@ -4,7 +4,7 @@ Copyright (C) 2009, 2012, 2014 Lawrence Sebald CrabEmu is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 + it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. CrabEmu is distributed in the hope that it will be useful, diff --git a/CrabEmu.xcodeproj/project.pbxproj b/CrabEmu.xcodeproj/project.pbxproj index 4ae7b75..c66a8d4 100644 --- a/CrabEmu.xcodeproj/project.pbxproj +++ b/CrabEmu.xcodeproj/project.pbxproj @@ -143,6 +143,9 @@ 878700E21B675EB4006841C9 /* nesmapper9.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = nesmapper9.c; sourceTree = ""; }; 878700E31B675EB4006841C9 /* nesmapper66.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = nesmapper66.c; sourceTree = ""; }; 878700E41B675EF0006841C9 /* console.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = console.h; sourceTree = ""; }; + 87ACB6E41D26C1F600138B7E /* CrabZ80_gbmacros.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CrabZ80_gbmacros.h; sourceTree = ""; }; + 87ACB6E51D26C1F600138B7E /* CrabZ80gbops.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CrabZ80gbops.h; sourceTree = ""; }; + 87ACB6E61D26C1F700138B7E /* CrabZ80gbopsCB.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CrabZ80gbopsCB.h; sourceTree = ""; }; 8D5B49B6048680CD000E48DA /* CrabEmu.oecoreplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CrabEmu.oecoreplugin; sourceTree = BUILT_PRODUCTS_DIR; }; 8D5B49B7048680CD000E48DA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 9443D39B1715F2EB00E452AC /* colecomem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = colecomem.c; sourceTree = ""; }; @@ -495,6 +498,9 @@ 9443D3FF1715F31000E452AC /* CrabZ80_tables.h */, 9443D4001715F31000E452AC /* CrabZ80d.c */, 9443D4011715F31000E452AC /* CrabZ80d.h */, + 87ACB6E41D26C1F600138B7E /* CrabZ80_gbmacros.h */, + 87ACB6E51D26C1F600138B7E /* CrabZ80gbops.h */, + 87ACB6E61D26C1F700138B7E /* CrabZ80gbopsCB.h */, 9443D4021715F31000E452AC /* CrabZ80ops.h */, 9443D4031715F31000E452AC /* CrabZ80opsCB.h */, 9443D4041715F31000E452AC /* CrabZ80opsDD-FD.h */, diff --git a/Info.plist b/Info.plist index 4d535e4..f982dca 100644 --- a/Info.plist +++ b/Info.plist @@ -17,7 +17,7 @@ CFBundleSignature OpEm CFBundleVersion - 0.2.1.256 + 0.2.1.261 NSPrincipalClass OEGameCoreController OEGameCoreClass diff --git a/console.h b/console.h index 8b731a1..67628e3 100644 --- a/console.h +++ b/console.h @@ -1,7 +1,7 @@ /* This file is part of CrabEmu. - Copyright (C) 2014, 2015 Lawrence Sebald + Copyright (C) 2014, 2015, 2016 Lawrence Sebald CrabEmu is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 @@ -36,6 +36,12 @@ CLINKAGE /* 7 left blank for now... */ #define CONSOLE_CHIP8 8 /* Chip-8 "Console" */ +/* Region codes. */ +#define REGION_NONE 0x00 +#define REGION_JAPAN 0x01 +#define REGION_US 0x02 +#define REGION_EUROPE 0x04 + /* This structure is meant to provide an abstraction of a console, such that there can be less console-specific code up at the GUI level. Rignt now, this doesn't take care of everything, but that might eventually change... Each diff --git a/consoles/colecovision/colecovision.c b/consoles/colecovision/colecovision.c index 816c7a0..3f0bcf5 100644 --- a/consoles/colecovision/colecovision.c +++ b/consoles/colecovision/colecovision.c @@ -4,7 +4,7 @@ Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2012, 2014 Lawrence Sebald CrabEmu is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 + it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. CrabEmu is distributed in the hope that it will be useful, @@ -103,18 +103,18 @@ colecovision_t colecovision_cons = { &tms9918a_vdp_activeframe, NULL, /* save_cheats */ #ifndef _arch_dreamcast - &coleco_scanline, - &coleco_single_step, - &coleco_finish_frame, - &coleco_finish_scanline, + &coleco_scanline, + &coleco_single_step, + &coleco_finish_frame, + &coleco_finish_scanline, #else NULL, NULL, NULL, NULL, #endif - &coleco_current_scanline, - &coleco_cycles_left, + &coleco_current_scanline, + &coleco_cycles_left, NULL /* set_control */ } }; @@ -148,7 +148,7 @@ int coleco_init(int video_system) { for(i = 0; i < PAL_LINES_PER_FRAME; ++i) { psg_samples[i] = (uint32) (tmp * (i + 1)) - - (uint32) (tmp * i); + (uint32) (tmp * i); } /* We need 882 samples per frame @ 44100 Hz, 50fps. */ @@ -308,7 +308,7 @@ void coleco_button_released(int player, int button) { } #ifndef _arch_dreamcast -static __INLINE__ int update_sound(int16 buf[], int start, int line) { +static __INLINE__ int update_sound(int16 buf[], int start, int line) { if(sms_psg_enabled) sn76489_execute_samples(&psg, buf + start, psg_samples[line]); else diff --git a/consoles/sms/mappers.c b/consoles/sms/mappers.c index ee91d92..b1ce9d6 100644 --- a/consoles/sms/mappers.c +++ b/consoles/sms/mappers.c @@ -1,10 +1,10 @@ /* This file is part of CrabEmu. - Copyright (C) 2008, 2012 Lawrence Sebald + Copyright (C) 2008, 2012, 2015 Lawrence Sebald CrabEmu is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 + it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. CrabEmu is distributed in the hope that it will be useful, diff --git a/consoles/sms/sms.h b/consoles/sms/sms.h index c44ab59..cb9cdc7 100644 --- a/consoles/sms/sms.h +++ b/consoles/sms/sms.h @@ -4,7 +4,7 @@ Copyright (C) 2005, 2007, 2009, 2012, 2014 Lawrence Sebald CrabEmu is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 + it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. CrabEmu is distributed in the hope that it will be useful, @@ -95,8 +95,8 @@ extern int sms_read_state(FILE *fp); #define SMS_TH_MASK 0xC000 /* Region types */ -#define SMS_REGION_DOMESTIC 0x01 -#define SMS_REGION_EXPORT 0x02 +#define SMS_REGION_DOMESTIC REGION_JAPAN +#define SMS_REGION_EXPORT REGION_US /* Video Standards */ #define SMS_VIDEO_NTSC VIDEO_NTSC diff --git a/consoles/sms/smsz80.c b/consoles/sms/smsz80.c index 306589f..28cbd98 100644 --- a/consoles/sms/smsz80.c +++ b/consoles/sms/smsz80.c @@ -4,7 +4,7 @@ Copyright (C) 2005, 2006, 2007, 2008, 2009 Lawrence Sebald CrabEmu is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 + it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. CrabEmu is distributed in the hope that it will be useful, @@ -34,7 +34,7 @@ int sms_z80_init(void) { return -1; } - CrabZ80_init(cpuz80); + CrabZ80_init(cpuz80, CRABZ80_CPU_Z80); CrabZ80_reset(cpuz80); CrabZ80_set_portwrite(cpuz80, sms_port_write); diff --git a/cpu/CrabZ80/CrabZ80.c b/cpu/CrabZ80/CrabZ80.c index 8adff2b..dfeab62 100644 --- a/cpu/CrabZ80/CrabZ80.c +++ b/cpu/CrabZ80/CrabZ80.c @@ -1,12 +1,13 @@ /* This file is part of CrabEmu. - Copyright (C) 2005, 2006, 2007, 2008, 2009, 2011, 2012 Lawrence Sebald + Copyright (C) 2005, 2006, 2007, 2008, 2009, 2011, 2012, 2015, + 2016 Lawrence Sebald CrabEmu is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 + it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. - + CrabEmu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -17,14 +18,16 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "CrabZ80.h" -#include "CrabZ80_tables.h" -#include "CrabZ80_macros.h" #include #include #include -static CrabZ80_t *cpu = NULL; +#include "CrabZ80.h" +#include "CrabZ80_tables.h" +#include "CrabZ80_macros.h" +#include "CrabZ80_gbmacros.h" + +static Z80 *cpu = NULL; #ifndef CRABZ80_NO_READMAP_FALLBACK @@ -62,6 +65,9 @@ static CrabZ80_t *cpu = NULL; #endif +static uint32 CrabZ80_exec_z80(Z80 *cpuin, uint32 cycles); +static uint32 CrabZ80_exec_lr35902(Z80 *cpuin, uint32 cycles); + static uint8 CrabZ80_dummy_read(uint16 addr) { (void)addr; return 0; @@ -95,57 +101,57 @@ static void CrabZ80_default_mwrite16(uint16 addr, uint16 data) { cpu->mwrite(addr, data & 0xFF); } -void CrabZ80_set_portread(CrabZ80_t *cpuz80, uint8 (*pread)(uint16 port)) { +void CRABZ80_FUNC(set_portread)(Z80 *cpuz80, uint8 (*pread)(uint16 port)) { if(pread == NULL) cpuz80->pread = CrabZ80_dummy_read; else cpuz80->pread = pread; } -void CrabZ80_set_memread(CrabZ80_t *cpuz80, uint8 (*mread)(uint16 addr)) { +void CRABZ80_FUNC(set_memread)(Z80 *cpuz80, uint8 (*mread)(uint16 addr)) { if(mread == NULL) cpuz80->mread = CrabZ80_dummy_read; else cpuz80->mread = mread; } -void CrabZ80_set_portwrite(CrabZ80_t *cpuz80, - void (*pwrite)(uint16 port, uint8 data)) { +void CRABZ80_FUNC(set_portwrite)(Z80 *cpuz80, + void (*pwrite)(uint16 port, uint8 data)) { if(pwrite == NULL) cpuz80->pwrite = CrabZ80_dummy_write; else cpuz80->pwrite = pwrite; } -void CrabZ80_set_memwrite(CrabZ80_t *cpuz80, - void (*mwrite)(uint16 addr, uint8 data)) { +void CRABZ80_FUNC(set_memwrite)(Z80 *cpuz80, + void (*mwrite)(uint16 addr, uint8 data)) { if(mwrite == NULL) cpuz80->mwrite = CrabZ80_dummy_write; else cpuz80->mwrite = mwrite; } -void CrabZ80_set_memread16(CrabZ80_t *cpuz80, - uint16 (*mread16)(uint16 addr)) { +void CRABZ80_FUNC(set_memread16)(Z80 *cpuz80, + uint16 (*mread16)(uint16 addr)) { if(mread16 == NULL) cpuz80->mread16 = CrabZ80_default_mread16; else cpuz80->mread16 = mread16; } -void CrabZ80_set_memwrite16(CrabZ80_t *cpuz80, - void (*mwrite16)(uint16 addr, uint16 data)) { +void CRABZ80_FUNC(set_memwrite16)(Z80 *cpuz80, + void (*mwrite16)(uint16 addr, uint16 data)) { if(mwrite16 == NULL) cpuz80->mwrite16 = CrabZ80_default_mwrite16; else cpuz80->mwrite16 = mwrite16; } -void CrabZ80_set_readmap(CrabZ80_t *cpuz80, uint8 *readmap[256]) { +void CRABZ80_FUNC(set_readmap)(Z80 *cpuz80, uint8 *readmap[256]) { memcpy(cpuz80->readmap, readmap, 256 * sizeof(uint8 *)); } -void CrabZ80_init(CrabZ80_t *cpuz80) { +void CRABZ80_FUNC(init)(Z80 *cpuz80, int model) { cpuz80->pread = CrabZ80_dummy_read; cpuz80->mread = CrabZ80_dummy_read; cpuz80->pwrite = CrabZ80_dummy_write; @@ -154,9 +160,24 @@ void CrabZ80_init(CrabZ80_t *cpuz80) { cpuz80->mwrite16 = CrabZ80_default_mwrite16; memset(cpuz80->readmap, 0, 256 * sizeof(uint8 *)); + + switch(model) { + case CRABZ80_CPU_Z80: + cpuz80->exec = &CrabZ80_exec_z80; + break; + + case CRABZ80_CPU_LR35902: + cpuz80->exec = &CrabZ80_exec_lr35902; + break; + + default: + fprintf(stderr, "Unknown CPU type (%d), selecting Z80.\n", model); + cpuz80->exec = &CrabZ80_exec_z80; + break; + } } -void CrabZ80_reset(CrabZ80_t *cpuz80) { +void CRABZ80_FUNC(reset)(Z80 *cpuz80) { cpuz80->pc.w = 0x0000; cpuz80->iff1 = 0; cpuz80->iff2 = 0; @@ -181,7 +202,7 @@ void CrabZ80_reset(CrabZ80_t *cpuz80) { cpuz80->irq_pending = 0; } -static uint32 CrabZ80_take_nmi(CrabZ80_t *cpuz80) { +static uint32 CrabZ80_take_nmi(Z80 *cpuz80) { if(cpuz80->halt) { cpuz80->pc.w++; cpuz80->halt = 0; @@ -201,7 +222,7 @@ static uint32 CrabZ80_take_nmi(CrabZ80_t *cpuz80) { return 11; } -static uint32 CrabZ80_take_irq(CrabZ80_t *cpuz80) { +static uint32 CrabZ80_take_irq(Z80 *cpuz80) { if(cpuz80->halt) { cpuz80->pc.w++; cpuz80->halt = 0; @@ -223,7 +244,7 @@ static uint32 CrabZ80_take_irq(CrabZ80_t *cpuz80) { case 0: case 1: cpuz80->sp.w -= 2; - cpuz80->mwrite16(cpu->sp.w, cpu->pc.w); + cpuz80->mwrite16(cpuz80->sp.w, cpuz80->pc.w); cpuz80->pc.w = 0x0038; return 13; @@ -231,8 +252,8 @@ static uint32 CrabZ80_take_irq(CrabZ80_t *cpuz80) { { uint16 tmp = (cpuz80->ir.b.h << 8) + (cpuz80->irq_vector & 0xFF); cpuz80->sp.w -= 2; - cpuz80->mwrite16(cpu->sp.w, cpu->pc.w); - cpuz80->pc.w = cpu->mread16(tmp); + cpuz80->mwrite16(cpuz80->sp.w, cpuz80->pc.w); + cpuz80->pc.w = cpuz80->mread16(tmp); return 19; } @@ -246,24 +267,37 @@ static uint32 CrabZ80_take_irq(CrabZ80_t *cpuz80) { } } -void CrabZ80_pulse_nmi(CrabZ80_t *cpuz80) { +void CRABZ80_FUNC(pulse_nmi)(Z80 *cpuz80) { cpuz80->irq_pending |= 2; } -void CrabZ80_assert_irq(CrabZ80_t *cpuz80, uint32 vector) { +void CRABZ80_FUNC(assert_irq)(Z80 *cpuz80, uint32 vector) { cpuz80->irq_pending |= 1; cpuz80->irq_vector = vector; } -void CrabZ80_clear_irq(CrabZ80_t *cpuz80) { +void CRABZ80_FUNC(clear_irq)(Z80 *cpuz80) { cpuz80->irq_pending &= 2; } -void CrabZ80_release_cycles(CrabZ80_t *cpuz80) { +void CRABZ80_FUNC(set_irqflag_lr35902)(Z80 *cpuz80, uint8 irqs) { + cpuz80->irq_pending = irqs; +} + +void CRABZ80_FUNC(set_irqen_lr35902)(Z80 *cpuz80, uint8 irqs) { + /* Reuse IFF2, since it doesn't exist on the LR35902. */ + cpuz80->iff2 = irqs; +} + +void CRABZ80_FUNC(release_cycles)(Z80 *cpuz80) { cpuz80->cycles_in = 0; } -uint32 CrabZ80_execute(CrabZ80_t *cpuin, uint32 cycles) { +uint32 CRABZ80_FUNC(execute)(Z80 *cpuin, uint32 cycles) { + return cpuin->exec(cpuin, cycles); +} + +static uint32 CrabZ80_exec_z80(Z80 *cpuin, uint32 cycles) { register uint32 cycles_done = 0; CrabZ80_t *oldcpu = NULL; uint32 oldcyclesin = 0, oldcycles = 0; @@ -311,3 +345,79 @@ uint32 CrabZ80_execute(CrabZ80_t *cpuin, uint32 cycles) { return cycles_done; } + +static uint32 CrabZ80_exec_lr35902(Z80 *cpuin, uint32 cycles) { + register uint32 cycles_done = 0; + CrabZ80_t *oldcpu = NULL; + uint32 oldcyclesin = 0, oldcycles = 0; + + if(cpu) { + oldcyclesin = cpu->cycles_in; + oldcycles = cpu->cycles; + oldcpu = cpu; + } + + cpu = cpuin; + + cycles_done = 0; + cpuin->cycles_in = cycles; + cpuin->cycles = 0; + + while(cycles_done < cpuin->cycles_in) { + /* If interrupts are enabled, then check if we have any waiting. */ + if(!cpuin->ei && cpuin->iff1) { + uint8 irqs; + + /* Do we actually have any IRQs pending? */ + irqs = cpuin->irq_pending & cpuin->iff2; + if(irqs) { + uint8 i; + + /* Un-halt the CPU if it is halted. */ + if(cpuin->halt) { + cpuin->pc.w++; + cpuin->halt = 0; + } + + /* Look through all interrupts being asserted (that are enabled) + until we find the highest priority one being asserted. */ + for(i = 0; i < 5; ++i) { + if((irqs & (1 << i))) { + /* Clear the IRQ pending flag and disable interrupts. */ + cpuin->irq_pending &= ~(1 << i); + cpuin->iff1 = 0; + + /* Push the PC onto the stack and set the new PC. */ + cpuin->sp.w -= 2; + cpuin->mwrite16(cpuin->sp.w, cpuin->pc.w); + cpuin->pc.w = 0x40 + (i << 3); + cycles_done += 12; + goto out; + } + } + } + } + + cpuin->ei = 0; + { + uint8 inst; + FETCH_ARG8(inst); + ++cpuin->ir.b.l; +#define INSIDE_CRABZ80_GBEXECUTE +#include "CrabZ80gbops.h" +#undef INSIDE_CRABZ80_GBEXECUTE + } + +out: + cpuin->cycles = cycles_done; + } + + cpu = oldcpu; + + if(cpu) { + cpu->cycles = oldcycles; + cpu->cycles_in = oldcyclesin; + } + + return cycles_done; +} diff --git a/cpu/CrabZ80/CrabZ80.h b/cpu/CrabZ80/CrabZ80.h index 07ca250..4617e30 100644 --- a/cpu/CrabZ80/CrabZ80.h +++ b/cpu/CrabZ80/CrabZ80.h @@ -1,10 +1,10 @@ /* This file is part of CrabEmu. - Copyright (C) 2005, 2006, 2007, 2008, 2009 Lawrence Sebald + Copyright (C) 2005, 2006, 2007, 2008, 2009, 2015 Lawrence Sebald CrabEmu is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 + it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. CrabEmu is distributed in the hope that it will be useful, @@ -52,8 +52,38 @@ typedef uint32_t int32; #endif /* CRABEMU_TYPEDEFS */ #endif /* IN_CRABEMU */ +/****************************************************************************** + DANGER WILL ROBINSON! + + No User-serviceable parts below this block. + + DANGER WILL ROBINSON! + ******************************************************************************/ CLINKAGE +#ifndef CRABZ80_PREFIX +#define CRABZ80_PREFIX CrabZ80 +#endif + +/* Because any of this makes sense... */ +#define CRABZ80_SYM_3(x, y) x ## _ ## y +#define CRABZ80_SYM_2(x, y) CRABZ80_SYM_3(x, y) +#define CRABZ80_SYM(x) CRABZ80_SYM_2(CRABZ80_PREFIX, x) + +#define CRABZ80_FUNC(fn) CRABZ80_SYM(fn) +#define CRABZ80_CPU CRABZ80_SYM(t) +#define Z80 CRABZ80_CPU + +/* CPU Types. + + These control various parts of the code to implement emulation for different + Z80-like CPUs. */ +#define CRABZ80_CPU_Z80 0 +#define CRABZ80_CPU_LR35902 1 +#define CRABZ80_CPU_GB CRABZ80_CPU_LR35902 + +#define CRABZ80_CPU_MAX 1 /* Don't use this one... */ + typedef union { struct { #ifdef __BIG_ENDIAN__ @@ -66,7 +96,7 @@ typedef union { } b; uint8 bytes[2]; uint16 w; -} CrabZ80_reg_t; +} CRABZ80_SYM(reg_t); typedef union { struct { @@ -79,7 +109,7 @@ typedef union { #endif } b; uint16 w; -} CrabZ80_regAF_t; +} CRABZ80_SYM(regAF_t); #ifdef __BIG_ENDIAN__ #define REG8(x) cpu->regs8[(x) & 0x07] @@ -91,28 +121,28 @@ typedef union { #define REG16(x) cpu->regs16[(x) & 0x03] -typedef struct CrabZ80_struct { +typedef struct CRABZ80_SYM(struct) { union { uint8 regs8[8]; uint16 regs16[4]; struct { - CrabZ80_reg_t bc; - CrabZ80_reg_t de; - CrabZ80_reg_t hl; - CrabZ80_regAF_t af; + CRABZ80_SYM(reg_t) bc; + CRABZ80_SYM(reg_t) de; + CRABZ80_SYM(reg_t) hl; + CRABZ80_SYM(regAF_t) af; }; }; - CrabZ80_reg_t ix; - CrabZ80_reg_t iy; - CrabZ80_reg_t pc; - CrabZ80_reg_t sp; - CrabZ80_reg_t ir; - CrabZ80_regAF_t afp; - CrabZ80_reg_t bcp; - CrabZ80_reg_t dep; - CrabZ80_reg_t hlp; - - CrabZ80_reg_t *offset; + CRABZ80_SYM(reg_t) ix; + CRABZ80_SYM(reg_t) iy; + CRABZ80_SYM(reg_t) pc; + CRABZ80_SYM(reg_t) sp; + CRABZ80_SYM(reg_t) ir; + CRABZ80_SYM(regAF_t) afp; + CRABZ80_SYM(reg_t) bcp; + CRABZ80_SYM(reg_t) dep; + CRABZ80_SYM(reg_t) hlp; + + CRABZ80_SYM(reg_t) *offset; uint8 iff1; uint8 iff2; @@ -137,8 +167,10 @@ typedef struct CrabZ80_struct { uint16 (*mread16)(uint16 addr); void (*mwrite16)(uint16 addr, uint16 data); + uint32 (*exec)(struct CRABZ80_SYM(struct) *, uint32); + uint8 *readmap[256]; -} CrabZ80_t; +} CRABZ80_SYM(t); /* Flag definitions */ #define CRABZ80_CF 0 @@ -150,35 +182,47 @@ typedef struct CrabZ80_struct { #define CRABZ80_ZF 6 #define CRABZ80_SF 7 +/* Flags when emulating an LR35902. Other flag bits are all 0. */ +#define CRABZ80_LR35902_CF 4 +#define CRABZ80_LR35902_HF 5 +#define CRABZ80_LR35902_NF 6 +#define CRABZ80_LR35902_ZF 7 + /* Flag setting macros */ #define CRABZ80_SET_FLAG(z80, n) (z80)->af.b.l |= (1 << (n)) #define CRABZ80_CLEAR_FLAG(z80, n) (z80)->af.b.l &= (~(1 << (n))) #define CRABZ80_GET_FLAG(z80, n) ((z80)->af.b.l >> (n)) & 1 /* Function definitions */ -void CrabZ80_init(CrabZ80_t *cpu); -void CrabZ80_reset(CrabZ80_t *cpu); +void CRABZ80_FUNC(init)(Z80 *cpu, int model); +void CRABZ80_FUNC(reset)(Z80 *cpu); + +/* Z80 IRQs. */ +void CRABZ80_FUNC(pulse_nmi)(Z80 *cpu); +void CRABZ80_FUNC(assert_irq)(Z80 *cpu, uint32 vector); +void CRABZ80_FUNC(clear_irq)(Z80 *cpu); -void CrabZ80_pulse_nmi(CrabZ80_t *cpu); -void CrabZ80_assert_irq(CrabZ80_t *cpu, uint32 vector); -void CrabZ80_clear_irq(CrabZ80_t *cpu); +/* LR35902 IRQs. */ +void CRABZ80_FUNC(set_irqflag_lr35902)(Z80 *cpuz80, uint8 irqs); +void CRABZ80_FUNC(set_irqen_lr35902)(Z80 *cpuz80, uint8 irqs); -uint32 CrabZ80_execute(CrabZ80_t *cpu, uint32 cycles); +uint32 CRABZ80_FUNC(execute)(Z80 *cpu, uint32 cycles); -void CrabZ80_release_cycles(); +void CRABZ80_FUNC(release_cycles)(Z80 *cpu); -void CrabZ80_set_portread(CrabZ80_t *cpu, uint8 (*pread)(uint16 port)); -void CrabZ80_set_memread(CrabZ80_t *cpu, uint8 (*mread)(uint16 addr)); -void CrabZ80_set_portwrite(CrabZ80_t *cpu, - void (*pwrite)(uint16 port, uint8 data)); -void CrabZ80_set_memwrite(CrabZ80_t *cpu, - void (*mwrite)(uint16 addr, uint8 data)); +void CRABZ80_FUNC(set_portread)(Z80 *cpu, uint8 (*pread)(uint16 port)); +void CRABZ80_FUNC(set_memread)(Z80 *cpu, uint8 (*mread)(uint16 addr)); +void CRABZ80_FUNC(set_portwrite)(Z80 *cpu, + void (*pwrite)(uint16 port, uint8 data)); +void CRABZ80_FUNC(set_memwrite)(Z80 *cpu, + void (*mwrite)(uint16 addr, uint8 data)); -void CrabZ80_set_memread16(CrabZ80_t *cpu, uint16 (*mread16)(uint16 addr)); -void CrabZ80_set_memwrite16(CrabZ80_t *cpu, - void (*mwrite16)(uint16 addr, uint16 data)); +void CRABZ80_FUNC(set_memread16)(Z80 *cpu, + uint16 (*mread16)(uint16 addr)); +void CRABZ80_FUNC(set_memwrite16)(Z80 *cpu, + void (*mwrite16)(uint16 addr, uint16 data)); -void CrabZ80_set_readmap(CrabZ80_t *cpuz80, uint8 *readmap[256]); +void CRABZ80_FUNC(set_readmap)(Z80 *cpu, uint8 *readmap[256]); ENDCLINK diff --git a/cpu/CrabZ80/CrabZ80_gbmacros.h b/cpu/CrabZ80/CrabZ80_gbmacros.h new file mode 100644 index 0000000..a904542 --- /dev/null +++ b/cpu/CrabZ80/CrabZ80_gbmacros.h @@ -0,0 +1,133 @@ +/* + This file is part of CrabEmu. + + Copyright (C) 2005, 2006, 2007, 2008, 2015, 2016 Lawrence Sebald + + CrabEmu is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 + as published by the Free Software Foundation. + + CrabEmu is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CrabEmu; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#define GB_INC8(val) { \ + uint32 _tmp = (val) + 1; \ + cpu->af.b.l = ((!_tmp) << 7) | \ + ((_tmp & 0x0F) ? 0x00 : 0x20) | \ + (cpu->af.b.l & 0x10); \ + (val) = _tmp; \ +} + +#define GB_DEC8(val) { \ + uint32 _tmp = (val) - 1; \ + cpu->af.b.l = ((!_tmp) << 7) | \ + (cpu->af.b.l & 0x01) | \ + ((((val) ^ _tmp) & 0x10) << 1) | \ + 0x40; \ + (val) = _tmp; \ +} + +#define GB_RLCA() { \ + cpu->af.b.h = (cpu->af.b.h << 1) | (cpu->af.b.h >> 7); \ + cpu->af.b.l = (cpu->af.b.l & 0xEF) | ((cpu->af.b.h & 0x01) << 4); \ +} + +#define GB_RRCA() { \ + cpu->af.b.l = (cpu->af.b.l & 0xEF) | ((cpu->af.b.h & 0x01) << 4); \ + cpu->af.b.h = (cpu->af.b.h >> 1) | (cpu->af.b.h << 7); \ +} + +#define GB_RLA() { \ + cpu->af.b.l = (cpu->af.b.l & 0xEF) | ((cpu->af.b.h >> 3) & 0x10); \ + cpu->af.b.h = (cpu->af.b.h << 1) | (cpu->af.b.l & 0x01); \ +} + +#define GB_RRA() { \ + cpu->af.b.l = (cpu->af.b.l & 0xEF) | ((cpu->af.b.h & 0x01) << 4); \ + cpu->af.b.h = (cpu->af.b.h >> 1) | (cpu->af.b.l << 7); \ +} + +#define GB_CPL() { \ + cpu->af.b.h ^= 0xFF; \ + cpu->af.b.l = (cpu->af.b.l & 0x9F) | 0x60; \ +} + +#define GB_SCF() { \ + cpu->af.b.l = (cpu->af.b.l & 0x80) | 0x10; \ +} + +#define GB_CCF() { \ + cpu->af.b.l = (cpu->af.b.l & 0x80) | ((cpu->af.b.l ^ 0x10) & 0x10); \ +} + +#define GB_ADD() { \ + uint32 _tmp = cpu->af.b.h + _value; \ + cpu->af.b.l = ((!((uint8)_tmp)) << 7) | \ + (((cpu->af.b.h ^ _tmp ^ _value) & 0x10) << 1) | \ + ((_tmp >> 4) & 0x10); \ + cpu->af.b.h = _tmp; \ +} + +#define GB_ADC() { \ + uint32 _tmp = cpu->af.b.h + _value + (cpu->af.b.l & 0x01); \ + cpu->af.b.l = ((!((uint8)_tmp)) << 7) | \ + (((cpu->af.b.h ^ _tmp ^ _value) & 0x10) << 1) | \ + ((_tmp >> 4) & 0x10); \ + cpu->af.b.h = _tmp; \ +} + +#define GB_SUB() { \ + uint32 _tmp = cpu->af.b.h - _value; \ + cpu->af.b.l = ((!((uint8)_tmp)) << 7) | \ + (((cpu->af.b.h ^ _tmp ^ _value) & 0x10) << 1) | \ + 0x40 | ((_tmp >> 4) & 0x10); \ + cpu->af.b.h = _tmp; \ +} + +#define GB_SBC() { \ + uint32 _tmp = cpu->af.b.h - (cpu->af.b.l & 0x01) - _value; \ + cpu->af.b.l = ((!((uint8)_tmp)) << 7) | \ + (((cpu->af.b.h ^ _tmp ^ _value) & 0x10) << 1) | \ + 0x40 | ((_tmp >> 4) & 0x10); \ + cpu->af.b.h = _tmp; \ +} + +#define GB_AND() { \ + uint32 _tmp = cpu->af.b.h & _value; \ + cpu->af.b.l = ((!_tmp) << 7) | 0x10; \ + cpu->af.b.h = _tmp; \ +} + +#define GB_XOR() { \ + uint32 _tmp = cpu->af.b.h ^ _value; \ + cpu->af.b.l = ((!_tmp) << 7); \ + cpu->af.b.h = _tmp; \ +} + +#define GB_OR() { \ + uint32 _tmp = cpu->af.b.h | _value; \ + cpu->af.b.l = ((!_tmp) << 7); \ + cpu->af.b.h = _tmp; \ +} + +#define GB_CP() { \ + uint32 _tmp = cpu->af.b.h - _value; \ + cpu->af.b.l = ((!((uint8)_tmp)) << 7) | \ + (((cpu->af.b.h ^ _tmp ^ _value) & 0x10) << 1) | \ + 0x40 | ((_tmp >> 4) & 0x10); \ +} + +#define GB_ADDHL() { \ + uint32 _tmp = cpu->hl.w + _value; \ + cpu->af.b.l = (cpu->af.b.l & 0x8F) | \ + (((cpu->hl.w ^ _tmp ^ _value) >> 7) & 0x20) | \ + ((_tmp >> 12) & 0x10); \ + cpu->hl.w = _tmp; \ +} diff --git a/cpu/CrabZ80/CrabZ80_macros.h b/cpu/CrabZ80/CrabZ80_macros.h index 8ea3065..e6a88ae 100644 --- a/cpu/CrabZ80/CrabZ80_macros.h +++ b/cpu/CrabZ80/CrabZ80_macros.h @@ -4,7 +4,7 @@ Copyright (C) 2005, 2006, 2007, 2008 Lawrence Sebald CrabEmu is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 + it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. CrabEmu is distributed in the hope that it will be useful, @@ -350,7 +350,7 @@ #define OP_ADDIx() { \ uint32 _tmp = cpu->offset->w + _value; \ - cpu->af.b.l = (cpu->af.b.l & 0xC4) | \ + cpu->af.b.l = (cpu->af.b.l & 0xC4) | \ (((cpu->offset->w ^ _tmp ^ _value) >> 8) & 0x10) | \ ((_tmp >> 8) & 0x28) | \ ((_tmp >> 16) & 0x01); \ diff --git a/cpu/CrabZ80/CrabZ80_tables.h b/cpu/CrabZ80/CrabZ80_tables.h index 7c9f40d..d3ab412 100644 --- a/cpu/CrabZ80/CrabZ80_tables.h +++ b/cpu/CrabZ80/CrabZ80_tables.h @@ -4,7 +4,7 @@ Copyright (C) 2005, 2006 Lawrence Sebald CrabEmu is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 + it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. CrabEmu is distributed in the hope that it will be useful, diff --git a/cpu/CrabZ80/CrabZ80gbops.h b/cpu/CrabZ80/CrabZ80gbops.h new file mode 100644 index 0000000..00774c5 --- /dev/null +++ b/cpu/CrabZ80/CrabZ80gbops.h @@ -0,0 +1,877 @@ +/* + This file is part of CrabEmu. + + Copyright (C) 2005, 2006, 2007, 2008, 2015, 2016 Lawrence Sebald + + CrabEmu is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 + as published by the Free Software Foundation. + + CrabEmu is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CrabEmu; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef INSIDE_CRABZ80_GBEXECUTE +#error This file can only be compiled inside of CrabZ80.c. Do not try to include +#error this file in other files. +#endif + +{ +uint32 _value; +uint32 _tmp; + +switch(inst) { + case 0x00: /* NOP */ //d + case 0x40: /* LD B, B */ //d + case 0x49: /* LD C, C */ //d + case 0x52: /* LD D, D */ //d + case 0x5B: /* LD E, E */ //d + case 0x64: /* LD H, H */ //d + case 0x6D: /* LD L, L */ //d + case 0x7F: /* LD A, A */ //d + cycles_done += 4; + goto out; + + case 0x01: /* LD BC, nn */ //d + case 0x11: /* LD DE, nn */ //d + case 0x21: /* LD HL, nn */ //d + FETCH_ARG16(_value); + REG16(inst >> 4) = _value; + cycles_done += 12; + goto out; + + case 0x31: /* LD SP, nn */ //d + FETCH_ARG16(_value); + cpu->sp.w = _value; + cycles_done += 12; + goto out; + + case 0x02: /* LD (BC), A */ //d + case 0x12: /* LD (DE), A */ //d + cpu->mwrite(REG16(inst >> 4), cpu->af.b.h); + cycles_done += 8; + goto out; + + case 0x03: /* INC BC */ //d + ++cpu->bc.w; + cycles_done += 8; + goto out; + + case 0x13: /* INC DE */ //d + ++cpu->de.w; + cycles_done += 8; + goto out; + + case 0x23: /* INC HL */ //d + ++cpu->hl.w; + cycles_done += 8; + goto out; + + case 0x33: /* INC SP */ //d + ++cpu->sp.w; + cycles_done += 8; + goto out; + + case 0x04: /* INC B */ //d + case 0x0C: /* INC C */ //d + case 0x14: /* INC D */ //d + case 0x1C: /* INC E */ //d + case 0x24: /* INC H */ //d + case 0x2C: /* INC L */ //d + case 0x3C: /* INC A */ //d + _value = REG8(inst >> 3); + GB_INC8(_value); + REG8(inst >> 3) = _value; + cycles_done += 4; + goto out; + + case 0x34: /* INC (HL) */ //d + _value = cpu->mread(cpu->hl.w); + GB_INC8(_value); + cpu->mwrite(cpu->hl.w, _value); + cycles_done += 12; + goto out; + + case 0x05: /* DEC B */ //d + case 0x0D: /* DEC C */ //d + case 0x15: /* DEC D */ //d + case 0x1D: /* DEC E */ //d + case 0x25: /* DEC H */ //d + case 0x2D: /* DEC L */ //d + case 0x3D: /* DEC A */ //d + _value = REG8(inst >> 3); + GB_DEC8(_value); + REG8(inst >> 3) = _value; + cycles_done += 4; + goto out; + + case 0x35: /* DEC (HL) */ //d + _value = cpu->mread(cpu->hl.w); + GB_DEC8(_value); + cpu->mwrite(cpu->hl.w, _value); + cycles_done += 12; + goto out; + + case 0x06: /* LD B, n */ //d + case 0x0E: /* LD C, n */ //d + case 0x16: /* LD D, n */ //d + case 0x1E: /* LD E, n */ //d + case 0x26: /* LD H, n */ //d + case 0x2E: /* LD L, n */ //d + case 0x3E: /* LD A, n */ //d + FETCH_ARG8(_value); + REG8(inst >> 3) = _value; + cycles_done += 8; + goto out; + + case 0x36: /* LD (HL), n */ //d + FETCH_ARG8(_value); + cpu->mwrite(cpu->hl.w, _value); + cycles_done += 12; + goto out; + + case 0x07: /* RLCA */ //d + GB_RLCA(); + cycles_done += 4; + goto out; + + case 0x09: /* ADD HL, BC */ //d + case 0x19: /* ADD HL, DE */ //d + case 0x29: /* ADD HL, HL */ //d + _value = REG16(inst >> 4); + +ADDHLOP: + cpu->internal_reg = cpu->hl.b.h; + GB_ADDHL(); + cycles_done += 8; + goto out; + + case 0x39: /* ADD HL, SP */ //d + _value = cpu->sp.w; + goto ADDHLOP; + + case 0x0A: /* LD A, (BC) */ //d + case 0x1A: /* LD A, (DE) */ //d + cpu->af.b.h = cpu->mread(REG16(inst >> 4)); + cycles_done += 8; + goto out; + + case 0x0B: /* DEC BC */ //d + --cpu->bc.w; + cycles_done += 8; + goto out; + + case 0x1B: /* DEC DE */ //d + --cpu->de.w; + cycles_done += 8; + goto out; + + case 0x2B: /* DEC HL */ //d + --cpu->hl.w; + cycles_done += 8; + goto out; + + case 0x3B: /* DEC SP */ //d + --cpu->sp.w; + cycles_done += 8; + goto out; + + case 0x0F: /* RRCA */ //d + GB_RRCA(); + cycles_done += 4; + goto out; + + case 0x18: /* JR e */ //d +JROP: + FETCH_ARG8(_value); + cpu->pc.w += (int8)_value; + cycles_done += 12; + cpu->internal_reg = cpu->pc.b.h; + goto out; + + case 0x20: /* JR NZ, e */ //d + if(!(cpu->af.b.l & 0x80)) { + goto JROP; + } + + ++cpu->pc.w; + cycles_done += 8; + goto out; + + case 0x28: /* JR Z, e */ //d + if(cpu->af.b.l & 0x80) { + goto JROP; + } + + ++cpu->pc.w; + cycles_done += 8; + goto out; + + case 0x30: /* JR NC, e */ //d + if(!(cpu->af.b.l & 0x10)) { + goto JROP; + } + + ++cpu->pc.w; + cycles_done += 8; + goto out; + + case 0x38: /* JR C, e */ //d + if(cpu->af.b.l & 0x10) { + goto JROP; + } + + ++cpu->pc.w; + cycles_done += 8; + goto out; + + case 0x17: /* RLA */ //d + GB_RLA(); + cycles_done += 4; + goto out; + + case 0x1F: /* RRA */ //d + GB_RRA(); + cycles_done += 4; + goto out; + + case 0x27: /* DAA */ //d + { + int low = cpu->af.b.h & 0x0F; + int high = cpu->af.b.h >> 4; + int cf = cpu->af.b.l & 0x10; + int hf = cpu->af.b.l & 0x20; + int nf = cpu->af.b.l & 0x40; + + if(cf) { + _value = (low < 0x0A && !hf) ? 0x60 : 0x66; + } + else { + if(low < 0x0A) { + if(high < 0x0A) { + _value = (hf) ? 0x06 : 0x00; + } + else { + _value = (hf) ? 0x66 : 0x60; + } + } + else { + _value = (high < 0x09) ? 0x06 : 0x66; + } + } + + if(nf) { + cpu->af.b.h -= _value; + } + else { + cpu->af.b.h += _value; + } + + cpu->af.b.l = ((!cpu->af.b.h) << 7) | (nf); + + if(_value >= 0x60) + cpu->af.b.l |= 0x01; + + if(nf) { + if(hf && low < 0x06) { + cpu->af.b.l |= 0x10; + } + } + else if(low >= 10) { + cpu->af.b.l |= 0x10; + } + + cycles_done += 4; + goto out; + } + + case 0x2F: /* CPL */ //d + GB_CPL(); + cycles_done += 4; + goto out; + + case 0x37: /* SCF */ //d + GB_SCF(); + cycles_done += 4; + goto out; + + case 0x3F: /* CCF */ //d + GB_CCF(); + cycles_done += 4; + goto out; + + case 0x41: /* LD B, C */ //d + case 0x42: /* LD B, D */ //d + case 0x43: /* LD B, E */ //d + case 0x44: /* LD B, H */ //d + case 0x45: /* LD B, L */ //d + case 0x47: /* LD B, A */ //d + case 0x48: /* LD C, B */ //d + case 0x4A: /* LD C, D */ //d + case 0x4B: /* LD C, E */ //d + case 0x4C: /* LD C, H */ //d + case 0x4D: /* LD C, L */ //d + case 0x4F: /* LD C, A */ //d + case 0x50: /* LD D, B */ //d + case 0x51: /* LD D, C */ //d + case 0x53: /* LD D, E */ //d + case 0x54: /* LD D, H */ //d + case 0x55: /* LD D, L */ //d + case 0x57: /* LD D, A */ //d + case 0x58: /* LD E, B */ //d + case 0x59: /* LD E, C */ //d + case 0x5A: /* LD E, D */ //d + case 0x5C: /* LD E, H */ //d + case 0x5D: /* LD E, L */ //d + case 0x5F: /* LD E, A */ //d + case 0x60: /* LD H, B */ //d + case 0x61: /* LD H, C */ //d + case 0x62: /* LD H, D */ //d + case 0x63: /* LD H, E */ //d + case 0x65: /* LD H, L */ //d + case 0x67: /* LD H, A */ //d + case 0x68: /* LD L, B */ //d + case 0x69: /* LD L, C */ //d + case 0x6A: /* LD L, D */ //d + case 0x6B: /* LD L, E */ //d + case 0x6C: /* LD L, H */ //d + case 0x6F: /* LD L, A */ //d + case 0x78: /* LD A, B */ //d + case 0x79: /* LD A, C */ //d + case 0x7A: /* LD A, D */ //d + case 0x7B: /* LD A, E */ //d + case 0x7C: /* LD A, H */ //d + case 0x7D: /* LD A, L */ //d + REG8(inst >> 3) = REG8(inst); + cycles_done += 4; + goto out; + + case 0x46: /* LD B, (HL) */ //d + case 0x4E: /* LD C, (HL) */ //d + case 0x56: /* LD D, (HL) */ //d + case 0x5E: /* LD E, (HL) */ //d + case 0x66: /* LD H, (HL) */ //d + case 0x6E: /* LD L, (HL) */ //d + case 0x7E: /* LD A, (HL) */ //d + REG8(inst >> 3) = cpu->mread(cpu->hl.w); + cycles_done += 8; + goto out; + + case 0x70: /* LD (HL), B */ //d + case 0x71: /* LD (HL), C */ //d + case 0x72: /* LD (HL), D */ //d + case 0x73: /* LD (HL), E */ //d + case 0x74: /* LD (HL), H */ //d + case 0x75: /* LD (HL), L */ //d + case 0x77: /* LD (HL), A */ //d + cpu->mwrite(cpu->hl.w, REG8(inst)); + cycles_done += 8; + goto out; + + case 0x76: /* HALT */ //d + --cpu->pc.w; + cpu->halt = 1; + cycles_done += 4; + goto out; + + case 0x80: /* ADD A, B */ //d + case 0x81: /* ADD A, C */ //d + case 0x82: /* ADD A, D */ //d + case 0x83: /* ADD A, E */ //d + case 0x84: /* ADD A, H */ //d + case 0x85: /* ADD A, L */ //d + case 0x87: /* ADD A, A */ //d + _value = REG8(inst); + cycles_done += 4; + +ADDOP: + GB_ADD(); + goto out; + + case 0x86: /* ADD A, (HL) */ //d + _value = cpu->mread(cpu->hl.w); + cycles_done += 8; + goto ADDOP; + + case 0xC6: /* ADD A, n */ //d + FETCH_ARG8(_value); + cycles_done += 8; + goto ADDOP; + + case 0x88: /* ADC A, B */ //d + case 0x89: /* ADC A, C */ //d + case 0x8A: /* ADC A, D */ //d + case 0x8B: /* ADC A, E */ //d + case 0x8C: /* ADC A, H */ //d + case 0x8D: /* ADC A, L */ //d + case 0x8F: /* ADC A, A */ //d + _value = REG8(inst); + cycles_done += 4; + +ADCOP: + GB_ADC(); + goto out; + + case 0x8E: /* ADC A, (HL) */ //d + _value = cpu->mread(cpu->hl.w); + cycles_done += 8; + goto ADCOP; + + case 0xCE: /* ADC A, n */ //d + FETCH_ARG8(_value); + cycles_done += 8; + goto ADCOP; + + case 0x90: /* SUB A, B */ //d + case 0x91: /* SUB A, C */ //d + case 0x92: /* SUB A, D */ //d + case 0x93: /* SUB A, E */ //d + case 0x94: /* SUB A, H */ //d + case 0x95: /* SUB A, L */ //d + case 0x97: /* SUB A, A */ //d + _value = REG8(inst); + cycles_done += 4; + +SUBOP: + GB_SUB(); + goto out; + + case 0x96: /* SUB A, (HL) */ //d + _value = cpu->mread(cpu->hl.w); + cycles_done += 8; + goto SUBOP; + + case 0xD6: /* SUB A, n */ //d + FETCH_ARG8(_value); + cycles_done += 8; + goto SUBOP; + + case 0x98: /* SBC A, B */ //d + case 0x99: /* SBC A, C */ //d + case 0x9A: /* SBC A, D */ //d + case 0x9B: /* SBC A, E */ //d + case 0x9C: /* SBC A, H */ //d + case 0x9D: /* SBC A, L */ //d + case 0x9F: /* SBC A, A */ //d + _value = REG8(inst); + cycles_done += 4; + +SBCOP: + GB_SBC(); + goto out; + + case 0x9E: /* SBC A, (HL) */ //d + _value = cpu->mread(cpu->hl.w); + cycles_done += 8; + goto SBCOP; + + case 0xDE: /* SBC A, n */ //d + FETCH_ARG8(_value); + cycles_done += 8; + goto SBCOP; + + case 0xA0: /* AND A, B */ //d + case 0xA1: /* AND A, C */ //d + case 0xA2: /* AND A, D */ //d + case 0xA3: /* AND A, E */ //d + case 0xA4: /* AND A, H */ //d + case 0xA5: /* AND A, L */ //d + case 0xA7: /* AND A, A */ //d + _value = REG8(inst); + cycles_done += 4; + +ANDOP: + GB_AND(); + goto out; + + case 0xA6: /* AND A, (HL) */ //d + _value = cpu->mread(cpu->hl.w); + cycles_done += 8; + goto ANDOP; + + case 0xE6: /* AND A, n */ //d + FETCH_ARG8(_value); + cycles_done += 8; + goto ANDOP; + + case 0xA8: /* XOR A, B */ //d + case 0xA9: /* XOR A, C */ //d + case 0xAA: /* XOR A, D */ //d + case 0xAB: /* XOR A, E */ //d + case 0xAC: /* XOR A, H */ //d + case 0xAD: /* XOR A, L */ //d + case 0xAF: /* XOR A, A */ //d + _value = REG8(inst); + cycles_done += 4; + +XOROP: + GB_XOR(); + goto out; + + case 0xAE: /* XOR A, (HL) */ //d + _value = cpu->mread(cpu->hl.w); + cycles_done += 8; + goto XOROP; + + case 0xEE: /* XOR A, n */ //d + FETCH_ARG8(_value); + cycles_done += 8; + goto XOROP; + + case 0xB0: /* OR A, B */ //d + case 0xB1: /* OR A, C */ //d + case 0xB2: /* OR A, D */ //d + case 0xB3: /* OR A, E */ //d + case 0xB4: /* OR A, H */ //d + case 0xB5: /* OR A, L */ //d + case 0xB7: /* OR A, A */ //d + _value = REG8(inst); + cycles_done += 4; + +OROP: + GB_OR(); + goto out; + + case 0xB6: /* OR A, (HL) */ //d + _value = cpu->mread(cpu->hl.w); + cycles_done += 8; + goto OROP; + + case 0xF6: /* OR A, n */ //d + FETCH_ARG8(_value); + cycles_done += 8; + goto OROP; + + case 0xB8: /* CP A, B */ //d + case 0xB9: /* CP A, C */ //d + case 0xBA: /* CP A, D */ //d + case 0xBB: /* CP A, E */ //d + case 0xBC: /* CP A, H */ //d + case 0xBD: /* CP A, L */ //d + case 0xBF: /* CP A, A */ //d + _value = REG8(inst); + cycles_done += 4; + +CPOP: + GB_CP(); + goto out; + + case 0xBE: /* CP A, (HL) */ //d + _value = cpu->mread(cpu->hl.w); + cycles_done += 8; + goto CPOP; + + case 0xFE: /* CP A, n */ //d + FETCH_ARG8(_value); + cycles_done += 8; + goto CPOP; + + case 0xC0: /* RET NZ */ //d + if(!(cpu->af.b.l & 0x80)) { + cycles_done += 4; + goto RETOP; + } + + cycles_done += 8; + goto out; + + case 0xC8: /* RET Z */ //d + if(!(cpu->af.b.l & 0x80)) { + cycles_done += 8; + goto out; + } + + cycles_done += 4; + /* Fall through... */ + + case 0xC9: /* RET */ //d +RETOP: + cpu->pc.w = cpu->mread16(cpu->sp.w); + cpu->sp.w += 2; + cycles_done += 16; + goto out; + + case 0xD0: /* RET NC */ //d + if(!(cpu->af.b.l & 0x10)) { + cycles_done += 4; + goto RETOP; + } + + cycles_done += 8; + goto out; + + case 0xD8: /* RET C */ //d + if(cpu->af.b.l & 0x10) { + cycles_done += 4; + goto RETOP; + } + + cycles_done += 8; + goto out; + + case 0xC1: /* POP BC */ //d + case 0xD1: /* POP DE */ //d + case 0xE1: /* POP HL */ //d + REG16(inst >> 4) = cpu->mread16(cpu->sp.w); + cpu->sp.w += 2; + cycles_done += 12; + goto out; + + case 0xF1: /* POP AF */ //d + cpu->af.b.l = cpu->mread(cpu->sp.w++); + cpu->af.b.h = cpu->mread(cpu->sp.w++); + cycles_done += 12; + goto out; + + case 0xC2: /* JP NZ, ee */ //d + if(cpu->af.b.l & 0x80) + goto out_nocondjump; + + cycles_done += 4; + /* Fall through... */ + + case 0xC3: /* JP ee */ //d +JPOP: + FETCH_ARG16(_value); + cpu->pc.w = _value; + cycles_done += 16; + goto out; + + case 0xCA: /* JP Z, ee */ //d + if(cpu->af.b.l & 0x80) { + cycles_done += 4; + goto JPOP; + } + + goto out_nocondjump; + + case 0xD2: /* JP NC, ee */ //d + if(!(cpu->af.b.l & 0x10)) { + cycles_done += 4; + goto JPOP; + } + + goto out_nocondjump; + + case 0xDA: /* JP C, ee */ //d + if(cpu->af.b.l & 0x10) { + cycles_done += 4; + goto JPOP; + } + + goto out_nocondjump; + + case 0xC4: /* CALL NZ, ee */ //d + if(!(cpu->af.b.l & 0x80)) + goto CALLOP; + + goto out_nocondjump; + + case 0xCC: /* CALL Z, ee */ //d + if(!(cpu->af.b.l & 0x80)) + goto out_nocondjump; + + /* Fall through... */ + + case 0xCD: /* CALL ee */ //d +CALLOP: + FETCH_ARG16(_value); + cpu->sp.w -= 2; + cpu->mwrite16(cpu->sp.w, cpu->pc.w); + cpu->pc.w = _value; + cycles_done += 24; + goto out; + + case 0xD4: /* CALL NC, ee */ //d + if(!(cpu->af.b.l & 0x10)) + goto CALLOP; + + goto out_nocondjump; + + case 0xDC: /* CALL C, ee */ //d + if(cpu->af.b.l & 0x10) + goto CALLOP; + + goto out_nocondjump; + + case 0xC5: /* PUSH BC */ //d + case 0xD5: /* PUSH DE */ //d + case 0xE5: /* PUSH HL */ //d + cpu->sp.w -= 2; + cpu->mwrite16(cpu->sp.w, REG16(inst >> 4)); + cycles_done += 16; + goto out; + + case 0xF5: /* PUSH AF */ //d + cpu->mwrite(--cpu->sp.w, cpu->af.b.h); + cpu->mwrite(--cpu->sp.w, cpu->af.b.l); + cycles_done += 16; + goto out; + + case 0xC7: /* RST 0h */ //d + case 0xCF: /* RST 8h */ //d + case 0xD7: /* RST 10h */ //d + case 0xDF: /* RST 18h */ //d + case 0xE7: /* RST 20h */ //d + case 0xEF: /* RST 28h */ //d + case 0xF7: /* RST 30h */ //d + case 0xFF: /* RST 38h */ //d + cpu->sp.w -= 2; + cpu->mwrite16(cpu->sp.w, cpu->pc.w); + cpu->pc.w = inst & 0x38; + cycles_done += 16; + goto out; + + case 0xE9: /* JP (HL) */ //d + cpu->pc.w = cpu->hl.w; + cycles_done += 4; + goto out; + + case 0xF3: /* DI */ //d + cpu->iff1 = 0; + cycles_done += 4; + goto out; + + case 0xF9: /* LD SP, HL */ //d + cpu->sp.w = cpu->hl.w; + cycles_done += 8; + goto out; + + case 0xFB: /* EI */ //d + cpu->iff1 = cpu->ei = 1; + cycles_done += 4; + goto out; + + /* Weird instructions that don't match Z80. */ + case 0x08: /* LD (nn), SP */ //d + FETCH_ARG16(_value) + cpu->mwrite16(_value, cpu->sp.w); + cycles_done += 20; + goto out; + + case 0x10: /* STOP */ //d, sorta. + // XXXX + --cpu->pc.w; + cpu->halt = 1; + cycles_done += 4; + goto out; + + case 0x22: /* LD (HL+), A */ //d + cpu->mwrite(cpu->hl.w++, cpu->af.b.h); + cycles_done += 8; + goto out; + + case 0x2A: /* LD A, (HL+) */ //d + cpu->af.b.l = cpu->mread(cpu->hl.w++); + cycles_done += 8; + goto out; + + case 0x32: /* LD (HL-), A */ //d + cpu->mwrite(cpu->hl.w--, cpu->af.b.h); + cycles_done += 8; + goto out; + + case 0x3A: /* LD A, (HL-) */ //d + cpu->af.b.l = cpu->mread(cpu->hl.w--); + cycles_done += 8; + goto out; + + case 0xD9: /* RETI */ //d + cpu->pc.w = cpu->mread16(cpu->sp.w); + cpu->sp.w += 2; + cpu->iff1 = 1; + cycles_done += 16; + goto out; + + case 0xE0: /* LD (0xFF00 + n), A */ //d + FETCH_ARG8(_value); + cpu->mwrite(0xFF00 + _value, cpu->af.b.h); + cycles_done += 12; + goto out; + + case 0xE2: /* LD (0xFF00 + C), A */ //d + cpu->mwrite(0xFF00 + cpu->bc.b.l, cpu->af.b.h); + cycles_done += 8; + goto out; + + case 0xE8: /* ADD SP, n */ //d + FETCH_ARG8(_value); + _tmp = cpu->sp.b.l + ((int8)_value); + /* ... Why? ... */ + cpu->af.b.l = (((cpu->sp.b.l ^ _tmp ^ _value) & 0x10) << 1) | + ((_tmp >> 4) & 0x10); + cpu->sp.w += (int8)_value; + cycles_done += 16; + goto out; + + case 0xEA: /* LD (nn), A */ //d + FETCH_ARG16(_value); + cpu->mwrite(_value, cpu->af.b.h); + cycles_done += 16; + goto out; + + case 0xF0: /* LD A, (0xFF00 + n) */ //d + FETCH_ARG8(_value); + cpu->af.b.h = cpu->mread(0xFF00 + _value); + cycles_done += 12; + goto out; + + case 0xF2: /* LD A, (0xFF00 + C) */ //d + cpu->af.b.h = cpu->mread(0xFF00 + cpu->bc.b.l); + cycles_done += 8; + goto out; + + case 0xF8: /* LD HL, SP + nn */ //d + FETCH_ARG8(_value); + _tmp = cpu->sp.b.l + ((int8)_value); + /* ... Why? ... */ + cpu->af.b.l = (((cpu->sp.b.l ^ _tmp ^ _value) & 0x10) << 1) | + ((_tmp >> 4) & 0x10); + cpu->hl.w = cpu->sp.w + ((int8)_value); + cycles_done += 12; + goto out; + + case 0xFA: /* LD A, (nn) */ //d + FETCH_ARG16(_value); + cpu->af.b.h = cpu->mread(_value); + cycles_done += 16; + goto out; + + /* Illegal opcodes.... */ + case 0xD3: + case 0xDB: + case 0xDD: + case 0xE3: + case 0xE4: + case 0xEB: + case 0xEC: + case 0xED: + case 0xF4: + case 0xFC: + case 0xFD: + /* XXXX */ + goto out; + + case 0xCB: /* CB-prefix */ + goto execCB; +} + +execCB: +#include "CrabZ80gbopsCB.h" +/* We shouldn't get here. */ + +/* Conditional JP and CALL instructions that don't end up jumping end up + coming here instead. This falls through back to CrabZ80.c (essentially to the + same place that goto out would put us). */ +out_nocondjump: //d + cycles_done += 12; + cpu->pc.w += 2; + + /* Fall through... */ +} diff --git a/cpu/CrabZ80/CrabZ80gbopsCB.h b/cpu/CrabZ80/CrabZ80gbopsCB.h new file mode 100644 index 0000000..228bf2e --- /dev/null +++ b/cpu/CrabZ80/CrabZ80gbopsCB.h @@ -0,0 +1,420 @@ +/* + This file is part of CrabEmu. + + Copyright (C) 2005, 2006, 2007, 2008, 2016 Lawrence Sebald + + CrabEmu is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 + as published by the Free Software Foundation. + + CrabEmu is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CrabEmu; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef INSIDE_CRABZ80_GBEXECUTE +#error This file can only be compiled inside of CrabZ80.c. Do not try to include +#error this file in other files. +#endif + +++cpu->ir.b.l; +FETCH_ARG8(inst); + +switch(inst) { + case 0x00: /* RLC B */ //d + case 0x01: /* RLC C */ //d + case 0x02: /* RLC D */ //d + case 0x03: /* RLC E */ //d + case 0x04: /* RLC H */ //d + case 0x05: /* RLC L */ //d + case 0x07: /* RLC A */ //d + _value = REG8(inst) = (uint8)((REG8(inst) << 1) | (REG8(inst) >> 7)); + cpu->af.b.l = ((!_value) << 7) | ((_value & 0x01) << 4); + cycles_done += 8; + goto out; + + case 0x06: /* RLC (HL) */ //d + _value = cpu->mread(cpu->hl.w); + _value = (uint8)((_value << 1) | (_value >> 7)); + cpu->af.b.l = ((!_value) << 7) | ((_value & 0x01) << 4); + cpu->mwrite(cpu->hl.w, _value); + cycles_done += 16; + goto out; + + case 0x08: /* RRC B */ //d + case 0x09: /* RRC C */ //d + case 0x0A: /* RRC D */ //d + case 0x0B: /* RRC E */ //d + case 0x0C: /* RRC H */ //d + case 0x0D: /* RRC L */ //d + case 0x0F: /* RRC A */ //d + _value = (uint8)((REG8(inst) >> 1) | (REG8(inst) << 7)); + cpu->af.b.l = ((!_value) << 7) | ((REG8(inst) & 0x01) << 4); + REG8(inst) = _value; + cycles_done += 8; + goto out; + + case 0x0E: /* RRC (HL) */ //d + _tmp = cpu->mread(cpu->hl.w); + _value = (uint8)((_tmp >> 1) | (_tmp << 7)); + cpu->af.b.l = ((!_value) << 7) | ((_tmp & 0x01) << 4); + cpu->mwrite(cpu->hl.w, _value); + cycles_done += 16; + goto out; + + case 0x10: /* RL B */ //d + case 0x11: /* RL C */ //d + case 0x12: /* RL D */ //d + case 0x13: /* RL E */ //d + case 0x14: /* RL H */ //d + case 0x15: /* RL L */ //d + case 0x17: /* RL A */ //d + _value = (uint8)((REG8(inst) << 1) | ((cpu->af.b.l & 0x10) >> 4)); + cpu->af.b.l = ((!_value) << 7) | ((REG8(inst) & 0x80) >> 3); + REG8(inst) = _value; + cycles_done += 8; + goto out; + + case 0x16: /* RL (HL) */ //d + _tmp = cpu->mread(cpu->hl.w); + _value = (uint8)(_tmp << 1) | ((cpu->af.b.l & 0x10) >> 4); + cpu->af.b.l = ((!_value) << 7) | ((_tmp & 0x80) >> 3); + cpu->mwrite(cpu->hl.w, _value); + cycles_done += 16; + goto out; + + case 0x18: /* RR B */ //d + case 0x19: /* RR C */ //d + case 0x1A: /* RR D */ //d + case 0x1B: /* RR E */ //d + case 0x1C: /* RR H */ //d + case 0x1D: /* RR L */ //d + case 0x1F: /* RR A */ //d + _value = (uint8)((REG8(inst) >> 1) | ((cpu->af.b.l & 0x10) << 3)); + cpu->af.b.l = ((!_value) << 7) | ((REG8(inst) & 0x01) << 4); + REG8(inst) = _value; + cycles_done += 8; + goto out; + + case 0x1E: /* RR (HL) */ //d + _tmp = cpu->mread(cpu->hl.w); + _value = (uint8)(_tmp >> 1) | ((cpu->af.b.l & 0x10) << 3); + cpu->af.b.l = ((!_value) << 7) | ((_tmp & 0x01) << 4); + cpu->mwrite(cpu->hl.w, _value); + cycles_done += 16; + goto out; + + case 0x20: /* SLA B */ //d + case 0x21: /* SLA C */ //d + case 0x22: /* SLA D */ //d + case 0x23: /* SLA E */ //d + case 0x24: /* SLA H */ //d + case 0x25: /* SLA L */ //d + case 0x27: /* SLA A */ //d + _value = (uint8)(REG8(inst) << 1); + cpu->af.b.l = ((!_value) << 7) | ((REG8(inst) & 0x80) >> 3); + REG8(inst) = _value; + cycles_done += 8; + goto out; + + case 0x26: /* SLA (HL) */ //d + _tmp = cpu->mread(cpu->hl.w); + _value = (uint8)(_tmp << 1); + cpu->af.b.l = ((!_value) << 7) | ((_tmp & 0x80) >> 3); + cpu->mwrite(cpu->hl.w, _value); + cycles_done += 16; + goto out; + + case 0x28: /* SRA B */ //d + case 0x29: /* SRA C */ //d + case 0x2A: /* SRA D */ //d + case 0x2B: /* SRA E */ //d + case 0x2C: /* SRA H */ //d + case 0x2D: /* SRA L */ //d + case 0x2F: /* SRA A */ //d + _value = (uint8)((REG8(inst) >> 1) | (REG8(inst) & 0x80)); + cpu->af.b.l = ((!_value) << 7) | ((REG8(inst) & 0x01) << 4); + REG8(inst) = _value; + cycles_done += 8; + goto out; + + case 0x2E: /* SRA (HL) */ //d + _tmp = cpu->mread(cpu->hl.w); + _value = (uint8)((_tmp >> 1) | (_tmp & 0x80)); + cpu->af.b.l = ((!_value) << 7) | ((_tmp & 0x01) << 4); + cpu->mwrite(cpu->hl.w, _value); + cycles_done += 16; + goto out; + + /* The SWAP instructions are unique to the LR35902. On the Z80, these are + the undocumented SLL instructions. */ + case 0x30: /* SWAP B */ //d + case 0x31: /* SWAP C */ //d + case 0x32: /* SWAP D */ //d + case 0x33: /* SWAP E */ //d + case 0x34: /* SWAP H */ //d + case 0x35: /* SWAP L */ //d + case 0x37: /* SWAP A */ //d + _value = REG8(inst); + /* Doesn't matter if we swap yet, because if it is zero after swapping, + it was zero before too (and that's the only bit that matters). */ + cpu->af.b.l = (!_value) << 7; + REG8(inst) = (_value >> 4) | (_value << 4); + cycles_done += 8; + goto out; + + case 0x36: /* SWAP (HL) */ //d + _value = cpu->mread(cpu->hl.w); + /* Doesn't matter if we swap yet, because if it is zero after swapping, + it was zero before too (and that's the only bit that matters). */ + cpu->af.b.l = (!_value) << 7; + cpu->mwrite(cpu->hl.w, (_value >> 4) | (_value << 4)); + cycles_done += 16; + goto out; + + case 0x38: /* SRL B */ //d + case 0x39: /* SRL C */ //d + case 0x3A: /* SRL D */ //d + case 0x3B: /* SRL E */ //d + case 0x3C: /* SRL H */ //d + case 0x3D: /* SRL L */ //d + case 0x3F: /* SRL A */ //d + _value = (uint8)(REG8(inst) >> 1); + cpu->af.b.l = ((!_value) << 7) | ((REG8(inst) & 0x01) << 4); + REG8(inst) = _value; + cycles_done += 8; + goto out; + + case 0x3E: /* SRL (HL) */ //d + _tmp = cpu->mread(cpu->hl.w); + _value = (uint8)(_tmp >> 1); + cpu->af.b.l = ((!_value) << 7) | ((_tmp & 0x01) << 4); + cpu->mwrite(cpu->hl.w, _value); + cycles_done += 16; + goto out; + + case 0x40: /* BIT 0, B */ //d + case 0x41: /* BIT 0, C */ //d + case 0x42: /* BIT 0, D */ //d + case 0x43: /* BIT 0, E */ //d + case 0x44: /* BIT 0, H */ //d + case 0x45: /* BIT 0, L */ //d + case 0x47: /* BIT 0, A */ //d + case 0x48: /* BIT 1, B */ //d + case 0x49: /* BIT 1, C */ //d + case 0x4A: /* BIT 1, D */ //d + case 0x4B: /* BIT 1, E */ //d + case 0x4C: /* BIT 1, H */ //d + case 0x4D: /* BIT 1, L */ //d + case 0x4F: /* BIT 1, A */ //d + case 0x50: /* BIT 2, B */ //d + case 0x51: /* BIT 2, C */ //d + case 0x52: /* BIT 2, D */ //d + case 0x53: /* BIT 2, E */ //d + case 0x54: /* BIT 2, H */ //d + case 0x55: /* BIT 2, L */ //d + case 0x57: /* BIT 2, A */ //d + case 0x58: /* BIT 3, B */ //d + case 0x59: /* BIT 3, C */ //d + case 0x5A: /* BIT 3, D */ //d + case 0x5B: /* BIT 3, E */ //d + case 0x5C: /* BIT 3, H */ //d + case 0x5D: /* BIT 3, L */ //d + case 0x5F: /* BIT 3, A */ //d + case 0x60: /* BIT 4, B */ //d + case 0x61: /* BIT 4, C */ //d + case 0x62: /* BIT 4, D */ //d + case 0x63: /* BIT 4, E */ //d + case 0x64: /* BIT 4, H */ //d + case 0x65: /* BIT 4, L */ //d + case 0x67: /* BIT 4, A */ //d + case 0x68: /* BIT 5, B */ //d + case 0x69: /* BIT 5, C */ //d + case 0x6A: /* BIT 5, D */ //d + case 0x6B: /* BIT 5, E */ //d + case 0x6C: /* BIT 5, H */ //d + case 0x6D: /* BIT 5, L */ //d + case 0x6F: /* BIT 5, A */ //d + case 0x70: /* BIT 6, B */ //d + case 0x71: /* BIT 6, C */ //d + case 0x72: /* BIT 6, D */ //d + case 0x73: /* BIT 6, E */ //d + case 0x74: /* BIT 6, H */ //d + case 0x75: /* BIT 6, L */ //d + case 0x77: /* BIT 6, A */ //d + case 0x78: /* BIT 7, B */ //d + case 0x79: /* BIT 7, C */ //d + case 0x7A: /* BIT 7, D */ //d + case 0x7B: /* BIT 7, E */ //d + case 0x7C: /* BIT 7, H */ //d + case 0x7D: /* BIT 7, L */ //d + case 0x7F: /* BIT 7, A */ //d + _tmp = REG8(inst) & (1 << ((inst >> 3) & 0x07)); + cpu->af.b.l = ((!_tmp) << 7) | 0x20 | (cpu->af.b.l & 0x10); + cycles_done += 8; + goto out; + + case 0x46: /* BIT 0, (HL) */ //d + case 0x4E: /* BIT 1, (HL) */ //d + case 0x56: /* BIT 2, (HL) */ //d + case 0x5E: /* BIT 3, (HL) */ //d + case 0x66: /* BIT 4, (HL) */ //d + case 0x6E: /* BIT 5, (HL) */ //d + case 0x76: /* BIT 6, (HL) */ //d + case 0x7E: /* BIT 7, (HL) */ //d + _tmp = cpu->mread(cpu->hl.w) & (1 << ((inst >> 3) & 0x07)); + cpu->af.b.l = ((!_tmp) << 7) | 0x20 | (cpu->af.b.l & 0x10); + cycles_done += 16; + goto out; + + case 0x80: /* RES 0, B */ //d + case 0x81: /* RES 0, C */ //d + case 0x82: /* RES 0, D */ //d + case 0x83: /* RES 0, E */ //d + case 0x84: /* RES 0, H */ //d + case 0x85: /* RES 0, L */ //d + case 0x87: /* RES 0, A */ //d + case 0x88: /* RES 1, B */ //d + case 0x89: /* RES 1, C */ //d + case 0x8A: /* RES 1, D */ //d + case 0x8B: /* RES 1, E */ //d + case 0x8C: /* RES 1, H */ //d + case 0x8D: /* RES 1, L */ //d + case 0x8F: /* RES 1, A */ //d + case 0x90: /* RES 2, B */ //d + case 0x91: /* RES 2, C */ //d + case 0x92: /* RES 2, D */ //d + case 0x93: /* RES 2, E */ //d + case 0x94: /* RES 2, H */ //d + case 0x95: /* RES 2, L */ //d + case 0x97: /* RES 2, A */ //d + case 0x98: /* RES 3, B */ //d + case 0x99: /* RES 3, C */ //d + case 0x9A: /* RES 3, D */ //d + case 0x9B: /* RES 3, E */ //d + case 0x9C: /* RES 3, H */ //d + case 0x9D: /* RES 3, L */ //d + case 0x9F: /* RES 3, A */ //d + case 0xA0: /* RES 4, B */ //d + case 0xA1: /* RES 4, C */ //d + case 0xA2: /* RES 4, D */ //d + case 0xA3: /* RES 4, E */ //d + case 0xA4: /* RES 4, H */ //d + case 0xA5: /* RES 4, L */ //d + case 0xA7: /* RES 4, A */ //d + case 0xA8: /* RES 5, B */ //d + case 0xA9: /* RES 5, C */ //d + case 0xAA: /* RES 5, D */ //d + case 0xAB: /* RES 5, E */ //d + case 0xAC: /* RES 5, H */ //d + case 0xAD: /* RES 5, L */ //d + case 0xAF: /* RES 5, A */ //d + case 0xB0: /* RES 6, B */ //d + case 0xB1: /* RES 6, C */ //d + case 0xB2: /* RES 6, D */ //d + case 0xB3: /* RES 6, E */ //d + case 0xB4: /* RES 6, H */ //d + case 0xB5: /* RES 6, L */ //d + case 0xB7: /* RES 6, A */ //d + case 0xB8: /* RES 7, B */ //d + case 0xB9: /* RES 7, C */ //d + case 0xBA: /* RES 7, D */ //d + case 0xBB: /* RES 7, E */ //d + case 0xBC: /* RES 7, H */ //d + case 0xBD: /* RES 7, L */ //d + case 0xBF: /* RES 7, A */ //d + REG8(inst) &= ~(1 << ((inst >> 3) & 0x07)); + cycles_done += 8; + goto out; + + case 0x86: /* RES 0, (HL) */ //d + case 0x8E: /* RES 1, (HL) */ //d + case 0x96: /* RES 2, (HL) */ //d + case 0x9E: /* RES 3, (HL) */ //d + case 0xA6: /* RES 4, (HL) */ //d + case 0xAE: /* RES 5, (HL) */ //d + case 0xB6: /* RES 6, (HL) */ //d + case 0xBE: /* RES 7, (HL) */ //d + _value = cpu->mread(cpu->hl.w); + cpu->mwrite(cpu->hl.w, _value & ~(1 << ((inst >> 3) & 0x07))); + cycles_done += 16; + goto out; + + case 0xC0: /* SET 0, B */ //d + case 0xC1: /* SET 0, C */ //d + case 0xC2: /* SET 0, D */ //d + case 0xC3: /* SET 0, E */ //d + case 0xC4: /* SET 0, H */ //d + case 0xC5: /* SET 0, L */ //d + case 0xC7: /* SET 0, A */ //d + case 0xC8: /* SET 1, B */ //d + case 0xC9: /* SET 1, C */ //d + case 0xCA: /* SET 1, D */ //d + case 0xCB: /* SET 1, E */ //d + case 0xCC: /* SET 1, H */ //d + case 0xCD: /* SET 1, L */ //d + case 0xCF: /* SET 1, A */ //d + case 0xD0: /* SET 2, B */ //d + case 0xD1: /* SET 2, C */ //d + case 0xD2: /* SET 2, D */ //d + case 0xD3: /* SET 2, E */ //d + case 0xD4: /* SET 2, H */ //d + case 0xD5: /* SET 2, L */ //d + case 0xD7: /* SET 2, A */ //d + case 0xD8: /* SET 3, B */ //d + case 0xD9: /* SET 3, C */ //d + case 0xDA: /* SET 3, D */ //d + case 0xDB: /* SET 3, E */ //d + case 0xDC: /* SET 3, H */ //d + case 0xDD: /* SET 3, L */ //d + case 0xDF: /* SET 3, A */ //d + case 0xE0: /* SET 4, B */ //d + case 0xE1: /* SET 4, C */ //d + case 0xE2: /* SET 4, D */ //d + case 0xE3: /* SET 4, E */ //d + case 0xE4: /* SET 4, H */ //d + case 0xE5: /* SET 4, L */ //d + case 0xE7: /* SET 4, A */ //d + case 0xE8: /* SET 5, B */ //d + case 0xE9: /* SET 5, C */ //d + case 0xEA: /* SET 5, D */ //d + case 0xEB: /* SET 5, E */ //d + case 0xEC: /* SET 5, H */ //d + case 0xED: /* SET 5, L */ //d + case 0xEF: /* SET 5, A */ //d + case 0xF0: /* SET 6, B */ //d + case 0xF1: /* SET 6, C */ //d + case 0xF2: /* SET 6, D */ //d + case 0xF3: /* SET 6, E */ //d + case 0xF4: /* SET 6, H */ //d + case 0xF5: /* SET 6, L */ //d + case 0xF7: /* SET 6, A */ //d + case 0xF8: /* SET 7, B */ //d + case 0xF9: /* SET 7, C */ //d + case 0xFA: /* SET 7, D */ //d + case 0xFB: /* SET 7, E */ //d + case 0xFC: /* SET 7, H */ //d + case 0xFD: /* SET 7, L */ //d + case 0xFF: /* SET 7, A */ //d + REG8(inst) |= (1 << ((inst >> 3) & 0x07)); + cycles_done += 8; + goto out; + + case 0xC6: /* SET 0, (HL) */ //d + case 0xCE: /* SET 1, (HL) */ //d + case 0xD6: /* SET 2, (HL) */ //d + case 0xDE: /* SET 3, (HL) */ //d + case 0xE6: /* SET 4, (HL) */ //d + case 0xEE: /* SET 5, (HL) */ //d + case 0xF6: /* SET 6, (HL) */ //d + case 0xFE: /* SET 7, (HL) */ //d + _value = cpu->mread(cpu->hl.w); + cpu->mwrite(cpu->hl.w, _value | (1 << ((inst >> 3) & 0x07))); + cycles_done += 16; + goto out; +}