|
|
1.1 root 1: //
2: // nono
1.1.1.3 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
7: #pragma once
8:
1.1.1.13! root 9: #include "bus.h"
1.1 root 10:
1.1.1.12 root 11: // どこ?
1.1 root 12: __BEGIN_DECLS
13: #include "fpu_emulate.h"
14: __END_DECLS
15:
1.1.1.12 root 16: // 定数
17: struct M68K
18: {
19: // SR(CCR)
20: static const uint32 SR_T = 0xc000;
21: static const uint32 SR_S = 0x2000;
22: static const uint32 SR_M = 0x1000;
23: static const uint32 SR_IMASK = 0x0700;
24: static const uint32 CCR_X = 0x0010;
25: static const uint32 CCR_N = 0x0008;
26: static const uint32 CCR_Z = 0x0004;
27: static const uint32 CCR_V = 0x0002;
28: static const uint32 CCR_C = 0x0001;
29:
30: // SSW
31: static constexpr uint32 SSW_SIZE(uint32 x) { return ((x) & 0x03) << 4; }
32: static const uint32 SSW_SIZE_LONG = (0 << 4);
33: static const uint32 SSW_SIZE_BYTE = (1 << 4);
34: static const uint32 SSW_SIZE_WORD = (2 << 4);
35: static const uint32 SSW_SIZE_3BYTES = (3 << 4);
36: static const uint32 SSW_SIZE_MASK = (0x03 << 4);
37:
38: static const uint32 SSW_FC_MASK = 0x0007; // FC_*
39: static const uint32 SSW_RW = 0x0040; // SSW_BUS_{R,W}
40: static const uint32 SSW_RM = 0x0080;
41: static const uint32 SSW_DF = 0x0100; // Data Fault
42: static const uint32 SSW_RB = 0x1000;
43: static const uint32 SSW_RC = 0x2000;
44: static const uint32 SSW_FB = 0x4000;
45: static const uint32 SSW_FC = 0x8000;
46:
47: static const uint32 SSW_BUS_R = 0x0040;
48: static const uint32 SSW_BUS_W = 0x0000;
49:
50: // FC
51: static const uint32 FC_DATA = 1;
52: static const uint32 FC_PROG = 2;
53: static const uint32 FC_USER = 0;
54: static const uint32 FC_SUPER = 4;
55: static const uint32 FC_UD = (FC_USER | FC_DATA);
56: static const uint32 FC_UP = (FC_USER | FC_PROG);
57: static const uint32 FC_SD = (FC_SUPER | FC_DATA);
58: static const uint32 FC_SP = (FC_SUPER | FC_PROG);
59:
60: // CACR
61: static const uint32 CACR_EI = 0x0001;
62: static const uint32 CACR_FI = 0x0002;
63: static const uint32 CACR_CEI = 0x0004;
64: static const uint32 CACR_CI = 0x0008;
65: static const uint32 CACR_IBE = 0x0010;
66: static const uint32 CACR_ED = 0x0100;
67: static const uint32 CACR_FD = 0x0200;
68: static const uint32 CACR_CED = 0x0400;
69: static const uint32 CACR_CD = 0x0800;
70: static const uint32 CACR_DBE = 0x1000;
71: static const uint32 CACR_WA = 0x2000;
1.1.1.13! root 72: static const uint32 CACR_MASK = 0x3f1f;
1.1.1.12 root 73:
74: // FP
75: static const uint32 FPCR_MASK = 0x0000fff0;
76: static const uint32 FPSR_MASK = 0x0ffffff8;
77:
78: // 例外
79: // (型は core.cpp の try-catch と揃えること)
80: static const int EXCEP_RESET = 0;
81: static const int EXCEP_BUSERR = 2;
82: static const int EXCEP_ADDRERR = 3;
83: static const int EXCEP_ILLEGAL = 4;
84: static const int EXCEP_ZERODIV = 5;
85: static const int EXCEP_CHK = 6;
86: static const int EXCEP_TRAPV = 7;
87: static const int EXCEP_PRIV = 8;
88: static const int EXCEP_TRACE = 9;
89: static const int EXCEP_ALINE = 10;
90: static const int EXCEP_FLINE = 11;
91: static const int EXCEP_COPRO = 13;
92: static const int EXCEP_FORMAT = 14;
93: static const int EXCEP_UNINIT_INTR = 16;
94: static const int EXCEP_SPURIOUS = 24;
95: static const int EXCEP_LEVEL_BASE = 24; // オートベクタ演算用
96: static const int EXCEP_LEVEL1 = 25;
97: static const int EXCEP_LEVEL7 = 31;
98: static const int EXCEP_TRAP0 = 32;
99: static const int EXCEP_TRAP15 = 47;
100: static const int EXCEP_FPCP_BRANCH = 48;
101: static const int EXCEP_FPCP_INEXACT = 49;
102: static const int EXCEP_FPCP_ZERODIV = 50;
103: static const int EXCEP_FPCP_UNFL = 51;
104: static const int EXCEP_FPCP_OPERR = 52;
105: static const int EXCEP_FPCP_OVFL = 53;
106: static const int EXCEP_FPCP_SNAN = 54;
107: static const int EXCEP_MMU_CONFIG = 56;
108: };
109:
110: struct m68030ccr
111: {
112: protected:
113: // X フラグは、X の X_BIT が立っていれば 1
114: // N フラグは、N の N_BIT が立っていれば 1
115: // Z フラグは、Z == 0 なら 1
116: // V フラグは、V の V_BIT が立っていれば 1
117: // C フラグは、C の C_BIT が立っていれば 1
118: static const uint32 X_BIT = 0x00000001;
119: static const uint32 N_BIT = 0x80000000;
120: static const uint32 V_BIT = 0x80000000;
121: static const uint32 C_BIT = 0x00000001;
122:
123: uint32 X;
124: uint32 V;
125: uint32 N;
126: union {
127: uint64 CZ;
128: struct {
129: #if BYTE_ORDER == LITTLE_ENDIAN
130: uint32 Z;
131: uint32 C;
132: #else
133: uint32 C;
134: uint32 Z;
135: #endif
136: } __packed;
137: };
1.1 root 138:
1.1.1.12 root 139: public:
140: // value をフラグにセットする
141: void SetX(bool value) { X = (value) ? X_BIT : 0; }
142: void SetN(bool value) { N = (value) ? N_BIT : 0; }
143: void SetZ(bool value) { Z = (value) ? 0 : 1; }
144: void SetV(bool value) { V = (value) ? V_BIT : 0; }
145: void SetC(bool value) { C = (value) ? C_BIT : 0; }
146:
147: // フラグが立っていれば真を返す
148: bool IsX() const { return ((X & X_BIT) != 0); }
149: bool IsN() const { return ((N & N_BIT) != 0); }
150: bool IsZ() const { return (Z == 0); }
151: bool IsV() const { return ((V & V_BIT) != 0); }
152: bool IsC() const { return ((C & C_BIT) != 0); }
153:
154: // CCR レジスタの内容を作って返す
155: uint8 Get() const {
156: return (IsX() ? M68K::CCR_X : 0)
157: | (IsN() ? M68K::CCR_N : 0)
158: | (IsZ() ? M68K::CCR_Z : 0)
159: | (IsV() ? M68K::CCR_V : 0)
160: | (IsC() ? M68K::CCR_C : 0);
161: }
1.1.1.10 root 162:
1.1.1.12 root 163: // CCR レジスタに val をセットする
164: void Set(uint8 val) {
165: SetX((val) & M68K::CCR_X);
166: SetN((val) & M68K::CCR_N);
167: SetZ((val) & M68K::CCR_Z);
168: SetV((val) & M68K::CCR_V);
169: SetC((val) & M68K::CCR_C);
170: }
1.1 root 171:
1.1.1.12 root 172: bool CondT() const { return true; }
173: bool CondF() const { return false; }
174: bool CondHI() const { return !IsC() && !IsZ(); }
175: bool CondLS() const { return IsC() || IsZ(); }
176: bool CondCC() const { return !IsC(); }
177: bool CondCS() const { return IsC(); }
178: bool CondNE() const { return !IsZ(); }
179: bool CondEQ() const { return IsZ(); }
180: bool CondVC() const { return !IsV(); }
181: bool CondVS() const { return IsV(); }
182: bool CondPL() const { return !IsN(); }
183: bool CondMI() const { return IsN(); }
184: bool CondGE() const { return (IsN() && IsV()) || (!IsN() && !IsV()); }
185: bool CondLT() const { return (IsN() && !IsV()) || (!IsN() && IsV()); }
186: bool CondGT() const {
187: return (IsN() && IsV() && !IsZ()) || (!IsN() && !IsV() && !IsZ());
188: }
189: bool CondLE() const {
190: return IsZ() || (IsN() && !IsV()) || (!IsN() && IsV());
191: }
192:
193: // cond で示される条件が成立すれば true を返す。
194: inline bool Cond(int cond) const {
195: switch (cond) {
196: case 0: // T
197: return CondT();
198: case 1: // F
199: return CondF();
200: case 2:
201: return CondHI();
202: case 3:
203: return CondLS();
204: case 4:
205: return CondCC();
206: case 5:
207: return CondCS();
208: case 6:
209: return CondNE();
210: case 7:
211: return CondEQ();
212: case 8:
213: return CondVC();
214: case 9:
215: return CondVS();
216: case 10:
217: return CondPL();
218: case 11:
219: return CondMI();
220: case 12:
221: return CondGE();
222: case 13:
223: return CondLT();
224: case 14:
225: return CondGT();
226: case 15:
227: return CondLE();
228: }
229: __unreachable();
230: }
231: };
1.1 root 232:
233: // レジスタイメージを保持する構造体。
234: // この構造体はコピーとか比較をするのでポインタとかは置かないこと。
1.1.1.12 root 235: struct m68kreg
236: {
1.1 root 237: uint32 pc;
1.1.1.12 root 238: union {
239: uint32 R[16] {};
240: struct {
241: uint32 D[8];
242: uint32 A[8];
243: };
244: };
1.1 root 245:
246: m68030ccr ccr;
247: bool s; // SR の S ビット
248: bool m; // SR の M ビット
1.1.1.11 root 249: int intr_mask; // SR の割り込みマスク (0-7)
1.1 root 250:
1.1.1.12 root 251: // 現在の SP は常に A[7]。A[7] が示しているときは対応する変数の
1.1.1.10 root 252: // ほうは更新されないため無効。
1.1.1.12 root 253: // ユーザ状態なら A[7] が USP を示し usp は無効、
1.1.1.10 root 254: // isp, msp は ISP, MSP を示して有効。
1.1.1.12 root 255: // スーパバイザ状態で SR_M なら A[7] が MSP を示し msp は無効、
1.1.1.10 root 256: // isp, usp は ISP, USP を示して有効。
1.1.1.12 root 257: // スーパバイザ状態で !SR_M なら A[7] が ISP を示し isp は無効、
1.1.1.10 root 258: // msp, usp は MSP, USP を示して有効。
1.1 root 259: uint32 usp;
260: uint32 isp;
261: uint32 msp;
262:
263: uint32 vbr;
1.1.1.13! root 264: busaddr sfc; // (R/W も含む)
! 265: busaddr dfc; // (R/W も含む)
1.1 root 266:
267: uint32 cacr;
268: uint32 caar;
269:
270: union64 srp;
271: union64 crp;
272: uint32 tt[2];
273: uint32 tc;
274: uint16 mmusr;
275:
276: struct fpframe fpframe;
277:
1.1.1.12 root 278: // SR レジスタ全体を返す
279: uint16 GetSR() const {
280: return (s ? M68K::SR_S : 0)
281: | (m ? M68K::SR_M : 0)
282: | (intr_mask << 8)
283: | ccr.Get();
1.1 root 284: }
1.1.1.13! root 285: // SFC, DFC レジスタの値を返す
! 286: uint32 GetSFC() const { return sfc.GetFC(); }
! 287: uint32 GetDFC() const { return dfc.GetFC(); }
1.1 root 288: };
289:
290: // バス状態
1.1.1.12 root 291: struct m68kbus
292: {
1.1.1.13! root 293: // 論理アドレス。(R/W, FC2-0, Addr すべて使用)
! 294: busaddr laddr;
! 295:
! 296: // 対応する物理アドレス (FC2, Addr のみ使用)
! 297: busaddr paddr;
! 298:
! 299: // アクセスサイズ (SSW_SIZE_*)
! 300: uint32 size;
1.1 root 301:
302: // データバス。
303: // 今の所書き込みだけで使う。読み込みデータは戻り値のみ。
304: uint32 data;
305:
1.1.1.13! root 306: // キャッシュ禁止。/CIIN
! 307: bool ci;
! 308:
! 309: // Supervisor アクセスなら true を返す
! 310: bool IsSuper() const { return laddr.IsSuper(); }
1.1 root 311:
312: // バスが Write なら true を返す
1.1.1.13! root 313: bool IsWrite() const { return laddr.IsWrite(); }
1.1 root 314:
1.1.1.13! root 315: // FC を取得する。(これは MMU ルーチンから呼ばれる)
! 316: uint GetFC() const { return laddr.GetFC(); }
1.1 root 317:
1.1.1.13! root 318: // SSW を取得する。
! 319: uint32 GetSSW() const { return laddr.GetSSW() | size; }
1.1.1.11 root 320:
1.1.1.13! root 321: // アクセス方向(R/W)を設定する。
! 322: void SetWrite(bool write_) { laddr.SetWrite(write_); }
1.1 root 323: };
324:
1.1.1.12 root 325: // 仮
326: #define RegFP(n) (reg.fpframe.fpf_regs[n])
327: #define RegFPCR (reg.fpframe.fpf_fpcr)
328: #define RegFPSR (reg.fpframe.fpf_fpsr)
329: #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.