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