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

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

unix.superglobalmegacorp.com

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