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