Annotation of nono/vm/human_mi.h, revision 1.1

1.1     ! root        1: //
        !             2: // nono
        !             3: // Copyright (C) 2021 nono project
        !             4: // Licensed under nono-license.txt
        !             5: //
        !             6: 
        !             7: #pragma once
        !             8: 
        !             9: #include "device.h"
        !            10: #include "mpu.h"
        !            11: #include <array>
        !            12: 
        !            13: class m68kcpu;
        !            14: class m88kcpu;
        !            15: 
        !            16: // 謎の機種非依存 Human68k(?) システムコール
        !            17: class HumanMI : public Object
        !            18: {
        !            19:        using inherited = Object;
        !            20:  protected:
        !            21:        // DOS コールの引数について
        !            22:        //
        !            23:        // m68k では引数はスタックに積まれる (本来の仕様のまま)。
        !            24:        // m88k では、m88k のサブルーチン呼び出し規約を真似てレジスタに置くことに
        !            25:        // する。ただしその際のレジスタは本来 r2..r9 固定だが、ここでは rS1 で
        !            26:        // その先頭レジスタを指定できることにする。
        !            27:        // どちらも Pop16()、Pop32() を使って引数を前から順番に取り出すことで
        !            28:        // その差を吸収する。
        !            29:        //
        !            30:        // 例えば DOS _OPEN は第1引数が 32bit ポインタ、第1引数が 16bit の mode
        !            31:        // なので、m68k では以下のようにコールする。
        !            32:        //
        !            33:        //              move.w  #MODE,-(sp)
        !            34:        //              pea             nameptr
        !            35:        //              DOS             _OPEN
        !            36:        //              addq.l  #6,sp
        !            37:        //
        !            38:        // m88k からこの DOS コールを呼ぶ際は、例えば引数を r4 以降に置き、
        !            39:        // 戻り値を r2 で受け取りたい場合は以下のようになる。
        !            40:        //
        !            41:        //              or.u    r4, r0, #(nameptr).Hi
        !            42:        //              or              r4, r4, #(nameptr).Lo
        !            43:        //              or              r5, r0, #mode
        !            44:        //              doscall r2, r4, #_OPEN
        !            45:        //
        !            46:        // どちらの場合でも HumanMI は
        !            47:        //
        !            48:        //              ptr  = Pop32();
        !            49:        //              mode = Pop16();
        !            50:        //
        !            51:        // として引数を取り出す。
        !            52: 
        !            53:        virtual uint64 Pop16() = 0;
        !            54:        virtual uint64 Pop32() = 0;
        !            55: 
        !            56:        // レジスタにアクセスする。
        !            57:        // レジスタ番号 rn は 機種依存。
        !            58:        virtual uint32 ReadReg(int rn) = 0;
        !            59:        virtual void WriteReg(int rn, uint32 data) = 0;
        !            60: 
        !            61:        // 結果をセットする。
        !            62:        // m68k の場合は d0.l に格納される。
        !            63:        // m88k の場合は rD に格納される。
        !            64:        virtual void Result(uint32 data) = 0;
        !            65: 
        !            66:  public:
        !            67:        HumanMI();
        !            68:        virtual ~HumanMI();
        !            69: 
        !            70:        virtual bool Init() = 0;
        !            71: 
        !            72:        // CPU からのシステムコール呼び出しを受け取る口。
        !            73:        // コール番号を解釈して引数リストを作る。
        !            74:        virtual bool SysCallEntry() = 0;
        !            75: 
        !            76:        // バスアクセス
        !            77:        uint64 Read8(uint32 addr) const { return gMPU->Read8(addr); }
        !            78:        uint64 Read16(uint32 addr) const { return gMPU->Read16(addr); }
        !            79:        uint64 Read32(uint32 addr) const { return gMPU->Read32(addr); }
        !            80:        uint64 Write8(uint32 addr, uint32 data) const {
        !            81:                return gMPU->Write8(addr, data); }
        !            82:        uint64 Write16(uint32 addr, uint32 data) const {
        !            83:                return gMPU->Write16(addr, data); }
        !            84:        uint64 Write32(uint32 addr, uint32 data) const {
        !            85:                return gMPU->Write32(addr, data); }
        !            86: 
        !            87: 
        !            88:        // システムコール
        !            89:        // システムコールは HumanMIFunc で、未実装など、エミュレートできないとき
        !            90:        // false を返す。
        !            91:        // システムコール自体のゲスト的なエラーは Result() 経由でゲストに
        !            92:        // 伝えられる。
        !            93: 
        !            94:        using HumanMIFunc = bool (HumanMI::*)(void);
        !            95:        std::array<HumanMIFunc, 256> scTable {};
        !            96: 
        !            97:        bool DOS_EXIT();
        !            98:        bool DOS_GETCHAR();
        !            99:        bool DOS_PUTCHAR();
        !           100:        bool DOS_COMINP() { return false; }
        !           101:        bool DOS_COMOUT() { return false; }
        !           102:        bool DOS_PRNOUT() { return false; }
        !           103:        bool DOS_INPOUT() { return false; }
        !           104:        bool DOS_INKEY() { return false; }
        !           105:        bool DOS_GETC() { return false; }
        !           106:        bool DOS_PRINT();
        !           107:        bool DOS_GETS() { return false; }
        !           108:        bool DOS_KEYSNS() { return false; }
        !           109:        bool DOS_KFLUSH() { return false; }
        !           110:        bool DOS_FFLUSH() { return false; }
        !           111:        bool DOS_CHGDRV() { return false; }
        !           112:        bool DOS_DRVCTRL() { return false; }
        !           113: 
        !           114:        bool DOS_CONSNS() { return false; }
        !           115:        bool DOS_PRNSNS() { return false; }
        !           116:        bool DOS_CINSNS() { return false; }
        !           117:        bool DOS_COUTSNS() { return false; }
        !           118:        bool DOS_FATCHK() { return false; }
        !           119:        bool DOS_HENDSP() { return false; }
        !           120:        bool DOS_CURDRV() { return false; }
        !           121:        bool DOS_GETSS() { return false; }
        !           122:        bool DOS_FGETC() { return false; }
        !           123:        bool DOS_FGETS() { return false; }
        !           124:        bool DOS_FPUTC() { return false; }
        !           125:        bool DOS_FPUTS() { return false; }
        !           126:        bool DOS_ALLCLOSE() { return false; }
        !           127: 
        !           128:        bool DOS_SUPER() { return false; }
        !           129:        bool DOS_FNCKEY() { return false; }
        !           130:        bool DOS_KNJCTRL() { return false; }
        !           131:        bool DOS_CONCTRL() { return false; }
        !           132:        bool DOS_KEYCTRL() { return false; }
        !           133:        bool DOS_INTVCS() { return false; }
        !           134:        bool DOS_PSPSET() { return false; }
        !           135:        bool DOS_GETTIM2() { return false; }
        !           136:        bool DOS_SETTIM2() { return false; }
        !           137:        bool DOS_NAMESTS() { return false; }
        !           138:        bool DOS_GETDATE() { return false; }
        !           139:        bool DOS_SETDATE() { return false; }
        !           140:        bool DOS_GETTIME() { return false; }
        !           141:        bool DOS_SETTIME() { return false; }
        !           142:        bool DOS_VERIFY() { return false; }
        !           143:        bool DOS_DUP0() { return false; }
        !           144: 
        !           145:        bool DOS_VERNUM() { return false; }
        !           146:        bool DOS_KEEPPR() { return false; }
        !           147:        bool DOS_GETDPB() { return false; }
        !           148:        bool DOS_BREAKCK() { return false; }
        !           149:        bool DOS_DRVXCHG() { return false; }
        !           150:        bool DOS_INTVCG() { return false; }
        !           151:        bool DOS_DSKFRE() { return false; }
        !           152:        bool DOS_NAMECK() { return false; }
        !           153:        bool DOS_MKDIR() { return false; }
        !           154:        bool DOS_RMDIR() { return false; }
        !           155:        bool DOS_CHDIR() { return false; }
        !           156:        bool DOS_CREATE() { return false; }
        !           157:        bool DOS_OPEN() { return false; }
        !           158:        bool DOS_CLOSE() { return false; }
        !           159:        bool DOS_READ() { return false; }
        !           160: 
        !           161:        bool DOS_WRITE();
        !           162:        bool DOS_DELETE() { return false; }
        !           163:        bool DOS_SEEK() { return false; }
        !           164:        bool DOS_CHMOD() { return false; }
        !           165:        bool DOS_IOCTRL() { return false; }
        !           166:        bool DOS_DUP() { return false; }
        !           167:        bool DOS_DUP2() { return false; }
        !           168:        bool DOS_CURDIR() { return false; }
        !           169:        bool DOS_MALLOC() { return false; }
        !           170:        bool DOS_MFREE() { return false; }
        !           171:        bool DOS_SETBLOCK();
        !           172:        bool DOS_EXEC() { return false; }
        !           173:        bool DOS_EXIT2();
        !           174:        bool DOS_WAIT() { return false; }
        !           175:        bool DOS_FILES() { return false; }
        !           176:        bool DOS_NFILES() { return false; }
        !           177: 
        !           178:        bool DOS_SETPDB() { return false; }
        !           179:        bool DOS_GETPDB() { return false; }
        !           180:        bool DOS_SETENV() { return false; }
        !           181:        bool DOS_GETENV() { return false; }
        !           182:        bool DOS_VERIFYG() { return false; }
        !           183:        bool DOS_COMMON() { return false; }
        !           184:        bool DOS_RENAME() { return false; }
        !           185:        bool DOS_FILEDATE() { return false; }
        !           186:        bool DOS_MALLOC2() { return false; }
        !           187:        bool DOS_MAKETMP() { return false; }
        !           188:        bool DOS_NEWFILE() { return false; }
        !           189:        bool DOS_LOCK() { return false; }
        !           190:        bool DOS_ASSIGN() { return false; }
        !           191: 
        !           192:        bool DOS_FFLUSH_SET() { return false; }
        !           193:        bool DOS_OS_PATCH() { return false; }
        !           194:        bool DOS_GETFCB() { return false; }
        !           195:        bool DOS_S_MALLOC() { return false; }
        !           196:        bool DOS_S_MFREE() { return false; }
        !           197:        bool DOS_S_PROCESS() { return false; }
        !           198: 
        !           199:        bool DOS_EXITVC() { return false; }
        !           200:        bool DOS_CTRLVC() { return false; }
        !           201:        bool DOS_ERRJVC() { return false; }
        !           202:        bool DOS_DISKRED() { return false; }
        !           203:        bool DOS_DISKWRT() { return false; }
        !           204:        bool DOS_INDOSFLG() { return false; }
        !           205:        bool DOS_SUPER_JSR() { return false; }
        !           206:        bool DOS_BUS_ERR() { return false; }
        !           207:        bool DOS_OPEN_PR() { return false; }
        !           208:        bool DOS_KILL_PR() { return false; }
        !           209:        bool DOS_GET_PR() { return false; }
        !           210:        bool DOS_SUSPEND_PR() { return false; }
        !           211:        bool DOS_SLEEP_PR() { return false; }
        !           212:        bool DOS_SEND_PR() { return false; }
        !           213:        bool DOS_TIME_PR() { return false; }
        !           214:        bool DOS_CHANGE_PR() { return false; }
        !           215: 
        !           216:        // エラーコード
        !           217:        struct Ecode {
        !           218:                int code;
        !           219:                std::string msg;
        !           220:        };
        !           221: 
        !           222:        const Ecode E_OK                        {   0, "" };
        !           223:        const Ecode E_INVALID_SC        {  -1, "Invalid system call" };
        !           224:        const Ecode E_FILE_NOTFOUND     {  -2, "File not found" };
        !           225:        const Ecode E_DIR_NOTFOUND      {  -3, "Directory not found" };
        !           226:        const Ecode E_MANY_OPEN         {  -4, "Too many open" };
        !           227:        const Ecode E_ACCESS            {  -5, "Access denied" };
        !           228:        const Ecode E_NO_HANDLE         {  -6, "Handle not open" };
        !           229:        const Ecode E_BROKEN_MD         {  -7, "Broken memory discriptor" };
        !           230:        const Ecode E_MEMORY            {  -8, "Not enough memory" };
        !           231:        const Ecode E_INVALID_MD        {  -9, "Invalid memory discriptor" };
        !           232:        const Ecode E_INVALID_ENV       { -10, "Invalid environment" };
        !           233:        const Ecode E_BAD_EXEC          { -11, "Bad executable format" };
        !           234:        const Ecode E_BAD_OPEN          { -12, "Bad open mode" };
        !           235:        const Ecode E_INVALID_FILE      { -13, "Invalid filename" };
        !           236:        const Ecode E_INVALID_PARAM     { -14, "Invalid parameter" };
        !           237:        const Ecode E_INVALID_DRIVE     { -15, "Invalid drive" };
        !           238:        const Ecode E_DEL_CURDIR        { -16, "Can not delete curdir" };
        !           239:        const Ecode E_INVALID_IOCTL     { -17, "Invalid ioctrl" };
        !           240:        const Ecode E_NO_FILE           { -18, "No more files" };
        !           241:        const Ecode E_CANT_WRITE        { -19, "Can not write file" };
        !           242:        const Ecode E_DIR_ARE_REG       { -20, "Directory already registered" };
        !           243:        const Ecode E_CANT_DEL          { -21, "Can not delete" };
        !           244:        const Ecode E_CANT_RENAME       { -22, "Can not rename" };
        !           245:        const Ecode E_DISK_FULL         { -23, "Disk full" };
        !           246:        const Ecode E_DIR_FULL          { -24, "Directory full" };
        !           247:        const Ecode E_CANT_SEEK         { -25, "Can not seek" };
        !           248:        const Ecode E_ARE_SUPER         { -26, "Already supervisor" };
        !           249:        const Ecode E_TH_ARE_EXIST      { -27, "Thread already exists" };
        !           250:        const Ecode E_CANT_IPC          { -28, "Can not write IPC" };
        !           251:        const Ecode E_MANY_PROC         { -29, "Too many process" };
        !           252: 
        !           253:        const Ecode E_MANY_LOCK         { -32, "Too many locks" };
        !           254:        const Ecode E_HANDLE_LOCKED     { -33, "Handle locked" };
        !           255:        const Ecode E_DRIVE_ARE_OP      { -34, "Drive already open" };
        !           256:        const Ecode E_MANY_SYMLINK      { -35, "Too many nest symlink" };
        !           257: 
        !           258:        const Ecode E_FILE_EXIST        { -80, "File exist" };
        !           259: 
        !           260:  protected:
        !           261:        bool Dispatch();
        !           262: 
        !           263:        void RequestExit(int code);
        !           264: 
        !           265:        uint scid;              // 実行中のシステムコール番号
        !           266: };
        !           267: 
        !           268: // m680x0 に合わせたインタフェース。
        !           269: class HumanMD_m680x0 : public HumanMI
        !           270: {
        !           271:  public:
        !           272:        bool Init() override;
        !           273:        bool SysCallEntry() override;
        !           274:  protected:
        !           275:        uint64 Pop16() override;
        !           276:        uint64 Pop32() override;
        !           277:        uint32 ReadReg(int rn) override;
        !           278:        void WriteReg(int rn, uint32 data) override;
        !           279:        void Result(uint32 data) override;
        !           280: 
        !           281:  protected:
        !           282:        // システムコール時点の SP。
        !           283:        // 引数の取り出しにより変化する。
        !           284:        uint32 sp;
        !           285: 
        !           286:        m68kcpu *cpu;
        !           287: };
        !           288: 
        !           289: // m88xx0 に合わせたインタフェース。
        !           290: class HumanMD_m88xx0 : public HumanMI
        !           291: {
        !           292:  public:
        !           293:        bool Init() override;
        !           294:        bool SysCallEntry() override;
        !           295:  protected:
        !           296:        uint64 Pop16() override;
        !           297:        uint64 Pop32() override;
        !           298:        uint32 ReadReg(int rn) override;
        !           299:        void WriteReg(int rn, uint32 data) override;
        !           300:        void Result(uint32 data) override;
        !           301: 
        !           302:  protected:
        !           303:        // システムコール時点の rS。
        !           304:        // 引数の取り出しにより変化する。
        !           305:        uint32 rs;
        !           306:        // システムコール時点の rD。
        !           307:        uint32 rd;
        !           308: 
        !           309:        m88kcpu *cpu;
        !           310: };

unix.superglobalmegacorp.com

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