|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: #pragma once
8:
9: #include "bus.h"
10:
11: // どこ?
12: __BEGIN_DECLS
13: #include "fpu_emulate.h"
14: __END_DECLS
15:
16: // MPU 種別
17: enum class m680x0MPUType
18: {
19: NONE = 0,
20: M68030 = (1U << 1),
21: M68040 = (1U << 2),
22: };
23:
24: // FPU 種別
25: struct m680x0FPUType
26: {
27: enum m680x0FPUType_ {
28: M68030_NOFPU = 0, // 68030 without 6888x
29: M68LC040 = (1U << 0),
30: M68LC060 = (1U << 1), // (reserved)
31: M68040 = (1U << 2),
32: M68060 = (1U << 3), // (reserved)
33: M68881 = (1U << 4),
34: M68882 = (1U << 5),
35:
36: M68LC0x0 = (M68LC040 | M68LC060),
37: M680x0 = (M68040 | M68060),
38: M6888x = (M68881 | M68882),
39: } type {};
40:
41: // コンストラクタ
42: m680x0FPUType() {
43: }
44: m680x0FPUType(m680x0FPUType_ type_)
45: : type(type_)
46: {
47: }
48:
49: bool IsNoFPU() const noexcept { return (type == M68030_NOFPU); }
50: bool Is4060LC() const noexcept { return (type & M68LC0x0) != 0; }
51: bool Is40FPU() const noexcept { return (type & M68040) != 0; }
52: bool Is4060FPU() const noexcept { return (type & M680x0) != 0; }
53: bool Is6888x() const noexcept { return (type & M6888x) != 0; }
54: };
55: static inline bool operator==(const m680x0FPUType& a, const m680x0FPUType& b) {
56: return (a.type == b.type);
57: }
58: static inline bool operator!=(const m680x0FPUType& a, const m680x0FPUType& b) {
59: return !(a == b);
60: }
61:
62: // 定数
63: struct M68K
64: {
65: // SR(CCR)
66: static const uint32 SR_T = 0xc000;
67: static const uint32 SR_S = 0x2000;
68: static const uint32 SR_M = 0x1000;
69: static const uint32 SR_IMASK = 0x0700;
70: static const uint32 CCR_X = 0x0010;
71: static const uint32 CCR_N = 0x0008;
72: static const uint32 CCR_Z = 0x0004;
73: static const uint32 CCR_V = 0x0002;
74: static const uint32 CCR_C = 0x0001;
75:
76: // FC
77: static const uint32 FC_DATA = 1;
78: static const uint32 FC_PROG = 2;
79: static const uint32 FC_USER = 0;
80: static const uint32 FC_SUPER = 4;
81: static const uint32 FC_UD = (FC_USER | FC_DATA);
82: static const uint32 FC_UP = (FC_USER | FC_PROG);
83: static const uint32 FC_SD = (FC_SUPER | FC_DATA);
84: static const uint32 FC_SP = (FC_SUPER | FC_PROG);
85:
86: // FP
87: static const uint32 FPCR_MASK = 0x0000fff0;
88: static const uint32 FPSR_MASK = 0x0ffffff8;
89:
90: // 例外 (型は core.cpp の try-catch と揃えること)。
91: // FPU_NOIMPL (浮動小数点未実装命令例外) はベクタ番号が 11 ($b) で
92: // F ラインと同じだが処理が色々違うので帯域外のビットで判別する。
93: static const uint EXCEP_RESET = 0;
94: static const uint EXCEP_BUSERR = 2;
95: static const uint EXCEP_ADDRERR = 3;
96: static const uint EXCEP_ILLEGAL = 4;
97: static const uint EXCEP_ZERODIV = 5;
98: static const uint EXCEP_CHK = 6;
99: static const uint EXCEP_TRAPV = 7;
100: static const uint EXCEP_PRIV = 8;
101: static const uint EXCEP_TRACE = 9;
102: static const uint EXCEP_ALINE = 10;
103: static const uint EXCEP_FLINE = 11;
104: static const uint EXCEP_FP_UNIMPL = (11 | 0x100);
105: static const uint EXCEP_COPRO = 13;
106: static const uint EXCEP_FORMAT = 14;
107: static const uint EXCEP_UNINIT_INTR = 16;
108: static const uint EXCEP_SPURIOUS = 24;
109: static const uint EXCEP_LEVEL_BASE = 24; // オートベクタ演算用
110: static const uint EXCEP_LEVEL1 = 25;
111: static const uint EXCEP_LEVEL7 = 31;
112: static const uint EXCEP_TRAP0 = 32;
113: static const uint EXCEP_TRAP15 = 47;
114: static const uint EXCEP_FP_BSUN = 48;
115: static const uint EXCEP_FP_INEX = 49;
116: static const uint EXCEP_FP_ZERODIV = 50;
117: static const uint EXCEP_FP_UNFL = 51;
118: static const uint EXCEP_FP_OPERR = 52;
119: static const uint EXCEP_FP_OVFL = 53;
120: static const uint EXCEP_FP_SNAN = 54;
121: static const uint EXCEP_FP_UNSUPP = 55;
122: static const uint EXCEP_MMU_CONFIG = 56;
123: };
124:
125: // 定数
126: struct M68030
127: {
128: // SSW
129: static constexpr uint32 SSW_SIZE(uint32 x) { return ((x) & 0x03) << 4; }
130: static const uint32 SSW_SIZE_LONG = (0 << 4);
131: static const uint32 SSW_SIZE_BYTE = (1 << 4);
132: static const uint32 SSW_SIZE_WORD = (2 << 4);
133: static const uint32 SSW_SIZE_3BYTES = (3 << 4);
134: static const uint32 SSW_SIZE_MASK = (0x03 << 4);
135:
136: static const uint32 SSW_FC_MASK = 0x0007; // FC_*
137: static const uint32 SSW_RW = 0x0040; // SSW_BUS_{R,W}
138: static const uint32 SSW_RM = 0x0080;
139: static const uint32 SSW_DF = 0x0100; // Data Fault
140: static const uint32 SSW_RB = 0x1000;
141: static const uint32 SSW_RC = 0x2000;
142: static const uint32 SSW_FB = 0x4000;
143: static const uint32 SSW_FC = 0x8000;
144:
145: static const uint32 SSW_BUS_R = 0x0040;
146: static const uint32 SSW_BUS_W = 0x0000;
147:
148: // CACR
149: static const uint32 CACR_EI = 0x0001;
150: static const uint32 CACR_FI = 0x0002;
151: static const uint32 CACR_CEI = 0x0004;
152: static const uint32 CACR_CI = 0x0008;
153: static const uint32 CACR_IBE = 0x0010;
154: static const uint32 CACR_ED = 0x0100;
155: static const uint32 CACR_FD = 0x0200;
156: static const uint32 CACR_CED = 0x0400;
157: static const uint32 CACR_CD = 0x0800;
158: static const uint32 CACR_DBE = 0x1000;
159: static const uint32 CACR_WA = 0x2000;
160: static const uint32 CACR_MASK = 0x3f1f;
161: };
162:
163: // 定数
164: struct M68040
165: {
166: // SSW
167: static const uint32 SSW_TM_MASK = 0x0007;
168: static const uint32 SSW_TT_MASK = 0x0018;
169: static const uint32 SSW_SIZE_MASK = 0x0060; // (0x03 << 5)
170: static const uint32 SSW_RW = 0x0100;
171: static const uint32 SSW_LK = 0x0200;
172: static const uint32 SSW_ATC = 0x0400;
173: static const uint32 SSW_MA = 0x0800;
174: static const uint32 SSW_CM = 0x1000;
175: static const uint32 SSW_CT = 0x2000;
176: static const uint32 SSW_CU = 0x4000;
177: static const uint32 SSW_CP = 0x8000;
178:
179: static const uint32 SSW_SIZE_LONG = (0x00 << 5);
180: static const uint32 SSW_SIZE_BYTE = (0x01 << 5);
181: static const uint32 SSW_SIZE_WORD = (0x02 << 5);
182: static const uint32 SSW_SIZE_LINE = (0x03 << 5);
183: // バイトサイズから SSW_SIZE フィールドを作成する。1, 2, 4 バイトのみ。
184: static constexpr uint32 SSW_SIZE(uint32 x) { return ((x) & 0x03) << 5; }
185:
186: // CACR
187: static const uint32 CACR_MASK = 0x80008000;
188: static const uint32 CACR_DE = 0x80000000;
189: static const uint32 CACR_IE = 0x00008000;
190: };
191:
192: struct m680x0CCR
193: {
194: protected:
195: // X フラグは、X の X_BIT が立っていれば 1
196: // N フラグは、N の N_BIT が立っていれば 1
197: // Z フラグは、Z == 0 なら 1
198: // V フラグは、V の V_BIT が立っていれば 1
199: // C フラグは、C の C_BIT が立っていれば 1
200: static const uint32 X_BIT = 0x00000001;
201: static const uint32 N_BIT = 0x80000000;
202: static const uint32 V_BIT = 0x80000000;
203: static const uint32 C_BIT = 0x00000001;
204:
205: uint32 X;
206: uint32 V;
207: uint32 N;
208: DEF_UNION64(, CZ, C, Z);
209:
210: public:
211: // value をフラグにセットする
212: void SetX(bool value) { X = (value) ? X_BIT : 0; }
213: void SetN(bool value) { N = (value) ? N_BIT : 0; }
214: void SetZ(bool value) { Z = (value) ? 0 : 1; }
215: void SetV(bool value) { V = (value) ? V_BIT : 0; }
216: void SetC(bool value) { C = (value) ? C_BIT : 0; }
217:
218: // フラグが立っていれば真を返す
219: bool IsX() const { return ((X & X_BIT) != 0); }
220: bool IsN() const { return ((N & N_BIT) != 0); }
221: bool IsZ() const { return (Z == 0); }
222: bool IsV() const { return ((V & V_BIT) != 0); }
223: bool IsC() const { return ((C & C_BIT) != 0); }
224:
225: // CCR レジスタの内容を作って返す
226: uint8 Get() const {
227: return (IsX() ? M68K::CCR_X : 0)
228: | (IsN() ? M68K::CCR_N : 0)
229: | (IsZ() ? M68K::CCR_Z : 0)
230: | (IsV() ? M68K::CCR_V : 0)
231: | (IsC() ? M68K::CCR_C : 0);
232: }
233:
234: // CCR レジスタに val をセットする
235: void Set(uint8 val) {
236: SetX((val) & M68K::CCR_X);
237: SetN((val) & M68K::CCR_N);
238: SetZ((val) & M68K::CCR_Z);
239: SetV((val) & M68K::CCR_V);
240: SetC((val) & M68K::CCR_C);
241: }
242:
243: bool CondT() const { return true; }
244: bool CondF() const { return false; }
245: bool CondHI() const { return !IsC() && !IsZ(); }
246: bool CondLS() const { return IsC() || IsZ(); }
247: bool CondCC() const { return !IsC(); }
248: bool CondCS() const { return IsC(); }
249: bool CondNE() const { return !IsZ(); }
250: bool CondEQ() const { return IsZ(); }
251: bool CondVC() const { return !IsV(); }
252: bool CondVS() const { return IsV(); }
253: bool CondPL() const { return !IsN(); }
254: bool CondMI() const { return IsN(); }
255: bool CondGE() const { return (IsN() && IsV()) || (!IsN() && !IsV()); }
256: bool CondLT() const { return (IsN() && !IsV()) || (!IsN() && IsV()); }
257: bool CondGT() const {
258: return (IsN() && IsV() && !IsZ()) || (!IsN() && !IsV() && !IsZ());
259: }
260: bool CondLE() const {
261: return IsZ() || (IsN() && !IsV()) || (!IsN() && IsV());
262: }
263:
264: // cond で示される条件が成立すれば true を返す。
265: inline bool Cond(uint cond) const {
266: switch (cond) {
267: case 0: // T
268: return CondT();
269: case 1: // F
270: return CondF();
271: case 2:
272: return CondHI();
273: case 3:
274: return CondLS();
275: case 4:
276: return CondCC();
277: case 5:
278: return CondCS();
279: case 6:
280: return CondNE();
281: case 7:
282: return CondEQ();
283: case 8:
284: return CondVC();
285: case 9:
286: return CondVS();
287: case 10:
288: return CondPL();
289: case 11:
290: return CondMI();
291: case 12:
292: return CondGE();
293: case 13:
294: return CondLT();
295: case 14:
296: return CondGT();
297: case 15:
298: return CondLE();
299: }
300: __unreachable();
301: }
302: };
303:
304: // レジスタイメージを保持する構造体。
305: // この構造体はコピーとか比較をするのでポインタとかは置かないこと。
306: struct m68kreg
307: {
308: uint32 pc;
309: union {
310: uint32 R[16] {};
311: struct {
312: uint32 D[8];
313: uint32 A[8];
314: };
315: };
316:
317: m680x0CCR ccr;
318: bool s; // SR の S ビット
319: bool m; // SR の M ビット
320: int intr_mask; // SR の割り込みマスク (0-7)
321:
322: // 現在の SP は常に A[7]。A[7] が示しているときは対応する変数の
323: // ほうは更新されないため無効 (図中 'x')。
324: //
325: // A[7] usp isp msp
326: // ---- --- --- ---
327: // ユーザ USP x ISP MSP
328: // スーパーバイザ(I) ISP USP x MSP
329: // スーパーバイザ(M) MSP USP ISP x
330: uint32 usp;
331: uint32 isp;
332: uint32 msp;
333:
334: uint32 vbr;
335: busaddr sfc; // (R/W も含む)
336: busaddr dfc; // (R/W も含む)
337:
338: uint32 cacr;
339: uint32 caar;
340:
341: // 68030 MMU
342: union64 srp;
343: union64 crp;
344: uint32 tt[2];
345: uint32 tc;
346: uint16 mmusr;
347:
348: // 68040 MMU
349: uint32 itt[2];
350: uint32 dtt[2];
351: uint32 srp40;
352: uint32 urp40;
353: uint16 tc40;
354: uint32 mmusr40;
355:
356: struct fpframe fpframe;
357:
358: // SR レジスタ全体を返す
359: uint16 GetSR() const {
360: return (s ? M68K::SR_S : 0)
361: | (m ? M68K::SR_M : 0)
362: | (intr_mask << 8)
363: | ccr.Get();
364: }
365: // SFC, DFC レジスタの値を返す
366: uint32 GetSFC() const { return sfc.GetFC(); }
367: uint32 GetDFC() const { return dfc.GetFC(); }
368: };
369:
370: // バス状態
371: struct m68kbus
372: {
373: // 論理アドレス。(R/W, FC2-0, Addr すべて使用)
374: busaddr laddr;
375:
376: // 対応する物理アドレス (FC2, Addr のみ使用)
377: busaddr paddr;
378:
379: // アクセスサイズ (バイト数で表す)
380: uint32 size;
381:
382: // データバス。
383: // 今の所書き込みだけで使う。読み込みデータは戻り値のみ。
384: uint32 data;
385:
386: // キャッシュ禁止。/CIIN
387: bool ci;
388:
389: // ATC フォールト (68040 only)
390: bool atcfault;
391:
392: // ATC フォールトが2ページ目で起きたら true (68040 only)
393: bool atcfault2;
394:
395: // Supervisor アクセスなら true を返す
396: bool IsSuper() const { return laddr.IsSuper(); }
397:
398: // バスが Write なら true を返す
399: bool IsWrite() const { return laddr.IsWrite(); }
400: };
401:
402: // 仮
403: #define RegFP(n) (reg.fpframe.fpf_regs[(n) * 3])
404: #define RegFPCR (reg.fpframe.fpf_fpcr)
405: #define RegFPSR (reg.fpframe.fpf_fpsr)
406: #define RegFPIAR (reg.fpframe.fpf_fpiar)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.