thumb: add execution of instructions

also arm: fix some instructions

Signed-off-by: Amneesh Singh <natto@weirdnatto.in>
This commit is contained in:
2023-09-30 01:31:09 +05:30
parent 03dbb7052f
commit 36d71a4ee2
19 changed files with 1632 additions and 157 deletions

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);
};

View File

@@ -1,5 +1,4 @@
tests_sources += files(
'fixture.cc',
'instruction.cc',
'exec.cc'
)