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