1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-05 10:28:58 +00:00

Made an attempt at implementing all three modes of IRQ.

This commit is contained in:
Thomas Harte 2017-06-03 17:07:05 -04:00
parent 1c0130fd02
commit a2ec902773

View File

@ -68,7 +68,7 @@ enum BusOperation {
Read, Write, Read, Write,
Input, Output, Input, Output,
Interrupt, Interrupt,
// BusRequest, BusAcknowledge, BusAcknowledge,
Internal Internal
}; };
@ -83,6 +83,7 @@ struct MicroOp {
enum Type { enum Type {
BusOperation, BusOperation,
DecodeOperation, DecodeOperation,
DecodeOperationNoRChange,
MoveToNextProgram, MoveToNextProgram,
Increment8, Increment8,
@ -133,6 +134,7 @@ struct MicroOp {
BeginNMI, BeginNMI,
BeginIRQ, BeginIRQ,
BeginIRQMode0,
RETN, RETN,
HALT, HALT,
@ -177,6 +179,7 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
RegisterPair ix_, iy_, pc_, sp_; RegisterPair ix_, iy_, pc_, sp_;
bool iff1_, iff2_; bool iff1_, iff2_;
int interrupt_mode_; int interrupt_mode_;
uint16_t pc_increment_;
uint8_t sign_result_; // the sign flag is set if the value in sign_result_ is negative uint8_t sign_result_; // the sign flag is set if the value in sign_result_ is negative
uint8_t zero_result_; // the zero flag is set if the value in zero_result_ is zero uint8_t zero_result_; // the zero flag is set if the value in zero_result_ is zero
uint8_t half_carry_result_; // the half-carry flag is set if bit 4 of half_carry_result_ is set uint8_t half_carry_result_; // the half-carry flag is set if bit 4 of half_carry_result_ is set
@ -316,7 +319,7 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
#define WAIT(n) {MicroOp::BusOperation, nullptr, nullptr, {Internal, n} } #define WAIT(n) {MicroOp::BusOperation, nullptr, nullptr, {Internal, n} }
#define Program(...) { __VA_ARGS__, {MicroOp::MoveToNextProgram} } #define Program(...) { __VA_ARGS__, {MicroOp::MoveToNextProgram} }
#define isTerminal(n) (n == MicroOp::MoveToNextProgram || n == MicroOp::DecodeOperation) #define isTerminal(n) (n == MicroOp::MoveToNextProgram || n == MicroOp::DecodeOperation || n == MicroOp::DecodeOperationNoRChange)
typedef MicroOp InstructionTable[256][20]; typedef MicroOp InstructionTable[256][20];
@ -672,7 +675,8 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
number_of_cycles_(0), number_of_cycles_(0),
request_status_(Interrupt::PowerOn), request_status_(Interrupt::PowerOn),
last_request_status_(Interrupt::PowerOn), last_request_status_(Interrupt::PowerOn),
irq_line_(false) { irq_line_(false),
pc_increment_(1) {
set_flags(0xff); set_flags(0xff);
assemble_base_page(base_page_, hl_, false, cb_page_); assemble_base_page(base_page_, hl_, false, cb_page_);
@ -699,9 +703,32 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
PUSH(pc_), PUSH(pc_),
{ MicroOp::MoveToNextProgram } { MicroOp::MoveToNextProgram }
}; };
MicroOp irq_mode0_program[] = {
{ MicroOp::BeginIRQMode0 },
{ MicroOp::BusOperation, nullptr, nullptr, {BusOperation::Interrupt, 7, nullptr, &operation_}},
{ MicroOp::DecodeOperationNoRChange }
};
MicroOp irq_mode1_program[] = {
{ MicroOp::BeginIRQ },
{ MicroOp::BusOperation, nullptr, nullptr, {BusOperation::Interrupt, 7, nullptr, &operation_}},
PUSH(pc_),
{ MicroOp::Move16, &temp16_.full, &pc_.full },
{ MicroOp::MoveToNextProgram }
};
MicroOp irq_mode2_program[] = {
{ MicroOp::BeginIRQ },
{ MicroOp::BusOperation, nullptr, nullptr, {BusOperation::Interrupt, 7, nullptr, &temp16_.bytes.low}},
PUSH(pc_),
{ MicroOp::Move8, &i_, &temp16_.bytes.high },
FETCH16L(pc_, temp16_),
{ MicroOp::MoveToNextProgram }
};
copy_program(reset_program, reset_program_); copy_program(reset_program, reset_program_);
copy_program(nmi_program, nmi_program_); copy_program(nmi_program, nmi_program_);
copy_program(irq_mode0_program, irq_program_[0]);
copy_program(irq_mode1_program, irq_program_[1]);
copy_program(irq_mode2_program, irq_program_[2]);
} }
/*! /*!
@ -716,6 +743,7 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
void run_for_cycles(int number_of_cycles) { void run_for_cycles(int number_of_cycles) {
#define advance_operation() \ #define advance_operation() \
pc_increment_ = 1; \
if(last_request_status_) { \ if(last_request_status_) { \
halt_mask_ = 0xff; \ halt_mask_ = 0xff; \
if(last_request_status_ & (Interrupt::PowerOn | Interrupt::Reset)) { \ if(last_request_status_ & (Interrupt::PowerOn | Interrupt::Reset)) { \
@ -759,12 +787,13 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
break; break;
case MicroOp::DecodeOperation: case MicroOp::DecodeOperation:
r_ = (r_ & 0x80) | ((r_ + current_instruction_page_->r_step_) & 0x7f); r_ = (r_ & 0x80) | ((r_ + current_instruction_page_->r_step_) & 0x7f);
pc_.full++; pc_.full += pc_increment_;
case MicroOp::DecodeOperationNoRChange:
scheduled_program_counter_ = current_instruction_page_->instructions[operation_ & halt_mask_]; scheduled_program_counter_ = current_instruction_page_->instructions[operation_ & halt_mask_];
break; break;
case MicroOp::Increment16: (*(uint16_t *)operation->source)++; break; case MicroOp::Increment16: (*(uint16_t *)operation->source)++; break;
case MicroOp::IncrementPC: pc_.full++; break; case MicroOp::IncrementPC: pc_.full += pc_increment_; break;
case MicroOp::Decrement16: (*(uint16_t *)operation->source)--; break; case MicroOp::Decrement16: (*(uint16_t *)operation->source)--; break;
case MicroOp::Move8: *(uint8_t *)operation->destination = *(uint8_t *)operation->source; break; case MicroOp::Move8: *(uint8_t *)operation->destination = *(uint8_t *)operation->source; break;
case MicroOp::Move16: *(uint16_t *)operation->destination = *(uint16_t *)operation->source; break; case MicroOp::Move16: *(uint16_t *)operation->destination = *(uint16_t *)operation->source; break;
@ -1433,9 +1462,12 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
#pragma mark - Special-case Flow #pragma mark - Special-case Flow
case MicroOp::BeginIRQMode0:
pc_increment_ = 0; // deliberate fallthrough
case MicroOp::BeginIRQ: case MicroOp::BeginIRQ:
iff2_ = iff1_ = false; iff2_ = iff1_ = false;
request_status_ &= ~Interrupt::IRQ; request_status_ &= ~Interrupt::IRQ;
temp16_.full = 0x38;
break; break;
case MicroOp::BeginNMI: case MicroOp::BeginNMI: