File:  [Isaki's NoNo m68k/m88k emulator] / nono / vm / test_busio.cpp
Revision 1.1.1.8 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:06:00 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v027, HEAD
nono 1.7.0

//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//

#include "bus.h"
#include "nono.h"
#include <stdint.h>
#include <vector>

// "device.h" の IODevice をリンクしてしまうと、芋づる式に依存オブジェクトが
// 増えてしまい収拾つかなくなるので、ダミークラスを用意する。
// なので、ここの実装は本物の IODevice のそれと同期しないといけない…。
class IODevice
{
 public:
	enum : uint {
		Capacity = 8,
	};
 public:
	IODevice()
	{
		reg.resize(Capacity);
		Reset();
	}
	virtual ~IODevice();

	virtual busdata Read(busaddr addr) { return 0xdf; }
	virtual busdata Write(busaddr addr, uint32 data) { return 0; }
	virtual busdata Peek1(uint32 addr) { return 0xff; }
	virtual bool Poke1(uint32 addr, uint32 data) { return false; }

	void Reset() {
		for (int i = 0; i < Capacity; i++) {
			reg[i] = i + 0x81;
		}
	}

	// uint32 だがバイトレジスタとして扱う
	std::vector<uint32> reg {};
};
IODevice::~IODevice() { }

#define SELFTEST
#include "busio.h"

class TestByteDev : public IODevice
{
 public:
	TestByteDev() {}
	~TestByteDev() override;

	static const uint32 NPORT = 4;
	busdata ReadPort(uint32 offset) {
		if ((int32)reg[offset] < 0)
			return BusData::BusErr;
		return reg[offset] | BusData::Size1;
	}
	busdata WritePort(uint32 offset, uint32 data) {
		assert(data <= 0xff);
		reg[offset] = data;
		return BusData::Size1;
	}
	busdata PeekPort(uint32 offset) {
		if ((int32)reg[offset] < 0)
			return BusData::BusErr;
		return reg[offset];
	}
	bool PokePort(uint32 offset, uint32 data) {
		return false;
	}
};
TestByteDev::~TestByteDev() { }

class TestWordDev : public IODevice
{
 public:
	TestWordDev() {}
	~TestWordDev() override;

	static const uint32 NPORT = 4;
	busdata ReadPort(uint32 offset) {
		busdata data = PeekPort(offset);
		data |= BusData::Size2;
		return data;
	}
	busdata WritePort(uint32 offset, uint32 data) {
		assert(data <= 0xffff);
		reg[offset * 2 + 0] = (uint8)(data >> 8);
		reg[offset * 2 + 1] = (uint8)(data & 0xff);
		return BusData::Size2;
	}
	busdata PeekPort(uint32 offset) {
		if ((int32)reg[offset] < 0)
			return BusData::BusErr;
		uint32 data;
		data  = (uint8)reg[offset * 2 + 0] << 8;
		data |= (uint8)reg[offset * 2 + 1];
		return data;
	}
};
TestWordDev::~TestWordDev() { }

class TestLongDev : public IODevice
{
 public:
	TestLongDev() {}
	~TestLongDev() override;

	static const uint32 NPORT = 4;
	busdata ReadPort(uint32 offset) {
		busdata data = PeekPort(offset);
		data |= BusData::Size4;
		return data;
	}
	busdata WritePort(uint32 offset, uint32 data) {
		reg[offset * 4 + 0] = (uint8)(data >> 24);
		reg[offset * 4 + 1] = (uint8)(data >> 16);
		reg[offset * 4 + 2] = (uint8)(data >>  8);
		reg[offset * 4 + 3] = (uint8)(data & 0xff);
		return BusData::Size4;
	}
	busdata PeekPort(uint32 offset) {
		if ((int32)reg[offset] < 0)
			return BusData::BusErr;
		uint32 data;
		data  = (uint8)reg[offset * 4 + 0] << 24;
		data |= (uint8)reg[offset * 4 + 1] << 16;
		data |= (uint8)reg[offset * 4 + 2] <<  8;
		data |= (uint8)reg[offset * 4 + 3];
		return data;
	}
};
TestLongDev::~TestLongDev() { }

void fail(const char *fmt, ...) __printflike(1, 2);
void
fail(const char *fmt, ...)
{
	va_list ap;

	printf(" FAIL: ");
	va_start(ap, fmt);
	vprintf(fmt, ap);
	va_end(ap);
}

// 入力アドレス(busaddr)と期待値(busdata)を列挙しやすいよう分解したもの。
struct TestItemR
{
	busaddr addr;	// 入力アドレス
	busdata exp;	// 期待値
};

struct TestItemW
{
	busaddr addr;	// 入力アドレス
	uint32 data;	// 入力データ
	busdata expres;		// 応答の期待値
	const char *expmem;	// 書き込み後のレジスタの期待値

	// memexp は表記を圧縮するため、
	// 0x81, 0x82, ... 0x88 を '1', '2', .. '8'、
	// 0xfa, 0xfb, 0xfc, 0xfd を 'A', 'B', 'C', 'D'、
	// 0x00 を '0'
	// と置き換えた 8文字の文字列で表現する。
};

struct TestData
{
	const char *name;
	std::vector<TestItemR> table_read;	// Read  テスト用データ
	std::vector<TestItemW> table_write;	// Write テスト用データ
};

static void
do_test(IODevice *dev, const TestData& testdata)
{
	int failcount = 0;

	printf("%s", testdata.name);
	fflush(stdout);

	// Read
	for (const auto& item : testdata.table_read) {
		busaddr addr = item.addr;
		busdata exp  = item.exp;

		busdata act = dev->Read(addr);
		if (act.Get() != exp.Get()) {
			if (failcount == 0) {
				printf("\n");
			}
			fail("%s::Read($%08x'%08x) expects $%08x'%08x but $%08x'%08x\n",
				testdata.name, addr.GetH(), addr.GetL(),
				exp.GetH(), exp.GetL(), act.GetH(), act.GetL());
			failcount++;
		} else if (0) {
			printf(" Read($%08x'%08x) -> $%08x'%08x\n",
				addr.GetH(), addr.GetL(), act.GetH(), act.GetL());
		}
	}

	// Write
	for (const auto& item : testdata.table_write) {
		busaddr addr = item.addr;
		uint32 srcdata = item.data;
		busdata exp = item.expres;
		const char *expmem_str = item.expmem;
		int memlen = std::min((int)strlen(expmem_str), (int)dev->Capacity);
		std::vector<uint32> expmem(memlen);

		// expmem_str から expmem[] を作成。
		for (int i = 0; i < memlen; i++) {
			uint8 ch = expmem_str[i];
			if (ch == '0') {
				expmem[i] = 0;
			} else if ('1' <= ch && ch <= '9') {
				expmem[i] = 0x80 + (ch - '0');
			} else if ('A' <= ch && ch <= 'D') {
				expmem[i] = 0xfa + (ch - 'A');
			} else {
				errx(1, "invalid char\n");
			}
		}

		// 実行
		dev->Reset();
		busdata act = dev->Write(addr, srcdata);

		// 応答を照合
		if (act.Get() != exp.Get()) {
			if (failcount == 0) {
				printf("\n");
			}
			fail("%s::Write($%08x'%08x, $%08x) "
					"expects $%08x'%08x but $%08x'%08x\n",
				testdata.name, addr.GetH(), addr.GetL(), srcdata,
				exp.GetH(), exp.GetL(), act.GetH(), act.GetL());
			failcount++;
		}

		// 書き込み結果を照合
		bool ok = true;
		for (int i = 0; i < memlen; i++) {
			if (dev->reg[i] != expmem[i]) {
				ok = false;
				break;
			}
		}
		if (!ok) {
			if (failcount == 0) {
				printf("\n");
			}
			fail("%s::Write($%08x'%08x, $%08x) expects "
					"mem=$%02x%02x'%02x%02x'%02x%02x'%02x%02x but "
				    "mem=$%02x%02x'%02x%02x'%02x%02x'%02x%02x\n",
				testdata.name, addr.GetH(), addr.GetL(), srcdata,
				expmem[0], expmem[1], expmem[2], expmem[3],
				expmem[4], expmem[5], expmem[6], expmem[7],
				dev->reg[0], dev->reg[1], dev->reg[2], dev->reg[3],
				dev->reg[4], dev->reg[5], dev->reg[6], dev->reg[7]);
			failcount++;
		}
	}

	if (failcount == 0) {
		printf(" .. OK\n");
	}
}

#define Size1	1U
#define Size2	2U
#define Size3	3U
#define Size4	4U
#define BA(addr_, size_)	(busaddr(addr_) | busaddr::Size(size_))
#define BD(data_, size_)	(busdata(data_) | busdata::Size(size_))

#define BusErr	(BusData::BusErr)

// 書き込みパターン (addr::Size と揃えること)
#define W1	(0xfa)
#define W2	(0xfafb)
#define W3	(0xfafbfc)
#define W4	(0xfafbfcfd)

static TestData
table_B = {
	.name = "BusIO_B",
	.table_read = {
		{ BA(0, Size1),		BD(0x00000081, Size1) },
		{ BA(1, Size1),		BD(0x00000082, Size1) },
		{ BA(2, Size1),		BD(0x00000083, Size1) },
		{ BA(3, Size1),		BD(0x00000084, Size1) },

		{ BA(0, Size2),		BD(0x00000081, Size1) },
		{ BA(1, Size2),		BD(0x00000082, Size1) },
		{ BA(2, Size2),		BD(0x00000083, Size1) },
		{ BA(3, Size2),		BD(0x00000084, Size1) },

		{ BA(0, Size3),		BD(0x00000081, Size1) },
		{ BA(1, Size3),		BD(0x00000082, Size1) },
		{ BA(2, Size3),		BD(0x00000083, Size1) },
		{ BA(3, Size3),		BD(0x00000084, Size1) },

		{ BA(0, Size4),		BD(0x00000081, Size1) },
		{ BA(1, Size4),		BD(0x00000082, Size1) },
		{ BA(2, Size4),		BD(0x00000083, Size1) },
		{ BA(3, Size4),		BD(0x00000084, Size1) },
	},
	.table_write = {
		{ BA(0, Size1), W1,		BD(0, Size1),	"A2345678" },
		{ BA(1, Size1), W1,		BD(0, Size1),	"1A345678" },
		{ BA(2, Size1), W1,		BD(0, Size1),	"12A45678" },
		{ BA(3, Size1), W1,		BD(0, Size1),	"123A5678" },

		{ BA(0, Size2), W2,		BD(0, Size1),	"A2345678" },
		{ BA(1, Size2), W2,		BD(0, Size1),	"1A345678" },
		{ BA(2, Size2), W2,		BD(0, Size1),	"12A45678" },
		{ BA(3, Size2), W2,		BD(0, Size1),	"123A5678" },

		{ BA(0, Size3), W3,		BD(0, Size1),	"A2345678" },
		{ BA(1, Size3), W3,		BD(0, Size1),	"1A345678" },
		{ BA(2, Size3), W3,		BD(0, Size1),	"12A45678" },
		{ BA(3, Size3), W3,		BD(0, Size1),	"123A5678" },

		{ BA(0, Size4), W4,		BD(0, Size1),	"A2345678" },
		{ BA(1, Size4), W4,		BD(0, Size1),	"1A345678" },
		{ BA(2, Size4), W4,		BD(0, Size1),	"12A45678" },
		{ BA(3, Size4), W4,		BD(0, Size1),	"123A5678" },
	},
};

static TestData
table_BB = {
	.name = "BusIO_BB",
	.table_read = {
		{ BA(0, Size1),		BD(0x00000081, Size1) },
		{ BA(1, Size1),		BD(0x00000081, Size1) },
		{ BA(2, Size1),		BD(0x00000082, Size1) },
		{ BA(3, Size1),		BD(0x00000082, Size1) },

		{ BA(0, Size2),		BD(0x00000081, Size1) },
		{ BA(1, Size2),		BD(0x00000081, Size1) },
		{ BA(2, Size2),		BD(0x00000082, Size1) },
		{ BA(3, Size2),		BD(0x00000082, Size1) },

		{ BA(0, Size3),		BD(0x00000081, Size1) },
		{ BA(1, Size3),		BD(0x00000081, Size1) },
		{ BA(2, Size3),		BD(0x00000082, Size1) },
		{ BA(3, Size3),		BD(0x00000082, Size1) },

		{ BA(0, Size4),		BD(0x00000081, Size1) },
		{ BA(1, Size4),		BD(0x00000081, Size1) },
		{ BA(2, Size4),		BD(0x00000082, Size1) },
		{ BA(3, Size4),		BD(0x00000082, Size1) },
	},
	.table_write = {
		{ BA(0, Size1), W1,		BD(0, Size1),	"A2345678" },
		{ BA(1, Size1), W1,		BD(0, Size1),	"A2345678" },
		{ BA(2, Size1), W1,		BD(0, Size1),	"1A345678" },
		{ BA(3, Size1), W1,		BD(0, Size1),	"1A345678" },

		{ BA(0, Size2), W2,		BD(0, Size1),	"A2345678" },
		{ BA(1, Size2), W2,		BD(0, Size1),	"A2345678" },
		{ BA(2, Size2), W2,		BD(0, Size1),	"1A345678" },
		{ BA(3, Size2), W2,		BD(0, Size1),	"1A345678" },

		{ BA(0, Size3), W3,		BD(0, Size1),	"A2345678" },
		{ BA(1, Size3), W3,		BD(0, Size1),	"A2345678" },
		{ BA(2, Size3), W3,		BD(0, Size1),	"1A345678" },
		{ BA(3, Size3), W3,		BD(0, Size1),	"1A345678" },

		{ BA(0, Size4), W4,		BD(0, Size1),	"A2345678" },
		{ BA(1, Size4), W4,		BD(0, Size1),	"A2345678" },
		{ BA(2, Size4), W4,		BD(0, Size1),	"1A345678" },
		{ BA(3, Size4), W4,		BD(0, Size1),	"1A345678" },
	},
};

static TestData
table_BBBB = {
	.name = "BusIO_BBBB",
	.table_read = {
		{ BA(0, Size1),		BD(0x00000081, Size1) },
		{ BA(1, Size1),		BD(0x00000081, Size1) },
		{ BA(2, Size1),		BD(0x00000081, Size1) },
		{ BA(3, Size1),		BD(0x00000081, Size1) },
		{ BA(4, Size1),		BD(0x00000082, Size1) },
		{ BA(5, Size1),		BD(0x00000082, Size1) },
		{ BA(6, Size1),		BD(0x00000082, Size1) },
		{ BA(7, Size1),		BD(0x00000082, Size1) },

		{ BA(0, Size2),		BD(0x00000081, Size1) },
		{ BA(1, Size2),		BD(0x00000081, Size1) },
		{ BA(2, Size2),		BD(0x00000081, Size1) },
		{ BA(3, Size2),		BD(0x00000081, Size1) },
		{ BA(4, Size2),		BD(0x00000082, Size1) },
		{ BA(5, Size2),		BD(0x00000082, Size1) },
		{ BA(6, Size2),		BD(0x00000082, Size1) },
		{ BA(7, Size2),		BD(0x00000082, Size1) },

		{ BA(0, Size3),		BD(0x00000081, Size1) },
		{ BA(1, Size3),		BD(0x00000081, Size1) },
		{ BA(2, Size3),		BD(0x00000081, Size1) },
		{ BA(3, Size3),		BD(0x00000081, Size1) },
		{ BA(4, Size3),		BD(0x00000082, Size1) },
		{ BA(5, Size3),		BD(0x00000082, Size1) },
		{ BA(6, Size3),		BD(0x00000082, Size1) },
		{ BA(7, Size3),		BD(0x00000082, Size1) },

		{ BA(0, Size4),		BD(0x00000081, Size1) },
		{ BA(1, Size4),		BD(0x00000081, Size1) },
		{ BA(2, Size4),		BD(0x00000081, Size1) },
		{ BA(3, Size4),		BD(0x00000081, Size1) },
		{ BA(4, Size4),		BD(0x00000082, Size1) },
		{ BA(5, Size4),		BD(0x00000082, Size1) },
		{ BA(6, Size4),		BD(0x00000082, Size1) },
		{ BA(7, Size4),		BD(0x00000082, Size1) },
	},
	.table_write = {
		{ BA(0, Size1), W1,		BD(0, Size1),	"A2345678" },
		{ BA(1, Size1), W1,		BD(0, Size1),	"A2345678" },
		{ BA(2, Size1), W1,		BD(0, Size1),	"A2345678" },
		{ BA(3, Size1), W1,		BD(0, Size1),	"A2345678" },
		{ BA(4, Size1), W1,		BD(0, Size1),	"1A345678" },
		{ BA(5, Size1), W1,		BD(0, Size1),	"1A345678" },
		{ BA(6, Size1), W1,		BD(0, Size1),	"1A345678" },
		{ BA(7, Size1), W1,		BD(0, Size1),	"1A345678" },

		{ BA(0, Size2), W2,		BD(0, Size1),	"A2345678" },
		{ BA(1, Size2), W2,		BD(0, Size1),	"A2345678" },
		{ BA(2, Size2), W2,		BD(0, Size1),	"A2345678" },
		{ BA(3, Size2), W2,		BD(0, Size1),	"A2345678" },
		{ BA(4, Size2), W2,		BD(0, Size1),	"1A345678" },
		{ BA(5, Size2), W2,		BD(0, Size1),	"1A345678" },
		{ BA(6, Size2), W2,		BD(0, Size1),	"1A345678" },
		{ BA(7, Size2), W2,		BD(0, Size1),	"1A345678" },

		{ BA(0, Size3), W3,		BD(0, Size1),	"A2345678" },
		{ BA(1, Size3), W3,		BD(0, Size1),	"A2345678" },
		{ BA(2, Size3), W3,		BD(0, Size1),	"A2345678" },
		{ BA(3, Size3), W3,		BD(0, Size1),	"A2345678" },
		{ BA(4, Size3), W3,		BD(0, Size1),	"1A345678" },
		{ BA(5, Size3), W3,		BD(0, Size1),	"1A345678" },
		{ BA(6, Size3), W3,		BD(0, Size1),	"1A345678" },
		{ BA(7, Size3), W3,		BD(0, Size1),	"1A345678" },

		{ BA(0, Size4), W4,		BD(0, Size1),	"A2345678" },
		{ BA(1, Size4), W4,		BD(0, Size1),	"A2345678" },
		{ BA(2, Size4), W4,		BD(0, Size1),	"A2345678" },
		{ BA(3, Size4), W4,		BD(0, Size1),	"A2345678" },
		{ BA(4, Size4), W4,		BD(0, Size1),	"1A345678" },
		{ BA(5, Size4), W4,		BD(0, Size1),	"1A345678" },
		{ BA(6, Size4), W4,		BD(0, Size1),	"1A345678" },
		{ BA(7, Size4), W4,		BD(0, Size1),	"1A345678" },
	},
};

static TestData
table_BFFF = {
	.name = "BusIO_BFFF",
	.table_read = {
		{ BA(0, Size1),		BD(0x81ffffff, Size4) },
		{ BA(1, Size1),		BD(0x81ffffff, Size4) },
		{ BA(2, Size1),		BD(0x81ffffff, Size4) },
		{ BA(3, Size1),		BD(0x81ffffff, Size4) },
		{ BA(4, Size1),		BD(0x82ffffff, Size4) },
		{ BA(5, Size1),		BD(0x82ffffff, Size4) },
		{ BA(6, Size1),		BD(0x82ffffff, Size4) },
		{ BA(7, Size1),		BD(0x82ffffff, Size4) },

		{ BA(0, Size2),		BD(0x81ffffff, Size4) },
		{ BA(1, Size2),		BD(0x81ffffff, Size4) },
		{ BA(2, Size2),		BD(0x81ffffff, Size4) },
		{ BA(3, Size2),		BD(0x81ffffff, Size4) },
		{ BA(4, Size2),		BD(0x82ffffff, Size4) },
		{ BA(5, Size2),		BD(0x82ffffff, Size4) },
		{ BA(6, Size2),		BD(0x82ffffff, Size4) },
		{ BA(7, Size2),		BD(0x82ffffff, Size4) },

		{ BA(0, Size3),		BD(0x81ffffff, Size4) },
		{ BA(1, Size3),		BD(0x81ffffff, Size4) },
		{ BA(2, Size3),		BD(0x81ffffff, Size4) },
		{ BA(3, Size3),		BD(0x81ffffff, Size4) },
		{ BA(4, Size3),		BD(0x82ffffff, Size4) },
		{ BA(5, Size3),		BD(0x82ffffff, Size4) },
		{ BA(6, Size3),		BD(0x82ffffff, Size4) },
		{ BA(7, Size3),		BD(0x82ffffff, Size4) },

		{ BA(0, Size4),		BD(0x81ffffff, Size4) },
		{ BA(1, Size4),		BD(0x81ffffff, Size4) },
		{ BA(2, Size4),		BD(0x81ffffff, Size4) },
		{ BA(3, Size4),		BD(0x81ffffff, Size4) },
		{ BA(4, Size4),		BD(0x82ffffff, Size4) },
		{ BA(5, Size4),		BD(0x82ffffff, Size4) },
		{ BA(6, Size4),		BD(0x82ffffff, Size4) },
		{ BA(7, Size4),		BD(0x82ffffff, Size4) },
	},
	.table_write = {
		{ BA(0, Size1), W1,		BD(0, Size4),	"A2345678" },
		{ BA(1, Size1), W1,		BD(0, Size4),	"A2345678" },
		{ BA(2, Size1), W1,		BD(0, Size4),	"A2345678" },
		{ BA(3, Size1), W1,		BD(0, Size4),	"A2345678" },
		{ BA(4, Size1), W1,		BD(0, Size4),	"1A345678" },
		{ BA(5, Size1), W1,		BD(0, Size4),	"1A345678" },
		{ BA(6, Size1), W1,		BD(0, Size4),	"1A345678" },
		{ BA(7, Size1), W1,		BD(0, Size4),	"1A345678" },

		{ BA(0, Size2), W2,		BD(0, Size4),	"A2345678" },
		{ BA(1, Size2), W2,		BD(0, Size4),	"A2345678" },
		{ BA(2, Size2), W2,		BD(0, Size4),	"A2345678" },
		{ BA(3, Size2), W2,		BD(0, Size4),	"A2345678" },
		{ BA(4, Size2), W2,		BD(0, Size4),	"1A345678" },
		{ BA(5, Size2), W2,		BD(0, Size4),	"1A345678" },
		{ BA(6, Size2), W2,		BD(0, Size4),	"1A345678" },
		{ BA(7, Size2), W2,		BD(0, Size4),	"1A345678" },

		{ BA(0, Size3), W3,		BD(0, Size4),	"A2345678" },
		{ BA(1, Size3), W3,		BD(0, Size4),	"A2345678" },
		{ BA(2, Size3), W3,		BD(0, Size4),	"A2345678" },
		{ BA(3, Size3), W3,		BD(0, Size4),	"A2345678" },
		{ BA(4, Size3), W3,		BD(0, Size4),	"1A345678" },
		{ BA(5, Size3), W3,		BD(0, Size4),	"1A345678" },
		{ BA(6, Size3), W3,		BD(0, Size4),	"1A345678" },
		{ BA(7, Size3), W3,		BD(0, Size4),	"1A345678" },

		{ BA(0, Size4), W4,		BD(0, Size4),	"A2345678" },
		{ BA(1, Size4), W4,		BD(0, Size4),	"A2345678" },
		{ BA(2, Size4), W4,		BD(0, Size4),	"A2345678" },
		{ BA(3, Size4), W4,		BD(0, Size4),	"A2345678" },
		{ BA(4, Size4), W4,		BD(0, Size4),	"1A345678" },
		{ BA(5, Size4), W4,		BD(0, Size4),	"1A345678" },
		{ BA(6, Size4), W4,		BD(0, Size4),	"1A345678" },
		{ BA(7, Size4), W4,		BD(0, Size4),	"1A345678" },
	},
};

static TestData
table_EB = {
	.name = "BusIO_EB",
	.table_read = {
		{ BA(0, Size1),		BusErr },
		{ BA(1, Size1),		BD(0x0000ff81, Size2) },
		{ BA(2, Size1),		BusErr },
		{ BA(3, Size1),		BD(0x0000ff82, Size2) },

		{ BA(0, Size2),		BD(0x0000ff81, Size2) },
		{ BA(1, Size2),		BD(0x0000ff81, Size2) },
		{ BA(2, Size2),		BD(0x0000ff82, Size2) },
		{ BA(3, Size2),		BD(0x0000ff82, Size2) },

		{ BA(0, Size3),		BD(0x0000ff81, Size2) },
		{ BA(1, Size3),		BD(0x0000ff81, Size2) },
		{ BA(2, Size3),		BD(0x0000ff82, Size2) },
		{ BA(3, Size3),		BD(0x0000ff82, Size2) },

		{ BA(0, Size4),		BD(0x0000ff81, Size2) },
		{ BA(1, Size4),		BD(0x0000ff81, Size2) },
		{ BA(2, Size4),		BD(0x0000ff82, Size2) },
		{ BA(3, Size4),		BD(0x0000ff82, Size2) },
	},
	.table_write = {
		{ BA(0, Size1), W1,		BusErr,			"12345678" },
		{ BA(1, Size1), W1,		BD(0, Size2),	"A2345678" },
		{ BA(2, Size1), W1,		BusErr,			"12345678" },
		{ BA(3, Size1), W1,		BD(0, Size2),	"1A345678" },

		{ BA(0, Size2), W2,		BD(0, Size2),	"B2345678" },
		{ BA(1, Size2), W2,		BD(0, Size2),	"A2345678" },
		{ BA(2, Size2), W2,		BD(0, Size2),	"1B345678" },
		{ BA(3, Size2), W2,		BD(0, Size2),	"1A345678" },

		{ BA(0, Size3), W3,		BD(0, Size2),	"B2345678" },
		{ BA(1, Size3), W3,		BD(0, Size2),	"A2345678" },
		{ BA(2, Size3), W3,		BD(0, Size2),	"1B345678" },
		{ BA(3, Size3), W3,		BD(0, Size2),	"1A345678" },

		{ BA(0, Size4), W4,		BD(0, Size2),	"B2345678" },
		{ BA(1, Size4), W4,		BD(0, Size2),	"A2345678" },
		{ BA(2, Size4), W4,		BD(0, Size2),	"1B345678" },
		{ BA(3, Size4), W4,		BD(0, Size2),	"1A345678" },
	},
};

static TestData
table_FB = {
	.name = "BusIO_FB",
	.table_read = {
		{ BA(0, Size1),		BD(0x0000ffff, Size2) },
		{ BA(1, Size1),		BD(0x0000ff81, Size2) },
		{ BA(2, Size1),		BD(0x0000ffff, Size2) },
		{ BA(3, Size1),		BD(0x0000ff82, Size2) },

		{ BA(0, Size2),		BD(0x0000ff81, Size2) },
		{ BA(1, Size2),		BD(0x0000ff81, Size2) },
		{ BA(2, Size2),		BD(0x0000ff82, Size2) },
		{ BA(3, Size2),		BD(0x0000ff82, Size2) },

		{ BA(0, Size3),		BD(0x0000ff81, Size2) },
		{ BA(1, Size3),		BD(0x0000ff81, Size2) },
		{ BA(2, Size3),		BD(0x0000ff82, Size2) },
		{ BA(3, Size3),		BD(0x0000ff82, Size2) },

		{ BA(0, Size4),		BD(0x0000ff81, Size2) },
		{ BA(1, Size4),		BD(0x0000ff81, Size2) },
		{ BA(2, Size4),		BD(0x0000ff82, Size2) },
		{ BA(3, Size4),		BD(0x0000ff82, Size2) },
	},
	.table_write = {
		{ BA(0, Size1), W1,		BD(0, Size2),	"12345678" },
		{ BA(1, Size1), W1,		BD(0, Size2),	"A2345678" },
		{ BA(2, Size1), W1,		BD(0, Size2),	"12345678" },
		{ BA(3, Size1), W1,		BD(0, Size2),	"1A345678" },

		{ BA(0, Size2), W2,		BD(0, Size2),	"B2345678" },
		{ BA(1, Size2), W2,		BD(0, Size2),	"A2345678" },
		{ BA(2, Size2), W2,		BD(0, Size2),	"1B345678" },
		{ BA(3, Size2), W2,		BD(0, Size2),	"1A345678" },

		{ BA(0, Size3), W3,		BD(0, Size2),	"B2345678" },
		{ BA(1, Size3), W3,		BD(0, Size2),	"A2345678" },
		{ BA(2, Size3), W3,		BD(0, Size2),	"1B345678" },
		{ BA(3, Size3), W3,		BD(0, Size2),	"1A345678" },

		{ BA(0, Size4), W4,		BD(0, Size2),	"B2345678" },
		{ BA(1, Size4), W4,		BD(0, Size2),	"A2345678" },
		{ BA(2, Size4), W4,		BD(0, Size2),	"1B345678" },
		{ BA(3, Size4), W4,		BD(0, Size2),	"1A345678" },
	},
};

static TestData
table_W = {
	.name = "BusIO_W",
	.table_read = {
		{ BA(0, Size1),		BD(0x00008182, Size2) },
		{ BA(1, Size1),		BD(0x00008182, Size2) },
		{ BA(2, Size1),		BD(0x00008384, Size2) },
		{ BA(3, Size1),		BD(0x00008384, Size2) },

		{ BA(0, Size2),		BD(0x00008182, Size2) },
		{ BA(1, Size2),		BD(0x00008182, Size2) },
		{ BA(2, Size2),		BD(0x00008384, Size2) },
		{ BA(3, Size2),		BD(0x00008384, Size2) },

		{ BA(0, Size3),		BD(0x00008182, Size2) },
		{ BA(1, Size3),		BD(0x00008182, Size2) },
		{ BA(2, Size3),		BD(0x00008384, Size2) },
		{ BA(3, Size3),		BD(0x00008384, Size2) },

		{ BA(0, Size4),		BD(0x00008182, Size2) },
		{ BA(1, Size4),		BD(0x00008182, Size2) },
		{ BA(2, Size4),		BD(0x00008384, Size2) },
		{ BA(3, Size4),		BD(0x00008384, Size2) },
	},
	.table_write = {
		{ BA(0, Size1), W1,		BD(0, Size2),	"AA345678" },
		{ BA(1, Size1), W1,		BD(0, Size2),	"AA345678" },
		{ BA(2, Size1), W1,		BD(0, Size2),	"12AA5678" },
		{ BA(3, Size1), W1,		BD(0, Size2),	"12AA5678" },

		{ BA(0, Size2), W2,		BD(0, Size2),	"AB345678" },
		{ BA(1, Size2), W2,		BD(0, Size2),	"AA345678" },
		{ BA(2, Size2), W2,		BD(0, Size2),	"12AB5678" },
		{ BA(3, Size2), W2,		BD(0, Size2),	"12AA5678" },

		{ BA(0, Size3), W3,		BD(0, Size2),	"AB345678" },
		{ BA(1, Size3), W3,		BD(0, Size2),	"AA345678" },
		{ BA(2, Size3), W3,		BD(0, Size2),	"12AB5678" },
		{ BA(3, Size3), W3,		BD(0, Size2),	"12AA5678" },

		{ BA(0, Size4), W4,		BD(0, Size2),	"AB345678" },
		{ BA(1, Size4), W4,		BD(0, Size2),	"AA345678" },
		{ BA(2, Size4), W4,		BD(0, Size2),	"12AB5678" },
		{ BA(3, Size4), W4,		BD(0, Size2),	"12AA5678" },
	},
};

static TestData
table_WF = {
	.name = "BusIO_WF",
	.table_read = {
		{ BA(0, Size1),		BD(0x8182ffff, Size4) },
		{ BA(1, Size1),		BD(0x8182ffff, Size4) },
		{ BA(2, Size1),		BD(0x8182ffff, Size4) },
		{ BA(3, Size1),		BD(0x8182ffff, Size4) },
		{ BA(4, Size1),		BD(0x8384ffff, Size4) },
		{ BA(5, Size1),		BD(0x8384ffff, Size4) },
		{ BA(6, Size1),		BD(0x8384ffff, Size4) },
		{ BA(7, Size1),		BD(0x8384ffff, Size4) },

		{ BA(0, Size2),		BD(0x8182ffff, Size4) },
		{ BA(1, Size2),		BD(0x8182ffff, Size4) },
		{ BA(2, Size2),		BD(0x8182ffff, Size4) },
		{ BA(3, Size2),		BD(0x8182ffff, Size4) },
		{ BA(4, Size2),		BD(0x8384ffff, Size4) },
		{ BA(5, Size2),		BD(0x8384ffff, Size4) },
		{ BA(6, Size2),		BD(0x8384ffff, Size4) },
		{ BA(7, Size2),		BD(0x8384ffff, Size4) },

		{ BA(0, Size3),		BD(0x8182ffff, Size4) },
		{ BA(1, Size3),		BD(0x8182ffff, Size4) },
		{ BA(2, Size3),		BD(0x8182ffff, Size4) },
		{ BA(3, Size3),		BD(0x8182ffff, Size4) },
		{ BA(4, Size3),		BD(0x8384ffff, Size4) },
		{ BA(5, Size3),		BD(0x8384ffff, Size4) },
		{ BA(6, Size3),		BD(0x8384ffff, Size4) },
		{ BA(7, Size3),		BD(0x8384ffff, Size4) },

		{ BA(0, Size4),		BD(0x8182ffff, Size4) },
		{ BA(1, Size4),		BD(0x8182ffff, Size4) },
		{ BA(2, Size4),		BD(0x8182ffff, Size4) },
		{ BA(3, Size4),		BD(0x8182ffff, Size4) },
		{ BA(4, Size4),		BD(0x8384ffff, Size4) },
		{ BA(5, Size4),		BD(0x8384ffff, Size4) },
		{ BA(6, Size4),		BD(0x8384ffff, Size4) },
		{ BA(7, Size4),		BD(0x8384ffff, Size4) },
	},
	.table_write = {
		{ BA(0, Size1), W1,		BD(0, Size4),	"AA345678" },
		{ BA(1, Size1), W1,		BD(0, Size4),	"AA345678" },
		{ BA(2, Size1), W1,		BD(0, Size4),	"AA345678" },
		{ BA(3, Size1), W1,		BD(0, Size4),	"AA345678" },
		{ BA(4, Size1), W1,		BD(0, Size4),	"12AA5678" },
		{ BA(5, Size1), W1,		BD(0, Size4),	"12AA5678" },
		{ BA(6, Size1), W1,		BD(0, Size4),	"12AA5678" },
		{ BA(7, Size1), W1,		BD(0, Size4),	"12AA5678" },

		{ BA(0, Size2), W2,		BD(0, Size4),	"AB345678" },
		{ BA(1, Size2), W2,		BD(0, Size4),	"AB345678" },
		{ BA(2, Size2), W2,		BD(0, Size4),	"AB345678" },
		{ BA(3, Size2), W2,		BD(0, Size4),	"AB345678" },
		{ BA(4, Size2), W2,		BD(0, Size4),	"12AB5678" },
		{ BA(5, Size2), W2,		BD(0, Size4),	"12AB5678" },
		{ BA(6, Size2), W2,		BD(0, Size4),	"12AB5678" },
		{ BA(7, Size2), W2,		BD(0, Size4),	"12AB5678" },

		// 3バイトは来ないはず?

		{ BA(0, Size4), W4,		BD(0, Size4),	"AB345678" },
		{ BA(1, Size4), W4,		BD(0, Size4),	"AB345678" },
		{ BA(2, Size4), W4,		BD(0, Size4),	"AB345678" },
		{ BA(3, Size4), W4,		BD(0, Size4),	"AB345678" },
		{ BA(4, Size4), W4,		BD(0, Size4),	"12AB5678" },
		{ BA(5, Size4), W4,		BD(0, Size4),	"12AB5678" },
		{ BA(6, Size4), W4,		BD(0, Size4),	"12AB5678" },
		{ BA(7, Size4), W4,		BD(0, Size4),	"12AB5678" },
	},
};

static TestData
table_L = {
	.name = "BusIO_L",
	.table_read = {
		{ BA(0, Size1),		BD(0x81828384, Size4) },
		{ BA(1, Size1),		BD(0x81828384, Size4) },
		{ BA(2, Size1),		BD(0x81828384, Size4) },
		{ BA(3, Size1),		BD(0x81828384, Size4) },
		{ BA(4, Size1),		BD(0x85868788, Size4) },
		{ BA(5, Size1),		BD(0x85868788, Size4) },
		{ BA(6, Size1),		BD(0x85868788, Size4) },
		{ BA(7, Size1),		BD(0x85868788, Size4) },

		{ BA(0, Size2),		BD(0x81828384, Size4) },
		{ BA(1, Size2),		BD(0x81828384, Size4) },
		{ BA(2, Size2),		BD(0x81828384, Size4) },
		{ BA(3, Size2),		BD(0x81828384, Size4) },
		{ BA(4, Size2),		BD(0x85868788, Size4) },
		{ BA(5, Size2),		BD(0x85868788, Size4) },
		{ BA(6, Size2),		BD(0x85868788, Size4) },
		{ BA(7, Size2),		BD(0x85868788, Size4) },

		{ BA(0, Size3),		BD(0x81828384, Size4) },
		{ BA(1, Size3),		BD(0x81828384, Size4) },
		{ BA(2, Size3),		BD(0x81828384, Size4) },
		{ BA(3, Size3),		BD(0x81828384, Size4) },
		{ BA(4, Size3),		BD(0x85868788, Size4) },
		{ BA(5, Size3),		BD(0x85868788, Size4) },
		{ BA(6, Size3),		BD(0x85868788, Size4) },
		{ BA(7, Size3),		BD(0x85868788, Size4) },

		{ BA(0, Size4),		BD(0x81828384, Size4) },
		{ BA(1, Size4),		BD(0x81828384, Size4) },
		{ BA(2, Size4),		BD(0x81828384, Size4) },
		{ BA(3, Size4),		BD(0x81828384, Size4) },
		{ BA(4, Size4),		BD(0x85868788, Size4) },
		{ BA(5, Size4),		BD(0x85868788, Size4) },
		{ BA(6, Size4),		BD(0x85868788, Size4) },
		{ BA(7, Size4),		BD(0x85868788, Size4) },
	},
	.table_write = {
		{ BA(0, Size1), W1,		BD(0, Size4),	"AAAA5678" },
		{ BA(1, Size1), W1,		BD(0, Size4),	"AAAA5678" },
		{ BA(2, Size1), W1,		BD(0, Size4),	"AAAA5678" },
		{ BA(3, Size1), W1,		BD(0, Size4),	"AAAA5678" },

		{ BA(0, Size2), W2,		BD(0, Size4),	"ABAB5678" },
		{ BA(1, Size2), W2,		BD(0, Size4),	"AABA5678" },
		{ BA(2, Size2), W2,		BD(0, Size4),	"ABAB5678" },
		{ BA(3, Size2), W2,		BD(0, Size4),	"AABA5678" },

		{ BA(0, Size3), W3,		BD(0, Size4),	"ABC05678" },
		{ BA(1, Size3), W3,		BD(0, Size4),	"AABC5678" },
		{ BA(2, Size3), W3,		BD(0, Size4),	"ABAB5678" },
		{ BA(3, Size3), W3,		BD(0, Size4),	"AABA5678" },

		{ BA(0, Size4), W4,		BD(0, Size4),	"ABCD5678" },
		{ BA(1, Size4), W4,		BD(0, Size4),	"AABC5678" },
		{ BA(2, Size4), W4,		BD(0, Size4),	"ABAB5678" },
		{ BA(3, Size4), W4,		BD(0, Size4),	"AABA5678" },
	},
};

int
main()
{
	do_test(new BusIO_B<TestByteDev>(),			table_B);
	do_test(new BusIO_BB<TestByteDev>(),		table_BB);
	do_test(new BusIO_BBBB<TestByteDev>(),		table_BBBB);
	do_test(new BusIO_BFFF<TestByteDev>(),		table_BFFF);
	do_test(new BusIO_EB<TestByteDev>(),		table_EB);
	do_test(new BusIO_FB<TestByteDev>(),		table_FB);

	do_test(new BusIO_W<TestWordDev>(),			table_W);
	do_test(new BusIO_WF<TestWordDev>(),		table_WF);

	do_test(new BusIO_L<TestLongDev>(),			table_L);

	return 0;
}

// リンカを通すためのダミー
void
vmpanic_func(const char *funcname, const char *fmt, ...)
{
	va_list ap;

	printf("panic: %s: ", funcname);
	va_start(ap, fmt);
	vprintf(fmt, ap);
	va_end(ap);
	exit(1);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.