2017-06-04 20:38:34 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
// Auxiliary carry logic from https://github.com/begoon/i8080-core
|
|
|
|
|
2017-10-22 20:57:01 +00:00
|
|
|
#include <cstdint>
|
|
|
|
#include <stdexcept>
|
|
|
|
|
2017-11-05 12:47:42 +00:00
|
|
|
#include <Bus.h>
|
|
|
|
#include <InputOutput.h>
|
2017-09-03 22:51:01 +00:00
|
|
|
#include <IntelProcessor.h>
|
2017-10-22 20:57:01 +00:00
|
|
|
#include <Signal.h>
|
|
|
|
#include <Register.h>
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
|
|
namespace EightBit {
|
2017-12-10 21:41:48 +00:00
|
|
|
class Intel8080 final : public IntelProcessor {
|
2017-06-04 20:38:34 +00:00
|
|
|
public:
|
2017-06-16 00:58:12 +00:00
|
|
|
enum StatusBits {
|
|
|
|
SF = Bit7,
|
|
|
|
ZF = Bit6,
|
|
|
|
AC = Bit4,
|
|
|
|
PF = Bit2,
|
|
|
|
CF = Bit0,
|
|
|
|
};
|
|
|
|
|
2017-09-06 12:22:23 +00:00
|
|
|
Intel8080(Bus& bus, InputOutput& ports);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
|
|
Signal<Intel8080> ExecutingInstruction;
|
|
|
|
|
2017-12-10 21:41:48 +00:00
|
|
|
virtual int execute(uint8_t opcode) final;
|
|
|
|
virtual int step() final;
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-12-10 21:41:48 +00:00
|
|
|
virtual register16_t& AF() final;
|
|
|
|
virtual register16_t& BC() final;
|
|
|
|
virtual register16_t& DE() final;
|
|
|
|
virtual register16_t& HL() final;
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-12-10 21:41:48 +00:00
|
|
|
protected:
|
|
|
|
virtual void reset() final;
|
2017-12-04 23:41:49 +00:00
|
|
|
|
2017-06-04 20:38:34 +00:00
|
|
|
private:
|
2017-12-02 23:50:59 +00:00
|
|
|
bool m_interruptEnable = false;
|
2017-12-03 00:57:47 +00:00
|
|
|
|
2017-06-04 21:59:56 +00:00
|
|
|
InputOutput& m_ports;
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-16 00:58:12 +00:00
|
|
|
register16_t af;
|
2017-12-10 21:41:48 +00:00
|
|
|
register16_t bc = { { 0xff, 0xff } };
|
|
|
|
register16_t de = { { 0xff, 0xff } };
|
|
|
|
register16_t hl = { { 0xff, 0xff } };
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-11-03 22:05:01 +00:00
|
|
|
uint8_t R(int r, uint8_t a) {
|
2017-07-24 21:00:49 +00:00
|
|
|
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:
|
2017-08-28 17:52:48 +00:00
|
|
|
return getByte(HL());
|
2017-07-24 21:00:49 +00:00
|
|
|
case 0b111:
|
2017-11-03 22:05:01 +00:00
|
|
|
return a;
|
2017-07-24 21:00:49 +00:00
|
|
|
default:
|
2017-09-03 20:30:46 +00:00
|
|
|
UNREACHABLE;
|
2017-07-24 21:00:49 +00:00
|
|
|
}
|
|
|
|
throw std::logic_error("Unhandled registry mechanism");
|
|
|
|
}
|
|
|
|
|
2017-11-03 22:05:01 +00:00
|
|
|
void R(int r, uint8_t& a, uint8_t value) {
|
2017-08-06 16:06:48 +00:00
|
|
|
switch (r) {
|
|
|
|
case 0b000:
|
|
|
|
B() = value;
|
|
|
|
break;
|
|
|
|
case 0b001:
|
|
|
|
C() = value;
|
|
|
|
break;
|
|
|
|
case 0b010:
|
|
|
|
D() = value;
|
|
|
|
break;
|
|
|
|
case 0b011:
|
|
|
|
E() = value;
|
|
|
|
break;
|
|
|
|
case 0b100:
|
|
|
|
H() = value;
|
|
|
|
break;
|
|
|
|
case 0b101:
|
|
|
|
L() = value;
|
|
|
|
break;
|
|
|
|
case 0b110:
|
2017-08-28 17:52:48 +00:00
|
|
|
setByte(HL(), value);
|
2017-08-06 16:06:48 +00:00
|
|
|
break;
|
|
|
|
case 0b111:
|
2017-11-03 22:05:01 +00:00
|
|
|
a = value;
|
2017-08-06 16:06:48 +00:00
|
|
|
break;
|
|
|
|
default:
|
2017-09-03 20:30:46 +00:00
|
|
|
UNREACHABLE;
|
2017-08-06 16:06:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-24 21:00:49 +00:00
|
|
|
register16_t& RP(int rp) {
|
|
|
|
switch (rp) {
|
|
|
|
case 0b00:
|
|
|
|
return BC();
|
|
|
|
case 0b01:
|
|
|
|
return DE();
|
|
|
|
case 0b10:
|
|
|
|
return HL();
|
|
|
|
case 0b11:
|
|
|
|
return SP();
|
|
|
|
default:
|
2017-09-03 20:30:46 +00:00
|
|
|
UNREACHABLE;
|
2017-07-24 21:00:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
register16_t& RP2(int rp) {
|
|
|
|
switch (rp) {
|
|
|
|
case 0b00:
|
|
|
|
return BC();
|
|
|
|
case 0b01:
|
|
|
|
return DE();
|
|
|
|
case 0b10:
|
|
|
|
return HL();
|
|
|
|
case 0b11:
|
|
|
|
return AF();
|
|
|
|
default:
|
2017-09-03 20:30:46 +00:00
|
|
|
UNREACHABLE;
|
2017-07-24 21:00:49 +00:00
|
|
|
}
|
|
|
|
}
|
2017-06-04 20:38:34 +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
|
|
|
|
2018-01-10 23:08:14 +00:00
|
|
|
void execute(uint8_t& a, uint8_t& f, 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);
|
|
|
|
static void decrement(uint8_t& f, uint8_t& operand);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-11-03 22:05:01 +00:00
|
|
|
void di();
|
|
|
|
void ei();
|
|
|
|
|
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-25 18:26:21 +00:00
|
|
|
static void add(uint8_t& f, register16_t& operand, register16_t value);
|
|
|
|
|
|
|
|
static void add(uint8_t& f, uint8_t& operand, uint8_t value, int carry = 0);
|
|
|
|
static void adc(uint8_t& f, uint8_t& operand, uint8_t value);
|
|
|
|
static void sbb(uint8_t& f, uint8_t& operand, uint8_t value);
|
|
|
|
static void andr(uint8_t& f, uint8_t& operand, uint8_t value);
|
|
|
|
static void xorr(uint8_t& f, uint8_t& operand, uint8_t value);
|
|
|
|
static void orr(uint8_t& f, uint8_t& operand, uint8_t value);
|
|
|
|
static void compare(uint8_t& f, uint8_t check, uint8_t value);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-07-25 20:22:15 +00:00
|
|
|
static void rlc(uint8_t& f, uint8_t& operand);
|
|
|
|
static void rrc(uint8_t& f, uint8_t& operand);
|
|
|
|
static void rl(uint8_t& f, uint8_t& operand);
|
|
|
|
static void rr(uint8_t& f, uint8_t& operand);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-07-25 20:22:15 +00:00
|
|
|
static void daa(uint8_t& a, uint8_t& f);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-07-25 20:22:15 +00:00
|
|
|
static void cma(uint8_t& a, uint8_t& f);
|
|
|
|
static void stc(uint8_t& a, uint8_t& f);
|
|
|
|
static void cmc(uint8_t& a, uint8_t& f);
|
2017-07-24 21:00:49 +00:00
|
|
|
|
2017-11-03 22:05:01 +00:00
|
|
|
void xhtl(register16_t& operand);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-11-03 22:05:01 +00:00
|
|
|
void writePort(uint8_t port, uint8_t a);
|
|
|
|
void writePort();
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-11-03 22:05:01 +00:00
|
|
|
void readPort(uint8_t port, uint8_t& a);
|
|
|
|
void readPort();
|
2017-06-04 20:38:34 +00:00
|
|
|
};
|
|
|
|
}
|