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