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

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2022 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
                      7: //
                      8: // NEWS の ROM エミュレーション (-X のみ対応)
                      9: //
                     10: 
1.1.1.3 ! root       11: // IODevice
        !            12: //  |
        !            13: //  +- ROMDevice (LoadROM()、ウェイト、マスク等を持つ)
        !            14: //  |   +- PROMDevice    (LUNA* の PROM)
        !            15: //  |   +- IPLROM1Device (X680x0 の IPLROM 後半)
        !            16: //  |   +- IPLROM2Device (X680x0 の IPLROM 前半)
        !            17: //  |   +- CGROMDevice   (X680x0 の CGROM)
        !            18: //  |   |
        !            19: //  |   +- ROMEmuDevice
        !            20: //  |       +- LunaPROMEmuDevice (LUNA PROM エミュレーションの共通部分)
        !            21: //  |       |   +- Luna1PROMEmuDevice   (LUNA-I の PROM エミュレーション)
        !            22: //  |       |   +- Luna88kPROMEmuDevice (LUNA-88K の PROM エミュレーション)
        !            23: //  |       |
        !            24: //  |       | +------------------+
        !            25: //  |       +-| NewsROMEmuDevice | (NEWS の ROM エミュレーション)
        !            26: //  |       | +------------------+
        !            27: //  |       |
        !            28: //  |       +- ROM30EmuDevice      (X68030 の ROM30 エミュレーション)
        !            29: //  |       +- Virt68kROMEmuDevice (virt-m68k の IPLROM 相当の何か)
        !            30: //  |
        !            31: //  +- PROM0Device   (LUNA* のブートページ切り替え用プロキシ)
        !            32: //  +- IPLROM0Device (X680x0 のブートページ切り替え用プロキシ)
        !            33: 
1.1       root       34: #include "romemu_news.h"
1.1.1.2   root       35: #include "mainbus.h"
1.1       root       36: #include "mainram.h"
                     37: #include "memorystream.h"
                     38: #include "mpu680x0.h"
                     39: #include "newsfb.h"
                     40: 
                     41: // コンストラクタ
                     42: NewsROMEmuDevice::NewsROMEmuDevice()
                     43:        : inherited(OBJ_PROM)
                     44: {
                     45:        // 適当
                     46:        uint devlen = 4096;
                     47:        imagebuf.reset(new uint8 [devlen]);
                     48:        memset(&imagebuf[0], 0, devlen);
                     49:        mem = &imagebuf[0];
                     50: 
                     51:        mask = devlen - 1;
                     52: }
                     53: 
                     54: // デストラクタ
                     55: NewsROMEmuDevice::~NewsROMEmuDevice()
                     56: {
                     57: }
                     58: 
                     59: // 初期化
                     60: bool
                     61: NewsROMEmuDevice::Init()
                     62: {
                     63:        if (inherited::Init() == false) {
                     64:                return false;
                     65:        }
                     66: 
                     67:        mainram = GetMainRAMDevice();
                     68: 
1.1.1.3 ! root       69:        MemoryStreamBE roms(imagebuf.get());
        !            70:        roms.Write4(0x00000400);        // +00: リセットベクタ SP
        !            71:        roms.Write4(0xf8000400);        // +04: リセットベクタ PC
1.1       root       72:        // ベクタ
                     73:        for (int i = 2; i < 256; i++) {
1.1.1.3 ! root       74:                roms.Write4(0);
1.1       root       75:        }
1.1.1.3 ! root       76:        roms.SetOffset(32 * 4);
        !            77:        roms.Write4(0xf8000500);        // Trap#0 で ROM のサービスコール
1.1.1.2   root       78:        // Trap#15 は ROM モニタらしい。今の所停止するだけ。
                     79:        // とりあえず Trap#1..#14 も全部ここへ向けておく。
                     80:        for (int i = 1; i < 16; i++) {
1.1.1.3 ! root       81:                roms.Write4(0xf8000600);
1.1.1.2   root       82:        }
1.1       root       83: 
                     84:        // リセット時に実行する命令
1.1.1.3 ! root       85:        roms.SetOffset(0x400);
        !            86:        roms.Write2(0x2039);            //      move.l  (ROMIO_INIT),d0
        !            87:        roms.Write4(ROMIO_INIT);
        !            88:        roms.Write2(0x2040);            //      move.l  d0,a0   ; ジャンプ先を a0 にセット
        !            89:        roms.Write2(0x4ed0);            //      jmp             (a0)    ; ジャンプ
1.1       root       90: 
                     91:        // ROM サービスコール
1.1.1.3 ! root       92:        roms.SetOffset(0x500);
        !            93:        roms.Write2(0x0c80);            //      cmpi.l  #3,d0
        !            94:        roms.Write4(0x00000003);        //
        !            95:        roms.Write2(0x6708);            //      beq             @f
        !            96:        roms.Write2(0x2039);            //      move.l  (ROMIO_SYS),d0
        !            97:        roms.Write4(ROMIO_SYS);         //
        !            98:        roms.Write2(0x4e73);            //      rte
1.1       root       99:                                                                //@@:                           ; Read は対応してないので
1.1.1.3 ! root      100:        roms.Write4(0x4e722500);        //      stop    #0x2500 ; STOP しつつ
        !           101:        roms.Write2(0x60fa);            //      bra             @b              ; 無限ループ。
        !           102:        roms.Write2(0x4e73);            //      rte
1.1       root      103: 
1.1.1.2   root      104:        // ROM モニタの TRAP#n。はないのでここに来たらとりあえず停止する?
1.1.1.3 ! root      105:        roms.SetOffset(0x600);
1.1.1.2   root      106:                                                                //@@:
1.1.1.3 ! root      107:        roms.Write4(0x4e722700);        //      stop    #0x2700 ; STOP しつつ
        !           108:        roms.Write2(0x60fa);            //      bra             @b              ; 無限ループ。
1.1.1.2   root      109: 
1.1       root      110:        return true;
                    111: }
                    112: 
                    113: void
                    114: NewsROMEmuDevice::ResetHard(bool poweron)
                    115: {
                    116:        // 起動時に RAM にリセットベクタを書き込んでおく。(手抜き)
1.1.1.3 ! root      117:        mainram->WriteMem(0, &imagebuf[0], 8);
1.1       root      118: }
                    119: 
1.1.1.3 ! root      120: // ROMIO から読み出す。
        !           121: // ROMIO が応答すべきでなければ (uint64)-1 を返す。
        !           122: uint64
        !           123: NewsROMEmuDevice::ReadROMIO(busaddr addr)
1.1       root      124: {
1.1.1.3 ! root      125:        if (addr.GetSize() == 4) {
        !           126:                switch (addr.Addr()) {
        !           127:                 case ROMIO_INIT:
        !           128:                        return ROM_Init();
1.1       root      129: 
1.1.1.3 ! root      130:                 case ROMIO_SYS:
        !           131:                        return ROM_Sys();
1.1       root      132: 
1.1.1.3 ! root      133:                 default:
        !           134:                        break;
        !           135:                }
1.1       root      136:        }
                    137: 
1.1.1.3 ! root      138:        return (uint64)-1;
1.1       root      139: }
                    140: 
                    141: uint32
                    142: NewsROMEmuDevice::ROM_Init()
                    143: {
1.1.1.2   root      144:        // -X file で指定されたホストファイルを読み込んでエントリポイント
                    145:        // アドレスをこの Read アクセスの読み出し値として返す。
1.1       root      146: 
1.1.1.2   root      147:        LoadInfo info(gMainApp.exec_file);
                    148:        if (mainram->LoadExec(&info) == false) {
                    149:                // XXX どうすべ
                    150:                PANIC("** Couldn't load specified host program");
                    151:                return -1;
1.1       root      152:        }
1.1.1.2   root      153:        putmsg(1, "Host program loaded.  Entry point = $%08x", info.entry);
1.1       root      154: 
                    155:        // ROMCONS のために VBR を設定
1.1.1.2   root      156:        m68kreg& reg = GetMPU680x0Device(mpu)->reg;
1.1       root      157:        reg.vbr = 0xf8000000;
                    158: 
                    159:        // %d2 には MARK_END (たぶん最後の番地)
                    160:        // %d4 にメモリサイズ。
                    161:        // %d5 には読み込んだファイル名の先頭番地?
                    162:        // %d6 に bootdev、NetBSD/news68k の場合は
                    163:        // bootdev = $MCxUHPTT
                    164:        //            || |||++ Type? (SD=0)
                    165:        //            || ||+-- Partition?
                    166:        //            || |+--- Host: 機種? (NEWS1700 は 0)
                    167:        //            || +---- Unit?
                    168:        //            |+------ Controller?
                    169:        //            +------- magic ($5)
                    170:        // 下位28ビット(7桁) は ROM から渡されるようだ。
                    171:        // %d7 は boothowto。
                    172:        reg.D[2] = info.sym;
                    173:        reg.D[4] = mainram->GetSize();
                    174:        reg.D[6] = 0x50000000;
                    175:        reg.D[7] = 0;
                    176: 
                    177:        return info.entry;
                    178: }
                    179: 
                    180: uint32
                    181: NewsROMEmuDevice::ROM_Sys()
                    182: {
1.1.1.2   root      183:        auto mainbus = GetMainbusDevice();
                    184:        auto mpu680x0 = GetMPU680x0Device(mpu);
1.1       root      185:        m68kreg& reg = mpu680x0->reg;
                    186:        auto newsfb = GetNewsfbDevice();
                    187: 
                    188:        if (reg.D[0] == SYS_write) {
                    189:                uint32 a6 = reg.A[6];
1.1.1.3 ! root      190:                uint32 fd  = mainbus->HVRead4(a6 + 8);
        !           191:                uint32 buf = mainbus->HVRead4(a6 + 12);
        !           192:                uint32 len = mainbus->HVRead4(a6 + 16);
1.1       root      193: 
                    194:                for (int i = 0; i < len; i++) {
1.1.1.3 ! root      195:                        busdata bd = mainbus->HVRead1(buf++);
1.1.1.2   root      196:                        if (bd.IsBusErr()) {
1.1       root      197:                                // XXX ?
                    198:                                return 0;
                    199:                        }
1.1.1.2   root      200:                        uint8 ch = bd.Data();
1.1       root      201:                        if (ch == '\r') {
                    202:                                continue;
                    203:                        }
                    204:                        newsfb->Putc(ch);
                    205:                }
                    206:                (void)fd;
                    207:                return len;
                    208:        }
                    209: 
                    210:        VMPANIC("Unknown service call $%02x", reg.D[0]);
                    211:        return 0;
                    212: }

unix.superglobalmegacorp.com

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