|
|
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: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.