# Conflicts:
#	Z80/src/Z80.vcxproj
This commit is contained in:
Adrian.Conlon 2017-06-08 21:55:33 +01:00
commit d4d92f21e6
7 changed files with 115 additions and 113 deletions

View File

@ -135,6 +135,14 @@ namespace EightBit {
// //
register16_t fetchWord() {
register16_t returned;
Processor::fetchWord(returned);
return returned;
}
//
void compare(uint8_t value) { void compare(uint8_t value) {
uint16_t subtraction = A() - value; uint16_t subtraction = A() - value;
adjustSZP((uint8_t)subtraction); adjustSZP((uint8_t)subtraction);
@ -325,9 +333,9 @@ namespace EightBit {
m_memory.set(HL().word, data); m_memory.set(HL().word, data);
} }
void lxi_b() { BC() = fetchWord(); } void lxi_b() { Processor::fetchWord(BC()); }
void lxi_d() { DE() = fetchWord(); } void lxi_d() { Processor::fetchWord(DE()); }
void lxi_h() { HL() = fetchWord(); } void lxi_h() { Processor::fetchWord(HL()); }
void stax_b() { m_memory.set(BC().word, A()); } void stax_b() { m_memory.set(BC().word, A()); }
void stax_d() { m_memory.set(DE().word, A()); } void stax_d() { m_memory.set(DE().word, A()); }
@ -371,14 +379,13 @@ namespace EightBit {
pushWord(pair); pushWord(pair);
} }
void pop_b() { BC() = popWord(); } void pop_b() { popWord(BC()); }
void pop_d() { DE() = popWord(); } void pop_d() { popWord(DE()); }
void pop_h() { HL() = popWord(); } void pop_h() { popWord(HL()); }
void pop_psw() { void pop_psw() {
auto af = popWord(); F() = pop();
A() = af.high; A() = pop();
F() = af.low;
} }
void xhtl() { void xhtl() {
@ -392,7 +399,7 @@ namespace EightBit {
} }
void lxi_sp() { void lxi_sp() {
sp = fetchWord(); Processor::fetchWord(sp);
} }
void inx_sp() { ++sp.word; } void inx_sp() { ++sp.word; }
@ -440,7 +447,7 @@ namespace EightBit {
// return // return
void ret() { void ret() {
pc = popWord(); popWord(pc);
} }
void rc() { returnConditional(F().C); } void rc() { returnConditional(F().C); }

View File

@ -183,12 +183,12 @@
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
<Import Project="..\..\packages\boost.1.64.0.0\build\native\boost.targets" Condition="Exists('..\..\packages\boost.1.64.0.0\build\native\boost.targets')" /> <Import Project="..\..\..\..\packages\boost.1.64.0.0\build\native\boost.targets" Condition="Exists('..\..\..\..\packages\boost.1.64.0.0\build\native\boost.targets')" />
</ImportGroup> </ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup> <PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup> </PropertyGroup>
<Error Condition="!Exists('..\..\packages\boost.1.64.0.0\build\native\boost.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\boost.1.64.0.0\build\native\boost.targets'))" /> <Error Condition="!Exists('..\..\..\..\packages\boost.1.64.0.0\build\native\boost.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\boost.1.64.0.0\build\native\boost.targets'))" />
</Target> </Target>
</Project> </Project>

View File

@ -131,6 +131,10 @@ namespace EightBit {
std::array<bool, 8> m_halfCarryTableAdd = { { false, false, true, false, true, false, true, true } }; std::array<bool, 8> m_halfCarryTableAdd = { { false, false, true, false, true, false, true, true } };
std::array<bool, 8> m_halfCarryTableSub = { { false, true, true, true, false, false, false, true } }; std::array<bool, 8> m_halfCarryTableSub = { { false, true, true, true, false, false, false, true } };
void fetchWord() {
Processor::fetchWord(MEMPTR());
}
int fetchExecute() { int fetchExecute() {
M1() = true; M1() = true;
return execute(fetchByteExecute()); return execute(fetchByteExecute());
@ -251,40 +255,33 @@ namespace EightBit {
} }
} }
uint8_t getViaMemptr(register16_t address) { uint8_t getViaMemptr() {
m_memory.ADDRESS() = address; m_memory.ADDRESS() = MEMPTR();
MEMPTR().word = address.word + 1; MEMPTR().word++;
return m_memory.reference(); return m_memory.reference();
} }
void setViaMemptr(register16_t address, uint8_t value) { void setViaMemptr(uint8_t value) {
m_memory.ADDRESS() = address; m_memory.ADDRESS() = MEMPTR();
MEMPTR().word++;
m_memory.reference() = value; m_memory.reference() = value;
++address.word;
MEMPTR().low = address.low;
MEMPTR().high = value; MEMPTR().high = value;
} }
register16_t getWordViaMemptr(register16_t address) { void getWordViaMemptr(register16_t& value) {
register16_t returned; m_memory.ADDRESS() = MEMPTR();
m_memory.ADDRESS() = address; MEMPTR().word++;
returned.low = m_memory.reference(); value.low = m_memory.reference();
m_memory.ADDRESS().word++; m_memory.ADDRESS().word++;
returned.high = m_memory.reference(); value.high = m_memory.reference();
MEMPTR() = m_memory.ADDRESS();
return returned;
} }
void setWordViaMemptr(register16_t address, register16_t value) { void setWordViaMemptr(register16_t value) {
m_memory.ADDRESS() = address; m_memory.ADDRESS() = MEMPTR();
MEMPTR().word++;
m_memory.reference() = value.low; m_memory.reference() = value.low;
m_memory.ADDRESS().word++; m_memory.ADDRESS().word++;
m_memory.reference() = value.high; m_memory.reference() = value.high;
MEMPTR() = m_memory.ADDRESS();
}
void setPcViaMemptr(register16_t address) {
MEMPTR() = pc = address;
} }
void addViaMemptr(register16_t& hl, register16_t operand) { void addViaMemptr(register16_t& hl, register16_t operand) {
@ -365,9 +362,9 @@ namespace EightBit {
void jumpConditional(int condition); void jumpConditional(int condition);
void jumpConditionalFlag(int flag); void jumpConditionalFlag(int flag);
void call(register16_t address); void call();
void callConditional(register16_t address, int condition); void callConditional(int condition);
void callConditionalFlag(register16_t address, int flag); void callConditionalFlag(int flag);
void sbc(register16_t& operand, register16_t value); void sbc(register16_t& operand, register16_t value);
void adc(register16_t& operand, register16_t value); void adc(register16_t& operand, register16_t value);

View File

@ -167,17 +167,15 @@ void EightBit::Z80::postDecrement(uint8_t value) {
void EightBit::Z80::restart(uint8_t address) { void EightBit::Z80::restart(uint8_t address) {
pushWord(pc); pushWord(pc);
register16_t destination; pc.low = MEMPTR().low = address;
destination.word = address; pc.high = MEMPTR().high = 0;
setPcViaMemptr(destination);
} }
void EightBit::Z80::jrConditional(int conditional) { void EightBit::Z80::jrConditional(int conditional) {
auto offset = (int8_t)fetchByteData(); auto offset = (int8_t)fetchByteData();
if (conditional) { if (conditional) {
register16_t destination; MEMPTR().word = pc.word + offset;
destination.word = pc.word + offset; pc = MEMPTR();
setPcViaMemptr(destination);
cycles += 5; cycles += 5;
} }
} }
@ -212,10 +210,8 @@ void EightBit::Z80::jrConditionalFlag(int flag) {
} }
void EightBit::Z80::jumpConditional(int conditional) { void EightBit::Z80::jumpConditional(int conditional) {
auto address = fetchWord();
if (conditional) if (conditional)
pc = address; pc = MEMPTR();
MEMPTR() = address;
} }
void EightBit::Z80::jumpConditionalFlag(int flag) { void EightBit::Z80::jumpConditionalFlag(int flag) {
@ -248,7 +244,8 @@ void EightBit::Z80::jumpConditionalFlag(int flag) {
} }
void EightBit::Z80::ret() { void EightBit::Z80::ret() {
setPcViaMemptr(popWord()); popWord(MEMPTR());
pc = MEMPTR();
} }
void EightBit::Z80::retn() { void EightBit::Z80::retn() {
@ -296,44 +293,42 @@ void EightBit::Z80::returnConditionalFlag(int flag) {
} }
} }
void EightBit::Z80::call(register16_t address) { void EightBit::Z80::call() {
pushWord(pc); pushWord(pc);
pc = address; pc = MEMPTR();
cycles += 7;
} }
void EightBit::Z80::callConditional(register16_t address, int condition) { void EightBit::Z80::callConditional(int condition) {
if (condition) { if (condition)
call(address); call();
cycles += 7;
}
MEMPTR() = address;
} }
void EightBit::Z80::callConditionalFlag(register16_t address, int flag) { void EightBit::Z80::callConditionalFlag(int flag) {
switch (flag) { switch (flag) {
case 0: // NZ case 0: // NZ
callConditional(address, !(F() & ZF)); callConditional(!(F() & ZF));
break; break;
case 1: // Z case 1: // Z
callConditional(address, F() & ZF); callConditional(F() & ZF);
break; break;
case 2: // NC case 2: // NC
callConditional(address, !(F() & CF)); callConditional(!(F() & CF));
break; break;
case 3: // C case 3: // C
callConditional(address, F() & CF); callConditional(F() & CF);
break; break;
case 4: // PO case 4: // PO
callConditional(address, !(F() & PF)); callConditional(!(F() & PF));
break; break;
case 5: // PE case 5: // PE
callConditional(address, F() & PF); callConditional(F() & PF);
break; break;
case 6: // P case 6: // P
callConditional(address, !(F() & SF)); callConditional(!(F() & SF));
break; break;
case 7: // M case 7: // M
callConditional(address, F() & SF); callConditional(F() & SF);
break; break;
} }
} }
@ -656,12 +651,7 @@ void EightBit::Z80::xhtl(register16_t& operand) {
} }
void EightBit::Z80::xhtl() { void EightBit::Z80::xhtl() {
if (m_prefixDD) xhtl(ALT_HL());
xhtl(IX());
else if (m_prefixFD)
xhtl(IY());
else
xhtl(HL());
} }
#pragma endregion Miscellaneous instructions #pragma endregion Miscellaneous instructions
@ -775,27 +765,25 @@ void EightBit::Z80::lddr() {
#pragma region Block input instructions #pragma region Block input instructions
void EightBit::Z80::ini() { void EightBit::Z80::ini() {
auto bc = BC().word; MEMPTR() = m_memory.ADDRESS() = BC();
m_memory.ADDRESS().word = bc; MEMPTR().word++;
readPort(); readPort();
auto value = m_memory.DATA(); auto value = m_memory.DATA();
m_memory.ADDRESS().word = HL().word++; m_memory.ADDRESS().word = HL().word++;
m_memory.reference() = value; m_memory.reference() = value;
postDecrement(--B()); postDecrement(--B());
setFlag(NF); setFlag(NF);
MEMPTR().word = ++bc;
} }
void EightBit::Z80::ind() { void EightBit::Z80::ind() {
auto bc = BC().word; MEMPTR() = m_memory.ADDRESS() = BC();
m_memory.ADDRESS().word = bc; MEMPTR().word--;
readPort(); readPort();
auto value = m_memory.DATA(); auto value = m_memory.DATA();
m_memory.ADDRESS().word = HL().word--; m_memory.ADDRESS().word = HL().word--;
m_memory.reference() = value; m_memory.reference() = value;
postDecrement(--B()); postDecrement(--B());
setFlag(NF); setFlag(NF);
MEMPTR().word = --bc;
} }
void EightBit::Z80::inir() { void EightBit::Z80::inir() {
@ -863,27 +851,27 @@ void EightBit::Z80::otdr() {
#pragma region Nibble rotation #pragma region Nibble rotation
void EightBit::Z80::rrd() { void EightBit::Z80::rrd() {
auto accumulator = A(); MEMPTR() = m_memory.ADDRESS() = HL();
m_memory.ADDRESS() = HL(); MEMPTR().word++;
auto memory = m_memory.reference(); auto memory = m_memory.reference();
auto accumulator = A();
A() = (accumulator & 0xf0) | lowNibble(memory); A() = (accumulator & 0xf0) | lowNibble(memory);
uint8_t updated = promoteNibble(lowNibble(accumulator)) | highNibble(memory); uint8_t updated = promoteNibble(lowNibble(accumulator)) | highNibble(memory);
m_memory.reference() = updated; m_memory.reference() = updated;
adjustSZPXY(A()); adjustSZPXY(A());
clearFlag(NF | HC); clearFlag(NF | HC);
MEMPTR().word = HL().word + 1;
} }
void EightBit::Z80::rld() { void EightBit::Z80::rld() {
auto accumulator = A(); MEMPTR() = m_memory.ADDRESS() = HL();
m_memory.ADDRESS() = HL(); MEMPTR().word++;
auto memory = m_memory.reference(); auto memory = m_memory.reference();
auto accumulator = A();
uint8_t updated = lowNibble(accumulator) | promoteNibble(memory); uint8_t updated = lowNibble(accumulator) | promoteNibble(memory);
A() = (accumulator & 0xf0) | highNibble(memory); A() = (accumulator & 0xf0) | highNibble(memory);
m_memory.reference() = updated; m_memory.reference() = updated;
adjustSZPXY(A()); adjustSZPXY(A());
clearFlag(NF | HC); clearFlag(NF | HC);
MEMPTR().word = HL().word + 1;
} }
#pragma endregion Nibble rotation #pragma endregion Nibble rotation
@ -1060,22 +1048,22 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
switch (z) { switch (z) {
case 0: // Input from port with 16-bit address case 0: // Input from port with 16-bit address
MEMPTR() = m_memory.ADDRESS() = BC(); MEMPTR() = m_memory.ADDRESS() = BC();
MEMPTR().word++;
readPort(); readPort();
if (y != 6) // IN r[y],(C) if (y != 6) // IN r[y],(C)
R(y) = m_memory.DATA(); R(y) = m_memory.DATA();
adjustSZPXY(m_memory.DATA()); adjustSZPXY(m_memory.DATA());
clearFlag(HC | NF); clearFlag(HC | NF);
MEMPTR().word++;
cycles += 12; cycles += 12;
break; break;
case 1: // Output to port with 16-bit address case 1: // Output to port with 16-bit address
MEMPTR() = m_memory.ADDRESS() = BC(); MEMPTR() = m_memory.ADDRESS() = BC();
MEMPTR().word++;
if (y == 6) // OUT (C),0 if (y == 6) // OUT (C),0
m_memory.placeDATA(0); m_memory.placeDATA(0);
else // OUT (C),r[y] else // OUT (C),r[y]
m_memory.placeDATA(R(y)); m_memory.placeDATA(R(y));
writePort(); writePort();
MEMPTR().word++;
cycles += 12; cycles += 12;
break; break;
case 2: // 16-bit add/subtract with carry case 2: // 16-bit add/subtract with carry
@ -1092,10 +1080,12 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
case 3: // Retrieve/store register pair from/to immediate address case 3: // Retrieve/store register pair from/to immediate address
switch (q) { switch (q) {
case 0: // LD (nn), rp[p] case 0: // LD (nn), rp[p]
setWordViaMemptr(fetchWord(), RP(p)); fetchWord();
setWordViaMemptr(RP(p));
break; break;
case 1: // LD rp[p], (nn) case 1: // LD rp[p], (nn)
RP(p) = getWordViaMemptr(fetchWord()); fetchWord();
getWordViaMemptr(RP(p));
break; break;
} }
cycles += 20; cycles += 20;
@ -1276,8 +1266,8 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
break; break;
case 1: // 16-bit load immediate/add case 1: // 16-bit load immediate/add
switch (q) { switch (q) {
case 0: // LD rp,nn case 0: // LD rp,nn
RP(p) = fetchWord(); Processor::fetchWord(RP(p));
cycles += 10; cycles += 10;
break; break;
case 1: // ADD HL,rp case 1: // ADD HL,rp
@ -1291,19 +1281,23 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
case 0: case 0:
switch (p) { switch (p) {
case 0: // LD (BC),A case 0: // LD (BC),A
setViaMemptr(BC(), A()); MEMPTR() = BC();
setViaMemptr(A());
cycles += 7; cycles += 7;
break; break;
case 1: // LD (DE),A case 1: // LD (DE),A
setViaMemptr(DE(), A()); MEMPTR() = DE();
setViaMemptr(A());
cycles += 7; cycles += 7;
break; break;
case 2: // LD (nn),HL case 2: // LD (nn),HL
setWordViaMemptr(fetchWord(), ALT_HL()); fetchWord();
setWordViaMemptr(ALT_HL());
cycles += 16; cycles += 16;
break; break;
case 3: // LD (nn),A case 3: // LD (nn),A
setViaMemptr(fetchWord(), A()); fetchWord();
setViaMemptr(A());
cycles += 13; cycles += 13;
break; break;
} }
@ -1311,19 +1305,23 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
case 1: case 1:
switch (p) { switch (p) {
case 0: // LD A,(BC) case 0: // LD A,(BC)
A() = getViaMemptr(BC()); MEMPTR() = BC();
A() = getViaMemptr();
cycles += 7; cycles += 7;
break; break;
case 1: // LD A,(DE) case 1: // LD A,(DE)
A() = getViaMemptr(DE()); MEMPTR() = DE();
A() = getViaMemptr();
cycles += 7; cycles += 7;
break; break;
case 2: // LD HL,(nn) case 2: // LD HL,(nn)
ALT_HL() = getWordViaMemptr(fetchWord()); fetchWord();
getWordViaMemptr(ALT_HL());
cycles += 16; cycles += 16;
break; break;
case 3: // LD A,(nn) case 3: // LD A,(nn)
A() = getViaMemptr(fetchWord()); fetchWord();
A() = getViaMemptr();
cycles += 13; cycles += 13;
break; break;
} }
@ -1466,7 +1464,7 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
case 1: // POP & various ops case 1: // POP & various ops
switch (q) { switch (q) {
case 0: // POP rp2[p] case 0: // POP rp2[p]
RP2(p) = popWord(); popWord(RP2(p));
cycles += 10; cycles += 10;
break; break;
case 1: case 1:
@ -1491,13 +1489,15 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
} }
break; break;
case 2: // Conditional jump case 2: // Conditional jump
fetchWord();
jumpConditionalFlag(y); jumpConditionalFlag(y);
cycles += 10; cycles += 10;
break; break;
case 3: // Assorted operations case 3: // Assorted operations
switch (y) { switch (y) {
case 0: // JP nn case 0: // JP nn
setPcViaMemptr(fetchWord()); fetchWord();
pc = MEMPTR();
cycles += 10; cycles += 10;
break; break;
case 1: // CB prefix case 1: // CB prefix
@ -1543,7 +1543,8 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
} }
break; break;
case 4: // Conditional call: CALL cc[y], nn case 4: // Conditional call: CALL cc[y], nn
callConditionalFlag(fetchWord(), y); fetchWord();
callConditionalFlag(y);
cycles += 10; cycles += 10;
break; break;
case 5: // PUSH & various ops case 5: // PUSH & various ops
@ -1555,7 +1556,8 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
case 1: case 1:
switch (p) { switch (p) {
case 0: // CALL nn case 0: // CALL nn
callConditional(fetchWord(), true); fetchWord();
call();
cycles += 17; cycles += 17;
break; break;
case 1: // DD prefix case 1: // DD prefix

View File

@ -174,12 +174,12 @@
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
<Import Project="..\..\packages\boost.1.64.0.0\build\native\boost.targets" Condition="Exists('..\..\packages\boost.1.64.0.0\build\native\boost.targets')" /> <Import Project="..\..\..\..\packages\boost.1.64.0.0\build\native\boost.targets" Condition="Exists('..\..\..\..\packages\boost.1.64.0.0\build\native\boost.targets')" />
</ImportGroup> </ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup> <PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup> </PropertyGroup>
<Error Condition="!Exists('..\..\packages\boost.1.64.0.0\build\native\boost.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\boost.1.64.0.0\build\native\boost.targets'))" /> <Error Condition="!Exists('..\..\..\..\packages\boost.1.64.0.0\build\native\boost.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\boost.1.64.0.0\build\native\boost.targets'))" />
</Target> </Target>
</Project> </Project>

View File

@ -78,7 +78,7 @@ namespace EightBit {
void pushWord(register16_t value); void pushWord(register16_t value);
uint8_t pop(); uint8_t pop();
register16_t popWord(); void popWord(register16_t& output);
uint8_t fetchByte() { uint8_t fetchByte() {
m_memory.ADDRESS() = pc; m_memory.ADDRESS() = pc;
@ -86,11 +86,9 @@ namespace EightBit {
return m_memory.reference(); return m_memory.reference();
} }
register16_t fetchWord() { void fetchWord(register16_t& output) {
register16_t returned; output.low = fetchByte();
returned.low = fetchByte(); output.high = fetchByte();
returned.high = fetchByte();
return returned;
} }
}; };
} }

View File

@ -35,9 +35,7 @@ uint8_t EightBit::Processor::pop() {
return m_memory.reference(); return m_memory.reference();
} }
EightBit::register16_t EightBit::Processor::popWord() { void EightBit::Processor::popWord(register16_t& output) {
register16_t returned; output.low = pop();
returned.low = pop(); output.high = pop();
returned.high = pop();
return returned;
} }