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

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

unix.superglobalmegacorp.com

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