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

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

unix.superglobalmegacorp.com

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