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

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

unix.superglobalmegacorp.com

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