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

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

unix.superglobalmegacorp.com

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