diff options
Diffstat (limited to 'gearboy/src/opcodes.cpp')
| -rw-r--r-- | gearboy/src/opcodes.cpp | 1865 |
1 files changed, 1865 insertions, 0 deletions
diff --git a/gearboy/src/opcodes.cpp b/gearboy/src/opcodes.cpp new file mode 100644 index 00000000..1ed04d42 --- /dev/null +++ b/gearboy/src/opcodes.cpp @@ -0,0 +1,1865 @@ +/* + * Gearboy - Nintendo Game Boy Emulator + * Copyright (C) 2012 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program 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 this program. If not, see http://www.gnu.org/licenses/ + * + */ + +#include "Processor.h" +#include "Memory.h" +#include "opcode_timing.h" + +void Processor::OPCode0x00() +{ + // NOP +} + +void Processor::OPCode0x01() +{ + // LD BC,nn + OPCodes_LD(BC.GetLowRegister(), PC.GetValue()); + PC.Increment(); + OPCodes_LD(BC.GetHighRegister(), PC.GetValue()); + PC.Increment(); +} + +void Processor::OPCode0x02() +{ + // LD (BC),A + OPCodes_LD(BC.GetValue(), AF.GetHigh()); +} + +void Processor::OPCode0x03() +{ + // INC BC + BC.Increment(); +} + +void Processor::OPCode0x04() +{ + // INC B + OPCodes_INC(BC.GetHighRegister()); +} + +void Processor::OPCode0x05() +{ + // DEC B + OPCodes_DEC(BC.GetHighRegister()); +} + +void Processor::OPCode0x06() +{ + // LD B,n + OPCodes_LD(BC.GetHighRegister(), PC.GetValue()); + PC.Increment(); +} + +void Processor::OPCode0x07() +{ + // RLCA + OPCodes_RLC(AF.GetHighRegister(), true); +} + +void Processor::OPCode0x08() +{ + // LD (nn),SP + u8 l = m_pMemory->Read(PC.GetValue()); + PC.Increment(); + u8 h = m_pMemory->Read(PC.GetValue()); + PC.Increment(); + u16 address = ((h << 8) + l); + m_pMemory->Write(address, SP.GetLow()); + m_pMemory->Write(address + 1, SP.GetHigh()); +} + +void Processor::OPCode0x09() +{ + // ADD HL,BC + OPCodes_ADD_HL(BC.GetValue()); +} + +void Processor::OPCode0x0A() +{ + // LD A,(BC) + OPCodes_LD(AF.GetHighRegister(), BC.GetValue()); +} + +void Processor::OPCode0x0B() +{ + // DEC BC + BC.Decrement(); +} + +void Processor::OPCode0x0C() +{ + // INC C + OPCodes_INC(BC.GetLowRegister()); +} + +void Processor::OPCode0x0D() +{ + // DEC C + OPCodes_DEC(BC.GetLowRegister()); +} + +void Processor::OPCode0x0E() +{ + // LD C,n + OPCodes_LD(BC.GetLowRegister(), PC.GetValue()); + PC.Increment(); +} + +void Processor::OPCode0x0F() +{ + // RRCA + OPCodes_RRC(AF.GetHighRegister(), true); +} + +void Processor::OPCode0x10() +{ + // STOP + PC.Increment(); + + if (m_bCGB) + { + u8 current_key1 = m_pMemory->Retrieve(0xFF4D); + + if (IsSetBit(current_key1, 0)) + { + m_bCGBSpeed = !m_bCGBSpeed; + + if (m_bCGBSpeed) + { + m_iSpeedMultiplier = 1; + m_pMemory->Load(0xFF4D, 0x80); + } + else + { + m_iSpeedMultiplier = 0; + m_pMemory->Load(0xFF4D, 0x00); + } + } + } +} + +void Processor::OPCode0x11() +{ + // LD DE,nn + OPCodes_LD(DE.GetLowRegister(), PC.GetValue()); + PC.Increment(); + OPCodes_LD(DE.GetHighRegister(), PC.GetValue()); + PC.Increment(); +} + +void Processor::OPCode0x12() +{ + // LD (DE),A + OPCodes_LD(DE.GetValue(), AF.GetHigh()); +} + +void Processor::OPCode0x13() +{ + // INC DE + DE.Increment(); +} + +void Processor::OPCode0x14() +{ + // INC D + OPCodes_INC(DE.GetHighRegister()); +} + +void Processor::OPCode0x15() +{ + // DEC D + OPCodes_DEC(DE.GetHighRegister()); +} + +void Processor::OPCode0x16() +{ + // LD D,n + OPCodes_LD(DE.GetHighRegister(), PC.GetValue()); + PC.Increment(); +} + +void Processor::OPCode0x17() +{ + // RLA + OPCodes_RL(AF.GetHighRegister(), true); +} + +void Processor::OPCode0x18() +{ + // JR n + PC.SetValue(PC.GetValue() + 1 + (static_cast<s8> (m_pMemory->Read(PC.GetValue())))); +} + +void Processor::OPCode0x19() +{ + // ADD HL,DE + OPCodes_ADD_HL(DE.GetValue()); +} + +void Processor::OPCode0x1A() +{ + // LD A,(DE) + OPCodes_LD(AF.GetHighRegister(), DE.GetValue()); +} + +void Processor::OPCode0x1B() +{ + // DEC DE + DE.Decrement(); +} + +void Processor::OPCode0x1C() +{ + // INC E + OPCodes_INC(DE.GetLowRegister()); +} + +void Processor::OPCode0x1D() +{ + // DEC E + OPCodes_DEC(DE.GetLowRegister()); +} + +void Processor::OPCode0x1E() +{ + // LD E,n + OPCodes_LD(DE.GetLowRegister(), PC.GetValue()); + PC.Increment(); +} + +void Processor::OPCode0x1F() +{ + // RRA + OPCodes_RR(AF.GetHighRegister(), true); +} + +void Processor::OPCode0x20() +{ + // JR NZ,n + if (!IsSetFlag(FLAG_ZERO)) + { + PC.SetValue(PC.GetValue() + 1 + (static_cast<s8> (m_pMemory->Read(PC.GetValue())))); + m_bBranchTaken = true; + } + else + { + PC.Increment(); + } +} + +void Processor::OPCode0x21() +{ + // LD HL,nn + OPCodes_LD(HL.GetLowRegister(), PC.GetValue()); + PC.Increment(); + OPCodes_LD(HL.GetHighRegister(), PC.GetValue()); + PC.Increment(); +} + +void Processor::OPCode0x22() +{ + // LD (HLI),A + OPCodes_LD(HL.GetValue(), AF.GetHigh()); + HL.Increment(); +} + +void Processor::OPCode0x23() +{ + // INC HL + HL.Increment(); +} + +void Processor::OPCode0x24() +{ + // INC H + OPCodes_INC(HL.GetHighRegister()); +} + +void Processor::OPCode0x25() +{ + // DEC H + OPCodes_DEC(HL.GetHighRegister()); +} + +void Processor::OPCode0x26() +{ + // LD H,n + OPCodes_LD(HL.GetHighRegister(), PC.GetValue()); + PC.Increment(); +} + +void Processor::OPCode0x27() +{ + // DAA + int a = AF.GetHigh(); + + if (!IsSetFlag(FLAG_SUB)) + { + if (IsSetFlag(FLAG_HALF) || ((a & 0xF) > 9)) + a += 0x06; + + if (IsSetFlag(FLAG_CARRY) || (a > 0x9F)) + a += 0x60; + } + else + { + if (IsSetFlag(FLAG_HALF)) + a = (a - 6) & 0xFF; + + if (IsSetFlag(FLAG_CARRY)) + a -= 0x60; + } + + UntoggleFlag(FLAG_HALF); + UntoggleFlag(FLAG_ZERO); + + if ((a & 0x100) == 0x100) + ToggleFlag(FLAG_CARRY); + + a &= 0xFF; + + ToggleZeroFlagFromResult(a); + + AF.SetHigh(a); +} + +void Processor::OPCode0x28() +{ + // JR Z,n + if (IsSetFlag(FLAG_ZERO)) + { + PC.SetValue(PC.GetValue() + 1 + (static_cast<s8> (m_pMemory->Read(PC.GetValue())))); + m_bBranchTaken = true; + } + else + { + PC.Increment(); + } +} + +void Processor::OPCode0x29() +{ + // ADD HL,HL + OPCodes_ADD_HL(HL.GetValue()); +} + +void Processor::OPCode0x2A() +{ + // LD A,(HLI) + OPCodes_LD(AF.GetHighRegister(), HL.GetValue()); + HL.Increment(); +} + +void Processor::OPCode0x2B() +{ + // DEC HL + HL.Decrement(); +} + +void Processor::OPCode0x2C() +{ + // INC L + OPCodes_INC(HL.GetLowRegister()); +} + +void Processor::OPCode0x2D() +{ + // DEC L + OPCodes_DEC(HL.GetLowRegister()); +} + +void Processor::OPCode0x2E() +{ + // LD L,n + OPCodes_LD(HL.GetLowRegister(), PC.GetValue()); + PC.Increment(); + +} + +void Processor::OPCode0x2F() +{ + // CPL + AF.SetHigh(~AF.GetHigh()); + ToggleFlag(FLAG_HALF); + ToggleFlag(FLAG_SUB); +} + +void Processor::OPCode0x30() +{ + // JR NC,n + if (!IsSetFlag(FLAG_CARRY)) + { + PC.SetValue(PC.GetValue() + 1 + (static_cast<s8> (m_pMemory->Read(PC.GetValue())))); + m_bBranchTaken = true; + } + else + { + PC.Increment(); + } +} + +void Processor::OPCode0x31() +{ + // LD SP,nn + SP.SetLow(m_pMemory->Read(PC.GetValue())); + PC.Increment(); + SP.SetHigh(m_pMemory->Read(PC.GetValue())); + PC.Increment(); +} + +void Processor::OPCode0x32() +{ + // LD (HLD), A + OPCodes_LD(HL.GetValue(), AF.GetHigh()); + HL.Decrement(); +} + +void Processor::OPCode0x33() +{ + // INC SP + SP.Increment(); +} + +void Processor::OPCode0x34() +{ + // INC (HL) + OPCodes_INC_HL(); +} + +void Processor::OPCode0x35() +{ + // DEC (HL) + OPCodes_DEC_HL(); +} + +void Processor::OPCode0x36() +{ + // LD (HL),n + m_pMemory->Write(HL.GetValue(), m_pMemory->Read(PC.GetValue())); + PC.Increment(); +} + +void Processor::OPCode0x37() +{ + // SCF + ToggleFlag(FLAG_CARRY); + UntoggleFlag(FLAG_HALF); + UntoggleFlag(FLAG_SUB); +} + +void Processor::OPCode0x38() +{ + // JR C,n + if (IsSetFlag(FLAG_CARRY)) + { + PC.SetValue(PC.GetValue() + 1 + (static_cast<s8> (m_pMemory->Read(PC.GetValue())))); + m_bBranchTaken = true; + } + else + { + PC.Increment(); + } +} + +void Processor::OPCode0x39() +{ + // ADD HL,SP + OPCodes_ADD_HL(SP.GetValue()); +} + +void Processor::OPCode0x3A() +{ + // LD A,(HLD) + OPCodes_LD(AF.GetHighRegister(), HL.GetValue()); + HL.Decrement(); +} + +void Processor::OPCode0x3B() +{ + // DEC SP + SP.Decrement(); +} + +void Processor::OPCode0x3C() +{ + // INC A + OPCodes_INC(AF.GetHighRegister()); +} + +void Processor::OPCode0x3D() +{ + // DEC A + OPCodes_DEC(AF.GetHighRegister()); + +} + +void Processor::OPCode0x3E() +{ + // LD A,n + OPCodes_LD(AF.GetHighRegister(), PC.GetValue()); + PC.Increment(); +} + +void Processor::OPCode0x3F() +{ + // CCF + FlipFlag(FLAG_CARRY); + UntoggleFlag(FLAG_HALF); + UntoggleFlag(FLAG_SUB); +} + +void Processor::OPCode0x40() +{ + // LD B,B + OPCodes_LD(BC.GetHighRegister(), BC.GetHigh()); +} + +void Processor::OPCode0x41() +{ + // LD B,C + OPCodes_LD(BC.GetHighRegister(), BC.GetLow()); +} + +void Processor::OPCode0x42() +{ + // LD B,D + OPCodes_LD(BC.GetHighRegister(), DE.GetHigh()); +} + +void Processor::OPCode0x43() +{ + // LD B,E + OPCodes_LD(BC.GetHighRegister(), DE.GetLow()); +} + +void Processor::OPCode0x44() +{ + // LD B,H + OPCodes_LD(BC.GetHighRegister(), HL.GetHigh()); +} + +void Processor::OPCode0x45() +{ + // LD B,L + OPCodes_LD(BC.GetHighRegister(), HL.GetLow()); +} + +void Processor::OPCode0x46() +{ + // LD B,(HL) + OPCodes_LD(BC.GetHighRegister(), HL.GetValue()); +} + +void Processor::OPCode0x47() +{ + // LD B,A + OPCodes_LD(BC.GetHighRegister(), AF.GetHigh()); +} + +void Processor::OPCode0x48() +{ + // LD C,B + OPCodes_LD(BC.GetLowRegister(), BC.GetHigh()); +} + +void Processor::OPCode0x49() +{ + // LD C,C + OPCodes_LD(BC.GetLowRegister(), BC.GetLow()); +} + +void Processor::OPCode0x4A() +{ + // LD C,D + OPCodes_LD(BC.GetLowRegister(), DE.GetHigh()); +} + +void Processor::OPCode0x4B() +{ + // LD C,E + OPCodes_LD(BC.GetLowRegister(), DE.GetLow()); +} + +void Processor::OPCode0x4C() +{ + // LD C,H + OPCodes_LD(BC.GetLowRegister(), HL.GetHigh()); +} + +void Processor::OPCode0x4D() +{ + // LD C,L + OPCodes_LD(BC.GetLowRegister(), HL.GetLow()); +} + +void Processor::OPCode0x4E() +{ + // LD C,(HL) + OPCodes_LD(BC.GetLowRegister(), HL.GetValue()); +} + +void Processor::OPCode0x4F() +{ + // LD C,A + OPCodes_LD(BC.GetLowRegister(), AF.GetHigh()); +} + +void Processor::OPCode0x50() +{ + // LD D,B + OPCodes_LD(DE.GetHighRegister(), BC.GetHigh()); +} + +void Processor::OPCode0x51() +{ + // LD D,C + OPCodes_LD(DE.GetHighRegister(), BC.GetLow()); +} + +void Processor::OPCode0x52() +{ + // LD D,D + OPCodes_LD(DE.GetHighRegister(), DE.GetHigh()); +} + +void Processor::OPCode0x53() +{ + // LD D,E + OPCodes_LD(DE.GetHighRegister(), DE.GetLow()); +} + +void Processor::OPCode0x54() +{ + // LD D,H + OPCodes_LD(DE.GetHighRegister(), HL.GetHigh()); +} + +void Processor::OPCode0x55() +{ + // LD D,L + OPCodes_LD(DE.GetHighRegister(), HL.GetLow()); +} + +void Processor::OPCode0x56() +{ + // LD D,(HL) + OPCodes_LD(DE.GetHighRegister(), HL.GetValue()); +} + +void Processor::OPCode0x57() +{ + // LD D,A + OPCodes_LD(DE.GetHighRegister(), AF.GetHigh()); +} + +void Processor::OPCode0x58() +{ + // LD E,B + OPCodes_LD(DE.GetLowRegister(), BC.GetHigh()); +} + +void Processor::OPCode0x59() +{ + // LD E,C + OPCodes_LD(DE.GetLowRegister(), BC.GetLow()); +} + +void Processor::OPCode0x5A() +{ + // LD E,D + OPCodes_LD(DE.GetLowRegister(), DE.GetHigh()); +} + +void Processor::OPCode0x5B() +{ + // LD E,E + OPCodes_LD(DE.GetLowRegister(), DE.GetLow()); +} + +void Processor::OPCode0x5C() +{ + // LD E,H + OPCodes_LD(DE.GetLowRegister(), HL.GetHigh()); +} + +void Processor::OPCode0x5D() +{ + // LD E,L + OPCodes_LD(DE.GetLowRegister(), HL.GetLow()); +} + +void Processor::OPCode0x5E() +{ + // LD E,(HL) + OPCodes_LD(DE.GetLowRegister(), HL.GetValue()); +} + +void Processor::OPCode0x5F() +{ + // LD E,A + OPCodes_LD(DE.GetLowRegister(), AF.GetHigh()); +} + +void Processor::OPCode0x60() +{ + // LD H,B + OPCodes_LD(HL.GetHighRegister(), BC.GetHigh()); +} + +void Processor::OPCode0x61() +{ + // LD H,C + OPCodes_LD(HL.GetHighRegister(), BC.GetLow()); +} + +void Processor::OPCode0x62() +{ + // LD H,D + OPCodes_LD(HL.GetHighRegister(), DE.GetHigh()); +} + +void Processor::OPCode0x63() +{ + // LD H,E + OPCodes_LD(HL.GetHighRegister(), DE.GetLow()); +} + +void Processor::OPCode0x64() +{ + // LD H,H + OPCodes_LD(HL.GetHighRegister(), HL.GetHigh()); +} + +void Processor::OPCode0x65() +{ + // LD H,L + OPCodes_LD(HL.GetHighRegister(), HL.GetLow()); +} + +void Processor::OPCode0x66() +{ + // LD H,(HL) + OPCodes_LD(HL.GetHighRegister(), HL.GetValue()); +} + +void Processor::OPCode0x67() +{ + // LD H,A + OPCodes_LD(HL.GetHighRegister(), AF.GetHigh()); +} + +void Processor::OPCode0x68() +{ + // LD L,B + OPCodes_LD(HL.GetLowRegister(), BC.GetHigh()); +} + +void Processor::OPCode0x69() +{ + // LD L,C + OPCodes_LD(HL.GetLowRegister(), BC.GetLow()); +} + +void Processor::OPCode0x6A() +{ + // LD L,D + OPCodes_LD(HL.GetLowRegister(), DE.GetHigh()); +} + +void Processor::OPCode0x6B() +{ + // LD L,E + OPCodes_LD(HL.GetLowRegister(), DE.GetLow()); +} + +void Processor::OPCode0x6C() +{ + // LD L,H + OPCodes_LD(HL.GetLowRegister(), HL.GetHigh()); +} + +void Processor::OPCode0x6D() +{ + // LD L,L + OPCodes_LD(HL.GetLowRegister(), HL.GetLow()); +} + +void Processor::OPCode0x6E() +{ + // LD L,(HL) + OPCodes_LD(HL.GetLowRegister(), HL.GetValue()); +} + +void Processor::OPCode0x6F() +{ + // LD L,A + OPCodes_LD(HL.GetLowRegister(), AF.GetHigh()); +} + +void Processor::OPCode0x70() +{ + // LD (HL),B + OPCodes_LD(HL.GetValue(), BC.GetHigh()); +} + +void Processor::OPCode0x71() +{ + // LD (HL),C + OPCodes_LD(HL.GetValue(), BC.GetLow()); +} + +void Processor::OPCode0x72() +{ + // LD (HL),D + OPCodes_LD(HL.GetValue(), DE.GetHigh()); +} + +void Processor::OPCode0x73() +{ + // LD (HL),E + OPCodes_LD(HL.GetValue(), DE.GetLow()); +} + +void Processor::OPCode0x74() +{ + // LD (HL),H + OPCodes_LD(HL.GetValue(), HL.GetHigh()); +} + +void Processor::OPCode0x75() +{ + // LD (HL),L + OPCodes_LD(HL.GetValue(), HL.GetLow()); +} + +void Processor::OPCode0x76() +{ + // HALT + if (m_iIMECycles > 0) + { + // If EI is pending interrupts are triggered before Halt + m_iIMECycles = 0; + m_bIME = true; + PC.Decrement(); + } + else + { + u8 if_reg = m_pMemory->Retrieve(0xFF0F); + u8 ie_reg = m_pMemory->Retrieve(0xFFFF); + + m_bHalt = true; + + if (!m_bCGB && !m_bIME && (if_reg & ie_reg & 0x1F)) + { + m_bSkipPCBug = true; + } + } +} + +void Processor::OPCode0x77() +{ + // LD (HL),A + OPCodes_LD(HL.GetValue(), AF.GetHigh()); +} + +void Processor::OPCode0x78() +{ + // LD A,B + OPCodes_LD(AF.GetHighRegister(), BC.GetHigh()); +} + +void Processor::OPCode0x79() +{ + // LD A,C + OPCodes_LD(AF.GetHighRegister(), BC.GetLow()); +} + +void Processor::OPCode0x7A() +{ + // LD A,D + OPCodes_LD(AF.GetHighRegister(), DE.GetHigh()); +} + +void Processor::OPCode0x7B() +{ + // LD A,E + OPCodes_LD(AF.GetHighRegister(), DE.GetLow()); + +} + +void Processor::OPCode0x7C() +{ + // LD A,H + OPCodes_LD(AF.GetHighRegister(), HL.GetHigh()); +} + +void Processor::OPCode0x7D() +{ + // LD A,L + OPCodes_LD(AF.GetHighRegister(), HL.GetLow()); +} + +void Processor::OPCode0x7E() +{ + // LD A,(HL) + OPCodes_LD(AF.GetHighRegister(), HL.GetValue()); +} + +void Processor::OPCode0x7F() +{ + // LD A,A + OPCodes_LD(AF.GetHighRegister(), AF.GetHigh()); +} + +void Processor::OPCode0x80() +{ + // ADD A,B + OPCodes_ADD(BC.GetHigh()); +} + +void Processor::OPCode0x81() +{ + // ADD A,C + OPCodes_ADD(BC.GetLow()); +} + +void Processor::OPCode0x82() +{ + // ADD A,D + OPCodes_ADD(DE.GetHigh()); +} + +void Processor::OPCode0x83() +{ + // ADD A,E + OPCodes_ADD(DE.GetLow()); +} + +void Processor::OPCode0x84() +{ + // ADD A,H + OPCodes_ADD(HL.GetHigh()); +} + +void Processor::OPCode0x85() +{ + // ADD A,L + OPCodes_ADD(HL.GetLow()); +} + +void Processor::OPCode0x86() +{ + // ADD A,(HL) + OPCodes_ADD(m_pMemory->Read(HL.GetValue())); +} + +void Processor::OPCode0x87() +{ + // ADD A,A + OPCodes_ADD(AF.GetHigh()); +} + +void Processor::OPCode0x88() +{ + // ADC A,B + OPCodes_ADC(BC.GetHigh()); +} + +void Processor::OPCode0x89() +{ + // ADC A,C + OPCodes_ADC(BC.GetLow()); +} + +void Processor::OPCode0x8A() +{ + // ADC A,D + OPCodes_ADC(DE.GetHigh()); +} + +void Processor::OPCode0x8B() +{ + // ADC A,E + OPCodes_ADC(DE.GetLow()); +} + +void Processor::OPCode0x8C() +{ + // ADC A,H + OPCodes_ADC(HL.GetHigh()); +} + +void Processor::OPCode0x8D() +{ + // ADC A,L + OPCodes_ADC(HL.GetLow()); +} + +void Processor::OPCode0x8E() +{ + // ADC A,(HL) + OPCodes_ADC(m_pMemory->Read(HL.GetValue())); +} + +void Processor::OPCode0x8F() +{ + // ADC A,A + OPCodes_ADC(AF.GetHigh()); +} + +void Processor::OPCode0x90() +{ + // SUB B + OPCodes_SUB(BC.GetHigh()); +} + +void Processor::OPCode0x91() +{ + // SUB C + OPCodes_SUB(BC.GetLow()); +} + +void Processor::OPCode0x92() +{ + // SUB D + OPCodes_SUB(DE.GetHigh()); +} + +void Processor::OPCode0x93() +{ + // SUB E + OPCodes_SUB(DE.GetLow()); +} + +void Processor::OPCode0x94() +{ + // SUB H + OPCodes_SUB(HL.GetHigh()); +} + +void Processor::OPCode0x95() +{ + // SUB L + OPCodes_SUB(HL.GetLow()); +} + +void Processor::OPCode0x96() +{ + // SUB (HL) + OPCodes_SUB(m_pMemory->Read(HL.GetValue())); +} + +void Processor::OPCode0x97() +{ + // SUB A + OPCodes_SUB(AF.GetHigh()); +} + +void Processor::OPCode0x98() +{ + // SBC B + OPCodes_SBC(BC.GetHigh()); +} + +void Processor::OPCode0x99() +{ + // SBC C + OPCodes_SBC(BC.GetLow()); +} + +void Processor::OPCode0x9A() +{ + // SBC D + OPCodes_SBC(DE.GetHigh()); +} + +void Processor::OPCode0x9B() +{ + // SBC E + OPCodes_SBC(DE.GetLow()); +} + +void Processor::OPCode0x9C() +{ + // SBC H + OPCodes_SBC(HL.GetHigh()); +} + +void Processor::OPCode0x9D() +{ + // SBC L + OPCodes_SBC(HL.GetLow()); +} + +void Processor::OPCode0x9E() +{ + // SBC (HL) + OPCodes_SBC(m_pMemory->Read(HL.GetValue())); +} + +void Processor::OPCode0x9F() +{ + // SBC A + OPCodes_SBC(AF.GetHigh()); +} + +void Processor::OPCode0xA0() +{ + // AND B + OPCodes_AND(BC.GetHigh()); +} + +void Processor::OPCode0xA1() +{ + // AND C + OPCodes_AND(BC.GetLow()); +} + +void Processor::OPCode0xA2() +{ + // AND D + OPCodes_AND(DE.GetHigh()); +} + +void Processor::OPCode0xA3() +{ + // AND E + OPCodes_AND(DE.GetLow()); +} + +void Processor::OPCode0xA4() +{ + // AND H + OPCodes_AND(HL.GetHigh()); +} + +void Processor::OPCode0xA5() +{ + // AND L + OPCodes_AND(HL.GetLow()); +} + +void Processor::OPCode0xA6() +{ + // AND (HL) + OPCodes_AND(m_pMemory->Read(HL.GetValue())); +} + +void Processor::OPCode0xA7() +{ + // AND A + OPCodes_AND(AF.GetHigh()); +} + +void Processor::OPCode0xA8() +{ + // XOR B + OPCodes_XOR(BC.GetHigh()); +} + +void Processor::OPCode0xA9() +{ + // XOR C + OPCodes_XOR(BC.GetLow()); +} + +void Processor::OPCode0xAA() +{ + // XOR D + OPCodes_XOR(DE.GetHigh()); +} + +void Processor::OPCode0xAB() +{ + // XOR E + OPCodes_XOR(DE.GetLow()); +} + +void Processor::OPCode0xAC() +{ + // XOR H + OPCodes_XOR(HL.GetHigh()); +} + +void Processor::OPCode0xAD() +{ + // XOR L + OPCodes_XOR(HL.GetLow()); +} + +void Processor::OPCode0xAE() +{ + // XOR (HL) + OPCodes_XOR(m_pMemory->Read(HL.GetValue())); +} + +void Processor::OPCode0xAF() +{ + // XOR A + OPCodes_XOR(AF.GetHigh()); +} + +void Processor::OPCode0xB0() +{ + // OR B + OPCodes_OR(BC.GetHigh()); +} + +void Processor::OPCode0xB1() +{ + // OR C + OPCodes_OR(BC.GetLow()); +} + +void Processor::OPCode0xB2() +{ + // OR D + OPCodes_OR(DE.GetHigh()); +} + +void Processor::OPCode0xB3() +{ + // OR E + OPCodes_OR(DE.GetLow()); + +} + +void Processor::OPCode0xB4() +{ + // OR H + OPCodes_OR(HL.GetHigh()); +} + +void Processor::OPCode0xB5() +{ + // OR L + OPCodes_OR(HL.GetLow()); +} + +void Processor::OPCode0xB6() +{ + // OR (HL) + OPCodes_OR(m_pMemory->Read(HL.GetValue())); +} + +void Processor::OPCode0xB7() +{ + // OR A + OPCodes_OR(AF.GetHigh()); +} + +void Processor::OPCode0xB8() +{ + // CP B + OPCodes_CP(BC.GetHigh()); +} + +void Processor::OPCode0xB9() +{ + // CP C + OPCodes_CP(BC.GetLow()); +} + +void Processor::OPCode0xBA() +{ + // CP D + OPCodes_CP(DE.GetHigh()); +} + +void Processor::OPCode0xBB() +{ + // CP E + OPCodes_CP(DE.GetLow()); +} + +void Processor::OPCode0xBC() +{ + // CP H + OPCodes_CP(HL.GetHigh()); +} + +void Processor::OPCode0xBD() +{ + // CP L + OPCodes_CP(HL.GetLow()); +} + +void Processor::OPCode0xBE() +{ + // CP (HL) + OPCodes_CP(m_pMemory->Read(HL.GetValue())); +} + +void Processor::OPCode0xBF() +{ + // CP A + OPCodes_CP(AF.GetHigh()); +} + +void Processor::OPCode0xC0() +{ + // RET NZ + if (!IsSetFlag(FLAG_ZERO)) + { + StackPop(&PC); + m_bBranchTaken = true; + } +} + +void Processor::OPCode0xC1() +{ + // POP BC + StackPop(&BC); +} + +void Processor::OPCode0xC2() +{ + // JP NZ,nn + if (!IsSetFlag(FLAG_ZERO)) + { + u8 l = m_pMemory->Read(PC.GetValue()); + PC.Increment(); + u8 h = m_pMemory->Read(PC.GetValue()); + PC.SetHigh(h); + PC.SetLow(l); + m_bBranchTaken = true; + } + else + { + PC.Increment(); + PC.Increment(); + } +} + +void Processor::OPCode0xC3() +{ + // JP nn + u8 l = m_pMemory->Read(PC.GetValue()); + PC.Increment(); + u8 h = m_pMemory->Read(PC.GetValue()); + PC.SetHigh(h); + PC.SetLow(l); +} + +void Processor::OPCode0xC4() +{ + // CALL NZ,nn + if (!IsSetFlag(FLAG_ZERO)) + { + u8 l = m_pMemory->Read(PC.GetValue()); + PC.Increment(); + u8 h = m_pMemory->Read(PC.GetValue()); + PC.Increment(); + StackPush(&PC); + PC.SetHigh(h); + PC.SetLow(l); + m_bBranchTaken = true; + } + else + { + PC.Increment(); + PC.Increment(); + } +} + +void Processor::OPCode0xC5() +{ + // PUSH BC + StackPush(&BC); +} + +void Processor::OPCode0xC6() +{ + // ADD A,n + OPCodes_ADD(m_pMemory->Read(PC.GetValue())); + PC.Increment(); +} + +void Processor::OPCode0xC7() +{ + // RST 00H + StackPush(&PC); + PC.SetValue(0x0000); +} + +void Processor::OPCode0xC8() +{ + // RET Z + if (IsSetFlag(FLAG_ZERO)) + { + StackPop(&PC); + m_bBranchTaken = true; + } +} + +void Processor::OPCode0xC9() +{ + // RET + StackPop(&PC); +} + +void Processor::OPCode0xCA() +{ + // JP Z,nn + if (IsSetFlag(FLAG_ZERO)) + { + u8 l = m_pMemory->Read(PC.GetValue()); + PC.Increment(); + u8 h = m_pMemory->Read(PC.GetValue()); + PC.SetHigh(h); + PC.SetLow(l); + m_bBranchTaken = true; + } + else + { + PC.Increment(); + PC.Increment(); + } +} + +void Processor::OPCode0xCB() +{ + // CB prefixed instruction +} + +void Processor::OPCode0xCC() +{ + // CALL Z,nn + if (IsSetFlag(FLAG_ZERO)) + { + u8 l = m_pMemory->Read(PC.GetValue()); + PC.Increment(); + u8 h = m_pMemory->Read(PC.GetValue()); + PC.Increment(); + StackPush(&PC); + PC.SetHigh(h); + PC.SetLow(l); + m_bBranchTaken = true; + } + else + { + PC.Increment(); + PC.Increment(); + } +} + +void Processor::OPCode0xCD() +{ + // CALL nn + u8 l = m_pMemory->Read(PC.GetValue()); + PC.Increment(); + u8 h = m_pMemory->Read(PC.GetValue()); + PC.Increment(); + StackPush(&PC); + PC.SetHigh(h); + PC.SetLow(l); +} + +void Processor::OPCode0xCE() +{ + // ADC A,n + OPCodes_ADC(m_pMemory->Read(PC.GetValue())); + PC.Increment(); +} + +void Processor::OPCode0xCF() +{ + // RST 08H + StackPush(&PC); + PC.SetValue(0x0008); +} + +void Processor::OPCode0xD0() +{ + // RET NC + if (!IsSetFlag(FLAG_CARRY)) + { + StackPop(&PC); + m_bBranchTaken = true; + } +} + +void Processor::OPCode0xD1() +{ + // POP DE + StackPop(&DE); +} + +void Processor::OPCode0xD2() +{ + // JP NC,nn + if (!IsSetFlag(FLAG_CARRY)) + { + u8 l = m_pMemory->Read(PC.GetValue()); + PC.Increment(); + u8 h = m_pMemory->Read(PC.GetValue()); + PC.SetHigh(h); + PC.SetLow(l); + m_bBranchTaken = true; + } + else + { + PC.Increment(); + PC.Increment(); + } +} + +void Processor::OPCode0xD3() +{ + InvalidOPCode(); +} + +void Processor::OPCode0xD4() +{ + // CALL NC,nn + if (!IsSetFlag(FLAG_CARRY)) + { + u8 l = m_pMemory->Read(PC.GetValue()); + PC.Increment(); + u8 h = m_pMemory->Read(PC.GetValue()); + PC.Increment(); + StackPush(&PC); + PC.SetHigh(h); + PC.SetLow(l); + m_bBranchTaken = true; + } + else + { + PC.Increment(); + PC.Increment(); + } +} + +void Processor::OPCode0xD5() +{ + // PUSH DE + StackPush(&DE); +} + +void Processor::OPCode0xD6() +{ + // SUB n + OPCodes_SUB(m_pMemory->Read(PC.GetValue())); + PC.Increment(); +} + +void Processor::OPCode0xD7() +{ + // RST 10H + StackPush(&PC); + PC.SetValue(0x0010); +} + +void Processor::OPCode0xD8() +{ + // RET C + if (IsSetFlag(FLAG_CARRY)) + { + StackPop(&PC); + m_bBranchTaken = true; + } +} + +void Processor::OPCode0xD9() +{ + // RETI + StackPop(&PC); + m_bIME = true; +} + +void Processor::OPCode0xDA() +{ + // JP C,nn + if (IsSetFlag(FLAG_CARRY)) + { + u8 l = m_pMemory->Read(PC.GetValue()); + PC.Increment(); + u8 h = m_pMemory->Read(PC.GetValue()); + PC.SetHigh(h); + PC.SetLow(l); + m_bBranchTaken = true; + } + else + { + PC.Increment(); + PC.Increment(); + } +} + +void Processor::OPCode0xDB() +{ + InvalidOPCode(); +} + +void Processor::OPCode0xDC() +{ + // CALL C,nn + if (IsSetFlag(FLAG_CARRY)) + { + u8 l = m_pMemory->Read(PC.GetValue()); + PC.Increment(); + u8 h = m_pMemory->Read(PC.GetValue()); + PC.Increment(); + StackPush(&PC); + PC.SetHigh(h); + PC.SetLow(l); + m_bBranchTaken = true; + } + else + { + PC.Increment(); + PC.Increment(); + } +} + +void Processor::OPCode0xDD() +{ + InvalidOPCode(); +} + +void Processor::OPCode0xDE() +{ + // SBC n + OPCodes_SBC(m_pMemory->Read(PC.GetValue())); + PC.Increment(); +} + +void Processor::OPCode0xDF() +{ + // RST 18H + StackPush(&PC); + PC.SetValue(0x0018); +} + +void Processor::OPCode0xE0() +{ + // LD (0xFF00+n),A + OPCodes_LD(static_cast<u16> (0xFF00 + m_pMemory->Read(PC.GetValue())), AF.GetHigh()); + PC.Increment(); +} + +void Processor::OPCode0xE1() +{ + // POP HL + StackPop(&HL); +} + +void Processor::OPCode0xE2() +{ + // LD (0xFF00+C),A + OPCodes_LD(static_cast<u16> (0xFF00 + BC.GetLow()), AF.GetHigh()); +} + +void Processor::OPCode0xE3() +{ + InvalidOPCode(); +} + +void Processor::OPCode0xE4() +{ + InvalidOPCode(); +} + +void Processor::OPCode0xE5() +{ + // PUSH HL + StackPush(&HL); +} + +void Processor::OPCode0xE6() +{ + // AND n + OPCodes_AND(m_pMemory->Read(PC.GetValue())); + PC.Increment(); +} + +void Processor::OPCode0xE7() +{ + // RST 20H + StackPush(&PC); + PC.SetValue(0x0020); +} + +void Processor::OPCode0xE8() +{ + // ADD SP,n + OPCodes_ADD_SP(static_cast<u8> (m_pMemory->Read(PC.GetValue()))); + PC.Increment(); +} + +void Processor::OPCode0xE9() +{ + // JP (HL) + PC.SetValue(HL.GetValue()); +} + +void Processor::OPCode0xEA() +{ + // LD (nn),A + SixteenBitRegister tmp; + tmp.SetLow(m_pMemory->Read(PC.GetValue())); + PC.Increment(); + tmp.SetHigh(m_pMemory->Read(PC.GetValue())); + PC.Increment(); + OPCodes_LD(tmp.GetValue(), AF.GetHigh()); +} + +void Processor::OPCode0xEB() +{ + InvalidOPCode(); +} + +void Processor::OPCode0xEC() +{ + InvalidOPCode(); +} + +void Processor::OPCode0xED() +{ + InvalidOPCode(); +} + +void Processor::OPCode0xEE() +{ + // XOR n + OPCodes_XOR(m_pMemory->Read(PC.GetValue())); + PC.Increment(); +} + +void Processor::OPCode0xEF() +{ + // RST 28H + StackPush(&PC); + PC.SetValue(0x28); +} + +void Processor::OPCode0xF0() +{ + // LD A,(0xFF00+n) + OPCodes_LD(AF.GetHighRegister(), + static_cast<u16> (0xFF00 + m_pMemory->Read(PC.GetValue()))); + PC.Increment(); +} + +void Processor::OPCode0xF1() +{ + // POP AF + StackPop(&AF); + AF.SetLow(AF.GetLow() & 0xF0); +} + +void Processor::OPCode0xF2() +{ + // LD A,(C) + OPCodes_LD(AF.GetHighRegister(), static_cast<u16> (0xFF00 + BC.GetLow())); +} + +void Processor::OPCode0xF3() +{ + // DI + m_bIME = false; + m_iIMECycles = 0; +} + +void Processor::OPCode0xF4() +{ + InvalidOPCode(); +} + +void Processor::OPCode0xF5() +{ + // PUSH AF + StackPush(&AF); +} + +void Processor::OPCode0xF6() +{ + // OR n + OPCodes_OR(m_pMemory->Read(PC.GetValue())); + PC.Increment(); +} + +void Processor::OPCode0xF7() +{ + // RST 30H + StackPush(&PC); + PC.SetValue(0x0030); +} + +void Processor::OPCode0xF8() +{ + // LD HL,SP+n + s8 n = m_pMemory->Read(PC.GetValue()); + u16 result = SP.GetValue() + n; + ClearAllFlags(); + if (((SP.GetValue() ^ n ^ result) & 0x100) == 0x100) + ToggleFlag(FLAG_CARRY); + if (((SP.GetValue() ^ n ^ result) & 0x10) == 0x10) + ToggleFlag(FLAG_HALF); + HL.SetValue(result); + PC.Increment(); +} + +void Processor::OPCode0xF9() +{ + // LD SP,HL + SP.SetValue(HL.GetValue()); +} + +void Processor::OPCode0xFA() +{ + // LD A,(nn) + SixteenBitRegister tmp; + tmp.SetLow(m_pMemory->Read(PC.GetValue())); + PC.Increment(); + tmp.SetHigh(m_pMemory->Read(PC.GetValue())); + PC.Increment(); + OPCodes_LD(AF.GetHighRegister(), tmp.GetValue()); +} + +void Processor::OPCode0xFB() +{ + // EI + int ei_cycles = kOPCodeMachineCycles[0xFB] * AdjustedCycles(4); + m_iIMECycles = ei_cycles + 1; +} + +void Processor::OPCode0xFC() +{ + InvalidOPCode(); +} + +void Processor::OPCode0xFD() +{ + InvalidOPCode(); +} + +void Processor::OPCode0xFE() +{ + // CP n + OPCodes_CP(m_pMemory->Read(PC.GetValue())); + PC.Increment(); +} + +void Processor::OPCode0xFF() +{ + // RST 38H + StackPush(&PC); + PC.SetValue(0x0038); +} |
