1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-01-11 08:30:55 +00:00

Corrects performer storage, RMW/W confusion, implicit casts, port readback.

This commit is contained in:
Thomas Harte 2021-01-24 22:30:42 -05:00
parent e8e604dc3c
commit 8789ffda15
6 changed files with 30 additions and 21 deletions

View File

@ -93,7 +93,7 @@ template <
// Storage for the statically-allocated list of performers. It's a bit more // Storage for the statically-allocated list of performers. It's a bit more
// work for executors to fill this array, but subsequently performers can be // work for executors to fill this array, but subsequently performers can be
// indexed by array position, which is a lot more compact than a generic pointer. // indexed by array position, which is a lot more compact than a generic pointer.
std::array<Performer, max_performer_count> performers_; std::array<Performer, max_performer_count+1> performers_;
ProgramCounterType program_counter_; ProgramCounterType program_counter_;
/*! /*!
@ -149,10 +149,12 @@ template <
while(remaining_duration_ > 0) { while(remaining_duration_ > 0) {
has_branched_ = false; has_branched_ = false;
Executor *const executor = static_cast<Executor *>(this);
while(remaining_duration_ > 0 && !has_branched_) { while(remaining_duration_ > 0 && !has_branched_) {
const auto performer = performers_[program_[program_index_]]; const auto performer = performers_[program_[program_index_]];
++program_index_; ++program_index_;
(static_cast<Executor *>(this)->*performer)();
(executor->*performer)();
} }
} }
} }

View File

@ -305,9 +305,9 @@ template <Operation operation, AddressingMode addressing_mode> void Executor::pe
// sequence below that wraps the address and checks whether // sequence below that wraps the address and checks whether
// a write is valid [if required]. // a write is valid [if required].
int address; unsigned int address;
#define next8() memory_[(program_counter_ + 1) & 0x1fff] #define next8() memory_[(program_counter_ + 1) & 0x1fff]
#define next16() (memory_[(program_counter_ + 1) & 0x1fff] | (memory_[(program_counter_ + 2) & 0x1fff] << 8)) #define next16() uint16_t(memory_[(program_counter_ + 1) & 0x1fff] | (memory_[(program_counter_ + 2) & 0x1fff] << 8))
// Underlying assumption below: the instruction stream will never // Underlying assumption below: the instruction stream will never
// overlap with IO ports. // overlap with IO ports.
@ -333,7 +333,7 @@ template <Operation operation, AddressingMode addressing_mode> void Executor::pe
// Special-purpose addressing modes. // Special-purpose addressing modes.
case AddressingMode::Relative: case AddressingMode::Relative:
address = program_counter_ + 1 + size(addressing_mode) + int8_t(next8()); address = unsigned(program_counter_ + 1 + size(addressing_mode) + int8_t(next8()));
break; break;
case AddressingMode::SpecialPage: address = 0x1f00 | next8(); break; case AddressingMode::SpecialPage: address = 0x1f00 | next8(); break;
@ -350,16 +350,16 @@ template <Operation operation, AddressingMode addressing_mode> void Executor::pe
uint8_t value; uint8_t value;
if constexpr (addressing_mode == AddressingMode::AccumulatorRelative) { if constexpr (addressing_mode == AddressingMode::AccumulatorRelative) {
value = a_; value = a_;
address = program_counter_ + 1 + size(addressing_mode) + int8_t(next8()); address = unsigned(program_counter_ + 1 + size(addressing_mode) + int8_t(next8()));
} else { } else {
value = read(next8()); value = read(next8());
address = program_counter_ + 1 + size(addressing_mode) + int8_t(memory_[(program_counter_+2)&0x1fff]); address = unsigned(program_counter_ + 1 + size(addressing_mode) + int8_t(memory_[(program_counter_+2)&0x1fff]));
} }
program_counter_ += 1 + size(addressing_mode); program_counter_ += 1 + size(addressing_mode);
switch(operation) { switch(operation) {
case Operation::BBS0: case Operation::BBS1: case Operation::BBS2: case Operation::BBS3: case Operation::BBS0: case Operation::BBS1: case Operation::BBS2: case Operation::BBS3:
case Operation::BBS4: case Operation::BBS5: case Operation::BBS6: case Operation::BBS7: case Operation::BBS4: case Operation::BBS5: case Operation::BBS6: case Operation::BBS7:
if constexpr (operation >= Operation::BBS0 && operation < Operation::BBS7) { if constexpr (operation >= Operation::BBS0 && operation <= Operation::BBS7) {
if(value & (1 << (int(operation) - int(Operation::BBS0)))) { if(value & (1 << (int(operation) - int(Operation::BBS0)))) {
set_program_counter(uint16_t(address)); set_program_counter(uint16_t(address));
subtract_duration(2); subtract_duration(2);
@ -368,7 +368,7 @@ template <Operation operation, AddressingMode addressing_mode> void Executor::pe
return; return;
case Operation::BBC0: case Operation::BBC1: case Operation::BBC2: case Operation::BBC3: case Operation::BBC0: case Operation::BBC1: case Operation::BBC2: case Operation::BBC3:
case Operation::BBC4: case Operation::BBC5: case Operation::BBC6: case Operation::BBC7: case Operation::BBC4: case Operation::BBC5: case Operation::BBC6: case Operation::BBC7:
if constexpr (operation >= Operation::BBC0 && operation < Operation::BBS7) { if constexpr (operation >= Operation::BBC0 && operation <= Operation::BBS7) {
if(value & (1 << (int(operation) - int(Operation::BBC0)))) { if(value & (1 << (int(operation) - int(Operation::BBC0)))) {
set_program_counter(uint16_t(address)); set_program_counter(uint16_t(address));
subtract_duration(2); subtract_duration(2);
@ -390,21 +390,21 @@ template <Operation operation, AddressingMode addressing_mode> void Executor::pe
case AddressingMode::ZeroPageIndirect: case AddressingMode::ZeroPageIndirect:
address = next8(); address = next8();
address = memory_[address] | (memory_[(address + 1) & 0xff] << 8); address = unsigned(memory_[address] | (memory_[(address + 1) & 0xff] << 8));
break; break;
case AddressingMode::XIndirect: case AddressingMode::XIndirect:
address = (next8() + x_) & 0xff; address = (next8() + x_) & 0xff;
address = memory_[address] | (memory_[(address + 1)&0xff] << 8); address = unsigned(memory_[address] | (memory_[(address + 1)&0xff] << 8));
break; break;
case AddressingMode::IndirectY: case AddressingMode::IndirectY:
address = (memory_[next8()] | (memory_[(next8()+1)&0xff] << 8)) + y_; address = unsigned((memory_[next8()] | (memory_[(next8()+1)&0xff] << 8)) + y_);
break; break;
case AddressingMode::AbsoluteIndirect: case AddressingMode::AbsoluteIndirect:
address = next16(); address = next16();
address = memory_[address] | (memory_[(address + 1) & 0x1fff] << 8); address = unsigned(memory_[address] | (memory_[(address + 1) & 0x1fff] << 8));
break; break;
default: default:
@ -488,11 +488,15 @@ template <Operation operation> void Executor::perform(uint8_t *operand [[maybe_u
case Operation::SEB0: case Operation::SEB1: case Operation::SEB2: case Operation::SEB3: case Operation::SEB0: case Operation::SEB1: case Operation::SEB2: case Operation::SEB3:
case Operation::SEB4: case Operation::SEB5: case Operation::SEB6: case Operation::SEB7: case Operation::SEB4: case Operation::SEB5: case Operation::SEB6: case Operation::SEB7:
*operand |= 1 << (int(operation) - int(Operation::SEB0)); if constexpr(operation >= Operation::SEB0 && operation <= Operation::SEB7) {
*operand |= 1 << (int(operation) - int(Operation::SEB0));
}
break; break;
case Operation::CLB0: case Operation::CLB1: case Operation::CLB2: case Operation::CLB3: case Operation::CLB0: case Operation::CLB1: case Operation::CLB2: case Operation::CLB3:
case Operation::CLB4: case Operation::CLB5: case Operation::CLB6: case Operation::CLB7: case Operation::CLB4: case Operation::CLB5: case Operation::CLB6: case Operation::CLB7:
*operand &= ~(1 << (int(operation) - int(Operation::CLB0))); if constexpr(operation >= Operation::CLB0 && operation <= Operation::CLB7) {
*operand &= ~(1 << (int(operation) - int(Operation::CLB0)));
}
break; break;
case Operation::CLI: interrupt_disable_ = 0x00; break; case Operation::CLI: interrupt_disable_ = 0x00; break;

View File

@ -14,6 +14,7 @@
#include "../CachingExecutor.hpp" #include "../CachingExecutor.hpp"
#include "../../ClockReceiver/ClockReceiver.hpp" #include "../../ClockReceiver/ClockReceiver.hpp"
#include <array>
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
@ -63,7 +64,7 @@ class Executor: public CachingExecutor {
*/ */
inline void parse(uint16_t start, uint16_t closing_bound) { inline void parse(uint16_t start, uint16_t closing_bound) {
Parser<Executor, false> parser; Parser<Executor, false> parser;
parser.parse(*this, memory_, start & 0x1fff, closing_bound); parser.parse(*this, &memory_[0], start & 0x1fff, closing_bound);
} }
private: private:
@ -121,7 +122,7 @@ class Executor: public CachingExecutor {
// MARK: - Instruction set state. // MARK: - Instruction set state.
// Memory. // Memory.
uint8_t memory_[0x2000]; std::array<uint8_t, 0x2000> memory_;
// Registers. // Registers.
uint8_t a_, x_, y_, s_; uint8_t a_, x_, y_, s_;

View File

@ -94,8 +94,8 @@ static constexpr auto MinOperation = int(Operation::BBC0);
constexpr AccessType access_type(Operation operation) { constexpr AccessType access_type(Operation operation) {
if(operation < Operation::ADC) return AccessType::None; if(operation < Operation::ADC) return AccessType::None;
if(operation < Operation::ASL) return AccessType::Read; if(operation < Operation::ASL) return AccessType::Read;
if(operation < Operation::LDM) return AccessType::Write; if(operation < Operation::LDM) return AccessType::ReadModifyWrite;
return AccessType::ReadModifyWrite; return AccessType::Write;
} }
constexpr bool uses_index_mode(Operation operation) { constexpr bool uses_index_mode(Operation operation) {

View File

@ -226,6 +226,7 @@ void GLU::run_for(Cycles cycles) {
// MARK: - M50470 port handler // MARK: - M50470 port handler
void GLU::set_port_output(int port, uint8_t value) { void GLU::set_port_output(int port, uint8_t value) {
ports_[port] = value;
switch(port) { switch(port) {
case 0: case 0:
printf("Set R%d: %02x\n", register_address_, value); printf("Set R%d: %02x\n", register_address_, value);
@ -261,10 +262,10 @@ uint8_t GLU::get_port_input(int port) {
return 0x06; return 0x06;
case 2: case 2:
printf("ADB data line input, etc\n"); printf("ADB data line input, etc\n");
return 0xff; return ports_[2];
case 3: case 3:
// printf("ADB data line output, etc\n"); // printf("ADB data line output, etc\n");
break; return ports_[3];
default: assert(false); default: assert(false);
} }

View File

@ -67,6 +67,7 @@ class GLU: public InstructionSet::M50740::PortHandler {
uint8_t registers_[16]; uint8_t registers_[16];
uint8_t register_address_; uint8_t register_address_;
uint8_t ports_[4];
}; };
} }