File:  [Isaki's NoNo m68k/m88k emulator] / nono / vm / pedec.cpp
Revision 1.1.1.13 (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
//

//
// PEDEC
//

// IODevice
//    |
//    +-- InterruptDevice (割り込みコントローラの共通部)
//          |
//          +-- M680x0Interrupt (m68k 割り込みコントローラの共通部)
//          |     |
//          |     +-- X68030Interrupt  (X68030 の割り込みコントローラ)
//          |     +-- LunaInterrupt    (LUNA-I の割り込みコントローラ)
//          |
//          |  +-------------+
//          +--| PEDECDevice | (X68030 の Lv1 担当コントローラ)
//          |  +-------------+
//          |
//          +-- SysCtlrDevice  (LUNA-88K の割り込みコントローラ)

#include "pedec.h"
#include "fdc.h"
#include "fdd.h"
#include "mainapp.h"
#include "spc.h"

// コンストラクタ
PEDECDevice::PEDECDevice()
	: inherited(OBJ_PEDEC)
{
}

// デストラクタ
PEDECDevice::~PEDECDevice()
{
}

// 初期化
bool
PEDECDevice::Init()
{
	interrupt = GetInterruptDevice();

	// 検索順
	RegistINT(IntmapSPC,  "SPC",  GetSPCDevice());
	RegistINT(IntmapFDC,  "FDC",  GetFDCDevice());
	RegistINT(IntmapHDD,  "HDD",  NULL);
	RegistINT(IntmapPRT,  "PRT",  NULL);
	// FDD は4本を共有しているのでいろいろ特別扱い。
	RegistINT(IntmapFDD0, "FDD0", gMainApp.FindObject<FDDDevice>(OBJ_FDD(0)));
	RegistINT(IntmapFDD1, "FDD1", gMainApp.FindObject<FDDDevice>(OBJ_FDD(1)));
	RegistINT(IntmapFDD2, "FDD2", gMainApp.FindObject<FDDDevice>(OBJ_FDD(2)));
	RegistINT(IntmapFDD3, "FDD3", gMainApp.FindObject<FDDDevice>(OBJ_FDD(3)));
	// 名前表示用
	RegistINT(IntmapFDD,  "FDD",  NULL);

	// 表示順
	disp_list = {
		IntmapSPC,
		IntmapFDC,
		IntmapFDD,
		IntmapHDD,
		IntmapPRT,
	};

	return true;
}

// リセット
void
PEDECDevice::ResetHard(bool poweron)
{
	inherited::ResetHard(poweron);

	intmap_enable = IntmapSPC;
	ChangeInterrupt();

	// XXX vector
}

busdata
PEDECDevice::ReadPort(uint32 offset)
{
	busdata data;

	switch (offset) {
	 case 0:	// $E9C001 割り込みステータス
		data = GetStat();
		break;

	 case 1:	// $E9C003 割り込みベクタ
		// 書き込み専用
		data = 0xff;
		break;

	 default:
		data = 0xff;
		break;
	}

	// XXX wait?
	data |= BusData::Size1;
	return data;
}

busdata
PEDECDevice::WritePort(uint32 offset, uint32 data)
{
	switch (offset) {
	 case 0:	// $E9C001 割り込みマスク
		intmap_enable = IntmapSPC;
		intmap_enable |= (data & 0x08) ? IntmapHDD : 0;
		intmap_enable |= (data & 0x04) ? IntmapFDC : 0;
		intmap_enable |= (data & 0x02) ? IntmapFDD : 0;
		intmap_enable |= (data & 0x01) ? IntmapPRT : 0;

		putlog(1, "Set Interrupt Mask HDD=%u FDC=%u FDD=%u PRT=%u",
			((intmap_enable & IntmapHDD) ? 1 : 0),
			((intmap_enable & IntmapFDC) ? 1 : 0),
			((intmap_enable & IntmapFDD) ? 1 : 0),
			((intmap_enable & IntmapPRT) ? 1 : 0));
		break;

	 case 1:	// $E9C003 割り込みベクタ
		vector = data & 0xfc;
		putlog(1, "Set Interrupt Vector $%02x", vector);
		break;

	 default:
		break;
	}

	// XXX wait?
	busdata r = BusData::Size1;
	return r;
}

busdata
PEDECDevice::PeekPort(uint32 offset)
{
	switch (offset) {
	 case 0:
		return GetStat();

	 case 1:
		// 書き込み専用
		return 0xff;

	 default:
		return 0xff;
	}
}

bool
PEDECDevice::PokePort(uint32 offset, uint32 data)
{
	return false;
}

void
PEDECDevice::MonitorScreen(TextScreen& screen, uint intr_level, int y)
{
	for (uint32 map : disp_list) {
		int clz = __builtin_clz(map);
		screen.Puts(4, y, TA::OnOff(intmap_status & map), GetIntName(map));
		if (intr_level >= 1 || (intmap_enable & map) == 0) {
			screen.Puts(11, y, "Mask");
		}
		uint64 cnt = counter[clz];
		if (__predict_false(map == IntmapFDD)) {
			// FDD は4つの和
			cnt += counter[clz + 1] + counter[clz + 2] + counter[clz + 3];
		}
		screen.Print(15, y, "%26s", format_number(cnt).c_str());
		y++;
	}
}

// 割り込みステータスレジスタの値を取得。
// (Peek からも呼ばれるので副作用を持たせてはいけない)
uint32
PEDECDevice::GetStat() const
{
	uint32 data = 0;
	data |= (intmap_status & IntmapFDC) ? 0x80 : 0;
	data |= (intmap_status & IntmapFDD) ? 0x40 : 0;
	data |= (intmap_status & IntmapPRT) ? 0x20 : 0;
	data |= (intmap_status & IntmapHDD) ? 0x10 : 0;
	data |= (intmap_enable & IntmapHDD) ? 0x08 : 0;
	data |= (intmap_enable & IntmapFDC) ? 0x04 : 0;
	data |= (intmap_enable & IntmapFDD) ? 0x02 : 0;
	data |= (intmap_enable & IntmapPRT) ? 0x01 : 0;
	return data;
}

// 割り込み信号線の状態を変える
void
PEDECDevice::ChangeInterrupt()
{
#if 0 // こんなログ出したいかも
		// ログ表示のためだけ
		if ((intmap_enable & IntmapFDC)) {
			putlog(1, "FDC からの割り込み要求");
		} else {
			putlog(2, "FDC からの割り込み要求(マスク)");
		}
#endif

	uint32 stat = (intmap_status & intmap_enable);
	interrupt->ChangeINT(this, stat);
}

// 割り込みアクノリッジ
busdata
PEDECDevice::InterruptAcknowledge(int lv)
{
	uint32 stat = (intmap_status & intmap_enable);

	// SPC と I/O コントローラ担当の4本どっちが優先かは分からないので
	// SPC を優先しておくのでいいだろう。
	if ((stat & IntmapSPC)) {
		// XXX PEDEC のベクタに影響されるか?
		return 0x6c;
	}

	if ((stat & IntmapFDC)) {
		return vector + 0;
	} else if ((stat & IntmapFDD)) {
		return vector + 1;
	} else {
		return BusData::BusErr;
	}
}

unix.superglobalmegacorp.com

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