|
|
1.1 root 1: //
2: // nono
1.1.1.2 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
7: #pragma once
8:
9: #include "header.h"
1.1.1.2 root 10: #include "branchhistory.h"
1.1 root 11: #include "bus.h"
1.1.1.2 root 12: #include "m88200.h"
1.1.1.12 root 13: #include <array>
1.1 root 14: #include <atomic>
15:
16: // 外部リクエストフラグ
17: // XXX m680x0 側にもよく似たものがあってどうしたもんか
18: #define CPU_REQ_INTR (0x00000020) // 命令後に割り込みチェック
1.1.1.12 root 19:
20: class MPU88xx0Device;
1.1 root 21:
22: // m88100 レジスタイメージを保持する構造体。
23: // この構造体はコピーや比較をするので、ポインタとかは置かないこと。
24: struct m88100reg
25: {
26: // PID(cr0)
27: static const uint32 PID_REV_MASK = 0x0000ff00; // 0 = MC88100
28: static const uint32 PID_VER_MASK = 0x000000fe;
29: static const uint32 PID_MASTER = 0x00000001;
30: // PSR(cr1)
31: static const uint32 PSR_SUPER = 0x80000000;
32: static const uint32 PSR_BO_LE = 0x40000000; // ByteOrder(Little)
33: static const uint32 PSR_SER = 0x20000000;
34: static const uint32 PSR_C = 0x10000000; // Carry
35: static const uint32 PSR_SFD1 = 0x00000008; // SFU1 Disable
36: static const uint32 PSR_MXM = 0x00000004; // MisalignedAccessEnable
37: static const uint32 PSR_IND = 0x00000002; // Interrupt Disable
38: static const uint32 PSR_SFRZ = 0x00000001; // Shadow Freeze
39:
40: // 例外処理で使用される S*IP
41: static const uint32 SIP_MASK = 0xfffffffcU;
42: static const uint32 SIP_V = 0x00000002;
43: static const uint32 SIP_E = 0x00000001;
44:
45: // DMTn、データ例外
46: static const uint32 DM_BO = 0x00008000;
47: static const uint32 DM_DAS = 0x00004000;
48: static const uint32 DM_DOUB1 = 0x00002000;
49: static const uint32 DM_LOCK = 0x00001000;
50: static const uint32 DM_DREG_MASK = 0x00000f80;
51: static const uint32 DM_SIGNED = 0x00000040;
52: static const uint32 DM_EN3 = 0x00000020;
53: static const uint32 DM_EN2 = 0x00000010;
54: static const uint32 DM_EN1 = 0x00000008;
55: static const uint32 DM_EN0 = 0x00000004;
56: static const uint32 DM_EN_MASK = (DM_EN0 | DM_EN1 | DM_EN2 | DM_EN3);
57: static const uint32 DM_WRITE = 0x00000002;
58: static const uint32 DM_VALID = 0x00000001;
59: // 内部識別フラグ
60: static const uint32 DM_SIZE_B = (1U << 16) | DM_EN3;
61: static const uint32 DM_SIZE_H = (1U << 17) | DM_EN3 | DM_EN2;
62: static const uint32 DM_SIZE_W = (1U << 18) | DM_EN_MASK;
63: static const uint32 DM_USR = (1U << 20);
64: static const uint32 DM_BU = DM_SIZE_B;
65: static const uint32 DM_B = DM_SIZE_B | DM_SIGNED;
66: static const uint32 DM_HU = DM_SIZE_H;
67: static const uint32 DM_H = DM_SIZE_H | DM_SIGNED;
68: static const uint32 DM_W = DM_SIZE_W;
69: static const uint32 DM_D1 = DM_SIZE_W | DM_DOUB1;
70: static const uint32 DM_D2 = DM_SIZE_W;
71:
1.1.1.11 root 72: // FPECR(fcr0)
73: // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
74: // +---------------+---------------+---------------+-+-+-+-+-+-+-+-+
75: // | |I|U|P|O|D|U|O|I|
76: // | 0 |O|N|V|P|Z|F|V|N|
77: // +---------------+---------------+---------------+-+-+-+-+-+-+-+-+
78: static const uint32 FPECR_MASK = 0x000000ff; // 有効ビットマスク
79: static const uint32 FPECR_FIOV = 0x00000080; // FP Integer Overflow
80: static const uint32 FPECR_FUNIMP= 0x00000040; // FP Unimplemented
81: static const uint32 FPECR_FPRV = 0x00000020; // FP Privilege Violation
82: static const uint32 FPECR_FROP = 0x00000010; // FP Reserved Operand
83: static const uint32 FPECR_FDVZ = 0x00000008; // FP Divice-by-Zero
84: static const uint32 FPECR_FUNF = 0x00000004; // FP Underflow
85: static const uint32 FPECR_FOVF = 0x00000002; // FP Overflow
86: static const uint32 FPECR_FINX = 0x00000001; // FP Inexact
87:
88: // FPHS1(fcr1)
89: // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
90: // +-+---------------------+---------------------------------------+
91: // |S| Exponent | High order 20 bits of Mantissa |
92: // +-+---------------------+---------------------------------------+
93:
94: // FPLS1(fcr2)
95: // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
96: // +---------------------------------------------------------------+
97: // | Low order bits of Mantissa or Integer Operand |
98: // +---------------------------------------------------------------+
99:
100: // FPHS2(fcr3)
101: // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
102: // +-+---------------------+---------------------------------------+
103: // |S| Exponent | High order 20 bits of Mantissa |
104: // +-+---------------------+---------------------------------------+
105:
106: // FPLS2(fcr4)
107: // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
108: // +---------------------------------------------------------------+
109: // | Low order bits of Mantissa or Integer Operand |
110: // +---------------------------------------------------------------+
111:
112: // FPPT(fcr5)
113: // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
114: // +---------------+---------------+---------+---+---+---+---------+
115: // | 0 | OPCODE |T1 |T2 |TD | DestReg |
116: // +---------------+---------------+---------+---+---+---+---------+
117: static const uint32 FPPT_MASK = 0x0000ffff; // 有効ビットマスク
118: static const uint32 FPPT_OPCODE = 0x0000f800; // Opcode
119: static const uint32 FPPT_T1 = 0x00000600; // Source1 Operand Size
120: static const uint32 FPPT_T2 = 0x00000180; // Source2 Operand Size
121: static const uint32 FPPT_TD = 0x00000060; // Destination Size
122: static const uint32 FPPT_DEST = 0x0000001f; // Destination Register No.
123:
124: // FPRH(fcr6)
125: // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
126: // +-----+-+-+-+-+-+-----+---------+-------------+-----------------+
127: // |S|RM |G|R|S|A| 0 | High Order Bits of Mantissa |
128: // +-----+-+-+-+-+-+-----+---------+-------------+-----------------+
129: static const uint32 FPRH_MASK = 0xfe1fffff; // 有効ビットマスク
130: static const uint32 FPRH_SIGN = 0x80000000; // Result Sign
131: static const uint32 FPRH_RNDMODE= 0x60000000; // Rounding Mode for Res.
132: static const uint32 FPRH_GUARD = 0x10000000; // Guard Bit for Result
133: static const uint32 FPRH_ROUND = 0x08000000; // Round Bit for Result
134: static const uint32 FPRH_STICKY = 0x04000000; // Sticky Bit for Result
135: static const uint32 FPRH_ADDONE = 0x02000000; // Add One
136: static const uint32 FPRH_MANT = 0x001fffff; // Mantissa(High)
137: static const uint32 FPRH_1 = 0x00100000; // 隠し実数部の 1
138:
139: // FPRL(fcr7)
140: // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
141: // +---------------------------------------------------------------+
142: // | Low Order Bits of Mantissa |
143: // +---------------------------------------------------------------+
144:
145: // FPIT(fcr8)
146: // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
147: // +-----------------------+-------+---------+-+-+-+-+-+-+---------+
148: // | | | |D|E|E|E|E|E| |
149: // | RESEXP (12bits) | 0 | OPCODE |S|V|Z|U|O|N| DestReg |
150: // +-----------------------+-------+---------+-+-+-+-+-+-+---------+
151: static const uint32 FPIT_MASK = 0xfff0ffff; // 有効ビットマスク
152: static const uint32 FPIT_RESEXP = 0xfff00000; // Result Exponent
153: static const uint32 FPIT_OPCODE = 0x0000f800; // Opcode
154: static const uint32 FPIT_DESTSIZ= 0x00000400; // Destination Size
155: static const uint32 FPIT_EFINV = 0x00000200; // Enable Invalid Op.
156: static const uint32 FPIT_EFDVZ = 0x00000100; // Enable Divide-by-Zero
157: static const uint32 FPIT_EFUNF = 0x00000080; // Enable Underflow
158: static const uint32 FPIT_EFOVF = 0x00000040; // Enable Overflow
159: static const uint32 FPIT_EFINX = 0x00000020; // Enable Inexact
160: static const uint32 FPIT_DEST = 0x0000001f; // Destination Register No.
161:
162: // FPSR(fcr62)
163: // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
164: // +---------------+---------------+---------------+-----+-+-+-+-+-+
165: // | |A|A|A|A|A|
166: // | 0 |V|D|U|O|I|
167: // +---------------+---------------+---------------+-----+-+-+-+-+-+
168: static const uint32 FPSR_MASK = 0x0000001f; // 有効ビットマスク
169: static const uint32 FPSR_AFINV = 0x00000010; // Acc. Invalid Op. Flag
170: static const uint32 FPSR_AFDVZ = 0x00000008; // Acc. Divide-by-Zero Flag
171: static const uint32 FPSR_AFUNF = 0x00000004; // Acc. Underflow Flag
172: static const uint32 FPSR_AFOVF = 0x00000002; // Acc. Overflow Flag
173: static const uint32 FPSR_AFINX = 0x00000001; // Acc. Inexact Flag
174:
175: // FPCR(fcr63)
176: // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
177: // +---------------+---------------+---+-----------+-----+-+-+-+-+-+
178: // | | | |E|E|E|E|E|
179: // | 0 |RM | |V|D|U|O|I|
180: // +---------------+---------------+---+-----------+-----+-+-+-+-+-+
181: static const uint32 FPCR_MASK = 0x0000c01f; // 有効ビットマスク
182: static const uint32 FPCR_RM = 0x0000c000; // Rounding Mask
183: static const uint32 FPCR_EFINV = 0x00000010; // Enable Invalid Operation
184: static const uint32 FPCR_EFDVZ = 0x00000008; // Enable Divide-by-Zero
185: static const uint32 FPCR_EFUNF = 0x00000004; // Enable Underflow
186: static const uint32 FPCR_EFOVF = 0x00000002; // Enable Overflow
187: static const uint32 FPCR_EFINX = 0x00000001; // Enable Inexact
188:
1.1 root 189: // 頻繁にアクセスしそうな変数はオフセットの若いほうに持ってきておく。
190:
191: // 実行中の命令
192: uint64 opX = 0;
193: // プリフェッチ命令
194: uint64 opF = 0;
195:
196: uint32 xip = 0;
197: uint32 nip = 0;
198: uint32 fip = 0;
199:
200: uint32 r[32] {};
201: union {
202: uint32 cr[21] {};
203: struct {
204: uint32 pid; // cr0
205: uint32 psr; // cr1
206: uint32 epsr; // cr2
207: uint32 ssbr; // cr3
208: uint32 sxip; // cr4
209: uint32 snip; // cr5
210: uint32 sfip; // cr6
211: uint32 vbr; // cr7
212: uint32 dmt0; // cr8
213: uint32 dmd0; // cr9
214: uint32 dma0; // cr10
215: uint32 dmt1; // cr11
216: uint32 dmd1; // cr12
217: uint32 dma1; // cr13
218: uint32 dmt2; // cr14
219: uint32 dmd2; // cr15
220: uint32 dma2; // cr16
221: uint32 sr[4]; // cr17,18,19,20
222: };
223: };
224: union {
225: uint32 fcr[11] {};
226: struct {
227: uint32 fpecr; // fcr0
228: uint32 fphs1; // fcr1
229: uint32 fpls1; // fcr2
230: uint32 fphs2; // fcr3
231: uint32 fpls2; // fcr4
232: uint32 fppt; // fcr5
233: uint32 fprh; // fcr6
234: uint32 fprl; // fcr7
235: uint32 fpit; // fcr8
236: uint32 fpsr; // fcr62 [9]
237: uint32 fpcr; // fcr63 [10]
238: };
239: };
240:
241: // 直近のデータアクセスアドレス
242: uint32 lastaddr;
243:
244: // スーパーバイザ/ユーザモードなら true
245: bool IsSuper() const { return (psr & PSR_SUPER) != 0; }
246: bool IsUser() const { return (psr & PSR_SUPER) == 0; }
247:
1.1.1.5 root 248: // 割り込みが許可なら true
249: bool IsIntrEnable() const { return (psr & PSR_IND) == 0; }
250:
1.1.1.4 root 251: // SFU1(FPU)が有効なら true
252: bool IsFPUEnable() const { return (psr & PSR_SFD1) == 0; }
253:
1.1 root 254: // MXM (Misaligned Access Enable) なら true
255: bool IsMXM() const { return (psr & PSR_MXM) != 0; }
256:
257: // キャリーフラグが立っていれば 1 を返す
258: uint32 GetCY() const { return (psr >> 28) & 1; }
1.1.1.4 root 259:
260: // キャリーフラグをセットする。
261: // cy のうち最下位ビットのみ参照する (呼び出し側はマスクせず渡してよい)
1.1 root 262: void SetCY(uint cy) {
263: psr &= ~PSR_C;
264: psr |= ((cy & 1) << 28);
265: }
266:
1.1.1.11 root 267: static const uint32 fcr_mask[11];
1.1 root 268: static const char * const sipname[3];
1.1.1.2 root 269: static const char * const dmt_en_str[16];
1.1 root 270: };
271:
272: class m88kcpu : public m88100reg
273: {
1.1.1.4 root 274: static const uint64 DELAYSLOT = 1ULL << 62;
275:
276: enum ExceptionKind
277: {
278: NORMAL,
279: DATA,
280: ERROR,
281: INTR,
282: TRAP,
283: };
284:
1.1 root 285: public:
1.1.1.12 root 286: static const uint32 CPU_STATE_NORMAL = 0;
287: static const uint32 CPU_STATE_STOP = 1; // 疑似 STOP 状態
288:
289: public:
290: m88kcpu(MPU88xx0Device *dev_);
1.1 root 291: virtual ~m88kcpu();
292:
1.1.1.8 root 293: void PowerOn();
1.1.1.12 root 294: uint64 Reset();
1.1.1.8 root 295:
1.1.1.12 root 296: int Exec();
297: int ExecPseudoStop();
1.1 root 298:
1.1.1.5 root 299: // 割り込み信号線が変化したことの通知を受ける。
300: // level は 0 か 1。
301: void Interrupt(int level);
1.1 root 302:
1.1.1.2 root 303: // PID.VERSION を設定する (初期化時に呼ぶ)
304: void SetVersion(uint32 version);
305:
1.1.1.4 root 306: // クラス外部からの xip 取得
307: uint32 GetXIP() const { return xip; }
1.1 root 308:
1.1.1.12 root 309: // クラス外部からの vbr 取得
310: uint32 GetVBR() const { return vbr; }
311:
1.1 root 312: // op が>=0ならバスエラーは起きていない
313: // そのときに DELAYSLOT bit が 0 ならば通常
314: // bit32 が 1 ならば遅延スロット命令
315: // op が負数ならバスエラーが起きた
316: // そのときに DELAYSLOT bit が 1 ならば通常バスエラー
317: // bit32 が 0 ならば遅延スロットでのバスエラー
318: // バスエラーかどうかのチェックのほうが回数が多いため、
319: // バスエラー優先にしたい。
320:
1.1.1.4 root 321: static bool OpIsBusErr(uint64 op) {
1.1 root 322: return (int64)op < 0;
323: }
1.1.1.4 root 324:
325: // op が DelaySlot 実行なら true を返す。デバッガで表示用に使う。
326: static bool OpIsDelay(uint64 op) {
1.1 root 327: return (OpIsBusErr(op) ? ~op : op) & DELAYSLOT;
328: }
329:
1.1.1.4 root 330: // サイクルを加算 (m88200 から使う)
1.1.1.5 root 331: // 今は単純に加算しているだけでオーバーラップなどは考慮してない
332: void AddCycle(int32 wait) { used_cycle += wait; }
333:
1.1.1.4 root 334: std::atomic<uint32> atomic_reqflag {}; // リクエストフラグ
335:
1.1.1.12 root 336: // CPU の状態
337: uint32 cpu_state {};
338:
1.1.1.4 root 339: // [0] 命令バス
340: // [1] データバス
1.1.1.12 root 341: std::array<m88200, 2> cmmu {};
1.1.1.4 root 342:
343: // ブランチ履歴 (例外履歴を含む)
1.1.1.9 root 344: BranchHistory_m88xx0 brhist { BranchHistory::BrHist };
1.1.1.4 root 345: // 例外履歴のみ
1.1.1.9 root 346: BranchHistory_m88xx0 exhist { BranchHistory::ExHistOnly };
1.1.1.4 root 347:
1.1.1.5 root 348: // 32bit 命令コードからディスパッチ用の 12bit に変換。
349: static uint32 op32_to_12(uint32 op) {
350: return ((op >> 20) & 0x0fc0) | ((op >> 10) & 0x003f);
351: }
352:
1.1.1.9 root 353: // 疑似 STOP 状態に入る機能を有効にする場合 true
354: bool pseudo_stop_enable {};
355:
1.1.1.10 root 356: // DOS call エミュレーションコールバックを設定する
357: void SetFLineCallback(bool (*callback)(m88kcpu *, void *), void *arg);
358:
1.1.1.4 root 359: private:
360: uint64 fetch() {
361: nip = fip;
362: opF = cmmu[0].load_32(fip);
363: fip += 4;
364: return opF;
365: }
366:
1.1.1.13! root 367: void Prefetch();
! 368:
1.1.1.4 root 369: // PSR を newpsr に変更する。
1.1.1.2 root 370: // CY ビットは特別にこの関数を経由しないで変更してよいことにする。
371: void SetPSR(uint32 newpsr)
372: {
373: psr = newpsr;
1.1.1.4 root 374: SetPSR();
375: }
376: // 更新された psr に基づいて、PSR 変更によって必要な処理をする。
377: // CY ビットを変更した場合は呼ばなくてよいことにする。
378: void SetPSR()
379: {
1.1.1.2 root 380: // CMMU に S/U 信号を出す
381: cmmu[0].SetSuper(IsSuper());
382: cmmu[1].SetSuper(IsSuper());
383: }
384:
1.1.1.11 root 385: // FPxS1, FPxS2 レジスタを設定
386: void SetFPxS(uint32& h, uint32& l, double src, uint32 t);
387: void SetFPS1(double src, uint32 t1) { SetFPxS(fphs1, fpls1, src, t1); }
388: void SetFPS2(double src, uint32 t2) { SetFPxS(fphs2, fpls2, src, t2); }
389: void SetFPS1(uint32 src) { fpls1 = src; }
390: void SetFPS2(uint32 src) { fpls2 = src; }
391: // FP Result を FPIT, FPRH, FPRL レジスタに設定
392: void SetFPRx(double src);
393:
1.1 root 394: void Exception(int vec);
395: void ExceptionCore(int vec, ExceptionKind cause);
1.1.1.5 root 396: uint32 Calcdmt(uint32 flag);
397: void ReadDataException32(uint32 addr, uint32 flag);
398: void ReadDataException64(uint32 addr, uint32 flag);
399: void WriteDataException32(uint32 addr, uint32 flag);
400: void WriteDataException64(uint32 addr, uint32 flag);
401: void XmemDataException(uint32 addr, uint32 flag);
1.1.1.11 root 402: void FPPreciseException(uint32 cause, double s2);
403: void FPPreciseException(uint32 cause, double s1, double s2);
404: void FPPreciseException(uint32 cause);
405: void FPImpreciseException(uint32 cause);
1.1.1.2 root 406:
1.1 root 407: // ブランチ処理用
1.1.1.4 root 408: void EnterBranch(uint32 toaddr);
1.1 root 409: void ExitBranch();
410: void ExitDelayBranch();
1.1.1.2 root 411: uint32 nop_counter {}; // STOP 検出用の nop 命令カウンタ
412:
1.1 root 413: // ロードストア命令用の下処理
1.1.1.2 root 414: bool ldst_usr(uint32& usr);
1.1 root 415: uint32 ldst_scale(uint32 size);
416: bool ldst_align(uint32 size, uint32& addr);
1.1.1.11 root 417: // 浮動小数点数命令用の処理
418: void ops_int(int mode);
1.1 root 419:
420: #define OP_PROTO(name) void __CONCAT(op_,name)()
421: #include "m88100ops.h"
1.1.1.2 root 422: OP_PROTO(illegal);
1.1 root 423: #undef OP_PROTO
424:
425: void op_unimpl() {
426: printf("unimplemented op XIP=%08x opX=%08x\n", xip, (uint32)opX);
427: }
1.1.1.4 root 428: void fpu_unimpl();
429:
1.1.1.5 root 430: // 今のところサイクルを正確に実装するのは無理なので
431: // 適当に全部積み上げてある。
1.1.1.12 root 432:
433: // 電源オンからの累積消費サイクル
434: uint64 used_cycle {};
1.1.1.5 root 435:
436: // ペンディング中の割り込みレベル
437: int intr_pending {};
438:
1.1.1.11 root 439: // float,double と整数値の相互変換
440: static float u2f(uint32 u) {
441: float v;
442: memcpy(&v, &u, sizeof(v));
443: return v;
444: }
445: static double u2d(uint64 u) {
446: double v;
447: memcpy(&v, &u, sizeof(v));
448: return v;
449: }
450: static uint32 f2u(float v) {
451: uint32 u;
452: memcpy(&u, &v, sizeof(u));
453: return u;
454: }
455: static uint64 d2u(double v) {
456: uint64 u;
457: memcpy(&u, &v, sizeof(u));
458: return u;
459: }
460:
1.1.1.12 root 461: void ChangeState(uint32 new_state);
462:
463: int instruction_in_stop {};
464:
465: MPU88xx0Device *dev {};
466:
1.1.1.10 root 467: // DOS call エミュレーション
468: bool (*fline_callback)(m88kcpu *, void *) = NULL;
469: void *fline_arg {};
1.1 root 470: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.