|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2022 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: //
8: // NEWS の ROM エミュレーション (-X のみ対応)
9: //
10:
1.1.1.3 ! root 11: // IODevice
! 12: // |
! 13: // +- ROMDevice (LoadROM()、ウェイト、マスク等を持つ)
! 14: // | +- PROMDevice (LUNA* の PROM)
! 15: // | +- IPLROM1Device (X680x0 の IPLROM 後半)
! 16: // | +- IPLROM2Device (X680x0 の IPLROM 前半)
! 17: // | +- CGROMDevice (X680x0 の CGROM)
! 18: // | |
! 19: // | +- ROMEmuDevice
! 20: // | +- LunaPROMEmuDevice (LUNA PROM エミュレーションの共通部分)
! 21: // | | +- Luna1PROMEmuDevice (LUNA-I の PROM エミュレーション)
! 22: // | | +- Luna88kPROMEmuDevice (LUNA-88K の PROM エミュレーション)
! 23: // | |
! 24: // | | +------------------+
! 25: // | +-| NewsROMEmuDevice | (NEWS の ROM エミュレーション)
! 26: // | | +------------------+
! 27: // | |
! 28: // | +- ROM30EmuDevice (X68030 の ROM30 エミュレーション)
! 29: // | +- Virt68kROMEmuDevice (virt-m68k の IPLROM 相当の何か)
! 30: // |
! 31: // +- PROM0Device (LUNA* のブートページ切り替え用プロキシ)
! 32: // +- IPLROM0Device (X680x0 のブートページ切り替え用プロキシ)
! 33:
1.1 root 34: #include "romemu_news.h"
1.1.1.2 root 35: #include "mainbus.h"
1.1 root 36: #include "mainram.h"
37: #include "memorystream.h"
38: #include "mpu680x0.h"
39: #include "newsfb.h"
40:
41: // コンストラクタ
42: NewsROMEmuDevice::NewsROMEmuDevice()
43: : inherited(OBJ_PROM)
44: {
45: // 適当
46: uint devlen = 4096;
47: imagebuf.reset(new uint8 [devlen]);
48: memset(&imagebuf[0], 0, devlen);
49: mem = &imagebuf[0];
50:
51: mask = devlen - 1;
52: }
53:
54: // デストラクタ
55: NewsROMEmuDevice::~NewsROMEmuDevice()
56: {
57: }
58:
59: // 初期化
60: bool
61: NewsROMEmuDevice::Init()
62: {
63: if (inherited::Init() == false) {
64: return false;
65: }
66:
67: mainram = GetMainRAMDevice();
68:
1.1.1.3 ! root 69: MemoryStreamBE roms(imagebuf.get());
! 70: roms.Write4(0x00000400); // +00: リセットベクタ SP
! 71: roms.Write4(0xf8000400); // +04: リセットベクタ PC
1.1 root 72: // ベクタ
73: for (int i = 2; i < 256; i++) {
1.1.1.3 ! root 74: roms.Write4(0);
1.1 root 75: }
1.1.1.3 ! root 76: roms.SetOffset(32 * 4);
! 77: roms.Write4(0xf8000500); // Trap#0 で ROM のサービスコール
1.1.1.2 root 78: // Trap#15 は ROM モニタらしい。今の所停止するだけ。
79: // とりあえず Trap#1..#14 も全部ここへ向けておく。
80: for (int i = 1; i < 16; i++) {
1.1.1.3 ! root 81: roms.Write4(0xf8000600);
1.1.1.2 root 82: }
1.1 root 83:
84: // リセット時に実行する命令
1.1.1.3 ! root 85: roms.SetOffset(0x400);
! 86: roms.Write2(0x2039); // move.l (ROMIO_INIT),d0
! 87: roms.Write4(ROMIO_INIT);
! 88: roms.Write2(0x2040); // move.l d0,a0 ; ジャンプ先を a0 にセット
! 89: roms.Write2(0x4ed0); // jmp (a0) ; ジャンプ
1.1 root 90:
91: // ROM サービスコール
1.1.1.3 ! root 92: roms.SetOffset(0x500);
! 93: roms.Write2(0x0c80); // cmpi.l #3,d0
! 94: roms.Write4(0x00000003); //
! 95: roms.Write2(0x6708); // beq @f
! 96: roms.Write2(0x2039); // move.l (ROMIO_SYS),d0
! 97: roms.Write4(ROMIO_SYS); //
! 98: roms.Write2(0x4e73); // rte
1.1 root 99: //@@: ; Read は対応してないので
1.1.1.3 ! root 100: roms.Write4(0x4e722500); // stop #0x2500 ; STOP しつつ
! 101: roms.Write2(0x60fa); // bra @b ; 無限ループ。
! 102: roms.Write2(0x4e73); // rte
1.1 root 103:
1.1.1.2 root 104: // ROM モニタの TRAP#n。はないのでここに来たらとりあえず停止する?
1.1.1.3 ! root 105: roms.SetOffset(0x600);
1.1.1.2 root 106: //@@:
1.1.1.3 ! root 107: roms.Write4(0x4e722700); // stop #0x2700 ; STOP しつつ
! 108: roms.Write2(0x60fa); // bra @b ; 無限ループ。
1.1.1.2 root 109:
1.1 root 110: return true;
111: }
112:
113: void
114: NewsROMEmuDevice::ResetHard(bool poweron)
115: {
116: // 起動時に RAM にリセットベクタを書き込んでおく。(手抜き)
1.1.1.3 ! root 117: mainram->WriteMem(0, &imagebuf[0], 8);
1.1 root 118: }
119:
1.1.1.3 ! root 120: // ROMIO から読み出す。
! 121: // ROMIO が応答すべきでなければ (uint64)-1 を返す。
! 122: uint64
! 123: NewsROMEmuDevice::ReadROMIO(busaddr addr)
1.1 root 124: {
1.1.1.3 ! root 125: if (addr.GetSize() == 4) {
! 126: switch (addr.Addr()) {
! 127: case ROMIO_INIT:
! 128: return ROM_Init();
1.1 root 129:
1.1.1.3 ! root 130: case ROMIO_SYS:
! 131: return ROM_Sys();
1.1 root 132:
1.1.1.3 ! root 133: default:
! 134: break;
! 135: }
1.1 root 136: }
137:
1.1.1.3 ! root 138: return (uint64)-1;
1.1 root 139: }
140:
141: uint32
142: NewsROMEmuDevice::ROM_Init()
143: {
1.1.1.2 root 144: // -X file で指定されたホストファイルを読み込んでエントリポイント
145: // アドレスをこの Read アクセスの読み出し値として返す。
1.1 root 146:
1.1.1.2 root 147: LoadInfo info(gMainApp.exec_file);
148: if (mainram->LoadExec(&info) == false) {
149: // XXX どうすべ
150: PANIC("** Couldn't load specified host program");
151: return -1;
1.1 root 152: }
1.1.1.2 root 153: putmsg(1, "Host program loaded. Entry point = $%08x", info.entry);
1.1 root 154:
155: // ROMCONS のために VBR を設定
1.1.1.2 root 156: m68kreg& reg = GetMPU680x0Device(mpu)->reg;
1.1 root 157: reg.vbr = 0xf8000000;
158:
159: // %d2 には MARK_END (たぶん最後の番地)
160: // %d4 にメモリサイズ。
161: // %d5 には読み込んだファイル名の先頭番地?
162: // %d6 に bootdev、NetBSD/news68k の場合は
163: // bootdev = $MCxUHPTT
164: // || |||++ Type? (SD=0)
165: // || ||+-- Partition?
166: // || |+--- Host: 機種? (NEWS1700 は 0)
167: // || +---- Unit?
168: // |+------ Controller?
169: // +------- magic ($5)
170: // 下位28ビット(7桁) は ROM から渡されるようだ。
171: // %d7 は boothowto。
172: reg.D[2] = info.sym;
173: reg.D[4] = mainram->GetSize();
174: reg.D[6] = 0x50000000;
175: reg.D[7] = 0;
176:
177: return info.entry;
178: }
179:
180: uint32
181: NewsROMEmuDevice::ROM_Sys()
182: {
1.1.1.2 root 183: auto mainbus = GetMainbusDevice();
184: auto mpu680x0 = GetMPU680x0Device(mpu);
1.1 root 185: m68kreg& reg = mpu680x0->reg;
186: auto newsfb = GetNewsfbDevice();
187:
188: if (reg.D[0] == SYS_write) {
189: uint32 a6 = reg.A[6];
1.1.1.3 ! root 190: uint32 fd = mainbus->HVRead4(a6 + 8);
! 191: uint32 buf = mainbus->HVRead4(a6 + 12);
! 192: uint32 len = mainbus->HVRead4(a6 + 16);
1.1 root 193:
194: for (int i = 0; i < len; i++) {
1.1.1.3 ! root 195: busdata bd = mainbus->HVRead1(buf++);
1.1.1.2 root 196: if (bd.IsBusErr()) {
1.1 root 197: // XXX ?
198: return 0;
199: }
1.1.1.2 root 200: uint8 ch = bd.Data();
1.1 root 201: if (ch == '\r') {
202: continue;
203: }
204: newsfb->Putc(ch);
205: }
206: (void)fd;
207: return len;
208: }
209:
210: VMPANIC("Unknown service call $%02x", reg.D[0]);
211: return 0;
212: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.