Annotation of nono/vm/pluto.cpp, revision 1.1.1.8

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.