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