--- nono/vm/pluto.cpp 2026/04/29 17:04:28 1.1.1.1 +++ nono/vm/pluto.cpp 2026/04/29 17:04:59 1.1.1.7 @@ -1,15 +1,20 @@ // // nono -// Copyright (C) 2017 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // #include "pluto.h" -#include "mpu.h" +#include "aout.h" +#include "mainapp.h" +#include "mpu680x0.h" +#include "ram.h" + +std::unique_ptr gPluto; PlutoDevice::PlutoDevice() + : inherited("Pluto") { - logname = "pluto"; - devname = "Pluto"; devaddr = 0xeac000; devlen = 0x2000; } @@ -18,6 +23,169 @@ PlutoDevice::~PlutoDevice() { } +void +PlutoDevice::ResetHard() +{ + // XXX not yet + m_count = 0; +} + +// ROM +/*static*/ const uint16 +PlutoDevice::rom[] = { + // ホストファイル起動 + 0x00ea, 0xc004, // .dc.l _start ; 起動アドレス + //_start: + 0x2039, 0x00ea, 0xc450, // move.l (ROMIO_LOAD),%d0 + 0x6704, // beq.s _err + 0x2040, // move.l %d0,%a2 + 0x4ed0, // jmp (%a2) + //_err: + 0x43fa, 0x000c, // lea.l (_errmsg),%a1 + 0x7021, 0x4e4f, // IOCS B_PRINT + //_loop: + 0x4e72, 0x2600, // stop #0x2600 + 0x60fa, // bra.s _loop + //_errmsg: + 0x2a2a, 0x2043, 0x616e, // .dc.b "** Can" + 0x6e6f, 0x7420, 0x6c6f, // .dc.b "not lo" + 0x6164, 0x2068, 0x6f73, // .dc.b "ad hos" + 0x7420, 0x6669, 0x6c65, // .dc.b "t file" + 0x2e00, // .dc.b ".",0 +}; + +uint64 +PlutoDevice::Read8(uint32 addr) +{ + uint32 offset = addr - devaddr; + uint32 data; + + if (offset < sizeof(rom)) { + data = rom[offset / 2]; + if ((offset & 1) == 0) { + return data >> 8; + } else { + return data & 0xff; + } + } + + return (uint64)-1; +} + +uint64 +PlutoDevice::Read16(uint32 addr) +{ + uint32 offset = addr - devaddr; + + if (offset < sizeof(rom)) { + return rom[offset / 2]; + } + + return (uint64)-1; +} + +uint64 +PlutoDevice::Read32(uint32 addr) +{ + uint32 offset = addr - devaddr; + uint32 data; + + if (offset < sizeof(rom)) { + data = rom[offset / 2] << 16; + data |= rom[(offset / 2) + 1]; + return data; + } + switch (offset) { + case 0x450: // ROMIO_LOAD + return ROM_Load(); + + default: + break; + } + return (uint64)-1; +} + +uint64 +PlutoDevice::Write8(uint32 addr, uint32 data) +{ + switch (addr) { + case 0xeac403: + write_8_benchmark(addr, data); + break; + default: + break; + } + putlog(0, "未実装バイト書き込み $%06x", addr); + return 0; +} + +uint64 +PlutoDevice::Write16(uint32 addr, uint32 data) +{ + putlog(0, "未実装ワード書き込み $%06x", addr); + return 0; +} + +uint64 +PlutoDevice::Peek8(uint32 addr) +{ + uint32 offset = addr - devaddr; + uint32 data; + + if (offset < sizeof(rom)) { + data = rom[offset / 2]; + if ((offset & 1) == 0) { + return data >> 8; + } else { + return data & 0xff; + } + } + + return (uint64)-1; +} + +// +// ホストファイル起動 +// + +// -X オプションで指定されたホストファイルをロードする。 +// ロードできればエントリポイントを返す。 +// exec_file が指定されている時に呼ぶこと。 +uint32 +PlutoDevice::ROM_Load() +{ + assert(gMainApp.exec_file); + + // ホストファイルをロード + uint32 entry = gRAM->LoadFile(gMainApp.exec_file); + + if (entry) { + // NetBSD/x68k のプライマリブートローダが /boot を読み込む時には + // いくつかレジスタ渡しのパラメータがあるので、ここで用意する。 + // 本当はターゲットが NetBSD/x68k の /boot の時に限定すべきのような + // 気もするけど、とりあえず。 + // 必要なパラメータは + // %d6 に bootdev、NetBSD/x68k の場合は + // bootdev = $MACULPTT + // ||||||++- major type + // |||||+--- パーティション番号 + // ||||+---- SCSI なら LUN、それ以外なら 0 + // |||+----- unit (SCSI なら SCSI ID、FD ならドライブ番号) + // ||+------ ctlr (spc0 なら 0 のやつ) + // |+------- adaptor (spc = 1、mha = 2) + // +-------- magic ($a) + // major type は fd=2、MemoryDisk=8、sd=4、(st=5、)、cd=7、ne=255。 + // + // %d7 に howto だが今の所使ってないようだ。 + + m68kcpu *cpu = gMPU680x0->GetCPU(); + RegD(6) = 0xa1000004; + RegD(7) = 0; + } + + return entry; +} + // ベンチマーク開始 void PlutoDevice::benchmark_start(uint32 data) @@ -47,7 +215,7 @@ PlutoDevice::benchmark_start(uint32 data putlog(0, "ベンチマーク開始"); // 命令開始アドレス。この時点で REG_PC は次をさしている - m_start_addr = gMPU->GetPPC(); + m_start_addr = gMPU680x0->GetPPC(); } // 測定開始 @@ -83,10 +251,10 @@ PlutoDevice::benchmark_end() // 規定秒数に達していれば、測定終了 t = m_total.tv_sec * 1000*1000 + m_total.tv_usec; putlog(0, "ベンチマーク#%d 終了 (%d 回, 計 %d.%03d msec)", - benchmark_mode, m_count, t / 1000, t % 1000); + gMainApp.benchmark_mode, m_count, t / 1000, t % 1000); // 1ループ中の命令セット数を算出。REG_PPC はこの命令の開始番地 - num_of_inst = (gMPU->GetPPC() - m_start_addr) / m_inst_len; + num_of_inst = (gMPU680x0->GetPPC() - m_start_addr) / m_inst_len; // 68030 のクロック数 [MHz] に換算 speed = (double)(m_count * num_of_inst) * m_inst_cycle / t; @@ -129,45 +297,3 @@ PlutoDevice::write_8_benchmark(uint32 ad PANIC("not impl"); } } - -uint64 -PlutoDevice::Read8(uint32 addr) -{ - PANIC("not impl"); -} - -uint64 -PlutoDevice::Read16(uint32 addr) -{ - PANIC("not impl"); -} - -uint64 -PlutoDevice::Write8(uint32 addr, uint32 data) -{ - switch (addr) { - case 0xeac403: - write_8_benchmark(addr, data); - break; - default: - PANIC("not yet"); - } - return 0; -} - -uint64 -PlutoDevice::Write16(uint32 addr, uint32 data) -{ - PANIC("not impl"); - return 0; -} - -uint64 -PlutoDevice::Peek8(uint32 addr) -{ - PANIC("not yet"); - return 0; -} - -// ベンチマークモード。コマンドライン引数で指定される。 -/*static*/int PlutoDevice::benchmark_mode;