More MEMPTR clarifications.

This time to avoid temporary variables, in a similar manner to Z80 hardware.

Signed-off-by: Adrian.Conlon <adrian.conlon@gmail.com>
This commit is contained in:
Adrian.Conlon 2017-06-07 22:54:55 +01:00
parent 633ba49784
commit d8977d32d3
5 changed files with 110 additions and 103 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) {
uint16_t subtraction = A() - value;
adjustSZP((uint8_t)subtraction);
@ -325,9 +333,9 @@ namespace EightBit {
m_memory.set(HL().word, data);
}
void lxi_b() { BC() = fetchWord(); }
void lxi_d() { DE() = fetchWord(); }
void lxi_h() { HL() = fetchWord(); }
void lxi_b() { Processor::fetchWord(BC()); }
void lxi_d() { Processor::fetchWord(DE()); }
void lxi_h() { Processor::fetchWord(HL()); }
void stax_b() { m_memory.set(BC().word, A()); }
void stax_d() { m_memory.set(DE().word, A()); }
@ -371,14 +379,13 @@ namespace EightBit {
pushWord(pair);
}
void pop_b() { BC() = popWord(); }
void pop_d() { DE() = popWord(); }
void pop_h() { HL() = popWord(); }
void pop_b() { popWord(BC()); }
void pop_d() { popWord(DE()); }
void pop_h() { popWord(HL()); }
void pop_psw() {
auto af = popWord();
A() = af.high;
F() = af.low;
F() = pop();
A() = pop();
}
void xhtl() {
@ -392,7 +399,7 @@ namespace EightBit {
}
void lxi_sp() {
sp = fetchWord();
Processor::fetchWord(sp);
}
void inx_sp() { ++sp.word; }
@ -440,7 +447,7 @@ namespace EightBit {
// return
void ret() {
pc = popWord();
popWord(pc);
}
void rc() { returnConditional(F().C); }

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_halfCarryTableSub = { { false, true, true, true, false, false, false, true } };
void fetchWord() {
Processor::fetchWord(MEMPTR());
}
int fetchExecute() {
M1() = true;
return execute(fetchByteExecute());
@ -251,40 +255,33 @@ namespace EightBit {
}
}
uint8_t getViaMemptr(register16_t address) {
m_memory.ADDRESS() = address;
MEMPTR().word = address.word + 1;
uint8_t getViaMemptr() {
m_memory.ADDRESS() = MEMPTR();
MEMPTR().word++;
return m_memory.reference();
}
void setViaMemptr(register16_t address, uint8_t value) {
m_memory.ADDRESS() = address;
void setViaMemptr(uint8_t value) {
m_memory.ADDRESS() = MEMPTR();
MEMPTR().word++;
m_memory.reference() = value;
++address.word;
MEMPTR().low = address.low;
MEMPTR().high = value;
}
register16_t getWordViaMemptr(register16_t address) {
register16_t returned;
m_memory.ADDRESS() = address;
returned.low = m_memory.reference();
void getWordViaMemptr(register16_t& value) {
m_memory.ADDRESS() = MEMPTR();
MEMPTR().word++;
value.low = m_memory.reference();
m_memory.ADDRESS().word++;
returned.high = m_memory.reference();
MEMPTR() = m_memory.ADDRESS();
return returned;
value.high = m_memory.reference();
}
void setWordViaMemptr(register16_t address, register16_t value) {
m_memory.ADDRESS() = address;
void setWordViaMemptr(register16_t value) {
m_memory.ADDRESS() = MEMPTR();
MEMPTR().word++;
m_memory.reference() = value.low;
m_memory.ADDRESS().word++;
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) {
@ -365,9 +362,9 @@ namespace EightBit {
void jumpConditional(int condition);
void jumpConditionalFlag(int flag);
void call(register16_t address);
void callConditional(register16_t address, int condition);
void callConditionalFlag(register16_t address, int flag);
void call();
void callConditional(int condition);
void callConditionalFlag(int flag);
void sbc(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) {
pushWord(pc);
register16_t destination;
destination.word = address;
setPcViaMemptr(destination);
pc.low = MEMPTR().low = address;
pc.high = MEMPTR().high = 0;
}
void EightBit::Z80::jrConditional(int conditional) {
auto offset = (int8_t)fetchByteData();
if (conditional) {
register16_t destination;
destination.word = pc.word + offset;
setPcViaMemptr(destination);
MEMPTR().word = pc.word + offset;
pc = MEMPTR();
cycles += 5;
}
}
@ -212,10 +210,8 @@ void EightBit::Z80::jrConditionalFlag(int flag) {
}
void EightBit::Z80::jumpConditional(int conditional) {
auto address = fetchWord();
if (conditional)
pc = address;
MEMPTR() = address;
pc = MEMPTR();
}
void EightBit::Z80::jumpConditionalFlag(int flag) {
@ -248,7 +244,8 @@ void EightBit::Z80::jumpConditionalFlag(int flag) {
}
void EightBit::Z80::ret() {
setPcViaMemptr(popWord());
popWord(MEMPTR());
pc = MEMPTR();
}
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);
pc = address;
pc = MEMPTR();
cycles += 7;
}
void EightBit::Z80::callConditional(register16_t address, int condition) {
if (condition) {
call(address);
cycles += 7;
}
MEMPTR() = address;
void EightBit::Z80::callConditional(int condition) {
if (condition)
call();
}
void EightBit::Z80::callConditionalFlag(register16_t address, int flag) {
void EightBit::Z80::callConditionalFlag(int flag) {
switch (flag) {
case 0: // NZ
callConditional(address, !(F() & ZF));
callConditional(!(F() & ZF));
break;
case 1: // Z
callConditional(address, F() & ZF);
callConditional(F() & ZF);
break;
case 2: // NC
callConditional(address, !(F() & CF));
callConditional(!(F() & CF));
break;
case 3: // C
callConditional(address, F() & CF);
callConditional(F() & CF);
break;
case 4: // PO
callConditional(address, !(F() & PF));
callConditional(!(F() & PF));
break;
case 5: // PE
callConditional(address, F() & PF);
callConditional(F() & PF);
break;
case 6: // P
callConditional(address, !(F() & SF));
callConditional(!(F() & SF));
break;
case 7: // M
callConditional(address, F() & SF);
callConditional(F() & SF);
break;
}
}
@ -775,27 +770,25 @@ void EightBit::Z80::lddr() {
#pragma region Block input instructions
void EightBit::Z80::ini() {
auto bc = BC().word;
m_memory.ADDRESS().word = bc;
MEMPTR() = m_memory.ADDRESS() = BC();
MEMPTR().word++;
readPort();
auto value = m_memory.DATA();
m_memory.ADDRESS().word = HL().word++;
m_memory.reference() = value;
postDecrement(--B());
setFlag(NF);
MEMPTR().word = ++bc;
}
void EightBit::Z80::ind() {
auto bc = BC().word;
m_memory.ADDRESS().word = bc;
MEMPTR() = m_memory.ADDRESS() = BC();
MEMPTR().word--;
readPort();
auto value = m_memory.DATA();
m_memory.ADDRESS().word = HL().word--;
m_memory.reference() = value;
postDecrement(--B());
setFlag(NF);
MEMPTR().word = --bc;
}
void EightBit::Z80::inir() {
@ -863,27 +856,27 @@ void EightBit::Z80::otdr() {
#pragma region Nibble rotation
void EightBit::Z80::rrd() {
auto accumulator = A();
m_memory.ADDRESS() = HL();
MEMPTR() = m_memory.ADDRESS() = HL();
MEMPTR().word++;
auto memory = m_memory.reference();
auto accumulator = A();
A() = (accumulator & 0xf0) | lowNibble(memory);
uint8_t updated = promoteNibble(lowNibble(accumulator)) | highNibble(memory);
m_memory.reference() = updated;
adjustSZPXY(A());
clearFlag(NF | HC);
MEMPTR().word = HL().word + 1;
}
void EightBit::Z80::rld() {
auto accumulator = A();
m_memory.ADDRESS() = HL();
MEMPTR() = m_memory.ADDRESS() = HL();
MEMPTR().word++;
auto memory = m_memory.reference();
auto accumulator = A();
uint8_t updated = lowNibble(accumulator) | promoteNibble(memory);
A() = (accumulator & 0xf0) | highNibble(memory);
m_memory.reference() = updated;
adjustSZPXY(A());
clearFlag(NF | HC);
MEMPTR().word = HL().word + 1;
}
#pragma endregion Nibble rotation
@ -1060,22 +1053,22 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
switch (z) {
case 0: // Input from port with 16-bit address
MEMPTR() = m_memory.ADDRESS() = BC();
MEMPTR().word++;
readPort();
if (y != 6) // IN r[y],(C)
R(y) = m_memory.DATA();
adjustSZPXY(m_memory.DATA());
clearFlag(HC | NF);
MEMPTR().word++;
cycles += 12;
break;
case 1: // Output to port with 16-bit address
MEMPTR() = m_memory.ADDRESS() = BC();
MEMPTR().word++;
if (y == 6) // OUT (C),0
m_memory.placeDATA(0);
else // OUT (C),r[y]
m_memory.placeDATA(R(y));
writePort();
MEMPTR().word++;
cycles += 12;
break;
case 2: // 16-bit add/subtract with carry
@ -1092,10 +1085,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
switch (q) {
case 0: // LD (nn), rp[p]
setWordViaMemptr(fetchWord(), RP(p));
fetchWord();
setWordViaMemptr(RP(p));
break;
case 1: // LD rp[p], (nn)
RP(p) = getWordViaMemptr(fetchWord());
fetchWord();
getWordViaMemptr(RP(p));
break;
}
cycles += 20;
@ -1276,8 +1271,8 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
break;
case 1: // 16-bit load immediate/add
switch (q) {
case 0: // LD rp,nn
RP(p) = fetchWord();
case 0: // LD rp,nn
Processor::fetchWord(RP(p));
cycles += 10;
break;
case 1: // ADD HL,rp
@ -1291,19 +1286,23 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
case 0:
switch (p) {
case 0: // LD (BC),A
setViaMemptr(BC(), A());
MEMPTR() = BC();
setViaMemptr(A());
cycles += 7;
break;
case 1: // LD (DE),A
setViaMemptr(DE(), A());
MEMPTR() = DE();
setViaMemptr(A());
cycles += 7;
break;
case 2: // LD (nn),HL
setWordViaMemptr(fetchWord(), ALT_HL());
fetchWord();
setWordViaMemptr(ALT_HL());
cycles += 16;
break;
case 3: // LD (nn),A
setViaMemptr(fetchWord(), A());
fetchWord();
setViaMemptr(A());
cycles += 13;
break;
}
@ -1311,19 +1310,23 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
case 1:
switch (p) {
case 0: // LD A,(BC)
A() = getViaMemptr(BC());
MEMPTR() = BC();
A() = getViaMemptr();
cycles += 7;
break;
case 1: // LD A,(DE)
A() = getViaMemptr(DE());
MEMPTR() = DE();
A() = getViaMemptr();
cycles += 7;
break;
case 2: // LD HL,(nn)
ALT_HL() = getWordViaMemptr(fetchWord());
fetchWord();
getWordViaMemptr(ALT_HL());
cycles += 16;
break;
case 3: // LD A,(nn)
A() = getViaMemptr(fetchWord());
fetchWord();
A() = getViaMemptr();
cycles += 13;
break;
}
@ -1466,7 +1469,7 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
case 1: // POP & various ops
switch (q) {
case 0: // POP rp2[p]
RP2(p) = popWord();
popWord(RP2(p));
cycles += 10;
break;
case 1:
@ -1491,13 +1494,15 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
}
break;
case 2: // Conditional jump
fetchWord();
jumpConditionalFlag(y);
cycles += 10;
break;
case 3: // Assorted operations
switch (y) {
case 0: // JP nn
setPcViaMemptr(fetchWord());
fetchWord();
pc = MEMPTR();
cycles += 10;
break;
case 1: // CB prefix
@ -1543,7 +1548,8 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
}
break;
case 4: // Conditional call: CALL cc[y], nn
callConditionalFlag(fetchWord(), y);
fetchWord();
callConditionalFlag(y);
cycles += 10;
break;
case 5: // PUSH & various ops
@ -1555,7 +1561,8 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
case 1:
switch (p) {
case 0: // CALL nn
callConditional(fetchWord(), true);
fetchWord();
call();
cycles += 17;
break;
case 1: // DD prefix

View File

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

View File

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