1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-22 12:33:29 +00:00

Add further exposition.

This commit is contained in:
Thomas Harte 2024-03-03 21:38:27 -05:00
parent f2db1b4aae
commit 11c4d2f09e
3 changed files with 35 additions and 26 deletions

View File

@ -544,8 +544,7 @@ struct Executor {
registers_.exception<Registers::Exception::UndefinedInstruction>(); registers_.exception<Registers::Exception::UndefinedInstruction>();
} }
MemoryT bus; /// @returns The current registers state.
const Registers &registers() const { const Registers &registers() const {
return registers_; return registers_;
} }
@ -563,12 +562,14 @@ struct Executor {
return registers_.pc(0); return registers_.pc(0);
} }
MemoryT bus;
private: private:
Registers registers_; Registers registers_;
}; };
/// Provides an analogue of the @c OperationMapper -affiliated @c dispatch that also updates the /// Executes the instruction @c instruction which should have been fetched from @c executor.pc(),
/// executor's program counter appropriately. /// modifying @c executor.
template <Model model, typename MemoryT> template <Model model, typename MemoryT>
void execute(uint32_t instruction, Executor<model, MemoryT> &executor) { void execute(uint32_t instruction, Executor<model, MemoryT> &executor) {
executor.set_pc(executor.pc() + 4); executor.set_pc(executor.pc() + 4);

View File

@ -66,6 +66,7 @@ struct Registers {
overflow_flag_ = value; overflow_flag_ = value;
} }
/// @returns The current status bits, separate from the PC — mode, NVCZ and the two interrupt flags.
uint32_t status() const { uint32_t status() const {
return return
uint32_t(mode_) | uint32_t(mode_) |
@ -100,6 +101,7 @@ struct Registers {
} }
} }
/// @returns The current mode.
Mode mode() const { Mode mode() const {
return mode_; return mode_;
} }
@ -109,6 +111,7 @@ struct Registers {
active[15] = value & ConditionCode::Address; active[15] = value & ConditionCode::Address;
} }
/// @returns The stored PC plus @c offset limited to 26 bits.
uint32_t pc(uint32_t offset) const { uint32_t pc(uint32_t offset) const {
return (active[15] + offset) & ConditionCode::Address; return (active[15] + offset) & ConditionCode::Address;
} }
@ -136,6 +139,7 @@ struct Registers {
FIQ = 0x1c, FIQ = 0x1c,
}; };
/// Updates the program counter, interupt flags and link register if applicable to begin @c exception.
template <Exception exception> template <Exception exception>
void exception() { void exception() {
interrupt_flags_ |= ConditionCode::IRQDisable; interrupt_flags_ |= ConditionCode::IRQDisable;
@ -163,6 +167,7 @@ struct Registers {
// MARK: - Condition tests. // MARK: - Condition tests.
/// @returns @c true if @c condition tests as true; @c false otherwise.
bool test(Condition condition) { bool test(Condition condition) {
const auto ne = [&]() -> bool { const auto ne = [&]() -> bool {
return zero_result_; return zero_result_;
@ -208,8 +213,7 @@ struct Registers {
} }
} }
std::array<uint32_t, 16> active{}; /// Sets current execution mode.
void set_mode(Mode target_mode) { void set_mode(Mode target_mode) {
if(mode_ == target_mode) { if(mode_ == target_mode) {
return; return;
@ -258,6 +262,10 @@ struct Registers {
mode_ = target_mode; mode_ = target_mode;
} }
/// The active register set. TODO: switch to an implementation of operator[], hiding the
/// current implementation decision to maintain this as a linear block of memory.
std::array<uint32_t, 16> active{};
private: private:
Mode mode_ = Mode::Supervisor; Mode mode_ = Mode::Supervisor;

View File

@ -211,25 +211,25 @@ struct Memory {
} }
// TODO: turn the below into a trace-driven test case. // TODO: turn the below into a trace-driven test case.
- (void)testROM319 { //- (void)testROM319 {
constexpr ROM::Name rom_name = ROM::Name::AcornRISCOS319; // constexpr ROM::Name rom_name = ROM::Name::AcornRISCOS319;
ROM::Request request(rom_name); // ROM::Request request(rom_name);
const auto roms = CSROMFetcher()(request); // const auto roms = CSROMFetcher()(request);
//
auto executor = std::make_unique<Executor<Model::ARMv2, Memory>>(); // auto executor = std::make_unique<Executor<Model::ARMv2, Memory>>();
executor->bus.rom = roms.find(rom_name)->second; // executor->bus.rom = roms.find(rom_name)->second;
//
for(int c = 0; c < 1000; c++) { // for(int c = 0; c < 1000; c++) {
uint32_t instruction; // uint32_t instruction;
executor->bus.read(executor->pc(), instruction, executor->registers().mode(), false); // executor->bus.read(executor->pc(), instruction, executor->registers().mode(), false);
//
printf("%08x: %08x [", executor->pc(), instruction); // printf("%08x: %08x [", executor->pc(), instruction);
for(int c = 0; c < 15; c++) { // for(int c = 0; c < 15; c++) {
printf("r%d:%08x ", c, executor->registers().active[c]); // printf("r%d:%08x ", c, executor->registers().active[c]);
} // }
printf("psr:%08x]\n", executor->registers().status()); // printf("psr:%08x]\n", executor->registers().status());
execute<Model::ARMv2>(instruction, *executor); // execute<Model::ARMv2>(instruction, *executor);
} // }
} //}
@end @end