1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-02-19 23:29:05 +00:00

Obscure active.

This commit is contained in:
Thomas Harte 2024-03-03 21:43:30 -05:00
parent 11c4d2f09e
commit 230e9c6327
3 changed files with 46 additions and 39 deletions

View File

@ -36,7 +36,7 @@ struct Executor {
if(fields.operand2() == 15) { if(fields.operand2() == 15) {
operand2 = registers_.pc_status(pc_offset); operand2 = registers_.pc_status(pc_offset);
} else { } else {
operand2 = registers_.active[fields.operand2()]; operand2 = registers_[fields.operand2()];
} }
uint32_t shift_amount; uint32_t shift_amount;
@ -50,7 +50,7 @@ struct Executor {
shift_amount = shift_amount =
fields.shift_register() == 15 ? fields.shift_register() == 15 ?
registers_.pc(4) : registers_.pc(4) :
registers_.active[fields.shift_register()]; registers_[fields.shift_register()];
// A register shift amount of 0 has a different meaning than an in-instruction // A register shift amount of 0 has a different meaning than an in-instruction
// shift amount of 0. // shift amount of 0.
@ -74,7 +74,7 @@ struct Executor {
// Write a raw result into the PC proxy if the target is R15; it'll be stored properly later. // Write a raw result into the PC proxy if the target is R15; it'll be stored properly later.
uint32_t pc_proxy = 0; uint32_t pc_proxy = 0;
auto &destination = fields.destination() == 15 ? pc_proxy : registers_.active[fields.destination()]; auto &destination = fields.destination() == 15 ? pc_proxy : registers_[fields.destination()];
// "When R15 appears in either of the Rn or Rs positions it will give the value // "When R15 appears in either of the Rn or Rs positions it will give the value
// of the PC alone, with the PSR bits replaced by zeroes. ... // of the PC alone, with the PSR bits replaced by zeroes. ...
@ -85,7 +85,7 @@ struct Executor {
const uint32_t operand1 = const uint32_t operand1 =
(fields.operand1() == 15) ? (fields.operand1() == 15) ?
registers_.pc(shift_by_register ? 8 : 4) : registers_.pc(shift_by_register ? 8 : 4) :
registers_.active[fields.operand1()]; registers_[fields.operand1()];
uint32_t operand2; uint32_t operand2;
uint32_t rotate_carry = registers_.c(); uint32_t rotate_carry = registers_.c();
@ -216,11 +216,11 @@ struct Executor {
// * Rn: with PSR, 8 bytes ahead; // * Rn: with PSR, 8 bytes ahead;
// * Rm: with PSR, 12 bytes ahead. // * Rm: with PSR, 12 bytes ahead.
const uint32_t multiplicand = fields.multiplicand() == 15 ? registers_.pc(4) : registers_.active[fields.multiplicand()]; const uint32_t multiplicand = fields.multiplicand() == 15 ? registers_.pc(4) : registers_[fields.multiplicand()];
const uint32_t multiplier = fields.multiplier() == 15 ? registers_.pc_status(4) : registers_.active[fields.multiplier()]; const uint32_t multiplier = fields.multiplier() == 15 ? registers_.pc_status(4) : registers_[fields.multiplier()];
const uint32_t accumulator = const uint32_t accumulator =
flags.operation() == MultiplyFlags::Operation::MUL ? 0 : flags.operation() == MultiplyFlags::Operation::MUL ? 0 :
(fields.multiplicand() == 15 ? registers_.pc_status(8) : registers_.active[fields.accumulator()]); (fields.multiplicand() == 15 ? registers_.pc_status(8) : registers_[fields.accumulator()]);
const uint32_t result = multiplicand * multiplier + accumulator; const uint32_t result = multiplicand * multiplier + accumulator;
@ -230,7 +230,7 @@ struct Executor {
} }
if(fields.destination() != 15) { if(fields.destination() != 15) {
registers_.active[fields.destination()] = result; registers_[fields.destination()] = result;
} }
} }
@ -238,7 +238,7 @@ struct Executor {
constexpr BranchFlags flags(f); constexpr BranchFlags flags(f);
if constexpr (flags.operation() == BranchFlags::Operation::BL) { if constexpr (flags.operation() == BranchFlags::Operation::BL) {
registers_.active[14] = registers_.pc(0); registers_[14] = registers_.pc(0);
} }
registers_.set_pc(registers_.pc(4) + branch.offset()); registers_.set_pc(registers_.pc(4) + branch.offset());
} }
@ -262,7 +262,7 @@ struct Executor {
uint32_t address = uint32_t address =
transfer.base() == 15 ? transfer.base() == 15 ?
registers_.pc(4) : registers_.pc(4) :
registers_.active[transfer.base()]; registers_[transfer.base()];
// Determine what the address will be after offsetting. // Determine what the address will be after offsetting.
uint32_t offsetted_address = address; uint32_t offsetted_address = address;
@ -288,7 +288,7 @@ struct Executor {
const uint32_t source = const uint32_t source =
transfer.source() == 15 ? transfer.source() == 15 ?
registers_.pc_status(8) : registers_.pc_status(8) :
registers_.active[transfer.source()]; registers_[transfer.source()];
bool did_write; bool did_write;
if constexpr (flags.transfer_byte()) { if constexpr (flags.transfer_byte()) {
@ -331,7 +331,7 @@ struct Executor {
if(transfer.destination() == 15) { if(transfer.destination() == 15) {
registers_.set_pc(value); registers_.set_pc(value);
} else { } else {
registers_.active[transfer.destination()] = value; registers_[transfer.destination()] = value;
} }
} }
@ -340,7 +340,7 @@ struct Executor {
if(transfer.base() == 15) { if(transfer.base() == 15) {
registers_.set_pc(offsetted_address); registers_.set_pc(offsetted_address);
} else { } else {
registers_.active[transfer.base()] = offsetted_address; registers_[transfer.base()] = offsetted_address;
} }
} }
} }
@ -355,7 +355,7 @@ struct Executor {
// the final address if the base register is first in the write-out list. // the final address if the base register is first in the write-out list.
uint32_t address = transfer.base() == 15 ? uint32_t address = transfer.base() == 15 ?
registers_.pc_status(4) : registers_.pc_status(4) :
registers_.active[transfer.base()]; registers_[transfer.base()];
const uint32_t initial_address = address; const uint32_t initial_address = address;
// Figure out what the final address will be, since that's what'll be // Figure out what the final address will be, since that's what'll be
@ -449,9 +449,9 @@ struct Executor {
// Also restore the base register. // Also restore the base register.
if(transfer.base() != 15) { if(transfer.base() != 15) {
if constexpr (flags.write_back_address()) { if constexpr (flags.write_back_address()) {
registers_.active[transfer.base()] = final_address; registers_[transfer.base()] = final_address;
} else { } else {
registers_.active[transfer.base()] = initial_address; registers_[transfer.base()] = initial_address;
} }
} }
} }
@ -476,14 +476,14 @@ struct Executor {
// Write out registers 1 to 14. // Write out registers 1 to 14.
for(int c = 0; c < 15; c++) { for(int c = 0; c < 15; c++) {
if(list & (1 << c)) { if(list & (1 << c)) {
access(registers_.active[c]); access(registers_[c]);
// Modify base register after each write if writeback is enabled. // Modify base register after each write if writeback is enabled.
// This'll ensure the unmodified value goes out if it was the // This'll ensure the unmodified value goes out if it was the
// first-selected register only. // first-selected register only.
if constexpr (flags.write_back_address()) { if constexpr (flags.write_back_address()) {
if(transfer.base() != 15) { if(transfer.base() != 15) {
registers_.active[transfer.base()] = final_address; registers_[transfer.base()] = final_address;
} }
} }
} }
@ -493,7 +493,7 @@ struct Executor {
// was empty. // was empty.
if constexpr (flags.write_back_address()) { if constexpr (flags.write_back_address()) {
if(transfer.base() != 15) { if(transfer.base() != 15) {
registers_.active[transfer.base()] = final_address; registers_[transfer.base()] = final_address;
} }
} }

View File

@ -80,7 +80,7 @@ struct Registers {
/// @returns The full PC + status bits. /// @returns The full PC + status bits.
uint32_t pc_status(uint32_t offset) const { uint32_t pc_status(uint32_t offset) const {
return return
((active[15] + offset) & ConditionCode::Address) | ((active_[15] + offset) & ConditionCode::Address) |
status(); status();
} }
@ -108,12 +108,12 @@ struct Registers {
/// Sets a new PC. /// Sets a new PC.
void set_pc(uint32_t value) { void set_pc(uint32_t value) {
active[15] = value & ConditionCode::Address; active_[15] = value & ConditionCode::Address;
} }
/// @returns The stored PC plus @c offset limited to 26 bits. /// @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;
} }
// MARK: - Exceptions. // MARK: - Exceptions.
@ -150,15 +150,15 @@ struct Registers {
switch(exception) { switch(exception) {
case Exception::IRQ: case Exception::IRQ:
set_mode(Mode::IRQ); set_mode(Mode::IRQ);
active[14] = pc(8); active_[14] = pc(8);
break; break;
case Exception::FIQ: case Exception::FIQ:
set_mode(Mode::FIQ); set_mode(Mode::FIQ);
active[14] = pc(8); active_[14] = pc(8);
break; break;
default: default:
set_mode(Mode::Supervisor); set_mode(Mode::Supervisor);
active[14] = pc(4); active_[14] = pc(4);
break; break;
} }
@ -223,16 +223,16 @@ struct Registers {
// if the incoming mode is FIQ then the other five will be saved in the next switch. // if the incoming mode is FIQ then the other five will be saved in the next switch.
switch(mode_) { switch(mode_) {
case Mode::FIQ: case Mode::FIQ:
std::copy(active.begin() + 8, active.begin() + 15, fiq_registers_.begin()); std::copy(active_.begin() + 8, active_.begin() + 15, fiq_registers_.begin());
break; break;
case Mode::User: case Mode::User:
std::copy(active.begin() + 13, active.begin() + 15, user_registers_.begin() + 5); std::copy(active_.begin() + 13, active_.begin() + 15, user_registers_.begin() + 5);
break; break;
case Mode::Supervisor: case Mode::Supervisor:
std::copy(active.begin() + 13, active.begin() + 15, supervisor_registers_.begin()); std::copy(active_.begin() + 13, active_.begin() + 15, supervisor_registers_.begin());
break; break;
case Mode::IRQ: case Mode::IRQ:
std::copy(active.begin() + 13, active.begin() + 15, irq_registers_.begin()); std::copy(active_.begin() + 13, active_.begin() + 15, irq_registers_.begin());
break; break;
} }
@ -240,31 +240,35 @@ struct Registers {
// For FIQ: save an additional five, then overwrite seven. // For FIQ: save an additional five, then overwrite seven.
switch(target_mode) { switch(target_mode) {
case Mode::FIQ: case Mode::FIQ:
std::copy(active.begin() + 8, active.begin() + 13, user_registers_.begin()); std::copy(active_.begin() + 8, active_.begin() + 13, user_registers_.begin());
std::copy(fiq_registers_.begin(), fiq_registers_.end(), active.begin() + 8); std::copy(fiq_registers_.begin(), fiq_registers_.end(), active_.begin() + 8);
break; break;
case Mode::User: case Mode::User:
std::copy(user_registers_.begin() + 5, user_registers_.end(), active.begin() + 13); std::copy(user_registers_.begin() + 5, user_registers_.end(), active_.begin() + 13);
break; break;
case Mode::Supervisor: case Mode::Supervisor:
std::copy(supervisor_registers_.begin(), supervisor_registers_.end(), active.begin() + 13); std::copy(supervisor_registers_.begin(), supervisor_registers_.end(), active_.begin() + 13);
break; break;
case Mode::IRQ: case Mode::IRQ:
std::copy(irq_registers_.begin(), irq_registers_.end(), active.begin() + 13); std::copy(irq_registers_.begin(), irq_registers_.end(), active_.begin() + 13);
break; break;
} }
// If FIQ is outgoing then there's another five registers to restore. // If FIQ is outgoing then there's another five registers to restore.
if(mode_ == Mode::FIQ) { if(mode_ == Mode::FIQ) {
std::copy(user_registers_.begin(), user_registers_.begin() + 5, active.begin() + 8); std::copy(user_registers_.begin(), user_registers_.begin() + 5, active_.begin() + 8);
} }
mode_ = target_mode; mode_ = target_mode;
} }
/// The active register set. TODO: switch to an implementation of operator[], hiding the uint32_t &operator[](int offset) {
/// current implementation decision to maintain this as a linear block of memory. return active_[offset];
std::array<uint32_t, 16> active{}; }
const uint32_t operator[](int offset) const {
return active_[offset];
}
private: private:
Mode mode_ = Mode::Supervisor; Mode mode_ = Mode::Supervisor;
@ -280,6 +284,9 @@ struct Registers {
std::array<uint32_t, 7> fiq_registers_{}; std::array<uint32_t, 7> fiq_registers_{};
std::array<uint32_t, 2> irq_registers_{}; std::array<uint32_t, 2> irq_registers_{};
std::array<uint32_t, 2> supervisor_registers_{}; std::array<uint32_t, 2> supervisor_registers_{};
// The active register set.
std::array<uint32_t, 16> active_{};
}; };
} }

View File

@ -225,7 +225,7 @@ struct Memory {
// //
// 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()[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);