|
|
nono 1.3.0
//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//
//
// Pluto-X (独自の仮想ボード)
//
#include "pluto.h"
#include "mainapp.h"
#include "mainbus.h"
#include "mainram.h"
#include "mpu680x0.h"
#include "sram.h"
// コンストラクタ
PlutoDevice::PlutoDevice()
: inherited(OBJ_PLUTO)
{
}
// デストラクタ
PlutoDevice::~PlutoDevice()
{
}
// ROM
/*static*/ const uint16
PlutoDevice::rom[] = {
// ホストファイル起動
0x00ea, 0xc004, // .dc.l _start ; 起動アドレス
//_start:
0x46fc, 0x2700, // move.w #0x2700,%sr
0x2039, 0x00ea, 0xc450, // move.l (ROMIO_LOAD),%d0
0x6b04, // bmi.s _err
0x2040, // move.l %d0,%a0
0x46fc, 0x2000, // move.w #0x2000,%sr
0x4e90, // jsr (%a0)
//_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
};
busdata
PlutoDevice::Read(busaddr addr)
{
uint32 paddr = addr.Addr();
uint32 offset = paddr - baseaddr;
busdata data;
if (offset < sizeof(rom)) {
// ROM 部はワードデバイスっぽく応答するほうが都合がいい。
data = rom[offset / 2];
data |= BusData::Size2;
} else if (offset == 0x450 && addr.GetSize() == 4) {
// ここはロングワード応答するほうが都合がいい。
// 自 ROM からのアクセスなので細かいことは考えない。
data = ROM_Load();
data |= BusData::Size4;
} else {
data.SetBusErr();
}
return data;
}
busdata
PlutoDevice::Write(busaddr addr, uint32 data)
{
uint32 paddr = addr.Addr();
uint32 reqsize = addr.GetSize();
putlog(0, "Write $%06x.%u (NOT IMPLEMENTED)", paddr, reqsize);
return BusData::BusErr;
}
busdata
PlutoDevice::Peek1(uint32 addr)
{
uint32 offset = addr - baseaddr;
uint32 data;
if (offset < sizeof(rom)) {
data = rom[offset / 2];
if ((offset & 1) == 0) {
return data >> 8;
} else {
return data & 0xff;
}
}
return BusData::BusErr;
}
//
// ホストファイル起動
//
// -X オプションで指定されたホストファイルをロードする。
// ロードできればエントリポイントを返す。
// exec_file が指定されている時に呼ぶこと。
uint32
PlutoDevice::ROM_Load()
{
assert(gMainApp.exec_file);
auto mainbus = GetMainbusDevice();
auto mainram = GetMainRAMDevice();
auto mpu680x0 = GetMPU680x0Device(mpu);
auto sram = GetSRAMDevice();
// ホストファイルをロード
LoadInfo info(gMainApp.exec_file);
if (BootLoader::LoadExec(mainram, &info) == false) {
return -1;
}
// NetBSD/x68k のプライマリブートローダが /boot を読み込む時、および
// /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 だが今の所使ってないようだ。
//
// 一方、/boot がカーネルを読み込む時はこれに加えてスタック渡しの
// パラメータもある。これは (取り出す順に)
// firstpa.L .. 読み込んだカーネル先頭の物理アドレス?
// physsize.L .. RAM 容量 (SRAM の $ed0008.L の値)
// esym.L .. シンボルの後ろ、なので実質読み込んだ全体のサイズ
//
// これも本当はターゲットが NetBSD/x68k のカーネルの時に限定すべきの
// ような気もするけど、とりあえず。
mpu680x0->reg.D[6] = 0xa1000004;
mpu680x0->reg.D[7] = 0;
uint32 a7 = sram->GetRAMSize();
a7 -= 4;
mainbus->HVWrite4(a7, info.end - info.start); // esym
a7 -= 4;
mainbus->HVWrite4(a7, sram->GetRAMSize()); // physsize
a7 -= 4;
mainbus->HVWrite4(a7, 0x00000000); // firstpa
mpu680x0->reg.A[7] = a7;
return info.entry;
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.