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