mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2024-09-11 03:54:47 +00:00
Move to a more standard flag representation for the 8080
This commit is contained in:
parent
71e6902aeb
commit
675b82b5af
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
@ -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;
|
||||
|
@ -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() {
|
||||
|
@ -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>
|
||||
|
@ -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">
|
||||
|
Loading…
Reference in New Issue
Block a user