Move to a more standard flag representation for the 8080

This commit is contained in:
Adrian.Conlon 2017-06-16 01:58:12 +01:00
parent 71e6902aeb
commit 675b82b5af
7 changed files with 113 additions and 159 deletions

View File

@ -12,6 +12,8 @@ namespace EightBit {
static std::string state(Intel8080& cpu);
static std::string disassemble(Intel8080& cpu);
static std::string flag(uint8_t value, int flag, const std::string& represents);
static std::string flags(uint8_t value);
static std::string hex(uint8_t value);
static std::string hex(uint16_t value);
static std::string binary(uint8_t value);

View File

@ -3,7 +3,6 @@
// Auxiliary carry logic from https://github.com/begoon/i8080-core
#include "IntelProcessor.h"
#include "StatusFlags.h"
#include "InputOutput.h"
namespace EightBit {
@ -11,6 +10,14 @@ namespace EightBit {
public:
typedef std::function<void()> instruction_t;
enum StatusBits {
SF = Bit7,
ZF = Bit6,
AC = Bit4,
PF = Bit2,
CF = Bit0,
};
enum AddressingMode {
Unknown,
Implied, // zero bytes
@ -31,8 +38,14 @@ namespace EightBit {
const std::array<Instruction, 0x100>& getInstructions() const { return instructions; }
uint8_t& A() { return a; }
StatusFlags& F() { return f; }
register16_t& AF() {
af.low &= ~(Bit5 | Bit3);
af.low |= Bit1;
return af;
}
uint8_t& A() { return AF().high; }
uint8_t& F() { return AF().low; }
register16_t& BC() { return bc; }
uint8_t& B() { return BC().high; }
@ -66,15 +79,24 @@ namespace EightBit {
std::array<Instruction, 0x100> instructions;
uint8_t a;
StatusFlags f;
register16_t af;
register16_t bc;
register16_t de;
register16_t hl;
bool m_interrupt;
void clearFlag(int flag) { F() &= ~flag; }
void setFlag(int flag) { F() |= flag; }
void setFlag(int flag, int condition) { setFlag(flag, condition != 0); }
void setFlag(int flag, uint32_t condition) { setFlag(flag, condition != 0); }
void setFlag(int flag, bool condition) { condition ? setFlag(flag) : clearFlag(flag); }
void clearFlag(int flag, int condition) { clearFlag(flag, condition != 0); }
void clearFlag(int flag, uint32_t condition) { clearFlag(flag, condition != 0); }
void clearFlag(int flag, bool condition) { condition ? clearFlag(flag) : setFlag(flag); }
int execute(uint8_t opcode);
int execute(const Instruction& instruction) {
@ -83,13 +105,13 @@ namespace EightBit {
return cycles + instruction.count;
}
void adjustSign(uint8_t value) { F().S = ((value & Bit7) != 0); }
void adjustZero(uint8_t value) { F().Z = !value; }
void adjustSign(uint8_t value) { setFlag(SF, value & SF); }
void adjustZero(uint8_t value) { clearFlag(ZF, value);}
void adjustParity(uint8_t value) {
static const uint8_t lookup[0x10] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
auto set = (lookup[highNibble(value)] + lookup[lowNibble(value)]);
F().P = !(set % 2);
clearFlag(PF, set % 2);
}
void adjustSZP(uint8_t value) {
@ -99,21 +121,21 @@ namespace EightBit {
}
void adjustAuxiliaryCarryAdd(uint8_t value, int calculation) {
F().AC = calculateHalfCarryAdd(A(), value, calculation);
setFlag(AC, calculateHalfCarryAdd(A(), value, calculation));
}
void adjustAuxiliaryCarrySub(uint8_t value, int calculation) {
F().AC = !calculateHalfCarrySub(A(), value, calculation);
clearFlag(AC, calculateHalfCarrySub(A(), value, calculation));
}
void postIncrement(uint8_t value) {
adjustSZP(value);
F().AC = !lowNibble(value);
clearFlag(AC, lowNibble(value));
}
void postDecrement(uint8_t value) {
adjustSZP(value);
F().AC = lowNibble(value) != Mask4;
setFlag(AC, lowNibble(value) != Mask4);
}
static Instruction INS(instruction_t method, AddressingMode mode, std::string disassembly, int cycles);
@ -127,22 +149,22 @@ namespace EightBit {
uint16_t subtraction = A() - value;
adjustSZP((uint8_t)subtraction);
adjustAuxiliaryCarrySub(value, subtraction);
F().C = (subtraction & Bit8) != 0;
setFlag(CF, subtraction & Bit8);
}
void anda(uint8_t value) {
F().AC = (((A() | value) & Bit3) != 0);
F().C = false;
setFlag(AC, (A() | value) & Bit3);
clearFlag(CF);
adjustSZP(A() &= value);
}
void ora(uint8_t value) {
F().AC = F().C = false;
clearFlag(AC | CF);
adjustSZP(A() |= value);
}
void xra(uint8_t value) {
F().AC = F().C = false;
clearFlag(AC | CF);
adjustSZP(A() ^= value);
}
@ -151,17 +173,17 @@ namespace EightBit {
sum.word = A() + value + carry;
adjustAuxiliaryCarryAdd(value, sum.word);
A() = sum.low;
F().C = (sum.word & Bit8) != 0;
setFlag(CF, sum.word & Bit8);
adjustSZP(A());
}
void adc(uint8_t value) {
add(value, F().C);
add(value, F() & CF);
}
void dad(uint16_t value) {
uint32_t sum = HL().word + value;
F().C = sum > 0xffff;
setFlag(CF, sum > 0xffff);
HL().word = (uint16_t)sum;
}
@ -170,12 +192,12 @@ namespace EightBit {
difference.word = A() - value - carry;
adjustAuxiliaryCarrySub(value, difference.word);
A() = difference.low;
F().C = (difference.word & Bit8) != 0;
setFlag(CF, difference.word & Bit8);
adjustSZP(A());
}
void sbb(uint8_t value) {
sub(value, F().C);
sub(value, F() & CF);
}
void mov_m_r(uint8_t value) {
@ -316,22 +338,12 @@ namespace EightBit {
void push_b() { pushWord(BC()); }
void push_d() { pushWord(DE()); }
void push_h() { pushWord(HL()); }
void push_psw() {
register16_t pair;
pair.low = F();
pair.high = A();
pushWord(pair);
}
void push_psw() { pushWord(AF()); }
void pop_b() { popWord(BC()); }
void pop_d() { popWord(DE()); }
void pop_h() { popWord(HL()); }
void pop_psw() {
F() = pop();
A() = pop();
}
void pop_psw() { popWord(AF()); }
void xhtl() {
auto tos = m_memory.getWord(sp.word);
@ -354,17 +366,17 @@ namespace EightBit {
void jmp() { jumpConditional(true); }
void jc() { jumpConditional(F().C); }
void jnc() { jumpConditional(!F().C); }
void jc() { jumpConditional(F() & CF); }
void jnc() { jumpConditional(!(F() & CF)); }
void jz() { jumpConditional(F().Z); }
void jnz() { jumpConditional(!F().Z); }
void jz() { jumpConditional(F() & ZF); }
void jnz() { jumpConditional(!(F() & ZF)); }
void jpe() { jumpConditional(F().P); }
void jpo() { jumpConditional(!F().P); }
void jpe() { jumpConditional(F() & PF); }
void jpo() { jumpConditional(!(F() & PF)); }
void jm() { jumpConditional(F().S); }
void jp() { jumpConditional(!F().S); }
void jm() { jumpConditional(F() & SF); }
void jp() { jumpConditional(!(F() & SF)); }
void pchl() {
pc = HL();
@ -377,31 +389,31 @@ namespace EightBit {
call();
}
void cc() { if (callConditional(F().C)) cycles += 6; }
void cnc() { if (callConditional(!F().C)) cycles += 6; }
void cc() { if (callConditional(F() & CF)) cycles += 6; }
void cnc() { if (callConditional(!(F() & CF))) cycles += 6; }
void cpe() { if (callConditional(F().P)) cycles += 6; }
void cpo() { if (callConditional(!F().P)) cycles += 6; }
void cpe() { if (callConditional(F() & PF)) cycles += 6; }
void cpo() { if (callConditional(!(F() & PF))) cycles += 6; }
void cz() { if (callConditional(F().Z)) cycles += 6; }
void cnz() { if (callConditional(!F().Z)) cycles += 6; }
void cz() { if (callConditional(F() & ZF)) cycles += 6; }
void cnz() { if (callConditional(!(F() & ZF))) cycles += 6; }
void cm() { if (callConditional(F().S)) cycles += 6; }
void cp() { if (callConditional(!F().S)) cycles += 6; }
void cm() { if (callConditional(F() & SF)) cycles += 6; }
void cp() { if (callConditional(!(F() & SF))) cycles += 6; }
// return
void rc() { if (returnConditional(F().C)) cycles += 6; }
void rnc() { if (returnConditional(!F().C)) cycles += 6; }
void rc() { if (returnConditional(F() & CF)) cycles += 6; }
void rnc() { if (returnConditional(!(F() & CF))) cycles += 6; }
void rz() { if (returnConditional(F().Z)) cycles += 6; }
void rnz() { if (returnConditional(!F().Z)) cycles += 6; }
void rz() { if (returnConditional(F() & ZF)) cycles += 6; }
void rnz() { if (returnConditional(!(F() & ZF))) cycles += 6; }
void rpe() { if (returnConditional(F().P)) cycles += 6; }
void rpo() { if (returnConditional(!F().P)) cycles += 6; }
void rpe() { if (returnConditional(F() & PF)) cycles += 6; }
void rpo() { if (returnConditional(!(F() & PF))) cycles += 6; }
void rm() { if (returnConditional(F().S)) cycles += 6; }
void rp() { if (returnConditional(!F().S)) cycles += 6; }
void rm() { if (returnConditional(F() & SF)) cycles += 6; }
void rp() { if (returnConditional(!(F() & SF))) cycles += 6; }
// restart
@ -594,49 +606,49 @@ namespace EightBit {
void rlc() {
auto carry = A() & Bit7;
A() <<= 1;
A() |= carry >> 7;
F().C = carry != 0;
carry ? A() |= Bit0 : A() &= ~Bit0;
setFlag(CF, carry);
}
void rrc() {
auto carry = A() & 1;
auto carry = A() & Bit0;
A() >>= 1;
A() |= carry << 7;
F().C = carry != 0;
carry ? A() |= Bit7 : A() &= ~Bit7;
setFlag(CF, carry);
}
void ral() {
auto carry = A() & Bit7;
A() <<= 1;
A() |= (uint8_t)F().C;
F().C = carry != 0;
A() |= (F() & CF);
setFlag(CF, carry);
}
void rar() {
auto carry = A() & 1;
A() >>= 1;
A() |= F().C << 7;
F().C = carry != 0;
A() |= (F() & CF) << 7;
setFlag(CF, carry);
}
// specials
void cma() { A() ^= Mask8; }
void stc() { F().C = true; }
void cmc() { F().C = !F().C; }
void stc() { setFlag(CF); }
void cmc() { clearFlag(CF, F() & CF); }
void daa() {
auto carry = F().C;
auto carry = F() & CF;
uint8_t addition = 0;
if (F().AC || lowNibble(A()) > 9) {
if ((F() & AC) || lowNibble(A()) > 9) {
addition = 0x6;
}
if (F().C || highNibble(A()) > 9 || (highNibble(A()) >= 9 && lowNibble(A()) > 9)) {
if ((F() & CF) || highNibble(A()) > 9 || (highNibble(A()) >= 9 && lowNibble(A()) > 9)) {
addition |= 0x60;
carry = true;
}
add(addition);
F().C = carry;
setFlag(CF, carry);
}
// input/output

View File

@ -1,72 +0,0 @@
#pragma once
#include <string>
#include <cstdint>
namespace EightBit {
struct StatusFlags {
bool S;
bool Z;
bool AC;
bool P;
bool C;
enum StatusBits {
Sign = 0x80, // S
Zero = 0x40, // Z
AuxiliaryCarry = 0x10, // AC
Parity = 0x4, // Z
Carry = 0x1, // S
};
StatusFlags(uint8_t value) {
S = (value & StatusBits::Sign) != 0;
Z = (value & StatusBits::Zero) != 0;
AC = (value & StatusBits::AuxiliaryCarry) != 0;
P = (value & StatusBits::Parity) != 0;
C = (value & StatusBits::Carry) != 0;
}
operator uint8_t() const {
uint8_t flags = 0;
if (S)
flags |= StatusBits::Sign;
if (Z)
flags |= StatusBits::Zero;
flags &= ~0x20; // Reserved off
if (AC)
flags |= StatusBits::AuxiliaryCarry;
flags &= ~0x8; // Reserved off
if (P)
flags |= StatusBits::Parity;
flags |= 0x2; // Reserved on
if (C)
flags |= StatusBits::Carry;
return flags;
}
operator std::string() const {
std::string returned;
returned += S ? "S" : "-";
returned += Z ? "Z" : "-";
returned += "0";
returned += AC ? "A" : "-";
returned += "0";
returned += P ? "P" : "-";
returned += "1";
returned += C ? "C" : "-";
return returned;
}
};
}

View File

@ -7,7 +7,6 @@
#include "Memory.h"
#include "Intel8080.h"
#include "StatusFlags.h"
EightBit::Disassembler::Disassembler() {
}
@ -35,7 +34,7 @@ std::string EightBit::Disassembler::state(Intel8080& cpu) {
<< "PC=" << hex(pc.word)
<< " "
<< "SP=" << hex(sp.word)
<< " " << "A=" << hex(a) << " " << "F=" << (std::string)f
<< " " << "A=" << hex(a) << " " << "F=" << flags(f)
<< " " << "B=" << hex(b) << " " << "C=" << hex(c)
<< " " << "D=" << hex(d) << " " << "E=" << hex(e)
<< " " << "H=" << hex(h) << " " << "L=" << hex(l);
@ -87,6 +86,26 @@ std::string EightBit::Disassembler::disassemble(Intel8080& cpu) {
return output.str();
}
std::string EightBit::Disassembler::flag(uint8_t value, int flag, const std::string& represents) {
std::ostringstream output;
output << (value & flag ? represents : "-");
return output.str();
}
std::string EightBit::Disassembler::flags(uint8_t value) {
std::ostringstream output;
output
<< flag(value, Intel8080::SF, "S")
<< flag(value, Intel8080::ZF, "Z")
<< "0"
<< flag(value, Intel8080::AC, "A")
<< "0"
<< flag(value, Intel8080::PF, "P")
<< "1"
<< flag(value, Intel8080::CF, "C");
return output.str();
}
std::string EightBit::Disassembler::hex(uint8_t value) {
std::ostringstream output;
output << std::hex << std::setw(2) << std::setfill('0') << (int)value;

View File

@ -5,11 +5,9 @@
#include "Disassembler.h"
EightBit::Intel8080::Intel8080(Memory& memory, InputOutput& ports)
: IntelProcessor(memory),
a(0),
f(0),
m_interrupt(false),
m_ports(ports) {
: IntelProcessor(memory),
m_interrupt(false),
m_ports(ports) {
bc.word = de.word = hl.word = 0;
installInstructions();
}
@ -61,8 +59,7 @@ void EightBit::Intel8080::installInstructions() {
void EightBit::Intel8080::initialise() {
Processor::initialise();
bc.word = de.word = hl.word = 0;
a = f = 0;
AF().word = BC().word = DE().word = HL().word = 0;
}
int EightBit::Intel8080::step() {

View File

@ -148,7 +148,6 @@
<ClInclude Include="..\inc\Intel8080.h" />
<ClInclude Include="..\inc\PortEventArgs.h" />
<ClInclude Include="..\inc\Profiler.h" />
<ClInclude Include="..\inc\StatusFlags.h" />
<ClInclude Include="stdafx.h" />
</ItemGroup>
<ItemGroup>

View File

@ -29,9 +29,6 @@
<ClInclude Include="..\inc\Profiler.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\StatusFlags.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">