Path: blob/a-new-beginning/Cherry/Core/include/Processor_inline.h
2 views
/*1* Gearcoleco - ColecoVision Emulator2* Copyright (C) 2021 Ignacio Sanchez34* This program is free software: you can redistribute it and/or modify5* it under the terms of the GNU General Public License as published by6* the Free Software Foundation, either version 3 of the License, or7* any later version.89* This program is distributed in the hope that it will be useful,10* but WITHOUT ANY WARRANTY; without even the implied warranty of11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12* GNU General Public License for more details.1314* You should have received a copy of the GNU General Public License15* along with this program. If not, see http://www.gnu.org/licenses/16*17*/1819#ifndef PROCESSOR_INLINE_H20#define PROCESSOR_INLINE_H2122#include "definitions.h"23#include "SixteenBitRegister.h"24#include "Processor.h"25#include "IOPorts.h"2627inline u8 Processor::FetchOPCode()28{29u8 opcode = m_pMemory->Read(PC.GetValue());30PC.Increment();31return opcode;32}3334inline u16 Processor::FetchArg16()35{36u16 pc = PC.GetValue();37u8 l = m_pMemory->Read(pc);38u8 h = m_pMemory->Read(pc + 1);39PC.SetValue(pc + 2);40return (h << 8) | l;41}4243inline void Processor::LeaveHalt()44{45if (m_bHalt)46{47m_bHalt = false;48PC.Increment();49}50}5152inline void Processor::ClearAllFlags()53{54SetFlag(FLAG_NONE);55}5657inline void Processor::ToggleZeroFlagFromResult(u16 result)58{59if (result == 0)60ToggleFlag(FLAG_ZERO);61else62ClearFlag(FLAG_ZERO);63}6465inline void Processor::ToggleSignFlagFromResult(u8 result)66{67if ((result & 0x80) != 0)68ToggleFlag(FLAG_SIGN);69else70ClearFlag(FLAG_SIGN);71}7273inline void Processor::ToggleXYFlagsFromResult(u8 result)74{75if ((result & 0x08) != 0)76ToggleFlag(FLAG_X);77else78ClearFlag(FLAG_X);79if ((result & 0x20) != 0)80ToggleFlag(FLAG_Y);81else82ClearFlag(FLAG_Y);83}8485inline void Processor::ToggleParityFlagFromResult(u8 result)86{87if (kZ80ParityTable[result])88ToggleFlag(FLAG_PARITY);89else90ClearFlag(FLAG_PARITY);91}9293inline void Processor::SetFlag(u8 flag)94{95AF.SetLow(flag);96}9798inline void Processor::FlipFlag(u8 flag)99{100AF.SetLow(AF.GetLow() ^ flag);101}102103inline void Processor::ToggleFlag(u8 flag)104{105AF.SetLow(AF.GetLow() | flag);106}107108inline void Processor::ClearFlag(u8 flag)109{110AF.SetLow(AF.GetLow() & (~flag));111}112113inline bool Processor::IsSetFlag(u8 flag)114{115return (AF.GetLow() & flag) != 0;116}117118inline void Processor::StackPush(SixteenBitRegister* reg)119{120SP.Decrement();121m_pMemory->Write(SP.GetValue(), reg->GetHigh());122SP.Decrement();123m_pMemory->Write(SP.GetValue(), reg->GetLow());124}125126inline void Processor::StackPop(SixteenBitRegister* reg)127{128reg->SetLow(m_pMemory->Read(SP.GetValue()));129SP.Increment();130reg->SetHigh(m_pMemory->Read(SP.GetValue()));131SP.Increment();132}133134inline void Processor::SetInterruptMode(int mode)135{136if (mode == 1)137{138m_iInterruptMode = mode;139}140else141{142Debug("--> ** Attempting to set interrupt mode %d", mode);143}144}145146inline SixteenBitRegister* Processor::GetPrefixedRegister()147{148switch (m_CurrentPrefix)149{150case 0xDD:151return &IX;152case 0xFD:153return &IY;154default:155return &HL;156}157}158159inline u16 Processor::GetEffectiveAddress()160{161switch (m_CurrentPrefix)162{163case 0xDD:164{165u16 address = IX.GetValue();166if (m_bPrefixedCBOpcode)167{168address += static_cast<s8> (m_PrefixedCBValue);169}170else171{172address += static_cast<s8> (m_pMemory->Read(PC.GetValue()));173PC.Increment();174WZ.SetValue(address);175}176return address;177}178case 0xFD:179{180u16 address = IY.GetValue();181if (m_bPrefixedCBOpcode)182{183address += static_cast<s8> (m_PrefixedCBValue);184}185else186{187address += static_cast<s8> (m_pMemory->Read(PC.GetValue()));188PC.Increment();189WZ.SetValue(address);190}191return address;192}193default:194return HL.GetValue();195}196}197198inline bool Processor::IsPrefixedInstruction()199{200return (m_CurrentPrefix == 0xDD) || (m_CurrentPrefix == 0xFD);201}202203inline void Processor::IncreaseR()204{205u8 r = R;206R = ((r + 1) & 0x7F) | (r & 0x80);207m_iTStates++; // M1 1 cycle wait208}209210inline void Processor::OPCodes_LD(u8* reg1, u8 value)211{212*reg1 = value;213}214215inline void Processor::OPCodes_LD(u8* reg, u16 address)216{217*reg = m_pMemory->Read(address);218}219220inline void Processor::OPCodes_LD(u16 address, u8 reg)221{222m_pMemory->Write(address, reg);223}224225inline void Processor::OPCodes_LD_dd_nn(SixteenBitRegister* reg)226{227u16 address = FetchArg16();228reg->SetLow(m_pMemory->Read(address));229address++;230reg->SetHigh(m_pMemory->Read(address));231WZ.SetValue(address);232}233234inline void Processor::OPCodes_LD_nn_dd(SixteenBitRegister* reg)235{236u16 address = FetchArg16();237m_pMemory->Write(address, reg->GetLow());238address++;239m_pMemory->Write(address, reg->GetHigh());240WZ.SetValue(address);241}242243inline void Processor::OPCodes_LDI()244{245u8 result = m_pMemory->Read(HL.GetValue());246m_pMemory->Write(DE.GetValue(), result);247DE.Increment();248HL.Increment();249BC.Decrement();250ClearFlag(FLAG_NEGATIVE);251ClearFlag(FLAG_HALF);252if (BC.GetValue() != 0)253ToggleFlag(FLAG_PARITY);254else255ClearFlag(FLAG_PARITY);256u16 n = AF.GetHigh() + result;257if ((n & 0x08) != 0)258ToggleFlag(FLAG_X);259else260ClearFlag(FLAG_X);261if ((n & 0x02) != 0)262ToggleFlag(FLAG_Y);263else264ClearFlag(FLAG_Y);265}266267inline void Processor::OPCodes_LDD()268{269u8 result = m_pMemory->Read(HL.GetValue());270m_pMemory->Write(DE.GetValue(), result);271DE.Decrement();272HL.Decrement();273BC.Decrement();274ClearFlag(FLAG_NEGATIVE);275ClearFlag(FLAG_HALF);276if (BC.GetValue() != 0)277ToggleFlag(FLAG_PARITY);278else279ClearFlag(FLAG_PARITY);280u16 n = AF.GetHigh() + result;281if ((n & 0x08) != 0)282ToggleFlag(FLAG_X);283else284ClearFlag(FLAG_X);285if ((n & 0x02) != 0)286ToggleFlag(FLAG_Y);287else288ClearFlag(FLAG_Y);289}290291inline void Processor::OPCodes_RST(u16 address)292{293StackPush(&PC);294PC.SetValue(address);295WZ.SetValue(address);296}297298inline void Processor::OPCodes_CALL_nn()299{300u16 address = FetchArg16();301StackPush(&PC);302PC.SetValue(address);303WZ.SetValue(address);304}305306inline void Processor::OPCodes_CALL_nn_Conditional(bool condition)307{308u16 address = FetchArg16();309if (condition)310{311StackPush(&PC);312PC.SetValue(address);313m_bBranchTaken = true;314}315WZ.SetValue(address);316}317318inline void Processor::OPCodes_JP_nn()319{320u8 l = m_pMemory->Read(PC.GetValue());321u8 h = m_pMemory->Read(PC.GetValue() + 1);322u16 address = (h << 8) | l;323PC.SetValue(address);324WZ.SetValue(address);325}326327inline void Processor::OPCodes_JP_nn_Conditional(bool condition)328{329u8 l = m_pMemory->Read(PC.GetValue());330u8 h = m_pMemory->Read(PC.GetValue() + 1);331u16 address = (h << 8) | l;332if (condition)333{334PC.SetValue(address);335m_bBranchTaken = true;336}337else338{339PC.Increment();340PC.Increment();341}342WZ.SetValue(address);343}344345inline void Processor::OPCodes_JR_n()346{347u16 pc = PC.GetValue();348PC.SetValue(pc + 1 + (static_cast<s8> (m_pMemory->Read(pc))));349}350351inline void Processor::OPCodes_JR_n_conditional(bool condition)352{353if (condition)354{355OPCodes_JR_n();356m_bBranchTaken = true;357}358else359PC.Increment();360}361362inline void Processor::OPCodes_RET()363{364StackPop(&PC);365WZ.SetValue(PC.GetValue());366}367368inline void Processor::OPCodes_RET_Conditional(bool condition)369{370if (condition)371{372OPCodes_RET();373m_bBranchTaken = true;374}375}376377inline void Processor::OPCodes_IN_C(u8* reg)378{379u8 result = m_pIOPorts->In(BC.GetLow());380if (IsValidPointer(reg))381*reg = result;382IsSetFlag(FLAG_CARRY) ? SetFlag(FLAG_CARRY) : ClearAllFlags();383ToggleZeroFlagFromResult(result);384ToggleSignFlagFromResult(result);385ToggleParityFlagFromResult(result);386ToggleXYFlagsFromResult(result);387}388389inline void Processor::OPCodes_INI()390{391WZ.SetValue(BC.GetValue() + 1);392u8 result = m_pIOPorts->In(BC.GetLow());393m_pMemory->Write(HL.GetValue(), result);394OPCodes_DEC(BC.GetHighRegister());395HL.Increment();396if ((result & 0x80) != 0)397ToggleFlag(FLAG_NEGATIVE);398else399ClearFlag(FLAG_NEGATIVE);400if ((result + ((BC.GetLow() + 1) & 0xFF)) > 0xFF)401{402ToggleFlag(FLAG_CARRY);403ToggleFlag(FLAG_HALF);404}405else406{407ClearFlag(FLAG_CARRY);408ClearFlag(FLAG_HALF);409}410if (((result + ((BC.GetLow() + 1) & 0xFF)) & 0x07) ^ BC.GetHigh())411ToggleFlag(FLAG_PARITY);412else413ClearFlag(FLAG_PARITY);414}415416inline void Processor::OPCodes_IND()417{418WZ.SetValue(BC.GetValue() - 1);419u8 result = m_pIOPorts->In(BC.GetLow());420m_pMemory->Write(HL.GetValue(), result);421OPCodes_DEC(BC.GetHighRegister());422HL.Decrement();423if ((result & 0x80) != 0)424ToggleFlag(FLAG_NEGATIVE);425else426ClearFlag(FLAG_NEGATIVE);427if ((result + ((BC.GetLow() - 1) & 0xFF)) > 0xFF)428{429ToggleFlag(FLAG_CARRY);430ToggleFlag(FLAG_HALF);431}432else433{434ClearFlag(FLAG_CARRY);435ClearFlag(FLAG_HALF);436}437if (((result + ((BC.GetLow() + 1) & 0xFF)) & 0x07) ^ BC.GetHigh())438ToggleFlag(FLAG_PARITY);439else440ClearFlag(FLAG_PARITY);441}442443inline void Processor::OPCodes_OUT_C(u8* reg)444{445m_pIOPorts->Out(BC.GetLow(), *reg);446}447448inline void Processor::OPCodes_OUTI()449{450u8 result = m_pMemory->Read(HL.GetValue());451m_pIOPorts->Out(BC.GetLow(), result);452OPCodes_DEC(BC.GetHighRegister());453WZ.SetValue(BC.GetValue() + 1);454HL.Increment();455if ((result & 0x80) != 0)456ToggleFlag(FLAG_NEGATIVE);457else458ClearFlag(FLAG_NEGATIVE);459if ((HL.GetLow() + result) > 0xFF)460{461ToggleFlag(FLAG_CARRY);462ToggleFlag(FLAG_HALF);463}464else465{466ClearFlag(FLAG_CARRY);467ClearFlag(FLAG_HALF);468}469if (((HL.GetLow() + result) & 0x07) ^ BC.GetHigh())470ToggleFlag(FLAG_PARITY);471else472ClearFlag(FLAG_PARITY);473}474475inline void Processor::OPCodes_OUTD()476{477u8 result = m_pMemory->Read(HL.GetValue());478m_pIOPorts->Out(BC.GetLow(), result);479OPCodes_DEC(BC.GetHighRegister());480WZ.SetValue(BC.GetValue() - 1);481HL.Decrement();482if ((result & 0x80) != 0)483ToggleFlag(FLAG_NEGATIVE);484else485ClearFlag(FLAG_NEGATIVE);486if ((HL.GetLow() + result) > 0xFF)487{488ToggleFlag(FLAG_CARRY);489ToggleFlag(FLAG_HALF);490}491else492{493ClearFlag(FLAG_CARRY);494ClearFlag(FLAG_HALF);495}496if (((HL.GetLow() + result) & 0x07) ^ BC.GetHigh())497ToggleFlag(FLAG_PARITY);498else499ClearFlag(FLAG_PARITY);500}501502inline void Processor::OPCodes_EX(SixteenBitRegister* reg1, SixteenBitRegister* reg2)503{504u16 tmp = reg1->GetValue();505reg1->SetValue(reg2->GetValue());506reg2->SetValue(tmp);507}508509inline void Processor::OPCodes_OR(u8 number)510{511u8 result = AF.GetHigh() | number;512AF.SetHigh(result);513ClearAllFlags();514ToggleZeroFlagFromResult(result);515ToggleSignFlagFromResult(result);516ToggleXYFlagsFromResult(result);517ToggleParityFlagFromResult(result);518}519520inline void Processor::OPCodes_XOR(u8 number)521{522u8 result = AF.GetHigh() ^ number;523AF.SetHigh(result);524ClearAllFlags();525ToggleZeroFlagFromResult(result);526ToggleSignFlagFromResult(result);527ToggleXYFlagsFromResult(result);528ToggleParityFlagFromResult(result);529}530531inline void Processor::OPCodes_AND(u8 number)532{533u8 result = AF.GetHigh() & number;534AF.SetHigh(result);535SetFlag(FLAG_HALF);536ToggleZeroFlagFromResult(result);537ToggleSignFlagFromResult(result);538ToggleXYFlagsFromResult(result);539ToggleParityFlagFromResult(result);540}541542inline void Processor::OPCodes_CP(u8 number)543{544int result = AF.GetHigh() - number;545int carrybits = AF.GetHigh() ^ number ^ result;546u8 final_result = static_cast<u8> (result);547SetFlag(FLAG_NEGATIVE);548ToggleZeroFlagFromResult(final_result);549ToggleSignFlagFromResult(final_result);550ToggleXYFlagsFromResult(number);551if ((carrybits & 0x100) != 0)552ToggleFlag(FLAG_CARRY);553if ((carrybits & 0x10) != 0)554ToggleFlag(FLAG_HALF);555if ((((carrybits << 1) ^ carrybits) & 0x100) != 0)556ToggleFlag(FLAG_PARITY);557}558559inline void Processor::OPCodes_CPI()560{561u8 number = m_pMemory->Read(HL.GetValue());562int result = AF.GetHigh() - number;563int carrybits = AF.GetHigh() ^ number ^ result;564u8 final_result = static_cast<u8> (result);565ToggleFlag(FLAG_NEGATIVE);566ToggleZeroFlagFromResult(final_result);567ToggleSignFlagFromResult(final_result);568if ((carrybits & 0x10) != 0)569ToggleFlag(FLAG_HALF);570else571ClearFlag(FLAG_HALF);572HL.Increment();573BC.Decrement();574if (BC.GetValue() != 0)575ToggleFlag(FLAG_PARITY);576else577ClearFlag(FLAG_PARITY);578int n = AF.GetHigh() - number - (IsSetFlag(FLAG_HALF) ? 1 : 0);579if ((n & 0x08) != 0)580ToggleFlag(FLAG_X);581else582ClearFlag(FLAG_X);583if ((n & 0x02) != 0)584ToggleFlag(FLAG_Y);585else586ClearFlag(FLAG_Y);587WZ.Increment();588}589590inline void Processor::OPCodes_CPD()591{592u8 number = m_pMemory->Read(HL.GetValue());593int result = AF.GetHigh() - number;594int carrybits = AF.GetHigh() ^ number ^ result;595u8 final_result = static_cast<u8> (result);596ToggleFlag(FLAG_NEGATIVE);597ToggleZeroFlagFromResult(final_result);598ToggleSignFlagFromResult(final_result);599if ((carrybits & 0x10) != 0)600ToggleFlag(FLAG_HALF);601else602ClearFlag(FLAG_HALF);603HL.Decrement();604BC.Decrement();605if (BC.GetValue() != 0)606ToggleFlag(FLAG_PARITY);607else608ClearFlag(FLAG_PARITY);609int n = AF.GetHigh() - number - (IsSetFlag(FLAG_HALF) ? 1 : 0);610if ((n & 0x08) != 0)611ToggleFlag(FLAG_X);612else613ClearFlag(FLAG_X);614if ((n & 0x02) != 0)615ToggleFlag(FLAG_Y);616else617ClearFlag(FLAG_Y);618WZ.Decrement();619}620621inline void Processor::OPCodes_INC(u8* reg)622{623u8 result = *reg + 1;624*reg = result;625IsSetFlag(FLAG_CARRY) ? SetFlag(FLAG_CARRY) : ClearAllFlags();626ToggleZeroFlagFromResult(result);627ToggleSignFlagFromResult(result);628ToggleXYFlagsFromResult(result);629if ((result & 0x0F) == 0x00)630ToggleFlag(FLAG_HALF);631if (result == 0x80)632ToggleFlag(FLAG_PARITY);633}634635inline void Processor::OPCodes_INC_HL()636{637u16 address = GetEffectiveAddress();638u8 result = m_pMemory->Read(address) + 1;639m_pMemory->Write(address, result);640IsSetFlag(FLAG_CARRY) ? SetFlag(FLAG_CARRY) : ClearAllFlags();641ToggleZeroFlagFromResult(result);642ToggleSignFlagFromResult(result);643ToggleXYFlagsFromResult(result);644if ((result & 0x0F) == 0x00)645ToggleFlag(FLAG_HALF);646if (result == 0x80)647ToggleFlag(FLAG_PARITY);648}649650inline void Processor::OPCodes_DEC(u8* reg)651{652u8 result = *reg - 1;653*reg = result;654IsSetFlag(FLAG_CARRY) ? SetFlag(FLAG_CARRY) : ClearAllFlags();655ToggleFlag(FLAG_NEGATIVE);656ToggleZeroFlagFromResult(result);657ToggleSignFlagFromResult(result);658ToggleXYFlagsFromResult(result);659if ((result & 0x0F) == 0x0F)660ToggleFlag(FLAG_HALF);661if (result == 0x7F)662ToggleFlag(FLAG_PARITY);663}664665inline void Processor::OPCodes_DEC_HL()666{667u16 address = GetEffectiveAddress();668u8 result = m_pMemory->Read(address) - 1;669m_pMemory->Write(address, result);670IsSetFlag(FLAG_CARRY) ? SetFlag(FLAG_CARRY) : ClearAllFlags();671ToggleFlag(FLAG_NEGATIVE);672ToggleZeroFlagFromResult(result);673ToggleSignFlagFromResult(result);674ToggleXYFlagsFromResult(result);675if ((result & 0x0F) == 0x0F)676ToggleFlag(FLAG_HALF);677if (result == 0x7F)678ToggleFlag(FLAG_PARITY);679}680681inline void Processor::OPCodes_ADD(u8 number)682{683int result = AF.GetHigh() + number;684int carrybits = AF.GetHigh() ^ number ^ result;685u8 final_result = static_cast<u8> (result);686AF.SetHigh(final_result);687ClearAllFlags();688ToggleZeroFlagFromResult(final_result);689ToggleSignFlagFromResult(final_result);690ToggleXYFlagsFromResult(final_result);691if ((carrybits & 0x100) != 0)692ToggleFlag(FLAG_CARRY);693if ((carrybits & 0x10) != 0)694ToggleFlag(FLAG_HALF);695if ((((carrybits << 1) ^ carrybits) & 0x100) != 0)696ToggleFlag(FLAG_PARITY);697}698699inline void Processor::OPCodes_ADC(u8 number)700{701int result = AF.GetHigh() + number + (IsSetFlag(FLAG_CARRY) ? 1 : 0);702int carrybits = AF.GetHigh() ^ number ^ result;703u8 final_result = static_cast<u8> (result);704AF.SetHigh(final_result);705ClearAllFlags();706ToggleZeroFlagFromResult(final_result);707ToggleSignFlagFromResult(final_result);708ToggleXYFlagsFromResult(final_result);709if ((carrybits & 0x100) != 0)710ToggleFlag(FLAG_CARRY);711if ((carrybits & 0x10) != 0)712ToggleFlag(FLAG_HALF);713if ((((carrybits << 1) ^ carrybits) & 0x100) != 0)714ToggleFlag(FLAG_PARITY);715}716717inline void Processor::OPCodes_SUB(u8 number)718{719int result = AF.GetHigh() - number;720int carrybits = AF.GetHigh() ^ number ^ result;721u8 final_result = static_cast<u8> (result);722AF.SetHigh(final_result);723SetFlag(FLAG_NEGATIVE);724ToggleZeroFlagFromResult(final_result);725ToggleSignFlagFromResult(final_result);726ToggleXYFlagsFromResult(final_result);727if ((carrybits & 0x100) != 0)728ToggleFlag(FLAG_CARRY);729if ((carrybits & 0x10) != 0)730ToggleFlag(FLAG_HALF);731if ((((carrybits << 1) ^ carrybits) & 0x100) != 0)732ToggleFlag(FLAG_PARITY);733}734735inline void Processor::OPCodes_SBC(u8 number)736{737int result = AF.GetHigh() - number - (IsSetFlag(FLAG_CARRY) ? 1 : 0);738int carrybits = AF.GetHigh() ^ number ^ result;739u8 final_result = static_cast<u8> (result);740AF.SetHigh(final_result);741SetFlag(FLAG_NEGATIVE);742ToggleZeroFlagFromResult(final_result);743ToggleSignFlagFromResult(final_result);744ToggleXYFlagsFromResult(final_result);745if ((carrybits & 0x100) != 0)746ToggleFlag(FLAG_CARRY);747if ((carrybits & 0x10) != 0)748ToggleFlag(FLAG_HALF);749if ((((carrybits << 1) ^ carrybits) & 0x100) != 0)750ToggleFlag(FLAG_PARITY);751}752753inline void Processor::OPCodes_ADD_HL(u16 number)754{755SixteenBitRegister* reg = GetPrefixedRegister();756WZ.SetValue(reg->GetValue() + 1);757int result = reg->GetValue() + number;758int carrybits = reg->GetValue() ^ number ^ result;759reg->SetValue(static_cast<u16> (result));760ClearFlag(FLAG_NEGATIVE);761ToggleXYFlagsFromResult(reg->GetHigh());762if ((carrybits & 0x10000) != 0)763ToggleFlag(FLAG_CARRY);764else765ClearFlag(FLAG_CARRY);766if ((carrybits & 0x1000) != 0)767ToggleFlag(FLAG_HALF);768else769ClearFlag(FLAG_HALF);770}771772inline void Processor::OPCodes_ADC_HL(u16 number)773{774WZ.SetValue(HL.GetValue() + 1);775int result = HL.GetValue() + number + (IsSetFlag(FLAG_CARRY) ? 1 : 0);776int carrybits = HL.GetValue() ^ number ^ result;777u16 final_result = static_cast<u16> (result);778HL.SetValue(final_result);779ClearAllFlags();780ToggleXYFlagsFromResult(HL.GetHigh());781ToggleSignFlagFromResult(HL.GetHigh());782ToggleZeroFlagFromResult(final_result);783if ((carrybits & 0x10000) != 0)784ToggleFlag(FLAG_CARRY);785if ((carrybits & 0x1000) != 0)786ToggleFlag(FLAG_HALF);787if ((((carrybits << 1) ^ carrybits) & 0x10000) != 0)788ToggleFlag(FLAG_PARITY);789}790791inline void Processor::OPCodes_SBC_HL(u16 number)792{793WZ.SetValue(HL.GetValue() + 1);794int result = HL.GetValue() - number - (IsSetFlag(FLAG_CARRY) ? 1 : 0);795int carrybits = HL.GetValue() ^ number ^ result;796u16 final_result = static_cast<u16> (result);797HL.SetValue(final_result);798SetFlag(FLAG_NEGATIVE);799ToggleXYFlagsFromResult(HL.GetHigh());800ToggleSignFlagFromResult(HL.GetHigh());801ToggleZeroFlagFromResult(final_result);802if ((carrybits & 0x10000) != 0)803ToggleFlag(FLAG_CARRY);804if ((carrybits & 0x1000) != 0)805ToggleFlag(FLAG_HALF);806if ((((carrybits << 1) ^ carrybits) & 0x10000) != 0)807ToggleFlag(FLAG_PARITY);808}809810inline void Processor::OPCodes_SLL(u8* reg)811{812u16 address = 0x0000;813if (IsPrefixedInstruction())814{815address = GetEffectiveAddress();816*reg = m_pMemory->Read(address);817}818(*reg & 0x80) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags();819u8 result = (*reg << 1) | 0x01;820*reg = result;821if (IsPrefixedInstruction())822m_pMemory->Write(address, *reg);823ToggleZeroFlagFromResult(result);824ToggleSignFlagFromResult(result);825ToggleParityFlagFromResult(result);826ToggleXYFlagsFromResult(result);827}828829inline void Processor::OPCodes_SLL_HL()830{831u16 address = GetEffectiveAddress();832u8 result = m_pMemory->Read(address);833(result & 0x80) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags();834result = (result << 1) | 0x01;835m_pMemory->Write(address, result);836ToggleZeroFlagFromResult(result);837ToggleSignFlagFromResult(result);838ToggleParityFlagFromResult(result);839ToggleXYFlagsFromResult(result);840}841842inline void Processor::OPCodes_SLA(u8* reg)843{844u16 address = 0x0000;845if (IsPrefixedInstruction())846{847address = GetEffectiveAddress();848*reg = m_pMemory->Read(address);849}850(*reg & 0x80) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags();851u8 result = *reg << 1;852*reg = result;853if (IsPrefixedInstruction())854m_pMemory->Write(address, *reg);855ToggleZeroFlagFromResult(result);856ToggleSignFlagFromResult(result);857ToggleParityFlagFromResult(result);858ToggleXYFlagsFromResult(result);859}860861inline void Processor::OPCodes_SLA_HL()862{863u16 address = GetEffectiveAddress();864u8 result = m_pMemory->Read(address);865(result & 0x80) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags();866result <<= 1;867m_pMemory->Write(address, result);868ToggleZeroFlagFromResult(result);869ToggleSignFlagFromResult(result);870ToggleParityFlagFromResult(result);871ToggleXYFlagsFromResult(result);872}873874inline void Processor::OPCodes_SRA(u8* reg)875{876u16 address = 0x0000;877if (IsPrefixedInstruction())878{879address = GetEffectiveAddress();880*reg = m_pMemory->Read(address);881}882u8 result = *reg;883(result & 0x01) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags();884if ((result & 0x80) != 0)885{886result >>= 1;887result |= 0x80;888}889else890result >>= 1;891*reg = result;892if (IsPrefixedInstruction())893m_pMemory->Write(address, *reg);894ToggleZeroFlagFromResult(result);895ToggleSignFlagFromResult(result);896ToggleParityFlagFromResult(result);897ToggleXYFlagsFromResult(result);898}899900inline void Processor::OPCodes_SRA_HL()901{902u16 address = GetEffectiveAddress();903u8 result = m_pMemory->Read(address);904(result & 0x01) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags();905if ((result & 0x80) != 0)906{907result >>= 1;908result |= 0x80;909}910else911result >>= 1;912m_pMemory->Write(address, result);913ToggleZeroFlagFromResult(result);914ToggleSignFlagFromResult(result);915ToggleParityFlagFromResult(result);916ToggleXYFlagsFromResult(result);917}918919inline void Processor::OPCodes_SRL(u8* reg)920{921u16 address = 0x0000;922if (IsPrefixedInstruction())923{924address = GetEffectiveAddress();925*reg = m_pMemory->Read(address);926}927u8 result = *reg;928(result & 0x01) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags();929result >>= 1;930*reg = result;931if (IsPrefixedInstruction())932m_pMemory->Write(address, *reg);933ToggleZeroFlagFromResult(result);934ToggleSignFlagFromResult(result);935ToggleParityFlagFromResult(result);936ToggleXYFlagsFromResult(result);937}938939inline void Processor::OPCodes_SRL_HL()940{941u16 address = GetEffectiveAddress();942u8 result = m_pMemory->Read(address);943(result & 0x01) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags();944result >>= 1;945m_pMemory->Write(address, result);946ToggleZeroFlagFromResult(result);947ToggleSignFlagFromResult(result);948ToggleParityFlagFromResult(result);949ToggleXYFlagsFromResult(result);950}951952inline void Processor::OPCodes_RLC(u8* reg, bool isRegisterA)953{954u16 address = 0x0000;955if (!isRegisterA && IsPrefixedInstruction())956{957address = GetEffectiveAddress();958*reg = m_pMemory->Read(address);959}960u8 result = *reg;961if ((result & 0x80) != 0)962{963ToggleFlag(FLAG_CARRY);964result <<= 1;965result |= 0x1;966}967else968{969ClearFlag(FLAG_CARRY);970result <<= 1;971}972*reg = result;973if (!isRegisterA && IsPrefixedInstruction())974m_pMemory->Write(address, *reg);975ClearFlag(FLAG_HALF);976ClearFlag(FLAG_NEGATIVE);977ToggleXYFlagsFromResult(result);978if (!isRegisterA)979{980ToggleZeroFlagFromResult(result);981ToggleSignFlagFromResult(result);982ToggleParityFlagFromResult(result);983}984}985986inline void Processor::OPCodes_RLC_HL()987{988u16 address = GetEffectiveAddress();989u8 result = m_pMemory->Read(address);990if ((result & 0x80) != 0)991{992SetFlag(FLAG_CARRY);993result <<= 1;994result |= 0x1;995}996else997{998ClearAllFlags();999result <<= 1;1000}1001m_pMemory->Write(address, result);1002ToggleZeroFlagFromResult(result);1003ToggleSignFlagFromResult(result);1004ToggleParityFlagFromResult(result);1005ToggleXYFlagsFromResult(result);1006}10071008inline void Processor::OPCodes_RL(u8* reg, bool isRegisterA)1009{1010u16 address = 0x0000;1011if (!isRegisterA && IsPrefixedInstruction())1012{1013address = GetEffectiveAddress();1014*reg = m_pMemory->Read(address);1015}1016u8 carry = IsSetFlag(FLAG_CARRY) ? 1 : 0;1017u8 result = *reg;1018((result & 0x80) != 0) ? ToggleFlag(FLAG_CARRY) : ClearFlag(FLAG_CARRY);1019result <<= 1;1020result |= carry;1021*reg = result;1022if (!isRegisterA && IsPrefixedInstruction())1023m_pMemory->Write(address, *reg);1024ClearFlag(FLAG_HALF);1025ClearFlag(FLAG_NEGATIVE);1026ToggleXYFlagsFromResult(result);1027if (!isRegisterA)1028{1029ToggleZeroFlagFromResult(result);1030ToggleSignFlagFromResult(result);1031ToggleParityFlagFromResult(result);1032}1033}10341035inline void Processor::OPCodes_RL_HL()1036{1037u16 address = GetEffectiveAddress();1038u8 carry = IsSetFlag(FLAG_CARRY) ? 1 : 0;1039u8 result = m_pMemory->Read(address);1040((result & 0x80) != 0) ? SetFlag(FLAG_CARRY) : ClearAllFlags();1041result <<= 1;1042result |= carry;1043m_pMemory->Write(address, result);1044ToggleZeroFlagFromResult(result);1045ToggleSignFlagFromResult(result);1046ToggleParityFlagFromResult(result);1047ToggleXYFlagsFromResult(result);1048}10491050inline void Processor::OPCodes_RRC(u8* reg, bool isRegisterA)1051{1052u16 address = 0x0000;1053if (!isRegisterA && IsPrefixedInstruction())1054{1055address = GetEffectiveAddress();1056*reg = m_pMemory->Read(address);1057}1058u8 result = *reg;1059if ((result & 0x01) != 0)1060{1061ToggleFlag(FLAG_CARRY);1062result >>= 1;1063result |= 0x80;1064}1065else1066{1067ClearFlag(FLAG_CARRY);1068result >>= 1;1069}1070*reg = result;1071if (!isRegisterA && IsPrefixedInstruction())1072m_pMemory->Write(address, *reg);1073ClearFlag(FLAG_HALF);1074ClearFlag(FLAG_NEGATIVE);1075ToggleXYFlagsFromResult(result);1076if (!isRegisterA)1077{1078ToggleZeroFlagFromResult(result);1079ToggleSignFlagFromResult(result);1080ToggleParityFlagFromResult(result);1081}1082}10831084inline void Processor::OPCodes_RRC_HL()1085{1086u16 address = GetEffectiveAddress();1087u8 result = m_pMemory->Read(address);1088if ((result & 0x01) != 0)1089{1090SetFlag(FLAG_CARRY);1091result >>= 1;1092result |= 0x80;1093}1094else1095{1096ClearAllFlags();1097result >>= 1;1098}1099m_pMemory->Write(address, result);1100ToggleZeroFlagFromResult(result);1101ToggleSignFlagFromResult(result);1102ToggleParityFlagFromResult(result);1103ToggleXYFlagsFromResult(result);1104}11051106inline void Processor::OPCodes_RR(u8* reg, bool isRegisterA)1107{1108u16 address = 0x0000;1109if (!isRegisterA && IsPrefixedInstruction())1110{1111address = GetEffectiveAddress();1112*reg = m_pMemory->Read(address);1113}1114u8 carry = IsSetFlag(FLAG_CARRY) ? 0x80 : 0x00;1115u8 result = *reg;1116((result & 0x01) != 0) ? ToggleFlag(FLAG_CARRY) : ClearFlag(FLAG_CARRY);1117result >>= 1;1118result |= carry;1119*reg = result;1120if (!isRegisterA && IsPrefixedInstruction())1121m_pMemory->Write(address, *reg);1122ClearFlag(FLAG_HALF);1123ClearFlag(FLAG_NEGATIVE);1124ToggleXYFlagsFromResult(result);1125if (!isRegisterA)1126{1127ToggleZeroFlagFromResult(result);1128ToggleSignFlagFromResult(result);1129ToggleParityFlagFromResult(result);1130}1131}11321133inline void Processor::OPCodes_RR_HL()1134{1135u16 address = GetEffectiveAddress();1136u8 carry = IsSetFlag(FLAG_CARRY) ? 0x80 : 0x00;1137u8 result = m_pMemory->Read(address);1138((result & 0x01) != 0) ? SetFlag(FLAG_CARRY) : ClearAllFlags();1139result >>= 1;1140result |= carry;1141m_pMemory->Write(address, result);1142ToggleZeroFlagFromResult(result);1143ToggleSignFlagFromResult(result);1144ToggleParityFlagFromResult(result);1145ToggleXYFlagsFromResult(result);1146}11471148inline void Processor::OPCodes_BIT(u8* reg, int bit)1149{1150IsSetFlag(FLAG_CARRY) ? SetFlag(FLAG_CARRY) : ClearAllFlags();1151u8 value = *reg;1152if (IsPrefixedInstruction())1153value = m_pMemory->Read(GetEffectiveAddress());1154if (!IsSetBit(value, bit))1155{1156ToggleFlag(FLAG_ZERO);1157ToggleFlag(FLAG_PARITY);1158}1159else if (bit == 7)1160ToggleFlag(FLAG_SIGN);1161if (IsSetBit(value, 3))1162ToggleFlag(FLAG_X);1163if (IsSetBit(value, 5))1164ToggleFlag(FLAG_Y);1165ToggleFlag(FLAG_HALF);1166}11671168inline void Processor::OPCodes_BIT_HL(int bit)1169{1170IsSetFlag(FLAG_CARRY) ? SetFlag(FLAG_CARRY) : ClearAllFlags();1171u16 address = GetEffectiveAddress();1172if (!IsSetBit(m_pMemory->Read(address), bit))1173{1174ToggleFlag(FLAG_ZERO);1175ToggleFlag(FLAG_PARITY);1176}1177else if (bit == 7)1178ToggleFlag(FLAG_SIGN);1179u8 xy = IsPrefixedInstruction() ? ((address >> 8) & 0xFF) : WZ.GetHigh();1180if (IsSetBit(xy, 3))1181ToggleFlag(FLAG_X);1182if (IsSetBit(xy, 5))1183ToggleFlag(FLAG_Y);1184ToggleFlag(FLAG_HALF);1185}11861187inline void Processor::OPCodes_SET(u8* reg, int bit)1188{1189u16 address = 0x0000;1190if (IsPrefixedInstruction())1191{1192address = GetEffectiveAddress();1193*reg = m_pMemory->Read(address);1194}1195*reg = *reg | (0x1 << bit);1196if (IsPrefixedInstruction())1197m_pMemory->Write(address, *reg);1198}11991200inline void Processor::OPCodes_SET_HL(int bit)1201{1202u16 address = GetEffectiveAddress();1203u8 result = m_pMemory->Read(address);1204result |= (0x1 << bit);1205m_pMemory->Write(address, result);1206}12071208inline void Processor::OPCodes_RES(u8* reg, int bit)1209{1210u16 address = 0x0000;1211if (IsPrefixedInstruction())1212{1213address = GetEffectiveAddress();1214*reg = m_pMemory->Read(address);1215}1216*reg = *reg & (~(0x1 << bit));1217if (IsPrefixedInstruction())1218m_pMemory->Write(address, *reg);1219}12201221inline void Processor::OPCodes_RES_HL(int bit)1222{1223u16 address = GetEffectiveAddress();1224u8 result = m_pMemory->Read(address);1225result &= ~(0x1 << bit);1226m_pMemory->Write(address, result);1227}12281229#endif /* PROCESSOR_INLINE_H */1230123112321233