File:  [Isaki's NoNo m68k/m88k emulator] / nono / m680x0 / m68030bus.h
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:05:15 2026 UTC (3 months ago) by root
Branches: MAIN, Isaki
CVS tags: v018, v017, HEAD
nono 0.5.0

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

#pragma once

//
// 1回の(アラインド)物理アクセスを担当するマクロ。
// これらは続く _mmu テンプレートで使用する。
// goto を含むことに注意。gcc 拡張式(?)に注意。
// Translate* は Fetch, Read, Write の3種だが、Mainbus には
// Read, Write しかないことに注意。物理バスに FC0 と FC1、つまりプログラム
// 空間かどうかの情報は出していないため。
//

#define FETCH(size) ({	\
	bus.paddr = bus.laddr;	\
	if (use_mmu && TranslateFetch() == false)	\
		goto buserr;	\
	uint64 data_ = mainbus->__CONCAT(Read,size)(bus.paddr);	\
	if ((int64)data_ < 0)	\
		goto buserr;	\
	data_;	/* これが戻り値 */	\
})

#define READ(size) ({	\
	bus.paddr = bus.laddr;	\
	if (use_mmu && TranslateRead() == false)	\
		goto buserr;	\
	uint64 data_ = mainbus->__CONCAT(Read,size)(bus.paddr);	\
	if ((int64)data_ < 0)	\
		goto buserr;	\
	data_;	/* これが戻り値 */	\
})

#define WRITE(size, data)	({	\
	bus.paddr = bus.laddr;	\
	if (use_mmu && TranslateWrite() == false)	\
		goto buserr;	\
	int64 berr_ = mainbus->__CONCAT(Write,size)(bus.paddr, (data));	\
	if (berr_ < 0)	\
		goto buserr;	\
	0;	/* 戻り値不要だけど一応 */	\
})

//
// MMU を考慮した下請けテンプレート。
// 1回分のミスアラインドありのアクセスを担当。
//

template<bool use_mmu> uint32
fetch_16_mmu()
{
	uint64 data;

	data = FETCH(16);
	// XXX バスエラー時に PC をインクリメントするタイミングは?
	reg.pc += 2;

	return data;

 buserr:
	bus.SET_SSW(use_mmu, M68K::SSW_SIZE_WORD);
	throw M68K::EXCEP_BUSERR;
}

template<bool use_mmu> uint32
fetch_32_mmu()
{
	uint64 data;

	if ((bus.laddr & 3) == 0) {
		data = FETCH(32);
	} else {
		uint64 h, l;

		h = FETCH(16);
		bus.laddr += 2;

		l = FETCH(16);
		data = (h << 16) | l;
	}
	// XXX バスエラー時に PC をインクリメントするタイミングは?
	reg.pc += 4;
	return data;

 buserr:
	bus.SET_SSW(use_mmu, M68K::SSW_SIZE_LONG);
	throw M68K::EXCEP_BUSERR;
}

template<bool use_mmu> uint32
read_8_mmu()
{
	uint64 data;

	data = READ(8);

	if (1)
		putlog(2, "read_8   %08X -> %02X", bus.laddr, (uint32)data);
	return data;

 buserr:
	bus.SET_SSW(use_mmu, M68K::SSW_SIZE_BYTE);
	throw M68K::EXCEP_BUSERR;
}

template<bool use_mmu> uint32
read_16_mmu()
{
	uint64 data;

	if ((bus.laddr & 1) == 0) {
		data = READ(16);
	} else {
		uint64 h, l;

		h = READ(8);
		bus.laddr += 1;

		l = READ(8);
		data = (h << 8) | l;
	}

	if (1)
		putlog(2, "read_16  %08X -> %04X", bus.laddr, (uint32)data);
	return data;

 buserr:
	bus.SET_SSW(use_mmu, M68K::SSW_SIZE_WORD);
	throw M68K::EXCEP_BUSERR;
}

template<bool use_mmu> uint32
read_32_mmu()
{
	uint64 data;

	if ((bus.laddr & 3) == 0) {
		data = READ(32);
	} else if ((bus.laddr & 1) == 0) {
		uint64 h, l;

		h = READ(16);
		bus.laddr += 2;

		l = READ(16);
		data = (h << 16) | l;
	} else {
		uint64 h, m, l;

		h = READ(8);
		bus.laddr += 1;

		m = READ(16);
		bus.laddr += 2;

		l = READ(8);
		data = (h << 24) | (m << 8) | l;
	}

	if (1)
		putlog(2, "read_32  %08X -> %08X", bus.laddr, (uint32)data);
	return data;

 buserr:
	bus.SET_SSW(use_mmu, M68K::SSW_SIZE_LONG);
	throw M68K::EXCEP_BUSERR;
}

template<bool use_mmu> void
write_8_mmu()
{
	uint32 data = bus.data;

	if (1)
		putlog(2, "write_8  %08X <- %02X", bus.laddr, data);

	WRITE(8, data);
	return;

 buserr:
	bus.SET_SSW(use_mmu, M68K::SSW_SIZE_BYTE);
	throw M68K::EXCEP_BUSERR;
}

template<bool use_mmu> void
write_16_mmu()
{
	uint32 data = bus.data;

	if (1)
		putlog(2, "write_16 %08X <- %04X", bus.laddr, data);

	if ((bus.laddr & 1) == 0) {
		WRITE(16, data);
	} else {
		WRITE(8, data >> 8);

		bus.laddr += 1;
		WRITE(8, data & 0xff);
	}
	return;

 buserr:
	bus.SET_SSW(use_mmu, M68K::SSW_SIZE_WORD);
	throw M68K::EXCEP_BUSERR;
}

template<bool use_mmu> void
write_32_mmu()
{
	uint32 data = bus.data;

	if (1)
		putlog(2, "write_32 %08X <- %08X", bus.laddr, data);

	if ((bus.laddr & 3) == 0) {
		WRITE(32, data);
	} else if ((bus.laddr & 1) == 0) {
		WRITE(16, data >> 16);

		bus.laddr += 2;
		WRITE(16, data & 0xffff);
	} else {
		WRITE(8, data >> 24);

		bus.laddr += 1;
		WRITE(16, (data >> 8) & 0xffff);

		bus.laddr += 2;
		WRITE(8, data & 0xff);
	}
	return;

 buserr:
	bus.SET_SSW(use_mmu, M68K::SSW_SIZE_LONG);
	throw M68K::EXCEP_BUSERR;
}

unix.superglobalmegacorp.com

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