mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-27 00:30:26 +00:00
Tie down more corners.
This commit is contained in:
parent
7a5ed6c427
commit
b42a6e447d
@ -248,14 +248,14 @@ struct Executor {
|
|||||||
|
|
||||||
// Calculate offset.
|
// Calculate offset.
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
if constexpr (flags.offset_is_immediate()) {
|
if constexpr (!flags.offset_is_immediate()) {
|
||||||
offset = transfer.immediate();
|
|
||||||
} else {
|
|
||||||
// The 8 shift control bits are described in 6.2.3, but
|
// The 8 shift control bits are described in 6.2.3, but
|
||||||
// the register specified shift amounts are not available
|
// the register specified shift amounts are not available
|
||||||
// in this instruction class.
|
// in this instruction class.
|
||||||
uint32_t carry = registers_.c();
|
uint32_t carry = registers_.c();
|
||||||
offset = decode_shift<false, false>(transfer, carry, 4);
|
offset = decode_shift<false, false>(transfer, carry, 4);
|
||||||
|
} else {
|
||||||
|
offset = transfer.immediate();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtain base address.
|
// Obtain base address.
|
||||||
@ -546,6 +546,10 @@ struct Executor {
|
|||||||
|
|
||||||
MemoryT bus;
|
MemoryT bus;
|
||||||
|
|
||||||
|
const Registers ®isters() const {
|
||||||
|
return registers_;
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets the expected address of the instruction after whichever is about to be executed.
|
/// Sets the expected address of the instruction after whichever is about to be executed.
|
||||||
/// So it's PC+4 compared to most other systems.
|
/// So it's PC+4 compared to most other systems.
|
||||||
void set_pc(uint32_t pc) {
|
void set_pc(uint32_t pc) {
|
||||||
@ -559,11 +563,6 @@ struct Executor {
|
|||||||
return registers_.pc(0);
|
return registers_.pc(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @returns The current processor mode.
|
|
||||||
Mode mode() const {
|
|
||||||
return registers_.mode();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Registers registers_;
|
Registers registers_;
|
||||||
};
|
};
|
||||||
|
@ -66,11 +66,9 @@ struct Registers {
|
|||||||
overflow_flag_ = value;
|
overflow_flag_ = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @returns The full PC + status bits.
|
uint32_t status() const {
|
||||||
uint32_t pc_status(uint32_t offset) const {
|
|
||||||
return
|
return
|
||||||
uint32_t(mode_) |
|
uint32_t(mode_) |
|
||||||
((active[15] + offset) & ConditionCode::Address) |
|
|
||||||
(negative_flag_ & ConditionCode::Negative) |
|
(negative_flag_ & ConditionCode::Negative) |
|
||||||
(zero_result_ ? 0 : ConditionCode::Zero) |
|
(zero_result_ ? 0 : ConditionCode::Zero) |
|
||||||
(carry_flag_ ? ConditionCode::Carry : 0) |
|
(carry_flag_ ? ConditionCode::Carry : 0) |
|
||||||
@ -78,6 +76,13 @@ struct Registers {
|
|||||||
interrupt_flags_;
|
interrupt_flags_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @returns The full PC + status bits.
|
||||||
|
uint32_t pc_status(uint32_t offset) const {
|
||||||
|
return
|
||||||
|
((active[15] + offset) & ConditionCode::Address) |
|
||||||
|
status();
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets status bits only, subject to mode.
|
/// Sets status bits only, subject to mode.
|
||||||
void set_status(uint32_t status) {
|
void set_status(uint32_t status) {
|
||||||
// ... in user mode the other flags (I, F, M1, M0) are protected from direct change
|
// ... in user mode the other flags (I, F, M1, M0) are protected from direct change
|
||||||
@ -100,7 +105,6 @@ struct Registers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Sets a new PC.
|
/// Sets a new PC.
|
||||||
/// TODO: communicate this onward.
|
|
||||||
void set_pc(uint32_t value) {
|
void set_pc(uint32_t value) {
|
||||||
active[15] = value & ConditionCode::Address;
|
active[15] = value & ConditionCode::Address;
|
||||||
}
|
}
|
||||||
@ -204,7 +208,7 @@ struct Registers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<uint32_t, 16> active;
|
std::array<uint32_t, 16> active{};
|
||||||
|
|
||||||
void set_mode(Mode target_mode) {
|
void set_mode(Mode target_mode) {
|
||||||
if(mode_ == target_mode) {
|
if(mode_ == target_mode) {
|
||||||
@ -257,17 +261,17 @@ struct Registers {
|
|||||||
private:
|
private:
|
||||||
Mode mode_ = Mode::Supervisor;
|
Mode mode_ = Mode::Supervisor;
|
||||||
|
|
||||||
uint32_t zero_result_ = 0;
|
uint32_t zero_result_ = 1;
|
||||||
uint32_t negative_flag_ = 0;
|
uint32_t negative_flag_ = 0;
|
||||||
uint32_t interrupt_flags_ = 0;
|
uint32_t interrupt_flags_ = ConditionCode::IRQDisable | ConditionCode::FIQDisable;
|
||||||
uint32_t carry_flag_ = 0;
|
uint32_t carry_flag_ = 0;
|
||||||
uint32_t overflow_flag_ = 0;
|
uint32_t overflow_flag_ = 0;
|
||||||
|
|
||||||
// Various shadow registers.
|
// Various shadow registers.
|
||||||
std::array<uint32_t, 7> user_registers_;
|
std::array<uint32_t, 7> user_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_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,33 +20,42 @@ struct Memory {
|
|||||||
|
|
||||||
template <typename IntT>
|
template <typename IntT>
|
||||||
bool write(uint32_t address, IntT source, Mode mode, bool trans) {
|
bool write(uint32_t address, IntT source, Mode mode, bool trans) {
|
||||||
(void)address;
|
|
||||||
(void)source;
|
|
||||||
(void)mode;
|
(void)mode;
|
||||||
(void)trans;
|
(void)trans;
|
||||||
|
|
||||||
printf("W of %08x to %08x [%lu]\n", source, address, sizeof(IntT));
|
printf("W of %08x to %08x [%lu]\n", source, address, sizeof(IntT));
|
||||||
|
|
||||||
|
if(has_moved_rom_ && address < ram_.size()) {
|
||||||
|
*reinterpret_cast<IntT *>(&ram_[address]) = source;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename IntT>
|
template <typename IntT>
|
||||||
bool read(uint32_t address, IntT &source, Mode mode, bool trans) {
|
bool read(uint32_t address, IntT &source, Mode mode, bool trans) {
|
||||||
if(address > 0x3800000) {
|
(void)mode;
|
||||||
|
(void)trans;
|
||||||
|
|
||||||
|
if(address >= 0x3800000) {
|
||||||
has_moved_rom_ = true;
|
has_moved_rom_ = true;
|
||||||
source = *reinterpret_cast<const IntT *>(&rom[address - 0x3800000]);
|
source = *reinterpret_cast<const IntT *>(&rom[address - 0x3800000]);
|
||||||
} else if(!has_moved_rom_) {
|
} else if(!has_moved_rom_) {
|
||||||
// TODO: this is true only very transiently.
|
// TODO: this is true only very transiently.
|
||||||
source = *reinterpret_cast<const IntT *>(&rom[address]);
|
source = *reinterpret_cast<const IntT *>(&rom[address]);
|
||||||
|
} else if(address < ram_.size()) {
|
||||||
|
source = *reinterpret_cast<const IntT *>(&ram_[address]);
|
||||||
} else {
|
} else {
|
||||||
|
source = 0;
|
||||||
printf("Unknown read from %08x [%lu]\n", address, sizeof(IntT));
|
printf("Unknown read from %08x [%lu]\n", address, sizeof(IntT));
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)mode;
|
|
||||||
(void)trans;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool has_moved_rom_ = false;
|
bool has_moved_rom_ = false;
|
||||||
|
std::array<uint8_t, 4*1024*1024> ram_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -202,21 +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);
|
||||||
|
|
||||||
Executor<Model::ARMv2, Memory> executor;
|
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.mode(), false);
|
executor->bus.read(executor->pc(), instruction, executor->registers().mode(), false);
|
||||||
|
|
||||||
printf("%08x: %08x\n", executor.pc(), instruction);
|
printf("%08x: %08x [", executor->pc(), instruction);
|
||||||
execute<Model::ARMv2>(instruction, executor);
|
for(int c = 0; c < 15; c++) {
|
||||||
|
printf("r%d:%08x ", c, executor->registers().active[c]);
|
||||||
|
}
|
||||||
|
printf("psr:%08x]\n", executor->registers().status());
|
||||||
|
execute<Model::ARMv2>(instruction, *executor);
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user