thumb: add execution of instructions
also arm: fix some instructions Signed-off-by: Amneesh Singh <natto@weirdnatto.in>
This commit is contained in:
@@ -1,9 +1,7 @@
|
||||
#include "cpu/cpu-fixture.hh"
|
||||
#include "cpu/cpu-impl.hh"
|
||||
#include "fixture.hh"
|
||||
#include "util/bits.hh"
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <limits>
|
||||
#include <variant>
|
||||
|
||||
using namespace matar;
|
||||
|
||||
@@ -14,11 +12,11 @@ using namespace arm;
|
||||
TEST_CASE_METHOD(CpuFixture, "Branch and Exchange", TAG) {
|
||||
InstructionData data = BranchAndExchange{ .rn = 3 };
|
||||
|
||||
setr(3, 342890);
|
||||
setr(3, 342800);
|
||||
|
||||
exec(data);
|
||||
|
||||
CHECK(getr(15) == 342890);
|
||||
CHECK(getr(15) == 342800);
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(CpuFixture, "Branch", TAG) {
|
||||
@@ -806,14 +804,11 @@ TEST_CASE_METHOD(CpuFixture, "Data Processing", TAG) {
|
||||
|
||||
processing->opcode = OpCode::AND;
|
||||
|
||||
cpsr.set_z(false);
|
||||
set_psr(cpsr);
|
||||
exec(data, Condition::EQ);
|
||||
|
||||
// condition is false
|
||||
CHECK(getr(5) == 0);
|
||||
|
||||
cpsr = psr();
|
||||
cpsr.set_z(true);
|
||||
set_psr(cpsr);
|
||||
exec(data, Condition::EQ);
|
||||
|
@@ -1,96 +0,0 @@
|
||||
#include "fixture.hh"
|
||||
|
||||
Psr
|
||||
CpuFixture::psr(bool spsr) {
|
||||
Psr psr(0);
|
||||
CpuImpl tmp = cpu;
|
||||
arm::Instruction instruction(
|
||||
Condition::AL,
|
||||
arm::PsrTransfer{ .operand = 0,
|
||||
.spsr = spsr,
|
||||
.type = arm::PsrTransfer::Type::Mrs,
|
||||
.imm = false });
|
||||
|
||||
instruction.exec(tmp);
|
||||
|
||||
psr.set_all(getr_(0, tmp));
|
||||
return psr;
|
||||
}
|
||||
|
||||
void
|
||||
CpuFixture::set_psr(Psr psr, bool spsr) {
|
||||
// R0
|
||||
uint32_t old = getr(0);
|
||||
|
||||
setr(0, psr.raw());
|
||||
|
||||
arm::Instruction instruction(
|
||||
Condition::AL,
|
||||
arm::PsrTransfer{ .operand = 0,
|
||||
.spsr = spsr,
|
||||
.type = arm::PsrTransfer::Type::Msr,
|
||||
.imm = false });
|
||||
|
||||
instruction.exec(cpu);
|
||||
|
||||
setr(0, old);
|
||||
}
|
||||
|
||||
// We need these workarounds to just use the public API and not private
|
||||
// fields. Assuming that these work correctly is necessary. Besides, all it
|
||||
// matters is that the public API is correct.
|
||||
uint32_t
|
||||
CpuFixture::getr_(uint8_t r, CpuImpl& cpu) {
|
||||
size_t addr = 13000;
|
||||
size_t offset = r == 15 ? 4 : 0;
|
||||
uint32_t word = bus.read_word(addr + offset);
|
||||
CpuImpl tmp = cpu;
|
||||
uint32_t ret = 0xFFFFFFFF;
|
||||
uint8_t base = r ? 0 : 1;
|
||||
|
||||
// set R0/R1 = 0
|
||||
arm::Instruction zero(
|
||||
Condition::AL,
|
||||
arm::DataProcessing{ .operand = 0u,
|
||||
.rd = base,
|
||||
.rn = 0,
|
||||
.set = false,
|
||||
.opcode = arm::DataProcessing::OpCode::MOV });
|
||||
|
||||
// get register
|
||||
arm::Instruction get(
|
||||
Condition::AL,
|
||||
arm::SingleDataTransfer{ .offset = static_cast<uint16_t>(addr),
|
||||
.rd = r,
|
||||
.rn = base,
|
||||
.load = false,
|
||||
.write = false,
|
||||
.byte = false,
|
||||
.up = true,
|
||||
.pre = true });
|
||||
|
||||
zero.exec(tmp);
|
||||
get.exec(tmp);
|
||||
|
||||
addr += offset;
|
||||
|
||||
ret = bus.read_word(addr);
|
||||
|
||||
bus.write_word(addr, word);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
CpuFixture::setr_(uint8_t r, uint32_t value, CpuImpl& cpu) {
|
||||
// set register
|
||||
arm::Instruction set(
|
||||
Condition::AL,
|
||||
arm::DataProcessing{ .operand = value,
|
||||
.rd = r,
|
||||
.rn = 0,
|
||||
.set = false,
|
||||
.opcode = arm::DataProcessing::OpCode::MOV });
|
||||
|
||||
set.exec(cpu);
|
||||
}
|
@@ -1,37 +0,0 @@
|
||||
#include "cpu/cpu-impl.hh"
|
||||
|
||||
using namespace matar;
|
||||
|
||||
class CpuFixture {
|
||||
public:
|
||||
CpuFixture()
|
||||
: bus(Memory(std::array<uint8_t, Memory::BIOS_SIZE>(),
|
||||
std::vector<uint8_t>(Header::HEADER_SIZE)))
|
||||
, cpu(bus) {}
|
||||
|
||||
protected:
|
||||
void exec(arm::InstructionData data, Condition condition = Condition::AL) {
|
||||
arm::Instruction instruction(condition, data);
|
||||
instruction.exec(cpu);
|
||||
}
|
||||
|
||||
void reset(uint32_t value = 0) { setr(15, value + 8); }
|
||||
|
||||
uint32_t getr(uint8_t r) { return getr_(r, cpu); }
|
||||
|
||||
void setr(uint8_t r, uint32_t value) { setr_(r, value, cpu); }
|
||||
|
||||
Psr psr(bool spsr = false);
|
||||
|
||||
void set_psr(Psr psr, bool spsr = false);
|
||||
|
||||
Bus bus;
|
||||
CpuImpl cpu;
|
||||
|
||||
private:
|
||||
// hack to get a register
|
||||
uint32_t getr_(uint8_t r, CpuImpl& cpu);
|
||||
|
||||
// hack to set a register
|
||||
void setr_(uint8_t r, uint32_t value, CpuImpl& cpu);
|
||||
};
|
@@ -1,5 +1,4 @@
|
||||
tests_sources += files(
|
||||
'fixture.cc',
|
||||
'instruction.cc',
|
||||
'exec.cc'
|
||||
)
|
Reference in New Issue
Block a user