memory: bus and rom should not be writeable
so fix tests and shit Signed-off-by: Amneesh Singh <natto@weirdnatto.in>
This commit is contained in:
@@ -282,17 +282,18 @@ Instruction::exec(Cpu& cpu) {
|
|||||||
cpu.is_flushed = true;
|
cpu.is_flushed = true;
|
||||||
},
|
},
|
||||||
[&cpu, pc_error](BlockDataTransfer& data) {
|
[&cpu, pc_error](BlockDataTransfer& data) {
|
||||||
|
static constexpr uint8_t alignment = 4; // word
|
||||||
|
|
||||||
uint32_t address = cpu.gpr[data.rn];
|
uint32_t address = cpu.gpr[data.rn];
|
||||||
Mode mode = cpu.cpsr.mode();
|
Mode mode = cpu.cpsr.mode();
|
||||||
uint8_t alignment = 4; // word
|
|
||||||
uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
uint8_t n_regs = std::popcount(data.regs);
|
uint8_t n_regs = std::popcount(data.regs);
|
||||||
|
|
||||||
pc_error(data.rn);
|
pc_error(data.rn);
|
||||||
|
|
||||||
if (cpu.cpsr.mode() == Mode::User && data.s) {
|
if (cpu.cpsr.mode() == Mode::User && data.s) {
|
||||||
glogger.error("Bit S is set outside priviliged modes in {}",
|
glogger.error("Bit S is set outside priviliged modes in block "
|
||||||
typeid(data).name());
|
"data transfer");
|
||||||
}
|
}
|
||||||
|
|
||||||
// we just change modes to load user registers
|
// we just change modes to load user registers
|
||||||
@@ -301,9 +302,8 @@ Instruction::exec(Cpu& cpu) {
|
|||||||
cpu.chg_mode(Mode::User);
|
cpu.chg_mode(Mode::User);
|
||||||
|
|
||||||
if (data.write) {
|
if (data.write) {
|
||||||
glogger.error(
|
glogger.error("Write-back enable for user bank registers "
|
||||||
"Write-back enable for user bank registers in {}",
|
"in block data transfer");
|
||||||
typeid(data).name());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -286,47 +286,51 @@ Instruction::exec(Cpu& cpu) {
|
|||||||
},
|
},
|
||||||
[&cpu](AddOffsetStackPointer& data) { cpu.sp += data.word; },
|
[&cpu](AddOffsetStackPointer& data) { cpu.sp += data.word; },
|
||||||
[&cpu](PushPopRegister& data) {
|
[&cpu](PushPopRegister& data) {
|
||||||
|
static constexpr uint8_t alignment = 4;
|
||||||
|
|
||||||
if (data.load) {
|
if (data.load) {
|
||||||
for (uint8_t i = 0; i < 8; i++) {
|
for (uint8_t i = 0; i < 8; i++) {
|
||||||
if (get_bit(data.regs, i)) {
|
if (get_bit(data.regs, i)) {
|
||||||
cpu.gpr[i] = cpu.bus->read_word(cpu.sp);
|
cpu.gpr[i] = cpu.bus->read_word(cpu.sp);
|
||||||
cpu.sp += 4;
|
cpu.sp += alignment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.pclr) {
|
if (data.pclr) {
|
||||||
cpu.pc = cpu.bus->read_word(cpu.sp);
|
cpu.pc = cpu.bus->read_word(cpu.sp);
|
||||||
cpu.sp += 4;
|
cpu.sp += alignment;
|
||||||
cpu.is_flushed = true;
|
cpu.is_flushed = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (data.pclr) {
|
if (data.pclr) {
|
||||||
cpu.sp -= 4;
|
cpu.sp -= alignment;
|
||||||
cpu.bus->write_word(cpu.sp, cpu.lr);
|
cpu.bus->write_word(cpu.sp, cpu.lr);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int8_t i = 7; i >= 0; i--) {
|
for (int8_t i = 7; i >= 0; i--) {
|
||||||
if (get_bit(data.regs, i)) {
|
if (get_bit(data.regs, i)) {
|
||||||
cpu.sp -= 4;
|
cpu.sp -= alignment;
|
||||||
cpu.bus->write_word(cpu.sp, cpu.gpr[i]);
|
cpu.bus->write_word(cpu.sp, cpu.gpr[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[&cpu](MultipleLoad& data) {
|
[&cpu](MultipleLoad& data) {
|
||||||
|
static constexpr uint8_t alignment = 4;
|
||||||
|
|
||||||
uint32_t rb = cpu.gpr[data.rb];
|
uint32_t rb = cpu.gpr[data.rb];
|
||||||
|
|
||||||
if (data.load) {
|
if (data.load) {
|
||||||
for (uint8_t i = 0; i < 8; i++) {
|
for (uint8_t i = 0; i < 8; i++) {
|
||||||
if (get_bit(data.regs, i)) {
|
if (get_bit(data.regs, i)) {
|
||||||
cpu.gpr[i] = cpu.bus->read_word(rb);
|
cpu.gpr[i] = cpu.bus->read_word(rb);
|
||||||
rb += 4;
|
rb += alignment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int8_t i = 7; i >= 0; i--) {
|
for (int8_t i = 7; i >= 0; i--) {
|
||||||
if (get_bit(data.regs, i)) {
|
if (get_bit(data.regs, i)) {
|
||||||
rb -= 4;
|
rb -= alignment;
|
||||||
cpu.bus->write_word(rb, cpu.gpr[i]);
|
cpu.bus->write_word(rb, cpu.gpr[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -64,23 +64,17 @@ Memory::write(size_t address, uint8_t byte) {
|
|||||||
return; \
|
return; \
|
||||||
}
|
}
|
||||||
|
|
||||||
MATCHES(BIOS, bios)
|
|
||||||
MATCHES(BOARD_WRAM, board_wram)
|
MATCHES(BOARD_WRAM, board_wram)
|
||||||
MATCHES(CHIP_WRAM, chip_wram)
|
MATCHES(CHIP_WRAM, chip_wram)
|
||||||
MATCHES(PALETTE_RAM, palette_ram)
|
MATCHES(PALETTE_RAM, palette_ram)
|
||||||
MATCHES(VRAM, vram)
|
MATCHES(VRAM, vram)
|
||||||
MATCHES(OAM_OBJ_ATTR, oam_obj_attr)
|
MATCHES(OAM_OBJ_ATTR, oam_obj_attr)
|
||||||
MATCHES(ROM_0, rom)
|
|
||||||
MATCHES(ROM_1, rom)
|
|
||||||
MATCHES(ROM_2, rom)
|
|
||||||
|
|
||||||
glogger.error("Invalid memory region accessed");
|
glogger.error("Invalid memory region accessed");
|
||||||
|
|
||||||
#undef MATCHES
|
#undef MATCHES
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef MATCHES
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Memory::parse_header() {
|
Memory::parse_header() {
|
||||||
if (rom.size() < header.HEADER_SIZE) {
|
if (rom.size() < header.HEADER_SIZE) {
|
||||||
|
30
tests/bus.cc
30
tests/bus.cc
@@ -16,30 +16,30 @@ class BusFixture {
|
|||||||
};
|
};
|
||||||
|
|
||||||
TEST_CASE_METHOD(BusFixture, "Byte", TAG) {
|
TEST_CASE_METHOD(BusFixture, "Byte", TAG) {
|
||||||
CHECK(bus.read_byte(3349) == 0);
|
CHECK(bus.read_byte(0x30001A9) == 0);
|
||||||
|
|
||||||
bus.write_byte(3349, 0xEC);
|
bus.write_byte(0x30001A9, 0xEC);
|
||||||
CHECK(bus.read_byte(3349) == 0xEC);
|
CHECK(bus.read_byte(0x30001A9) == 0xEC);
|
||||||
CHECK(bus.read_word(3349) == 0xEC);
|
CHECK(bus.read_word(0x30001A9) == 0xEC);
|
||||||
CHECK(bus.read_halfword(3349) == 0xEC);
|
CHECK(bus.read_halfword(0x30001A9) == 0xEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_METHOD(BusFixture, "Halfword", TAG) {
|
TEST_CASE_METHOD(BusFixture, "Halfword", TAG) {
|
||||||
CHECK(bus.read_halfword(33750745) == 0);
|
CHECK(bus.read_halfword(0x202FED9) == 0);
|
||||||
|
|
||||||
bus.write_halfword(33750745, 0x1A4A);
|
bus.write_halfword(0x202FED9, 0x1A4A);
|
||||||
CHECK(bus.read_halfword(33750745) == 0x1A4A);
|
CHECK(bus.read_halfword(0x202FED9) == 0x1A4A);
|
||||||
CHECK(bus.read_word(33750745) == 0x1A4A);
|
CHECK(bus.read_word(0x202FED9) == 0x1A4A);
|
||||||
CHECK(bus.read_byte(33750745) == 0x4A);
|
CHECK(bus.read_byte(0x202FED9) == 0x4A);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_METHOD(BusFixture, "Word", TAG) {
|
TEST_CASE_METHOD(BusFixture, "Word", TAG) {
|
||||||
CHECK(bus.read_word(100724276) == 0);
|
CHECK(bus.read_word(0x600EE34) == 0);
|
||||||
|
|
||||||
bus.write_word(100724276, 0x3ACC491D);
|
bus.write_word(0x600EE34, 0x3ACC491D);
|
||||||
CHECK(bus.read_word(100724276) == 0x3ACC491D);
|
CHECK(bus.read_word(0x600EE34) == 0x3ACC491D);
|
||||||
CHECK(bus.read_halfword(100724276) == 0x491D);
|
CHECK(bus.read_halfword(0x600EE34) == 0x491D);
|
||||||
CHECK(bus.read_byte(100724276) == 0x1D);
|
CHECK(bus.read_byte(0x600EE34) == 0x1D);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef TAG
|
#undef TAG
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
|
#include "cpu/arm/instruction.hh"
|
||||||
#include "cpu/cpu-fixture.hh"
|
#include "cpu/cpu-fixture.hh"
|
||||||
#include "util/bits.hh"
|
#include "util/bits.hh"
|
||||||
#include <catch2/catch_test_macros.hpp>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
using namespace matar;
|
using namespace matar;
|
||||||
|
|
||||||
@@ -170,7 +172,7 @@ TEST_CASE_METHOD(CpuFixture, "Single Data Swap", TAG) {
|
|||||||
SingleDataSwap{ .rm = 3, .rd = 4, .rn = 9, .byte = false };
|
SingleDataSwap{ .rm = 3, .rd = 4, .rn = 9, .byte = false };
|
||||||
SingleDataSwap* swap = std::get_if<SingleDataSwap>(&data);
|
SingleDataSwap* swap = std::get_if<SingleDataSwap>(&data);
|
||||||
|
|
||||||
setr(9, 0x3FED);
|
setr(9, 0x3003FED);
|
||||||
setr(3, 94235087);
|
setr(3, 94235087);
|
||||||
setr(3, -259039045);
|
setr(3, -259039045);
|
||||||
bus.write_word(getr(9), 3241011111);
|
bus.write_word(getr(9), 3241011111);
|
||||||
@@ -210,14 +212,14 @@ TEST_CASE_METHOD(CpuFixture, "Single Data Transfer", TAG) {
|
|||||||
.pre = true };
|
.pre = true };
|
||||||
SingleDataTransfer* data_transfer = std::get_if<SingleDataTransfer>(&data);
|
SingleDataTransfer* data_transfer = std::get_if<SingleDataTransfer>(&data);
|
||||||
|
|
||||||
setr(3, 1596);
|
setr(3, 0x63C);
|
||||||
setr(7, 6);
|
setr(7, 0x3000004);
|
||||||
setr(5, -911111);
|
setr(5, -911111);
|
||||||
|
|
||||||
// shifted register (immediate)
|
// shifted register (immediate)
|
||||||
{
|
{
|
||||||
// 12768 + 6
|
// 0x31E + 0x3000004
|
||||||
bus.write_word(12774, 95995);
|
bus.write_word(0x30031E4, 95995);
|
||||||
exec(data);
|
exec(data);
|
||||||
|
|
||||||
CHECK(getr(5) == 95995);
|
CHECK(getr(5) == 95995);
|
||||||
@@ -234,8 +236,8 @@ TEST_CASE_METHOD(CpuFixture, "Single Data Transfer", TAG) {
|
|||||||
} };
|
} };
|
||||||
|
|
||||||
setr(12, 2);
|
setr(12, 2);
|
||||||
// 6384 + 6
|
// 6384 + 0x3000004
|
||||||
bus.write_word(6390, 3948123487);
|
bus.write_word(0x30018F4, 3948123487);
|
||||||
exec(data);
|
exec(data);
|
||||||
|
|
||||||
CHECK(getr(5) == 3948123487);
|
CHECK(getr(5) == 3948123487);
|
||||||
@@ -243,9 +245,9 @@ TEST_CASE_METHOD(CpuFixture, "Single Data Transfer", TAG) {
|
|||||||
|
|
||||||
// immediate
|
// immediate
|
||||||
{
|
{
|
||||||
data_transfer->offset = static_cast<uint16_t>(3489);
|
data_transfer->offset = static_cast<uint16_t>(0xDA1);
|
||||||
// 6 + 3489
|
// 0xDA1 + 0x3000004
|
||||||
bus.write_word(3495, 68795467);
|
bus.write_word(0x3000DA5, 68795467);
|
||||||
|
|
||||||
exec(data);
|
exec(data);
|
||||||
|
|
||||||
@@ -254,41 +256,42 @@ TEST_CASE_METHOD(CpuFixture, "Single Data Transfer", TAG) {
|
|||||||
|
|
||||||
// down
|
// down
|
||||||
{
|
{
|
||||||
setr(7, 18044);
|
setr(7, 0x3005E0D);
|
||||||
data_transfer->up = false;
|
data_transfer->up = false;
|
||||||
// 18044 - 3489
|
// 0x3005E0D - 0xDA1
|
||||||
bus.write_word(14555, 5949595);
|
bus.write_word(0x300506C, 5949595);
|
||||||
|
|
||||||
exec(data);
|
exec(data);
|
||||||
|
|
||||||
CHECK(getr(5) == 5949595);
|
CHECK(getr(5) == 5949595);
|
||||||
// no write back
|
// no write back
|
||||||
CHECK(getr(7) == 18044);
|
CHECK(getr(7) == 0x3005E0D);
|
||||||
}
|
}
|
||||||
|
|
||||||
// write
|
// write
|
||||||
{
|
{
|
||||||
data_transfer->write = true;
|
data_transfer->write = true;
|
||||||
bus.write_word(14555, 967844);
|
// 0x3005E0D - 0xDA1
|
||||||
|
bus.write_word(0x300506C, 967844);
|
||||||
|
|
||||||
exec(data);
|
exec(data);
|
||||||
|
|
||||||
CHECK(getr(5) == 967844);
|
CHECK(getr(5) == 967844);
|
||||||
// 18044 - 3489
|
// 0x3005E0D - 0xDA1
|
||||||
CHECK(getr(7) == 14555);
|
CHECK(getr(7) == 0x300506C);
|
||||||
}
|
}
|
||||||
|
|
||||||
// post
|
// post
|
||||||
{
|
{
|
||||||
data_transfer->write = false;
|
data_transfer->write = false;
|
||||||
data_transfer->pre = false;
|
data_transfer->pre = false;
|
||||||
bus.write_word(14555, 61119);
|
bus.write_word(0x300506C, 61119);
|
||||||
|
|
||||||
exec(data);
|
exec(data);
|
||||||
|
|
||||||
CHECK(getr(5) == 61119);
|
CHECK(getr(5) == 61119);
|
||||||
// 14555 - 3489
|
// 0x300506C - 0xDA1
|
||||||
CHECK(getr(7) == 11066);
|
CHECK(getr(7) == 0x30042CB);
|
||||||
}
|
}
|
||||||
|
|
||||||
// store
|
// store
|
||||||
@@ -297,21 +300,21 @@ TEST_CASE_METHOD(CpuFixture, "Single Data Transfer", TAG) {
|
|||||||
|
|
||||||
exec(data);
|
exec(data);
|
||||||
|
|
||||||
CHECK(bus.read_word(11066) == 61119);
|
CHECK(bus.read_word(0x30042CB) == 61119);
|
||||||
// 11066 - 3489
|
// 0x30042CB - 0xDA1
|
||||||
CHECK(getr(7) == 7577);
|
CHECK(getr(7) == 0x300352A);
|
||||||
}
|
}
|
||||||
|
|
||||||
// r15 as rn
|
// r15 as rn
|
||||||
{
|
{
|
||||||
data_transfer->rn = 15;
|
data_transfer->rn = 15;
|
||||||
setr(15, 7577);
|
setr(15, 0x300352A);
|
||||||
|
|
||||||
exec(data);
|
exec(data);
|
||||||
|
|
||||||
CHECK(bus.read_word(7577 - 2 * INSTRUCTION_SIZE) == 61119);
|
CHECK(bus.read_word(0x300352A - 2 * INSTRUCTION_SIZE) == 61119);
|
||||||
// 7577 - 3489
|
// 0x300352A - 0xDA1
|
||||||
CHECK(getr(15) == 4088 - 2 * INSTRUCTION_SIZE);
|
CHECK(getr(15) == 0x3002789 - 2 * INSTRUCTION_SIZE);
|
||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
data_transfer->rn = 7;
|
data_transfer->rn = 7;
|
||||||
@@ -319,15 +322,14 @@ TEST_CASE_METHOD(CpuFixture, "Single Data Transfer", TAG) {
|
|||||||
|
|
||||||
// r15 as rd
|
// r15 as rd
|
||||||
{
|
{
|
||||||
// 4088
|
|
||||||
data_transfer->rd = 15;
|
data_transfer->rd = 15;
|
||||||
setr(15, 444444);
|
setr(15, 444444);
|
||||||
|
|
||||||
exec(data);
|
exec(data);
|
||||||
|
|
||||||
CHECK(bus.read_word(7577 + INSTRUCTION_SIZE) == 444444);
|
CHECK(bus.read_word(0x300352A + INSTRUCTION_SIZE) == 444444);
|
||||||
// 7577 - 3489
|
// 0x300352A - 0xDA1
|
||||||
CHECK(getr(7) == 4088 + INSTRUCTION_SIZE);
|
CHECK(getr(7) == 0x3002789 + INSTRUCTION_SIZE);
|
||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
data_transfer->rd = 5;
|
data_transfer->rd = 5;
|
||||||
@@ -342,9 +344,9 @@ TEST_CASE_METHOD(CpuFixture, "Single Data Transfer", TAG) {
|
|||||||
|
|
||||||
exec(data);
|
exec(data);
|
||||||
|
|
||||||
CHECK(bus.read_word(4088) == (458267584 & 0xFF));
|
CHECK(bus.read_word(0x3002789) == (458267584 & 0xFF));
|
||||||
// 4088 - 3489
|
// 0x3002789 - 0xDA1
|
||||||
CHECK(getr(7) == 599);
|
CHECK(getr(7) == 0x30019E8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,14 +363,14 @@ TEST_CASE_METHOD(CpuFixture, "Halfword Transfer", TAG) {
|
|||||||
.pre = true };
|
.pre = true };
|
||||||
HalfwordTransfer* hw_transfer = std::get_if<HalfwordTransfer>(&data);
|
HalfwordTransfer* hw_transfer = std::get_if<HalfwordTransfer>(&data);
|
||||||
|
|
||||||
setr(12, 8404);
|
setr(12, 0x384);
|
||||||
setr(11, 459058287);
|
setr(11, 459058287);
|
||||||
setr(10, 900);
|
setr(10, 0x300611E);
|
||||||
|
|
||||||
// register offset
|
// register offset
|
||||||
{
|
{
|
||||||
// 900 + 8404
|
// 0x300611E + 0x384
|
||||||
bus.write_word(9304, 3948123487);
|
bus.write_word(0x30064A2, 3948123487);
|
||||||
exec(data);
|
exec(data);
|
||||||
|
|
||||||
CHECK(getr(11) == (3948123487 & 0xFFFF));
|
CHECK(getr(11) == (3948123487 & 0xFFFF));
|
||||||
@@ -377,9 +379,9 @@ TEST_CASE_METHOD(CpuFixture, "Halfword Transfer", TAG) {
|
|||||||
// immediate offset
|
// immediate offset
|
||||||
{
|
{
|
||||||
hw_transfer->imm = true;
|
hw_transfer->imm = true;
|
||||||
hw_transfer->offset = 167;
|
hw_transfer->offset = 0xA7;
|
||||||
// 900 + 167
|
// 0x300611E + 0xA7
|
||||||
bus.write_word(1067, 594633302);
|
bus.write_word(0x30061C5, 594633302);
|
||||||
exec(data);
|
exec(data);
|
||||||
|
|
||||||
CHECK(getr(11) == (594633302 & 0xFFFF));
|
CHECK(getr(11) == (594633302 & 0xFFFF));
|
||||||
@@ -388,40 +390,39 @@ TEST_CASE_METHOD(CpuFixture, "Halfword Transfer", TAG) {
|
|||||||
// down
|
// down
|
||||||
{
|
{
|
||||||
hw_transfer->up = false;
|
hw_transfer->up = false;
|
||||||
// 900 - 167
|
// 0x300611E - 0xA7
|
||||||
bus.write_word(733, 222221);
|
bus.write_word(0x3006077, 222221);
|
||||||
|
|
||||||
exec(data);
|
exec(data);
|
||||||
|
|
||||||
CHECK(getr(11) == (222221 & 0xFFFF));
|
CHECK(getr(11) == (222221 & 0xFFFF));
|
||||||
// no write back
|
// no write back
|
||||||
CHECK(getr(10) == 900);
|
CHECK(getr(10) == 0x300611E);
|
||||||
}
|
}
|
||||||
|
|
||||||
// write
|
// write
|
||||||
{
|
{
|
||||||
hw_transfer->write = true;
|
hw_transfer->write = true;
|
||||||
// 900 - 167
|
// 0x300611E - 0xA7
|
||||||
bus.write_word(733, 100000005);
|
bus.write_word(0x3006077, 100000005);
|
||||||
|
|
||||||
exec(data);
|
exec(data);
|
||||||
|
|
||||||
CHECK(getr(11) == (100000005 & 0xFFFF));
|
CHECK(getr(11) == (100000005 & 0xFFFF));
|
||||||
// 900 - 167
|
CHECK(getr(10) == 0x3006077);
|
||||||
CHECK(getr(10) == 733);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// post
|
// post
|
||||||
{
|
{
|
||||||
hw_transfer->pre = false;
|
hw_transfer->pre = false;
|
||||||
hw_transfer->write = false;
|
hw_transfer->write = false;
|
||||||
bus.write_word(733, 6111909);
|
bus.write_word(0x3006077, 6111909);
|
||||||
|
|
||||||
exec(data);
|
exec(data);
|
||||||
|
|
||||||
CHECK(getr(11) == (6111909 & 0xFFFF));
|
CHECK(getr(11) == (6111909 & 0xFFFF));
|
||||||
// 733 - 167
|
// 0x3006077 - 0xA7
|
||||||
CHECK(getr(10) == 566);
|
CHECK(getr(10) == 0x3005FD0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// store
|
// store
|
||||||
@@ -430,22 +431,22 @@ TEST_CASE_METHOD(CpuFixture, "Halfword Transfer", TAG) {
|
|||||||
|
|
||||||
exec(data);
|
exec(data);
|
||||||
|
|
||||||
CHECK(bus.read_halfword(566) == (6111909 & 0xFFFF));
|
CHECK(bus.read_halfword(0x3005FD0) == (6111909 & 0xFFFF));
|
||||||
// 566 - 167
|
// 0x3005FD0 - 0xA7
|
||||||
CHECK(getr(10) == 399);
|
CHECK(getr(10) == 0x3005F29);
|
||||||
}
|
}
|
||||||
|
|
||||||
// r15 as rn
|
// r15 as rn
|
||||||
{
|
{
|
||||||
hw_transfer->rn = 15;
|
hw_transfer->rn = 15;
|
||||||
setr(15, 399);
|
setr(15, 0x3005F29);
|
||||||
|
|
||||||
exec(data);
|
exec(data);
|
||||||
|
|
||||||
CHECK(bus.read_halfword(399 - 2 * INSTRUCTION_SIZE) ==
|
CHECK(bus.read_halfword(0x3005F29 - 2 * INSTRUCTION_SIZE) ==
|
||||||
(6111909 & 0xFFFF));
|
(6111909 & 0xFFFF));
|
||||||
// 399 - 167
|
// 0x3005F29 - 0xA7
|
||||||
CHECK(getr(15) == 232 - 2 * INSTRUCTION_SIZE);
|
CHECK(getr(15) == 0x3005E82 - 2 * INSTRUCTION_SIZE);
|
||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
hw_transfer->rn = 10;
|
hw_transfer->rn = 10;
|
||||||
@@ -458,38 +459,38 @@ TEST_CASE_METHOD(CpuFixture, "Halfword Transfer", TAG) {
|
|||||||
|
|
||||||
exec(data);
|
exec(data);
|
||||||
|
|
||||||
CHECK(bus.read_halfword(399 + INSTRUCTION_SIZE) == 224);
|
CHECK(bus.read_halfword(0x3005F29 + INSTRUCTION_SIZE) == 224);
|
||||||
// 399 - 167
|
// 0x3005F29 - 0xA7
|
||||||
CHECK(getr(10) == 232 + INSTRUCTION_SIZE);
|
CHECK(getr(10) == 0x3005E82 + INSTRUCTION_SIZE);
|
||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
hw_transfer->rd = 11;
|
hw_transfer->rd = 11;
|
||||||
setr(10, 399);
|
setr(10, getr(10) - INSTRUCTION_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// signed halfword
|
// signed halfword
|
||||||
{
|
{
|
||||||
hw_transfer->load = true;
|
hw_transfer->load = true;
|
||||||
hw_transfer->sign = true;
|
hw_transfer->sign = true;
|
||||||
bus.write_halfword(399, -12345);
|
bus.write_halfword(0x3005E82, -12345);
|
||||||
|
|
||||||
exec(data);
|
exec(data);
|
||||||
|
|
||||||
CHECK(getr(11) == static_cast<uint32_t>(-12345));
|
CHECK(getr(11) == static_cast<uint32_t>(-12345));
|
||||||
// 399 - 167
|
// 0x3005E82 - 0xA7
|
||||||
CHECK(getr(10) == 232);
|
CHECK(getr(10) == 0x3005DDB);
|
||||||
}
|
}
|
||||||
|
|
||||||
// signed byte
|
// signed byte
|
||||||
{
|
{
|
||||||
hw_transfer->half = false;
|
hw_transfer->half = false;
|
||||||
bus.write_byte(232, -56);
|
bus.write_byte(0x3005DDB, -56);
|
||||||
|
|
||||||
exec(data);
|
exec(data);
|
||||||
|
|
||||||
CHECK(getr(11) == static_cast<uint32_t>(-56));
|
CHECK(getr(11) == static_cast<uint32_t>(-56));
|
||||||
// 232 - 167
|
// 0x3005DDB - 0xA7
|
||||||
CHECK(getr(10) == 65);
|
CHECK(getr(10) == 0x3005D34);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -503,18 +504,20 @@ TEST_CASE_METHOD(CpuFixture, "Block Data Transfer", TAG) {
|
|||||||
.pre = true };
|
.pre = true };
|
||||||
|
|
||||||
BlockDataTransfer* block_transfer = std::get_if<BlockDataTransfer>(&data);
|
BlockDataTransfer* block_transfer = std::get_if<BlockDataTransfer>(&data);
|
||||||
|
static constexpr uint8_t alignment = 4;
|
||||||
|
|
||||||
// load
|
// load
|
||||||
SECTION("load") {
|
SECTION("load") {
|
||||||
|
static constexpr uint32_t address = 0x3000D78;
|
||||||
// populate memory
|
// populate memory
|
||||||
bus.write_word(3448, 38947234);
|
bus.write_word(address, 38947234);
|
||||||
bus.write_word(3452, 237164);
|
bus.write_word(address + alignment, 237164);
|
||||||
bus.write_word(3456, 679785111);
|
bus.write_word(address + alignment * 2, 679785111);
|
||||||
bus.write_word(3460, 905895898);
|
bus.write_word(address + alignment * 3, 905895898);
|
||||||
bus.write_word(3464, 131313333);
|
bus.write_word(address + alignment * 4, 131313333);
|
||||||
bus.write_word(3468, 131);
|
bus.write_word(address + alignment * 5, 131);
|
||||||
bus.write_word(3472, 989231);
|
bus.write_word(address + alignment * 6, 989231);
|
||||||
bus.write_word(3476, 6);
|
bus.write_word(address + alignment * 7, 6);
|
||||||
|
|
||||||
auto checker = [this](uint32_t rnval = 0) {
|
auto checker = [this](uint32_t rnval = 0) {
|
||||||
CHECK(getr(0) == 237164);
|
CHECK(getr(0) == 237164);
|
||||||
@@ -539,45 +542,45 @@ TEST_CASE_METHOD(CpuFixture, "Block Data Transfer", TAG) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
setr(10, 3448);
|
setr(10, address);
|
||||||
exec(data);
|
exec(data);
|
||||||
checker(3448);
|
checker(address);
|
||||||
|
|
||||||
// with write
|
// with write
|
||||||
setr(10, 3448);
|
setr(10, address);
|
||||||
block_transfer->write = true;
|
block_transfer->write = true;
|
||||||
exec(data);
|
exec(data);
|
||||||
checker(3448 + INSTRUCTION_SIZE);
|
checker(address + alignment);
|
||||||
|
|
||||||
// decrement
|
// decrement
|
||||||
block_transfer->write = false;
|
block_transfer->write = false;
|
||||||
block_transfer->up = false;
|
block_transfer->up = false;
|
||||||
// adjust rn
|
// adjust rn
|
||||||
setr(10, 3480);
|
setr(10, address + alignment * 8);
|
||||||
exec(data);
|
exec(data);
|
||||||
checker(3480);
|
checker(address + alignment * 8);
|
||||||
|
|
||||||
// with write
|
// with write
|
||||||
setr(10, 3480);
|
setr(10, 0x3000D98);
|
||||||
block_transfer->write = true;
|
block_transfer->write = true;
|
||||||
exec(data);
|
exec(data);
|
||||||
checker(3480 - INSTRUCTION_SIZE);
|
checker(address + alignment * 7);
|
||||||
|
|
||||||
// post increment
|
// post increment
|
||||||
block_transfer->write = false;
|
block_transfer->write = false;
|
||||||
block_transfer->up = true;
|
block_transfer->up = true;
|
||||||
block_transfer->pre = false;
|
block_transfer->pre = false;
|
||||||
// adjust rn
|
// adjust rn
|
||||||
setr(10, 3452);
|
setr(10, address + alignment);
|
||||||
exec(data);
|
exec(data);
|
||||||
checker(3452 + INSTRUCTION_SIZE);
|
checker(address + alignment * 2);
|
||||||
|
|
||||||
// post decrement
|
// post decrement
|
||||||
block_transfer->up = false;
|
block_transfer->up = false;
|
||||||
// adjust rn
|
// adjust rn
|
||||||
setr(10, 3476);
|
setr(10, address + alignment * 7);
|
||||||
exec(data);
|
exec(data);
|
||||||
checker(3476 - INSTRUCTION_SIZE);
|
checker(address + alignment * 6);
|
||||||
|
|
||||||
// with s bit
|
// with s bit
|
||||||
cpu.chg_mode(Mode::Fiq);
|
cpu.chg_mode(Mode::Fiq);
|
||||||
@@ -589,6 +592,8 @@ TEST_CASE_METHOD(CpuFixture, "Block Data Transfer", TAG) {
|
|||||||
|
|
||||||
// store
|
// store
|
||||||
SECTION("store") {
|
SECTION("store") {
|
||||||
|
static constexpr uint32_t address = 0x30015A8;
|
||||||
|
|
||||||
block_transfer->load = false;
|
block_transfer->load = false;
|
||||||
|
|
||||||
// populate registers
|
// populate registers
|
||||||
@@ -601,19 +606,19 @@ TEST_CASE_METHOD(CpuFixture, "Block Data Transfer", TAG) {
|
|||||||
setr(15, 6);
|
setr(15, 6);
|
||||||
|
|
||||||
auto checker = [this]() {
|
auto checker = [this]() {
|
||||||
CHECK(bus.read_word(5548) == 237164);
|
CHECK(bus.read_word(address + alignment) == 237164);
|
||||||
CHECK(bus.read_word(5552) == 679785111);
|
CHECK(bus.read_word(address + alignment * 2) == 679785111);
|
||||||
CHECK(bus.read_word(5556) == 905895898);
|
CHECK(bus.read_word(address + alignment * 3) == 905895898);
|
||||||
CHECK(bus.read_word(5560) == 131313333);
|
CHECK(bus.read_word(address + alignment * 4) == 131313333);
|
||||||
CHECK(bus.read_word(5564) == 131);
|
CHECK(bus.read_word(address + alignment * 5) == 131);
|
||||||
CHECK(bus.read_word(5568) == 989231);
|
CHECK(bus.read_word(address + alignment * 6) == 989231);
|
||||||
CHECK(bus.read_word(5572) == 6);
|
CHECK(bus.read_word(address + alignment * 7) == 6);
|
||||||
|
|
||||||
for (uint8_t i = 0; i < 8; i++)
|
for (uint8_t i = 1; i < 8; i++)
|
||||||
bus.write_word(5548 + i * 4, 0);
|
bus.write_word(address + alignment * i, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
setr(10, 5544); // base
|
setr(10, address); // base
|
||||||
exec(data);
|
exec(data);
|
||||||
checker();
|
checker();
|
||||||
|
|
||||||
@@ -621,7 +626,7 @@ TEST_CASE_METHOD(CpuFixture, "Block Data Transfer", TAG) {
|
|||||||
block_transfer->write = false;
|
block_transfer->write = false;
|
||||||
block_transfer->up = false;
|
block_transfer->up = false;
|
||||||
// adjust rn
|
// adjust rn
|
||||||
setr(10, 5576);
|
setr(10, address + alignment * 8);
|
||||||
exec(data);
|
exec(data);
|
||||||
checker();
|
checker();
|
||||||
|
|
||||||
@@ -629,24 +634,23 @@ TEST_CASE_METHOD(CpuFixture, "Block Data Transfer", TAG) {
|
|||||||
block_transfer->up = true;
|
block_transfer->up = true;
|
||||||
block_transfer->pre = false;
|
block_transfer->pre = false;
|
||||||
// adjust rn
|
// adjust rn
|
||||||
setr(10, 5548);
|
setr(10, address + alignment);
|
||||||
exec(data);
|
exec(data);
|
||||||
checker();
|
checker();
|
||||||
|
|
||||||
// post decrement
|
// post decrement
|
||||||
block_transfer->up = false;
|
block_transfer->up = false;
|
||||||
// adjust rn
|
// adjust rn
|
||||||
setr(10, 5572);
|
setr(10, address + alignment * 7);
|
||||||
exec(data);
|
exec(data);
|
||||||
checker();
|
checker();
|
||||||
|
|
||||||
// with s bit
|
// with s bit
|
||||||
cpu.chg_mode(Mode::Fiq);
|
cpu.chg_mode(Mode::Fiq);
|
||||||
block_transfer->s = true;
|
block_transfer->s = true;
|
||||||
cpu.chg_mode(Mode::Supervisor);
|
|
||||||
// User's R13 is different (unset at this point)
|
|
||||||
CHECK(bus.read_word(5568) == 0);
|
|
||||||
exec(data);
|
exec(data);
|
||||||
|
// User's R13 is different (unset at this point)
|
||||||
|
CHECK(bus.read_word(address + alignment * 6) == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -41,17 +41,17 @@ CpuFixture::set_psr(Psr psr, bool spsr) {
|
|||||||
// matters is that the public API is correct.
|
// matters is that the public API is correct.
|
||||||
uint32_t
|
uint32_t
|
||||||
CpuFixture::getr_(uint8_t r, Cpu& cpu) {
|
CpuFixture::getr_(uint8_t r, Cpu& cpu) {
|
||||||
size_t addr = 13000;
|
uint32_t addr = 0x02000000;
|
||||||
size_t offset = r == 15 ? 4 : 0;
|
uint8_t offset = r == 15 ? 4 : 0;
|
||||||
uint32_t word = bus.read_word(addr + offset);
|
uint32_t word = bus.read_word(addr + offset);
|
||||||
Cpu tmp = cpu;
|
Cpu tmp = cpu;
|
||||||
uint32_t ret = 0xFFFFFFFF;
|
uint32_t ret = 0xFFFFFFFF;
|
||||||
uint8_t base = r ? 0 : 1;
|
uint8_t base = r ? 0 : 1;
|
||||||
|
|
||||||
// set R0/R1 = 0
|
// set R0/R1 = addr
|
||||||
arm::Instruction zero(
|
arm::Instruction zero(
|
||||||
Condition::AL,
|
Condition::AL,
|
||||||
arm::DataProcessing{ .operand = 0u,
|
arm::DataProcessing{ .operand = addr,
|
||||||
.rd = base,
|
.rd = base,
|
||||||
.rn = 0,
|
.rn = 0,
|
||||||
.set = false,
|
.set = false,
|
||||||
@@ -60,7 +60,7 @@ CpuFixture::getr_(uint8_t r, Cpu& cpu) {
|
|||||||
// get register
|
// get register
|
||||||
arm::Instruction get(
|
arm::Instruction get(
|
||||||
Condition::AL,
|
Condition::AL,
|
||||||
arm::SingleDataTransfer{ .offset = static_cast<uint16_t>(addr),
|
arm::SingleDataTransfer{ .offset = static_cast<uint16_t>(0),
|
||||||
.rd = r,
|
.rd = r,
|
||||||
.rn = base,
|
.rn = base,
|
||||||
.load = false,
|
.load = false,
|
||||||
|
@@ -528,11 +528,11 @@ TEST_CASE_METHOD(CpuFixture, "Hi Register Operations/Branch Exchange", TAG) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_METHOD(CpuFixture, "PC Relative Load", TAG) {
|
TEST_CASE_METHOD(CpuFixture, "PC Relative Load", TAG) {
|
||||||
InstructionData data = PcRelativeLoad{ .word = 380, .rd = 0 };
|
InstructionData data = PcRelativeLoad{ .word = 0x578, .rd = 0 };
|
||||||
|
|
||||||
setr(15, 13804);
|
setr(15, 0x3003FD5);
|
||||||
// 13804 + 380
|
// 0x3003FD5 + 0x578
|
||||||
bus.write_word(14184, 489753492);
|
bus.write_word(0x300454D, 489753492);
|
||||||
|
|
||||||
CHECK(getr(0) == 0);
|
CHECK(getr(0) == 0);
|
||||||
exec(data);
|
exec(data);
|
||||||
@@ -545,26 +545,26 @@ TEST_CASE_METHOD(CpuFixture, "Load/Store with Register Offset", TAG) {
|
|||||||
};
|
};
|
||||||
LoadStoreRegisterOffset* load = std::get_if<LoadStoreRegisterOffset>(&data);
|
LoadStoreRegisterOffset* load = std::get_if<LoadStoreRegisterOffset>(&data);
|
||||||
|
|
||||||
setr(7, 9910);
|
setr(7, 0x3003000);
|
||||||
setr(0, 1034);
|
setr(0, 0x332);
|
||||||
setr(3, 389524259);
|
setr(3, 389524259);
|
||||||
|
|
||||||
SECTION("store") {
|
SECTION("store") {
|
||||||
// 9910 + 1034
|
// 0x3003000 + 0x332
|
||||||
CHECK(bus.read_word(10944) == 0);
|
CHECK(bus.read_word(0x3003332) == 0);
|
||||||
exec(data);
|
exec(data);
|
||||||
CHECK(bus.read_word(10944) == 389524259);
|
CHECK(bus.read_word(0x3003332) == 389524259);
|
||||||
|
|
||||||
// byte
|
// byte
|
||||||
load->byte = true;
|
load->byte = true;
|
||||||
bus.write_word(10944, 0);
|
bus.write_word(0x3003332, 0);
|
||||||
exec(data);
|
exec(data);
|
||||||
CHECK(bus.read_word(10944) == 35);
|
CHECK(bus.read_word(0x3003332) == 35);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("load") {
|
SECTION("load") {
|
||||||
load->load = true;
|
load->load = true;
|
||||||
bus.write_word(10944, 11123489);
|
bus.write_word(0x3003332, 11123489);
|
||||||
exec(data);
|
exec(data);
|
||||||
CHECK(getr(3) == 11123489);
|
CHECK(getr(3) == 11123489);
|
||||||
|
|
||||||
@@ -582,27 +582,27 @@ TEST_CASE_METHOD(CpuFixture, "Load/Store Sign Extended Byte/Halfword", TAG) {
|
|||||||
LoadStoreSignExtendedHalfword* load =
|
LoadStoreSignExtendedHalfword* load =
|
||||||
std::get_if<LoadStoreSignExtendedHalfword>(&data);
|
std::get_if<LoadStoreSignExtendedHalfword>(&data);
|
||||||
|
|
||||||
setr(7, 9910);
|
setr(7, 0x3003000);
|
||||||
setr(0, 1034);
|
setr(0, 0x332);
|
||||||
setr(3, 389524259);
|
setr(3, 389524259);
|
||||||
|
|
||||||
SECTION("SH = 00") {
|
SECTION("SH = 00") {
|
||||||
// 9910 + 1034
|
// 0x3003000 + 0x332
|
||||||
CHECK(bus.read_word(10944) == 0);
|
CHECK(bus.read_word(0x3003332) == 0);
|
||||||
exec(data);
|
exec(data);
|
||||||
CHECK(bus.read_word(10944) == 43811);
|
CHECK(bus.read_word(0x3003332) == 43811);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("SH = 01") {
|
SECTION("SH = 01") {
|
||||||
load->h = true;
|
load->h = true;
|
||||||
bus.write_word(10944, 11123489);
|
bus.write_word(0x3003332, 11123489);
|
||||||
exec(data);
|
exec(data);
|
||||||
CHECK(getr(3) == 47905);
|
CHECK(getr(3) == 47905);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("SH = 10") {
|
SECTION("SH = 10") {
|
||||||
load->s = true;
|
load->s = true;
|
||||||
bus.write_word(10944, 34521594);
|
bus.write_word(0x3003332, 34521594);
|
||||||
exec(data);
|
exec(data);
|
||||||
// sign extended 250 byte (0xFA)
|
// sign extended 250 byte (0xFA)
|
||||||
CHECK(getr(3) == 4294967290);
|
CHECK(getr(3) == 4294967290);
|
||||||
@@ -611,7 +611,7 @@ TEST_CASE_METHOD(CpuFixture, "Load/Store Sign Extended Byte/Halfword", TAG) {
|
|||||||
SECTION("SH = 11") {
|
SECTION("SH = 11") {
|
||||||
load->s = true;
|
load->s = true;
|
||||||
load->h = true;
|
load->h = true;
|
||||||
bus.write_word(10944, 11123489);
|
bus.write_word(0x3003332, 11123489);
|
||||||
// sign extended 47905 halfword (0xBB21)
|
// sign extended 47905 halfword (0xBB21)
|
||||||
exec(data);
|
exec(data);
|
||||||
CHECK(getr(3) == 4294949665);
|
CHECK(getr(3) == 4294949665);
|
||||||
@@ -620,30 +620,30 @@ TEST_CASE_METHOD(CpuFixture, "Load/Store Sign Extended Byte/Halfword", TAG) {
|
|||||||
|
|
||||||
TEST_CASE_METHOD(CpuFixture, "Load/Store with Immediate Offset", TAG) {
|
TEST_CASE_METHOD(CpuFixture, "Load/Store with Immediate Offset", TAG) {
|
||||||
InstructionData data = LoadStoreImmediateOffset{
|
InstructionData data = LoadStoreImmediateOffset{
|
||||||
.rd = 3, .rb = 0, .offset = 110, .load = false, .byte = false
|
.rd = 3, .rb = 0, .offset = 0x6E, .load = false, .byte = false
|
||||||
};
|
};
|
||||||
LoadStoreImmediateOffset* load =
|
LoadStoreImmediateOffset* load =
|
||||||
std::get_if<LoadStoreImmediateOffset>(&data);
|
std::get_if<LoadStoreImmediateOffset>(&data);
|
||||||
|
|
||||||
setr(0, 1034);
|
setr(0, 0x300666A);
|
||||||
setr(3, 389524259);
|
setr(3, 389524259);
|
||||||
|
|
||||||
SECTION("store") {
|
SECTION("store") {
|
||||||
// 110 + 1034
|
// 0x30066A + 0x6E
|
||||||
CHECK(bus.read_word(1144) == 0);
|
CHECK(bus.read_word(0x30066D8) == 0);
|
||||||
exec(data);
|
exec(data);
|
||||||
CHECK(bus.read_word(1144) == 389524259);
|
CHECK(bus.read_word(0x30066D8) == 389524259);
|
||||||
|
|
||||||
// byte
|
// byte
|
||||||
load->byte = true;
|
load->byte = true;
|
||||||
bus.write_word(1144, 0);
|
bus.write_word(0x30066D8, 0);
|
||||||
exec(data);
|
exec(data);
|
||||||
CHECK(bus.read_word(1144) == 35);
|
CHECK(bus.read_word(0x30066D8) == 35);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("load") {
|
SECTION("load") {
|
||||||
load->load = true;
|
load->load = true;
|
||||||
bus.write_word(1144, 11123489);
|
bus.write_word(0x30066D8, 11123489);
|
||||||
exec(data);
|
exec(data);
|
||||||
CHECK(getr(3) == 11123489);
|
CHECK(getr(3) == 11123489);
|
||||||
|
|
||||||
@@ -656,22 +656,22 @@ TEST_CASE_METHOD(CpuFixture, "Load/Store with Immediate Offset", TAG) {
|
|||||||
|
|
||||||
TEST_CASE_METHOD(CpuFixture, "Load/Store Halfword", TAG) {
|
TEST_CASE_METHOD(CpuFixture, "Load/Store Halfword", TAG) {
|
||||||
InstructionData data =
|
InstructionData data =
|
||||||
LoadStoreHalfword{ .rd = 3, .rb = 0, .offset = 110, .load = false };
|
LoadStoreHalfword{ .rd = 3, .rb = 0, .offset = 0x6E, .load = false };
|
||||||
LoadStoreHalfword* load = std::get_if<LoadStoreHalfword>(&data);
|
LoadStoreHalfword* load = std::get_if<LoadStoreHalfword>(&data);
|
||||||
|
|
||||||
setr(0, 1034);
|
setr(0, 0x300666A);
|
||||||
setr(3, 389524259);
|
setr(3, 389524259);
|
||||||
|
|
||||||
SECTION("store") {
|
SECTION("store") {
|
||||||
// 110 + 1034
|
// 0x300666A + 0x6E
|
||||||
CHECK(bus.read_word(1144) == 0);
|
CHECK(bus.read_word(0x30066D8) == 0);
|
||||||
exec(data);
|
exec(data);
|
||||||
CHECK(bus.read_word(1144) == 43811);
|
CHECK(bus.read_word(0x30066D8) == 43811);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("load") {
|
SECTION("load") {
|
||||||
load->load = true;
|
load->load = true;
|
||||||
bus.write_word(1144, 11123489);
|
bus.write_word(0x30066D8, 11123489);
|
||||||
exec(data);
|
exec(data);
|
||||||
CHECK(getr(3) == 47905);
|
CHECK(getr(3) == 47905);
|
||||||
}
|
}
|
||||||
@@ -679,23 +679,23 @@ TEST_CASE_METHOD(CpuFixture, "Load/Store Halfword", TAG) {
|
|||||||
|
|
||||||
TEST_CASE_METHOD(CpuFixture, "SP Relative Load", TAG) {
|
TEST_CASE_METHOD(CpuFixture, "SP Relative Load", TAG) {
|
||||||
InstructionData data =
|
InstructionData data =
|
||||||
SpRelativeLoad{ .word = 808, .rd = 1, .load = false };
|
SpRelativeLoad{ .word = 0x328, .rd = 1, .load = false };
|
||||||
SpRelativeLoad* load = std::get_if<SpRelativeLoad>(&data);
|
SpRelativeLoad* load = std::get_if<SpRelativeLoad>(&data);
|
||||||
|
|
||||||
setr(1, 2349505744);
|
setr(1, 2349505744);
|
||||||
// sp
|
// sp
|
||||||
setr(13, 336);
|
setr(13, 0x3004A8A);
|
||||||
|
|
||||||
SECTION("store") {
|
SECTION("store") {
|
||||||
// 110 + 1034
|
// 0x3004A8A + 0x328
|
||||||
CHECK(bus.read_word(1144) == 0);
|
CHECK(bus.read_word(0x3004DB2) == 0);
|
||||||
exec(data);
|
exec(data);
|
||||||
CHECK(bus.read_word(1144) == 2349505744);
|
CHECK(bus.read_word(0x3004DB2) == 2349505744);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("load") {
|
SECTION("load") {
|
||||||
load->load = true;
|
load->load = true;
|
||||||
bus.write_word(1144, 11123489);
|
bus.write_word(0x3004DB2, 11123489);
|
||||||
exec(data);
|
exec(data);
|
||||||
CHECK(getr(1) == 11123489);
|
CHECK(getr(1) == 11123489);
|
||||||
}
|
}
|
||||||
@@ -745,8 +745,11 @@ TEST_CASE_METHOD(CpuFixture, "Push/Pop Registers", TAG) {
|
|||||||
InstructionData data =
|
InstructionData data =
|
||||||
PushPopRegister{ .regs = 0b11010011, .pclr = false, .load = false };
|
PushPopRegister{ .regs = 0b11010011, .pclr = false, .load = false };
|
||||||
PushPopRegister* push = std::get_if<PushPopRegister>(&data);
|
PushPopRegister* push = std::get_if<PushPopRegister>(&data);
|
||||||
// registers = 0, 1, 4, 6, 7
|
|
||||||
|
|
||||||
|
static constexpr uint8_t alignment = 4;
|
||||||
|
static constexpr uint32_t address = 0x30015AC;
|
||||||
|
|
||||||
|
// registers = 0, 1, 4, 6, 7
|
||||||
SECTION("push (store)") {
|
SECTION("push (store)") {
|
||||||
|
|
||||||
// populate registers
|
// populate registers
|
||||||
@@ -758,33 +761,33 @@ TEST_CASE_METHOD(CpuFixture, "Push/Pop Registers", TAG) {
|
|||||||
|
|
||||||
auto checker = [this]() {
|
auto checker = [this]() {
|
||||||
// address
|
// address
|
||||||
CHECK(bus.read_word(5548) == 237164);
|
CHECK(bus.read_word(address) == 237164);
|
||||||
CHECK(bus.read_word(5552) == 679785111);
|
CHECK(bus.read_word(address + alignment) == 679785111);
|
||||||
CHECK(bus.read_word(5556) == 905895898);
|
CHECK(bus.read_word(address + alignment * 2) == 905895898);
|
||||||
CHECK(bus.read_word(5560) == 131313333);
|
CHECK(bus.read_word(address + alignment * 3) == 131313333);
|
||||||
CHECK(bus.read_word(5564) == 131);
|
CHECK(bus.read_word(address + alignment * 4) == 131);
|
||||||
};
|
};
|
||||||
|
|
||||||
// set stack pointer to top of stack
|
// set stack pointer to top of stack
|
||||||
setr(13, 5568);
|
setr(13, address + alignment * 5);
|
||||||
|
|
||||||
SECTION("without LR") {
|
SECTION("without LR") {
|
||||||
exec(data);
|
exec(data);
|
||||||
checker();
|
checker();
|
||||||
CHECK(getr(13) == 5548);
|
CHECK(getr(13) == address);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("with LR") {
|
SECTION("with LR") {
|
||||||
push->pclr = true;
|
push->pclr = true;
|
||||||
// populate lr
|
// populate lr
|
||||||
setr(14, 999304);
|
setr(14, 999304);
|
||||||
// add another word on stack (5568 + 4)
|
// add another word on stack (top + 4)
|
||||||
setr(13, 5572);
|
setr(13, address + alignment * 6);
|
||||||
exec(data);
|
exec(data);
|
||||||
|
|
||||||
CHECK(bus.read_word(5568) == 999304);
|
CHECK(bus.read_word(address + alignment * 5) == 999304);
|
||||||
checker();
|
checker();
|
||||||
CHECK(getr(13) == 5548);
|
CHECK(getr(13) == address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -792,11 +795,11 @@ TEST_CASE_METHOD(CpuFixture, "Push/Pop Registers", TAG) {
|
|||||||
push->load = true;
|
push->load = true;
|
||||||
|
|
||||||
// populate memory
|
// populate memory
|
||||||
bus.write_word(5548, 237164);
|
bus.write_word(address, 237164);
|
||||||
bus.write_word(5552, 679785111);
|
bus.write_word(address + alignment, 679785111);
|
||||||
bus.write_word(5556, 905895898);
|
bus.write_word(address + alignment * 2, 905895898);
|
||||||
bus.write_word(5560, 131313333);
|
bus.write_word(address + alignment * 3, 131313333);
|
||||||
bus.write_word(5564, 131);
|
bus.write_word(address + alignment * 4, 131);
|
||||||
|
|
||||||
auto checker = [this]() {
|
auto checker = [this]() {
|
||||||
CHECK(getr(0) == 237164);
|
CHECK(getr(0) == 237164);
|
||||||
@@ -814,23 +817,23 @@ TEST_CASE_METHOD(CpuFixture, "Push/Pop Registers", TAG) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// set stack pointer to bottom of stack
|
// set stack pointer to bottom of stack
|
||||||
setr(13, 5548);
|
setr(13, address);
|
||||||
|
|
||||||
SECTION("without SP") {
|
SECTION("without SP") {
|
||||||
exec(data);
|
exec(data);
|
||||||
checker();
|
checker();
|
||||||
CHECK(getr(13) == 5568);
|
CHECK(getr(13) == address + alignment * 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("with SP") {
|
SECTION("with SP") {
|
||||||
push->pclr = true;
|
push->pclr = true;
|
||||||
// populate next address
|
// populate next address
|
||||||
bus.write_word(5568, 93333912);
|
bus.write_word(address + alignment * 5, 93333912);
|
||||||
exec(data);
|
exec(data);
|
||||||
|
|
||||||
CHECK(getr(15) == 93333912);
|
CHECK(getr(15) == 93333912);
|
||||||
checker();
|
checker();
|
||||||
CHECK(getr(13) == 5572);
|
CHECK(getr(13) == address + alignment * 6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -841,7 +844,10 @@ TEST_CASE_METHOD(CpuFixture, "Multiple Load/Store", TAG) {
|
|||||||
MultipleLoad* push = std::get_if<MultipleLoad>(&data);
|
MultipleLoad* push = std::get_if<MultipleLoad>(&data);
|
||||||
// registers = 0, 1, 4, 6, 7
|
// registers = 0, 1, 4, 6, 7
|
||||||
|
|
||||||
SECTION("push (store)") {
|
static constexpr uint8_t alignment = 4;
|
||||||
|
static constexpr uint32_t address = 0x30015AC;
|
||||||
|
|
||||||
|
SECTION("store") {
|
||||||
|
|
||||||
// populate registers
|
// populate registers
|
||||||
setr(0, 237164);
|
setr(0, 237164);
|
||||||
@@ -850,36 +856,36 @@ TEST_CASE_METHOD(CpuFixture, "Multiple Load/Store", TAG) {
|
|||||||
setr(7, 131);
|
setr(7, 131);
|
||||||
|
|
||||||
// set R2 (base) to top of stack
|
// set R2 (base) to top of stack
|
||||||
setr(2, 5568);
|
setr(2, address + alignment * 5);
|
||||||
|
|
||||||
exec(data);
|
exec(data);
|
||||||
|
|
||||||
CHECK(bus.read_word(5548) == 237164);
|
CHECK(bus.read_word(address) == 237164);
|
||||||
CHECK(bus.read_word(5552) == 5568);
|
CHECK(bus.read_word(address + alignment) == address + alignment * 5);
|
||||||
CHECK(bus.read_word(5556) == 905895898);
|
CHECK(bus.read_word(address + alignment * 2) == 905895898);
|
||||||
CHECK(bus.read_word(5560) == 131313333);
|
CHECK(bus.read_word(address + alignment * 3) == 131313333);
|
||||||
CHECK(bus.read_word(5564) == 131);
|
CHECK(bus.read_word(address + alignment * 4) == 131);
|
||||||
// write back
|
// write back
|
||||||
CHECK(getr(2) == 5548);
|
CHECK(getr(2) == address);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("pop (load)") {
|
SECTION("load") {
|
||||||
push->load = true;
|
push->load = true;
|
||||||
|
|
||||||
// populate memory
|
// populate memory
|
||||||
bus.write_word(5548, 237164);
|
bus.write_word(address, 237164);
|
||||||
bus.write_word(5552, 679785111);
|
bus.write_word(address + alignment, 679785111);
|
||||||
bus.write_word(5556, 905895898);
|
bus.write_word(address + alignment * 2, 905895898);
|
||||||
bus.write_word(5560, 131313333);
|
bus.write_word(address + alignment * 3, 131313333);
|
||||||
bus.write_word(5564, 131);
|
bus.write_word(address + alignment * 4, 131);
|
||||||
|
|
||||||
// base
|
// base
|
||||||
setr(2, 5548);
|
setr(2, address);
|
||||||
|
|
||||||
exec(data);
|
exec(data);
|
||||||
CHECK(getr(0) == 237164);
|
CHECK(getr(0) == 237164);
|
||||||
CHECK(getr(1) == 0);
|
CHECK(getr(1) == 0);
|
||||||
CHECK(getr(2) == 5568); // write back
|
CHECK(getr(2) == address + alignment * 5); // write back
|
||||||
CHECK(getr(3) == 0);
|
CHECK(getr(3) == 0);
|
||||||
CHECK(getr(4) == 905895898);
|
CHECK(getr(4) == 905895898);
|
||||||
CHECK(getr(5) == 0);
|
CHECK(getr(5) == 0);
|
||||||
|
@@ -15,14 +15,18 @@ class MemFixture {
|
|||||||
Memory memory;
|
Memory memory;
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_CASE_METHOD(MemFixture, "bios", TAG) {
|
TEST_CASE("bios", TAG) {
|
||||||
memory.write(0, 0xAC);
|
std::array<uint8_t, Memory::BIOS_SIZE> bios = { 0 };
|
||||||
|
|
||||||
|
// populate bios
|
||||||
|
bios[0] = 0xAC;
|
||||||
|
bios[0x3FFF] = 0x48;
|
||||||
|
bios[0x2A56] = 0x10;
|
||||||
|
|
||||||
|
Memory memory(std::move(bios), std::vector<uint8_t>(Header::HEADER_SIZE));
|
||||||
|
|
||||||
CHECK(memory.read(0) == 0xAC);
|
CHECK(memory.read(0) == 0xAC);
|
||||||
|
|
||||||
memory.write(0x3FFF, 0x48);
|
|
||||||
CHECK(memory.read(0x3FFF) == 0x48);
|
CHECK(memory.read(0x3FFF) == 0x48);
|
||||||
|
|
||||||
memory.write(0x2A56, 0x10);
|
|
||||||
CHECK(memory.read(0x2A56) == 0x10);
|
CHECK(memory.read(0x2A56) == 0x10);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,40 +86,31 @@ TEST_CASE_METHOD(MemFixture, "oam obj ram", TAG) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("rom", TAG) {
|
TEST_CASE("rom", TAG) {
|
||||||
|
std::vector<uint8_t> rom(32 * 1024 * 1024, 0);
|
||||||
|
|
||||||
|
// populate rom
|
||||||
|
rom[0] = 0xAC;
|
||||||
|
rom[0x1FFFFFF] = 0x48;
|
||||||
|
rom[0x0EF0256] = 0x10;
|
||||||
|
|
||||||
// 32 megabyte ROM
|
// 32 megabyte ROM
|
||||||
Memory memory(std::array<uint8_t, Memory::BIOS_SIZE>(),
|
Memory memory(std::array<uint8_t, Memory::BIOS_SIZE>(), std::move(rom));
|
||||||
std::vector<uint8_t>(32 * 1024 * 1024));
|
|
||||||
|
|
||||||
SECTION("ROM1") {
|
SECTION("ROM1") {
|
||||||
memory.write(0x8000000, 0xAC);
|
|
||||||
CHECK(memory.read(0x8000000) == 0xAC);
|
CHECK(memory.read(0x8000000) == 0xAC);
|
||||||
|
|
||||||
memory.write(0x9FFFFFF, 0x48);
|
|
||||||
CHECK(memory.read(0x9FFFFFF) == 0x48);
|
CHECK(memory.read(0x9FFFFFF) == 0x48);
|
||||||
|
CHECK(memory.read(0x8EF0256) == 0x10);
|
||||||
memory.write(0x8ef0256, 0x10);
|
|
||||||
CHECK(memory.read(0x8ef0256) == 0x10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("ROM2") {
|
SECTION("ROM2") {
|
||||||
memory.write(0xA000000, 0xAC);
|
|
||||||
CHECK(memory.read(0xA000000) == 0xAC);
|
CHECK(memory.read(0xA000000) == 0xAC);
|
||||||
|
|
||||||
memory.write(0xBFFFFFF, 0x48);
|
|
||||||
CHECK(memory.read(0xBFFFFFF) == 0x48);
|
CHECK(memory.read(0xBFFFFFF) == 0x48);
|
||||||
|
|
||||||
memory.write(0xAEF0256, 0x10);
|
|
||||||
CHECK(memory.read(0xAEF0256) == 0x10);
|
CHECK(memory.read(0xAEF0256) == 0x10);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("ROM3") {
|
SECTION("ROM3") {
|
||||||
memory.write(0xC000000, 0xAC);
|
|
||||||
CHECK(memory.read(0xC000000) == 0xAC);
|
CHECK(memory.read(0xC000000) == 0xAC);
|
||||||
|
|
||||||
memory.write(0xDFFFFFF, 0x48);
|
|
||||||
CHECK(memory.read(0xDFFFFFF) == 0x48);
|
CHECK(memory.read(0xDFFFFFF) == 0x48);
|
||||||
|
|
||||||
memory.write(0xCEF0256, 0x10);
|
|
||||||
CHECK(memory.read(0xCEF0256) == 0x10);
|
CHECK(memory.read(0xCEF0256) == 0x10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user