2017-06-04 20:38:34 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
// Auxiliary carry logic from https://github.com/begoon/i8080-core
|
|
|
|
|
2017-06-11 08:45:34 +00:00
|
|
|
#include "IntelProcessor.h"
|
2017-06-04 20:38:34 +00:00
|
|
|
#include "InputOutput.h"
|
|
|
|
|
|
|
|
namespace EightBit {
|
2017-06-11 08:45:34 +00:00
|
|
|
class Intel8080 : public IntelProcessor {
|
2017-06-04 20:38:34 +00:00
|
|
|
public:
|
|
|
|
typedef std::function<void()> instruction_t;
|
|
|
|
|
2017-06-16 00:58:12 +00:00
|
|
|
enum StatusBits {
|
|
|
|
SF = Bit7,
|
|
|
|
ZF = Bit6,
|
|
|
|
AC = Bit4,
|
|
|
|
PF = Bit2,
|
|
|
|
CF = Bit0,
|
|
|
|
};
|
|
|
|
|
2017-06-04 20:38:34 +00:00
|
|
|
enum AddressingMode {
|
|
|
|
Unknown,
|
|
|
|
Implied, // zero bytes
|
|
|
|
Immediate, // single byte
|
|
|
|
Absolute // two bytes, little endian
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Instruction {
|
|
|
|
instruction_t vector = nullptr;
|
|
|
|
AddressingMode mode = Unknown;
|
|
|
|
std::string disassembly;
|
|
|
|
int count = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
Intel8080(Memory& memory, InputOutput& ports);
|
|
|
|
|
|
|
|
Signal<Intel8080> ExecutingInstruction;
|
|
|
|
|
|
|
|
const std::array<Instruction, 0x100>& getInstructions() const { return instructions; }
|
|
|
|
|
2017-07-22 22:52:58 +00:00
|
|
|
bool isInterruptable() const;
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-07-22 22:52:58 +00:00
|
|
|
int interrupt(uint8_t value);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
|
|
int step();
|
|
|
|
|
2017-07-24 21:00:49 +00:00
|
|
|
virtual register16_t& AF() override {
|
|
|
|
return af;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual register16_t& BC() override {
|
|
|
|
return bc;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual register16_t& DE() override {
|
|
|
|
return de;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual register16_t& HL() override {
|
|
|
|
return hl;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void initialise();
|
|
|
|
|
2017-06-04 20:38:34 +00:00
|
|
|
private:
|
2017-06-04 21:59:56 +00:00
|
|
|
InputOutput& m_ports;
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
|
|
std::array<Instruction, 0x100> instructions;
|
|
|
|
|
2017-06-16 00:58:12 +00:00
|
|
|
register16_t af;
|
2017-06-04 20:38:34 +00:00
|
|
|
register16_t bc;
|
|
|
|
register16_t de;
|
|
|
|
register16_t hl;
|
|
|
|
|
|
|
|
bool m_interrupt;
|
|
|
|
|
2017-07-24 21:00:49 +00:00
|
|
|
uint8_t& R(int r) {
|
|
|
|
__assume(r < 8);
|
|
|
|
__assume(r >= 0);
|
|
|
|
switch (r) {
|
|
|
|
case 0b000:
|
|
|
|
return B();
|
|
|
|
case 0b001:
|
|
|
|
return C();
|
|
|
|
case 0b010:
|
|
|
|
return D();
|
|
|
|
case 0b011:
|
|
|
|
return E();
|
|
|
|
case 0b100:
|
|
|
|
return H();
|
|
|
|
case 0b101:
|
|
|
|
return L();
|
|
|
|
case 0b110:
|
|
|
|
m_memory.ADDRESS() = HL();
|
|
|
|
return m_memory.reference();
|
|
|
|
case 0b111:
|
|
|
|
return A();
|
|
|
|
default:
|
|
|
|
__assume(0);
|
|
|
|
}
|
|
|
|
throw std::logic_error("Unhandled registry mechanism");
|
|
|
|
}
|
|
|
|
|
|
|
|
register16_t& RP(int rp) {
|
|
|
|
__assume(rp < 4);
|
|
|
|
__assume(rp >= 0);
|
|
|
|
switch (rp) {
|
|
|
|
case 0b00:
|
|
|
|
return BC();
|
|
|
|
case 0b01:
|
|
|
|
return DE();
|
|
|
|
case 0b10:
|
|
|
|
return HL();
|
|
|
|
case 0b11:
|
|
|
|
return SP();
|
|
|
|
default:
|
|
|
|
__assume(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
register16_t& RP2(int rp) {
|
|
|
|
__assume(rp < 4);
|
|
|
|
__assume(rp >= 0);
|
|
|
|
switch (rp) {
|
|
|
|
case 0b00:
|
|
|
|
return BC();
|
|
|
|
case 0b01:
|
|
|
|
return DE();
|
|
|
|
case 0b10:
|
|
|
|
return HL();
|
|
|
|
case 0b11:
|
|
|
|
return AF();
|
|
|
|
default:
|
|
|
|
__assume(0);
|
|
|
|
}
|
|
|
|
}
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-16 12:35:08 +00:00
|
|
|
void adjustReservedFlags() {
|
2017-07-02 16:38:19 +00:00
|
|
|
F() = (F() | Bit1) & ~(Bit5 | Bit3);
|
2017-06-16 12:35:08 +00:00
|
|
|
}
|
|
|
|
|
2017-06-19 12:53:00 +00:00
|
|
|
static void adjustAuxiliaryCarryAdd(uint8_t& f, uint8_t before, uint8_t value, int calculation) {
|
|
|
|
setFlag(f, AC, calculateHalfCarryAdd(before, value, calculation));
|
2017-06-04 20:38:34 +00:00
|
|
|
}
|
|
|
|
|
2017-06-19 12:53:00 +00:00
|
|
|
static void adjustAuxiliaryCarrySub(uint8_t& f, uint8_t before, uint8_t value, int calculation) {
|
|
|
|
clearFlag(f, AC, calculateHalfCarrySub(before, value, calculation));
|
2017-06-04 20:38:34 +00:00
|
|
|
}
|
|
|
|
|
2017-07-24 21:00:49 +00:00
|
|
|
static void subtract(uint8_t& f, uint8_t& operand, uint8_t value, int carry = 0);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-07-24 21:00:49 +00:00
|
|
|
int execute(uint8_t opcode);
|
|
|
|
void execute(int x, int y, int z, int p, int q);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-07-24 21:00:49 +00:00
|
|
|
static void increment(uint8_t& f, uint8_t& operand);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-07-24 21:00:49 +00:00
|
|
|
static void decrement(uint8_t& f, uint8_t& operand);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-07-24 21:00:49 +00:00
|
|
|
bool returnConditionalFlag(uint8_t& f, int flag);
|
|
|
|
bool jumpConditionalFlag(uint8_t& f, int flag);
|
|
|
|
bool callConditionalFlag(uint8_t& f, int flag);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-07-24 21:00:49 +00:00
|
|
|
void dad(uint16_t value);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-07-22 22:52:58 +00:00
|
|
|
void add(uint8_t value, int carry = 0);
|
|
|
|
void adc(uint8_t value);
|
|
|
|
void sbb(uint8_t value);
|
2017-07-24 21:00:49 +00:00
|
|
|
void anda(uint8_t value);
|
|
|
|
void xra(uint8_t value);
|
|
|
|
void ora(uint8_t value);
|
|
|
|
void compare(uint8_t& f, uint8_t check, uint8_t value);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-07-22 22:52:58 +00:00
|
|
|
void rlc();
|
|
|
|
void rrc();
|
|
|
|
void ral();
|
|
|
|
void rar();
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-07-24 21:00:49 +00:00
|
|
|
void daa();
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-07-22 22:52:58 +00:00
|
|
|
void cma();
|
|
|
|
void stc();
|
|
|
|
void cmc();
|
2017-07-24 21:00:49 +00:00
|
|
|
|
|
|
|
void xhtl();
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
|
|
// input/output
|
|
|
|
|
2017-07-22 22:52:58 +00:00
|
|
|
void out();
|
|
|
|
void in();
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
|
|
// control
|
|
|
|
|
2017-07-22 22:52:58 +00:00
|
|
|
void ei();
|
|
|
|
void di();
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-07-24 21:00:49 +00:00
|
|
|
//
|
|
|
|
|
|
|
|
void ___();
|
2017-06-04 20:38:34 +00:00
|
|
|
void nop() {}
|
|
|
|
|
2017-07-24 21:00:49 +00:00
|
|
|
static Instruction INS(instruction_t method, AddressingMode mode, std::string disassembly, int cycles);
|
|
|
|
Instruction UNKNOWN();
|
|
|
|
void installInstructions();
|
2017-06-04 20:38:34 +00:00
|
|
|
};
|
|
|
|
}
|