|
|
1.1 root 1: //
2: // nono
1.1.1.3 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
1.1.1.8 root 7: //
8: // Pluto-X (独自の仮想ボード)
9: //
10:
1.1 root 11: #include "pluto.h"
1.1.1.2 root 12: #include "mainapp.h"
1.1.1.9 root 13: #include "mainbus.h"
14: #include "mainram.h"
1.1.1.3 root 15: #include "mpu680x0.h"
1.1.1.9 root 16: #include "sram.h"
1.1.1.5 root 17:
1.1.1.8 root 18: // コンストラクタ
1.1 root 19: PlutoDevice::PlutoDevice()
1.1.1.9 root 20: : inherited(OBJ_PLUTO)
1.1 root 21: {
22: }
23:
1.1.1.8 root 24: // デストラクタ
1.1 root 25: PlutoDevice::~PlutoDevice()
26: {
27: }
28:
1.1.1.8 root 29: // リセット
1.1.1.4 root 30: void
1.1.1.8 root 31: PlutoDevice::ResetHard(bool poweron)
1.1.1.4 root 32: {
33: // XXX not yet
34: m_count = 0;
35: }
36:
1.1.1.3 root 37: // ROM
38: /*static*/ const uint16
39: PlutoDevice::rom[] = {
40: // ホストファイル起動
41: 0x00ea, 0xc004, // .dc.l _start ; 起動アドレス
42: //_start:
1.1.1.9 root 43: 0x46fc, 0x2700, // move.w #0x2700,%sr
1.1.1.3 root 44: 0x2039, 0x00ea, 0xc450, // move.l (ROMIO_LOAD),%d0
1.1.1.9 root 45: 0x6b04, // bmi.s _err
46: 0x2040, // move.l %d0,%a0
1.1.1.10! root 47: 0x46fc, 0x2000, // move.w #0x2000,%sr
1.1.1.9 root 48: 0x4e90, // jsr (%a0)
1.1.1.3 root 49: //_err:
50: 0x43fa, 0x000c, // lea.l (_errmsg),%a1
51: 0x7021, 0x4e4f, // IOCS B_PRINT
52: //_loop:
53: 0x4e72, 0x2600, // stop #0x2600
54: 0x60fa, // bra.s _loop
55: //_errmsg:
56: 0x2a2a, 0x2043, 0x616e, // .dc.b "** Can"
57: 0x6e6f, 0x7420, 0x6c6f, // .dc.b "not lo"
58: 0x6164, 0x2068, 0x6f73, // .dc.b "ad hos"
59: 0x7420, 0x6669, 0x6c65, // .dc.b "t file"
60: 0x2e00, // .dc.b ".",0
61: };
62:
63: uint64
64: PlutoDevice::Read8(uint32 addr)
65: {
1.1.1.9 root 66: uint32 offset = addr - baseaddr;
1.1.1.3 root 67: uint32 data;
68:
69: if (offset < sizeof(rom)) {
70: data = rom[offset / 2];
71: if ((offset & 1) == 0) {
72: return data >> 8;
73: } else {
74: return data & 0xff;
75: }
76: }
77:
78: return (uint64)-1;
79: }
80:
81: uint64
82: PlutoDevice::Read16(uint32 addr)
83: {
1.1.1.9 root 84: uint32 offset = addr - baseaddr;
1.1.1.3 root 85:
86: if (offset < sizeof(rom)) {
87: return rom[offset / 2];
88: }
89:
90: return (uint64)-1;
91: }
92:
93: uint64
94: PlutoDevice::Read32(uint32 addr)
95: {
1.1.1.9 root 96: uint32 offset = addr - baseaddr;
1.1.1.3 root 97: uint32 data;
98:
99: if (offset < sizeof(rom)) {
100: data = rom[offset / 2] << 16;
101: data |= rom[(offset / 2) + 1];
102: return data;
103: }
104: switch (offset) {
105: case 0x450: // ROMIO_LOAD
106: return ROM_Load();
107:
108: default:
109: break;
110: }
111: return (uint64)-1;
112: }
113:
114: uint64
115: PlutoDevice::Write8(uint32 addr, uint32 data)
116: {
117: switch (addr) {
118: case 0xeac403:
119: write_8_benchmark(addr, data);
120: break;
121: default:
122: break;
123: }
124: putlog(0, "未実装バイト書き込み $%06x", addr);
125: return 0;
126: }
127:
128: uint64
129: PlutoDevice::Write16(uint32 addr, uint32 data)
130: {
131: putlog(0, "未実装ワード書き込み $%06x", addr);
132: return 0;
133: }
134:
135: uint64
136: PlutoDevice::Peek8(uint32 addr)
137: {
1.1.1.9 root 138: uint32 offset = addr - baseaddr;
1.1.1.3 root 139: uint32 data;
140:
141: if (offset < sizeof(rom)) {
142: data = rom[offset / 2];
143: if ((offset & 1) == 0) {
144: return data >> 8;
145: } else {
146: return data & 0xff;
147: }
148: }
149:
150: return (uint64)-1;
151: }
152:
153: //
154: // ホストファイル起動
155: //
156:
1.1.1.7 root 157: // -X オプションで指定されたホストファイルをロードする。
1.1.1.3 root 158: // ロードできればエントリポイントを返す。
1.1.1.7 root 159: // exec_file が指定されている時に呼ぶこと。
1.1.1.3 root 160: uint32
161: PlutoDevice::ROM_Load()
162: {
1.1.1.7 root 163: assert(gMainApp.exec_file);
1.1.1.3 root 164:
1.1.1.9 root 165: auto mainbus = GetMainbusDevice();
166: auto mainram = GetMainRAMDevice();
167: auto mpu680x0 = GetMPU680x0Device();
168: auto sram = GetSRAMDevice();
169:
1.1.1.3 root 170: // ホストファイルをロード
1.1.1.9 root 171: LoadInfo info(gMainApp.exec_file);
172: if (mainram->LoadFromFile(&info) == false) {
173: return -1;
174: }
175:
176: // NetBSD/x68k のプライマリブートローダが /boot を読み込む時、および
177: // /boot がカーネルを読み込む時には、レジスタ渡しのパラメータがあるので、
178: // ここで用意する。
179: // 本当はターゲットが NetBSD/x68k の /boot とカーネルの時に限定すべきの
180: // ような気もするけど、とりあえず。必要なパラメータは
181: //
182: // %d6 に bootdev、NetBSD/x68k の場合は
183: // bootdev = $MACULPTT
184: // ||||||++- major type
185: // |||||+--- パーティション番号
186: // ||||+---- SCSI なら LUN、それ以外なら 0
187: // |||+----- unit (SCSI なら SCSI ID、FD ならドライブ番号)
188: // ||+------ ctlr (spc0 なら 0 のやつ)
189: // |+------- adaptor (spc = 1、mha = 2)
190: // +-------- magic ($a)
191: // major type は fd=2、MemoryDisk=8、sd=4、(st=5、)、cd=7、ne=255。
192: //
193: // %d7 に howto だが今の所使ってないようだ。
194: //
195: // 一方、/boot がカーネルを読み込む時はこれに加えてスタック渡しの
196: // パラメータもある。これは (取り出す順に)
197: // firstpa.L .. 読み込んだカーネル先頭の物理アドレス?
198: // physsize.L .. RAM 容量 (SRAM の $ed0008.L の値)
199: // esym.L .. シンボルの後ろ、なので実質読み込んだ全体のサイズ
200: //
201: // これも本当はターゲットが NetBSD/x68k のカーネルの時に限定すべきの
202: // ような気もするけど、とりあえず。
203:
204: mpu680x0->reg.D[6] = 0xa1000004;
205: mpu680x0->reg.D[7] = 0;
206:
207: mpu680x0->reg.A[7] = sram->GetRAMSize();
208: mpu680x0->reg.A[7] -= 4;
209: mainbus->Write32(mpu680x0->reg.A[7], info.end - info.start); // esym
1.1.1.3 root 210:
1.1.1.9 root 211: mpu680x0->reg.A[7] -= 4;
212: mainbus->Write32(mpu680x0->reg.A[7], sram->GetRAMSize()); // physsize
213:
214: mpu680x0->reg.A[7] -= 4;
215: mainbus->Write32(mpu680x0->reg.A[7], 0x00000000); // firstpa
1.1.1.3 root 216:
1.1.1.9 root 217: return info.entry;
1.1.1.3 root 218: }
219:
1.1 root 220: // ベンチマーク開始
221: void
222: PlutoDevice::benchmark_start(uint32 data)
223: {
224: m_test_num = data;
225:
226: // テスト番号によってパラメータをセット
227: // #2,#3 は NOP による実行サイクル測定。
228: // #4,#5 は movem によるデータ空間アクセス測定。
229: switch (m_test_num) {
230: case 2:
231: case 3:
232: m_test_name = "NOP";
233: m_inst_len = 2;
234: m_inst_cycle = 2;
235: break;
236: case 4:
237: case 5:
238: m_test_name = "MOVEM";
239: m_inst_len = 8;
240: m_inst_cycle = 244; // XXX 見直すこと
241: break;
242: }
243:
244: // 測定開始時だけ表示
245: if (m_count == 0) {
246: putlog(0, "ベンチマーク開始");
247:
248: // 命令開始アドレス。この時点で REG_PC は次をさしている
1.1.1.9 root 249: m_start_addr = mpu->GetPPC();
1.1 root 250: }
251:
252: // 測定開始
253: gettimeofday(&m_start, NULL);
254: }
255:
256: // ベンチマーク終了
257: void
258: PlutoDevice::benchmark_end()
259: {
260: const int SECONDS = 5; // 測定秒数 [sec]
261: timeval end, result;
262: int t;
263: int num_of_inst; // 1ループ中の命令セット数
264: double speed;
265:
266: // 測定終了
267: gettimeofday(&end, NULL);
268: m_count++;
269:
270: // 今回1セット分の実行時間 [usec]
271: timersub(&end, &m_start, &result);
272:
273: // 総実行時間
274: timeradd(&result, &m_total, &m_total);
275:
276: // 規定秒数に満たなければ、もう1セット繰り返し。
277: // 次が jmp 命令なのでこの命令を抜けるだけでいい。
278: if (m_total.tv_sec < SECONDS) {
279: return;
280: }
281:
282: // 規定秒数に達していれば、測定終了
283: t = m_total.tv_sec * 1000*1000 + m_total.tv_usec;
284: putlog(0, "ベンチマーク#%d 終了 (%d 回, 計 %d.%03d msec)",
1.1.1.2 root 285: gMainApp.benchmark_mode, m_count, t / 1000, t % 1000);
1.1 root 286:
287: // 1ループ中の命令セット数を算出。REG_PPC はこの命令の開始番地
1.1.1.9 root 288: num_of_inst = (mpu->GetPPC() - m_start_addr) / m_inst_len;
1.1 root 289:
290: // 68030 のクロック数 [MHz] に換算
291: speed = (double)(m_count * num_of_inst) * m_inst_cycle / t;
292:
293: // 表示用にベンチマーク ROM のリビジョンを取得
294: int rev;
295: rev = 0;
296: #if 0
297: IPLROM1 *iplrom1 = (IPLROM1 *)vm->SearchDevice(DEVICE_IPLROM1);
298: ASSERT(iplrom1);
299: if (!iplrom1->GetBenchmarkROM(m_test_num, NULL, &rev)) {
300: rev = 0;
301: }
302: #endif
303:
304: // XXX NetBSD ホストでは有効桁2桁と思われる
305: putlog(0, "ベンチマーク#%d.%d (%s 実行速度) 68030/%3.0fMHz, %d MIPS",
306: m_test_num, rev, m_test_name, speed, (m_count * num_of_inst) / t);
307:
308: // 電源オフ
309: // XXX とりあえずね
310: exit(1);
311: }
312:
313: //
314: void
315: PlutoDevice::write_8_benchmark(uint32 addr, uint32 data)
316: {
317: switch (data) {
318: case 0: // ベンチマーク終了
319: benchmark_end();
320: break;
321: case 2: // ベンチマーク開始
322: case 3:
323: case 4:
324: case 5:
325: benchmark_start(data);
326: break;
327: default:
1.1.1.8 root 328: VMPANIC("not impl");
1.1 root 329: }
330: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.