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

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

unix.superglobalmegacorp.com

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