mirror of
https://github.com/TomHarte/CLK.git
synced 2024-10-04 01:57:54 +00:00
Made an attempt at implementing all three modes of IRQ.
This commit is contained in:
parent
1c0130fd02
commit
a2ec902773
@ -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:
|
||||||
|
Loading…
Reference in New Issue
Block a user