Annotation of nono/vm/romemu_luna88k.cpp, revision 1.1.1.5

1.1       root        1: //
                      2: // nono
1.1.1.2   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
1.1.1.2   root        7: // LUNA88K の ROM エミュレーション
                      8: 
                      9: //             IODevice
                     10: //                |
1.1.1.5 ! root       11: //     +----------+---------------------+
        !            12: //     v                                v
        !            13: // ROMDevice                 LunaPROMEmuDeivce (ROM エミュレーションの共通部分)
        !            14: //     |                                |
        !            15: //     |                   +------------+----------------+
        !            16: //     v                   v                             v
        !            17: // PROMDevice      Luna1PROMEmuDevice          Luna88kPROMEmuDevice
        !            18: // (実ROM)         (LUNA-I エミュレーション)   (LUNA88K エミュレーション)
1.1.1.2   root       19: 
                     20: #include "romemu_luna88k.h"
1.1.1.5 ! root       21: #include "bitmap.h"
        !            22: #include "iodevstream.h"
1.1       root       23: #include "mainapp.h"
                     24: #include "memorystream.h"
1.1.1.5 ! root       25: #include "pio.h"
1.1       root       26: #include "ram.h"
1.1.1.5 ! root       27: #include "sysctlr.h"
1.1       root       28: 
                     29: // コンストラクタ
                     30: Luna88kPROMEmuDevice::Luna88kPROMEmuDevice()
                     31: {
                     32:        devaddr = baseaddr;
1.1.1.5 ! root       33: 
        !            34:        // ROM の特定アドレスを読み出す人がいるかも知れないので、
        !            35:        // サイズは実 ROM と同じにしておく。LUNA-I からの類推。
1.1.1.2   root       36:        devlen = 256 * 1024;
1.1.1.5 ! root       37:        romdata.reset(new uint8 [devlen]);
1.1.1.2   root       38: 
1.1.1.5 ! root       39:        // プロンプトを初期化。
        !            40:        // 本物は "O>" というプロンプトでよく分からんけど、こっちは nono の
        !            41:        // 頭文字ということにしておく。
        !            42:        prompt = "N>";
1.1       root       43: }
                     44: 
                     45: // デストラクタ
                     46: Luna88kPROMEmuDevice::~Luna88kPROMEmuDevice()
                     47: {
                     48: }
                     49: 
                     50: bool
                     51: Luna88kPROMEmuDevice::Init()
                     52: {
1.1.1.5 ! root       53:        // 親クラス
        !            54:        if (inherited::Init() == false) {
        !            55:                return false;
        !            56:        }
        !            57: 
1.1.1.2   root       58:        MemoryStreamBE ms(romdata.get());
1.1       root       59: 
1.1.1.5 ! root       60:        // MPU を仕様通りに動作させるなら、リセット時に ROM を 0番地付近に見せて
        !            61:        // 実行中に RAM に切り替えるのが定番だが、nono ではそれは意図して実装して
        !            62:        // いない。従って xip = $41000000 から実行開始するのに対して vbr の初期値
        !            63:        // は 0 なので、ROM の $41000008 以降をベクタ用にリザーブする必要がない。
        !            64:        // よって $41000000 から直接コードを置いていく。
        !            65: 
        !            66:                                                                        //      ; 元の PSR を r10 に保存しつつ
        !            67:                                                                        //      ; 割り込み許可
        !            68:        ms.Write32(0x81404020);                 //      ldcr    r10, psr
        !            69:        ms.Write32(0xf04a8040);                 //      clr             r2, r10, 2<1>   ; IND,SFRZ
        !            70:        ms.Write32(0x80028022);                 //      stcr    r2, psr
        !            71:                                                                        //      ; r3 <- ROMIO_BASE
        !            72:        ms.Write32(0x5c600000 |                 //      or.u    r3, r0, #ROMIO_BASE.Hi
        !            73:                (ROMIO_BASE >> 16));            //
        !            74:        ms.Write32(0x58630000 |                 //      or              r3, r0, #ROMIO_BASE.Lo
        !            75:                (ROMIO_BASE & 0xffff));         //
        !            76:                                                                        //      ; ROMIO_INIT を読み出す
        !            77:        ms.Write32(0x14430000);                 //      ld              r2, r3, #+INIT
        !            78:                                                                        //      ; 起動先があれば GO
        !            79:        ms.Write32(0xe9a20005);                 //      bcnd    ne0, r2, _go
        !            80:                                                                        // _prompt:
        !            81:                                                                        //      ; 疑似 STOP でキー入力を待つ
        !            82:        ms.Write32(0xc8000001);                 //      bsr             _stop
        !            83:                                                                        //      ; この時点で r1 = _stop
        !            84:                                                                        // _stop:
        !            85:        ms.Write32(0xf400c001);                 //      jmp             r1
        !            86:                                                                        // _back:
        !            87:        ms.Write32(0x14430000 |                 //      ld              r2, r3, #+ENTRY
        !            88:                (ROMIO_ENTRY - ROMIO_BASE));//
        !            89:                                                                        //      ; 起動先がなければループ
        !            90:        ms.Write32(0xe842fffd);                 //      bcnd    eq0, r2, _prompt
        !            91:                                                                        //      ; 起動先があれば後始末して
        !            92:        ms.Write32(0x14030000 |                 // _go:
        !            93:                (ROMIO_CLOSE - ROMIO_BASE));//  ld              r0, r3, #+CLOSE
        !            94:                                                                        //      ; 割り込み禁止に戻す
        !            95:        ms.Write32(0x800a802a);                 //      stcr    r10, psr
        !            96:                                                                        //      ; ジャンプ
        !            97:        ms.Write32(0xf400c002);                 //      jmp             r2
        !            98: 
        !            99:        // ここから割り込みハンドラ。割り込みは SIO のみ許可にしてある。
        !           100:        // キーボード割り込みが上がったら KEYIN をコールして _back に戻る。
        !           101:        ms.SetPtr(&romdata[0x200]);
        !           102:        ms.Write32(0x14030000 |                 //      ld              r0, r3, #+KEYIN
        !           103:                (ROMIO_KEYIN - ROMIO_BASE));//
        !           104:                                                                        //      ; 戻ったところの jmp を抜ける
        !           105:        ms.Write32(0x60210004);                 //      addu    r1, r1, #4
        !           106:        ms.Write32(0xf400fc00);                 //      rte
1.1       root      107: 
                    108:        return true;
                    109: }
                    110: 
1.1.1.5 ! root      111: // 起動時の処理を行う。
        !           112: // 次段実行ファイルの読み込みに成功すればそのエントリポイントを返す。
        !           113: // そうでなければ 0 を返すので、プロンプトに処理を移すこと。
        !           114: uint32
        !           115: Luna88kPROMEmuDevice::ROM_Init()
1.1       root      116: {
1.1.1.5 ! root      117:        IODeviceStream rs(gRAM.get());
        !           118:        uint32 entry;
1.1       root      119: 
1.1.1.5 ! root      120:        // デバイスの初期化 (親クラス)
        !           121:        InitDevice();
        !           122:        // 割り込みマスクで SIO だけ許可
        !           123:        gInterrupt->Write32(0x65000000, 0x40000000);
1.1       root      124: 
1.1.1.5 ! root      125:        rs.SetAddr(0);
        !           126:        // ベクタテーブルを rte で埋めておく
        !           127:        for (int i = 0; i < 512 * 2; i++) {
        !           128:                rs.Write32(0xf400fc00 /* rte */);
        !           129:        }
        !           130:        // +$08: 割り込みベクタ
        !           131:        rs.Write32(8, 0xc00003fe);              // br   $00001000
        !           132: 
        !           133:        // 割り込みトランポリン (0x1000)
        !           134:        // ベクタテーブルは各2ワードしかないのに、0 番地付近にあるベクタテーブル
        !           135:        // から2ワードでは ROM まで飛べない。一体どういう設計してんだ…。
        !           136:        rs.SetAddr(0x1000);
        !           137:        rs.Write32(0x5cc04100);                 // or.u r6, r0, #0x4100
        !           138:        rs.Write32(0x58c60200);                 // or   r6, r6, #0x0200
        !           139:        rs.Write32(0xf400c006);                 // jmp  r6
1.1.1.2   root      140: 
1.1.1.5 ! root      141:        // ROM の機能テーブル
        !           142:        // 0x00001100 からあるようだ
        !           143:        // 0x0000110c GETC()
        !           144:        // 0x00001110 PUTC(c)
        !           145:        // 0x00001114 ビットマッププレーンの有効状態が入っている。
        !           146:        //  bit0: plane0 有効
        !           147:        //  bit1..7: plane1..7 有効
        !           148:        rs.SetAddr(0x110c);
        !           149:        rs.Write32(0x00001300);
        !           150:        rs.Write32(0x00001400);
        !           151:        rs.Write32(0x00000001);
        !           152: 
        !           153:        // ROM GETC エミュレータ
        !           154:        rs.SetAddr(0x1300);
        !           155:        rs.Write32(0xfc000c00);                 // internal inst getc
        !           156:        rs.Write32(0xf400c001);                 // jmp r1
1.1.1.2   root      157: 
1.1.1.5 ! root      158:        // ROM PUTC エミュレータ
        !           159:        rs.SetAddr(0x1400);
        !           160:        rs.Write32(0xfc001000);                 // internal inst putc
        !           161:        rs.Write32(0xf400c001);                 // jmp r1
        !           162: 
        !           163:        // スクリーンを初期化
        !           164:        InitScreen("LUNA88K");
        !           165: 
        !           166:        entry = 0;
        !           167: 
        !           168:        // 表示環境が整ったところで NVRAM を照合
        !           169:        if (VerifyNVRAM() == false) {
        !           170:                InitNVRAM();
        !           171:                text.Print("** NVRAM Initialized.\n");
        !           172:                text.Print("\n");
        !           173:                // NVRAM をクリアしたら DIPSW によらずプロンプトに降りる
        !           174:                goto done;
        !           175:        }
        !           176: 
        !           177:        // DIPSW#1-1 が UP なら自動起動、DOWN なら ROM モニタ起動なので、
        !           178:        // これを真似する。
        !           179:        if ((gPIO0->GetDIPSW1() & 1)) {
        !           180:                if (gMainApp.host_file) {
        !           181:                        // ホストのファイルを読み込んでエントリポイントアドレスを
        !           182:                        // この Read アクセスの読み出し値として返す。
        !           183:                        // エラーがあればエラーメッセージは呼び出し先側で表示してある。
        !           184:                        entry = LoadHostFile();
        !           185:                } else {
        !           186:                        // NVRAM の設定に従ってブート先を探す。
        !           187:                        errmsg.clear();
        !           188: 
        !           189:                        bootinfo_t bootinfo;
        !           190:                        GetNVRAM(bootinfo);
        !           191:                        entry = LoadGuestFile(bootinfo);
        !           192:                        if (entry == 0) {
        !           193:                                text.Print("** %s\n", errmsg.c_str());
        !           194:                        }
        !           195:                }
        !           196:        }
        !           197: 
        !           198:        // ここまでタイトルなどを Print してはいるが、実際の画面更新は
        !           199:        // ConsoleUpdate() を呼ぶまで行われないことを利用(悪用?)して、
        !           200:        // ここでエラーなくブートプログラムに制御を渡せる場合には何も表示せずに
        !           201:        // ゲストに処理を移す。意図して或いは意図せずプロンプトに降りる場合だけ
        !           202:        // ConsoleUpdate を呼ぶことでタイトルを含めて画面を表示する。
        !           203:  done:
        !           204:        if (entry == 0) {
        !           205:                ConsoleUpdate();
        !           206:        }
        !           207: 
        !           208:        return entry;
        !           209: }
        !           210: 
        !           211: // ROM 処理。エントリポイントを返す。
        !           212: uint32
        !           213: Luna88kPROMEmuDevice::ROM_Entry()
        !           214: {
        !           215:        if (b_entrypoint != 0) {
        !           216:                return b_entrypoint;
1.1.1.2   root      217:        } else {
1.1.1.5 ! root      218:                return 0;
1.1.1.2   root      219:        }
                    220: }
                    221: 
1.1.1.5 ! root      222: // 入力コマンド処理 (入力行が揃ったところで呼ばれる)。
        !           223: //
        !           224: // b                                   現在のパラメータで起動
        !           225: // b ...                               パラメータを指定して起動
        !           226: // nvram                               全パラメータを表示
        !           227: // nvram [<name>]              name のみ表示?
        !           228: // nvram <name> <val>  値を設定
        !           229: // nvram - <name>              削除
        !           230: // nvram--                             NVRAM 初期化
        !           231: 
        !           232: void
        !           233: Luna88kPROMEmuDevice::Command()
1.1.1.2   root      234: {
1.1.1.5 ! root      235:        std::vector<char> buf(inputbuf.length() + 1);
        !           236:        std::vector<std::string> arg;
1.1.1.2   root      237: 
1.1.1.5 ! root      238:        // 1ワードごとに分解
        !           239:        strcpy(&buf[0], inputbuf.c_str());
        !           240:        char *p = &buf[0];
        !           241:        char *s = p;
        !           242:        while (*p != '\0') {
        !           243:                if (*p == ' ') {
        !           244:                        *p++ = '\0';
        !           245:                        arg.push_back(std::string(s));
        !           246:                        s = p;
        !           247:                } else {
        !           248:                        p++;
        !           249:                }
        !           250:        }
        !           251:        if (p != s) {
        !           252:                arg.push_back(std::string(s));
        !           253:        }
        !           254:        if (loglevel >= 1) {
        !           255:                for (int i = 0; i < arg.size(); i++) {
        !           256:                        putmsgn("arg[%d]=|%s|", i, arg[i].c_str());
        !           257:                }
        !           258:        }
1.1.1.2   root      259: 
1.1.1.5 ! root      260:        // 空行
        !           261:        if (arg.size() == 0) {
        !           262:                return;
        !           263:        }
        !           264: 
        !           265:        // 1ワード目がコマンド
        !           266:        if (arg[0] == "h") {
        !           267:                // ヘルプメッセージ
        !           268:                text.Print(
        !           269: "         *** Help Message ***\n"
        !           270: "  b      : load and execute program\n"
        !           271: "  h      : show this message\n"
        !           272: #if 0
        !           273: "  nvram  : show/set nvram parameters\n"
        !           274: #endif
        !           275:                );
        !           276:                return;
        !           277:        }
        !           278:        if (arg[0] == "b") {
        !           279:                CommandB(arg);
        !           280:                return;
        !           281:        }
        !           282: #if 0
        !           283:        if (arg[0] == "nvram") {
        !           284:                CommandNvram(arg);
        !           285:                return;
1.1.1.2   root      286:        }
1.1.1.5 ! root      287: #endif
        !           288: 
        !           289:        text.Print("** Unknown command: %s\n", arg[0].c_str());
1.1.1.2   root      290: }
                    291: 
1.1.1.5 ! root      292: // "b" コマンド
        !           293: // 引数なしなら NVRAM の情報に従ってプログラムをロードして実行。
        !           294: // 引数ありのほうは未実装。
        !           295: void
        !           296: Luna88kPROMEmuDevice::CommandB(const std::vector<std::string>& arg)
1.1       root      297: {
1.1.1.5 ! root      298:        errmsg.clear();
1.1       root      299: 
1.1.1.5 ! root      300:        // XXX とりあえず boot を起動するだけ
        !           301:        bootinfo_t bootinfo;
        !           302:        GetNVRAM(bootinfo);
        !           303:        b_entrypoint = LoadGuestFile(bootinfo);
        !           304:        if (b_entrypoint == 0) {
        !           305:                text.Print("** %s\n", errmsg.c_str());
1.1       root      306:        }
1.1.1.5 ! root      307: }
1.1       root      308: 
1.1.1.5 ! root      309: // "bh" コマンド (勝手に拡張)
        !           310: // -A オプションで指定されたホストプログラムをロードして実行。
        !           311: void
        !           312: Luna88kPROMEmuDevice::CommandBH()
        !           313: {
        !           314:        // 指定されてたら読み込む
        !           315:        if (gMainApp.host_file == NULL) {
        !           316:                text.Print("** Cannot loaded; host program is not specified.\n");
        !           317:                return;
1.1.1.2   root      318:        }
1.1.1.5 ! root      319:        b_entrypoint = LoadHostFile();
1.1.1.2   root      320: }
                    321: 
1.1.1.5 ! root      322: void
        !           323: Luna88kPROMEmuDevice::CommandNvram(const std::vector<std::string>& arg)
1.1.1.2   root      324: {
1.1.1.5 ! root      325:        printf("%s\n", __func__);
1.1.1.2   root      326: }
                    327: 
1.1.1.5 ! root      328: // NVRAM のチェックサムを返す
        !           329: uint8
        !           330: Luna88kPROMEmuDevice::CalcNVRAMCsum()
1.1.1.2   root      331: {
                    332:        return 0;
                    333: }
                    334: 
1.1.1.5 ! root      335: // NVRAM のチェックサムを計算して書き込む
        !           336: void
        !           337: Luna88kPROMEmuDevice::WriteNVRAMCsum()
1.1.1.2   root      338: {
                    339: }
                    340: 
1.1.1.5 ! root      341: // NVRAM のマジックとチェックサムを照合する
        !           342: bool
        !           343: Luna88kPROMEmuDevice::VerifyNVRAM()
1.1.1.2   root      344: {
1.1.1.5 ! root      345:        return true;
1.1       root      346: }
                    347: 
1.1.1.5 ! root      348: // NVRAM を初期化する
        !           349: bool
        !           350: Luna88kPROMEmuDevice::InitNVRAM()
1.1       root      351: {
1.1.1.5 ! root      352:        return false;
        !           353: }
1.1       root      354: 
1.1.1.5 ! root      355: // NVRAM のブート設定を bootinfo に取得する。
        !           356: void
        !           357: Luna88kPROMEmuDevice::GetNVRAM(bootinfo_t& bootinfo)
        !           358: {
        !           359:        // XXX NVRAM 未調査につき ID=6 a: boot 固定
        !           360:        bootinfo.dkunit = 0;
        !           361:        bootinfo.dkpart = 0;
        !           362:        bootinfo.dkfile = "boot";
1.1       root      363: }

unix.superglobalmegacorp.com

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