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