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