|
|
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 root 13: #include <atomic>
14:
15: // 外部リクエストフラグ
16: // XXX m680x0 側にもよく似たものがあってどうしたもんか
1.1.1.2 root 17: #define CPU_REQ_STOP (0x00000001) // ストップ状態
1.1 root 18: #define CPU_REQ_TRACE (0x00000004) // デバッガ有効
19: #define CPU_REQ_PROMPT (0x00000008) // デバッガプロンプト
20: #define CPU_REQ_RELEASE (0x00000010) // 命令後に CPU 実行中断
21: #define CPU_REQ_INTR (0x00000020) // 命令後に割り込みチェック
22:
23: // m88100 レジスタイメージを保持する構造体。
24: // この構造体はコピーや比較をするので、ポインタとかは置かないこと。
25: struct m88100reg
26: {
27: // PID(cr0)
28: static const uint32 PID_REV_MASK = 0x0000ff00; // 0 = MC88100
29: static const uint32 PID_VER_MASK = 0x000000fe;
30: static const uint32 PID_MASTER = 0x00000001;
31: // PSR(cr1)
32: static const uint32 PSR_SUPER = 0x80000000;
33: static const uint32 PSR_BO_LE = 0x40000000; // ByteOrder(Little)
34: static const uint32 PSR_SER = 0x20000000;
35: static const uint32 PSR_C = 0x10000000; // Carry
36: static const uint32 PSR_SFD1 = 0x00000008; // SFU1 Disable
37: static const uint32 PSR_MXM = 0x00000004; // MisalignedAccessEnable
38: static const uint32 PSR_IND = 0x00000002; // Interrupt Disable
39: static const uint32 PSR_SFRZ = 0x00000001; // Shadow Freeze
40:
41: // 例外処理で使用される S*IP
42: static const uint32 SIP_MASK = 0xfffffffcU;
43: static const uint32 SIP_V = 0x00000002;
44: static const uint32 SIP_E = 0x00000001;
45:
46: // DMTn、データ例外
47: static const uint32 DM_BO = 0x00008000;
48: static const uint32 DM_DAS = 0x00004000;
49: static const uint32 DM_DOUB1 = 0x00002000;
50: static const uint32 DM_LOCK = 0x00001000;
51: static const uint32 DM_DREG_MASK = 0x00000f80;
52: static const uint32 DM_SIGNED = 0x00000040;
53: static const uint32 DM_EN3 = 0x00000020;
54: static const uint32 DM_EN2 = 0x00000010;
55: static const uint32 DM_EN1 = 0x00000008;
56: static const uint32 DM_EN0 = 0x00000004;
57: static const uint32 DM_EN_MASK = (DM_EN0 | DM_EN1 | DM_EN2 | DM_EN3);
58: static const uint32 DM_WRITE = 0x00000002;
59: static const uint32 DM_VALID = 0x00000001;
60: // 内部識別フラグ
61: static const uint32 DM_SIZE_B = (1U << 16) | DM_EN3;
62: static const uint32 DM_SIZE_H = (1U << 17) | DM_EN3 | DM_EN2;
63: static const uint32 DM_SIZE_W = (1U << 18) | DM_EN_MASK;
64: static const uint32 DM_USR = (1U << 20);
65: static const uint32 DM_BU = DM_SIZE_B;
66: static const uint32 DM_B = DM_SIZE_B | DM_SIGNED;
67: static const uint32 DM_HU = DM_SIZE_H;
68: static const uint32 DM_H = DM_SIZE_H | DM_SIGNED;
69: static const uint32 DM_W = DM_SIZE_W;
70: static const uint32 DM_D1 = DM_SIZE_W | DM_DOUB1;
71: static const uint32 DM_D2 = DM_SIZE_W;
72:
73: // 頻繁にアクセスしそうな変数はオフセットの若いほうに持ってきておく。
74:
75: // 実行中の命令
76: uint64 opX = 0;
77: // プリフェッチ命令
78: uint64 opF = 0;
79:
80: uint32 xip = 0;
81: uint32 nip = 0;
82: uint32 fip = 0;
83:
84: uint32 r[32] {};
85: union {
86: uint32 cr[21] {};
87: struct {
88: uint32 pid; // cr0
89: uint32 psr; // cr1
90: uint32 epsr; // cr2
91: uint32 ssbr; // cr3
92: uint32 sxip; // cr4
93: uint32 snip; // cr5
94: uint32 sfip; // cr6
95: uint32 vbr; // cr7
96: uint32 dmt0; // cr8
97: uint32 dmd0; // cr9
98: uint32 dma0; // cr10
99: uint32 dmt1; // cr11
100: uint32 dmd1; // cr12
101: uint32 dma1; // cr13
102: uint32 dmt2; // cr14
103: uint32 dmd2; // cr15
104: uint32 dma2; // cr16
105: uint32 sr[4]; // cr17,18,19,20
106: };
107: };
108: union {
109: uint32 fcr[11] {};
110: struct {
111: uint32 fpecr; // fcr0
112: uint32 fphs1; // fcr1
113: uint32 fpls1; // fcr2
114: uint32 fphs2; // fcr3
115: uint32 fpls2; // fcr4
116: uint32 fppt; // fcr5
117: uint32 fprh; // fcr6
118: uint32 fprl; // fcr7
119: uint32 fpit; // fcr8
120: uint32 fpsr; // fcr62 [9]
121: uint32 fpcr; // fcr63 [10]
122: };
123: };
124:
125: // 直近のデータアクセスアドレス
126: uint32 lastaddr;
127:
128: // スーパーバイザ/ユーザモードなら true
129: bool IsSuper() const { return (psr & PSR_SUPER) != 0; }
130: bool IsUser() const { return (psr & PSR_SUPER) == 0; }
131:
132: // MXM (Misaligned Access Enable) なら true
133: bool IsMXM() const { return (psr & PSR_MXM) != 0; }
134:
135: // キャリーフラグが立っていれば 1 を返す
136: uint32 GetCY() const { return (psr >> 28) & 1; }
137: // キャリーフラグをセットする。cy は最下位ビットのみ参照する
138: void SetCY(uint cy) {
139: psr &= ~PSR_C;
140: psr |= ((cy & 1) << 28);
141: }
142:
143: static const char * const sipname[3];
1.1.1.2 root 144: static const char * const dmt_en_str[16];
1.1 root 145: };
146:
147: class m88kcpu : public m88100reg
148: {
149: public:
150: m88kcpu();
151: virtual ~m88kcpu();
152:
153: public:
154: void Reset(uint32 reset_vector);
155: uint32 Run(uint64 request);
156: void Release();
157:
158: uint64 total_cycle = 0; // 積算実行サイクル数
159:
160: void Interrupt();
161:
1.1.1.2 root 162: // PID.VERSION を設定する (初期化時に呼ぶ)
163: void SetVersion(uint32 version);
164:
1.1 root 165: public:
166: // [0] 命令バス
167: // [1] データバス
168: m88200 cmmu[2];
169:
170: uint64 fetch() {
171: nip = fip;
172: opF = cmmu[0].load_32(fip);
173: fip += 4;
174: return opF;
175: }
176:
177: // op が>=0ならバスエラーは起きていない
178: // そのときに DELAYSLOT bit が 0 ならば通常
179: // bit32 が 1 ならば遅延スロット命令
180: // op が負数ならバスエラーが起きた
181: // そのときに DELAYSLOT bit が 1 ならば通常バスエラー
182: // bit32 が 0 ならば遅延スロットでのバスエラー
183: // バスエラーかどうかのチェックのほうが回数が多いため、
184: // バスエラー優先にしたい。
185:
186:
187: bool OpIsBusErr(uint64 op) const {
188: return (int64)op < 0;
189: }
190: bool OpIsDelay(uint64 op) const {
191: return (OpIsBusErr(op) ? ~op : op) & DELAYSLOT;
192: }
193:
1.1.1.2 root 194: // PSR を変更する。
195: // CY ビットは特別にこの関数を経由しないで変更してよいことにする。
196: void SetPSR(uint32 newpsr)
197: {
198: psr = newpsr;
199: // CMMU に S/U 信号を出す
200: cmmu[0].SetSuper(IsSuper());
201: cmmu[1].SetSuper(IsSuper());
202: }
203:
1.1 root 204: // クラス外部からの xip 取得
205: uint32 Getxip() const {
206: return xip;
207: }
208:
209: enum ExceptionKind
210: {
211: NORMAL,
1.1.1.2 root 212: DATA,
1.1 root 213: ERROR,
214: INTR,
215: TRAP,
216: };
217:
218: void Exception(int vec);
219: void ExceptionCore(int vec, ExceptionKind cause);
220: void ReadDataException(uint32 addr, uint32 flag);
221: void WriteDataException(uint32 addr, uint32 data, uint32 flag);
1.1.1.2 root 222: void XmemDataException(uint32 addr, uint32 data, uint32 flag);
223:
1.1.1.3 ! root 224: // 例外名を返す
! 225: static const char *GetExceptionName(int vector);
! 226:
! 227: // ブランチ履歴 (例外履歴を含む)
! 228: BranchHistory_m88xx0 brhist {};
! 229: // 例外履歴のみ
! 230: BranchHistory_m88xx0 exhist {};
1.1 root 231:
232: // FPU
233: bool IsFPUEnable() { return !(psr & PSR_SFD1); }
234: void fpu_unimpl();
235:
236: std::atomic<uint32> atomic_reqflag {}; // リクエストフラグ
237:
238: private:
239: const uint64 DELAYSLOT = 1ULL << 62;
240:
241: // OpSetDelay を一つの op に対して複数回呼ばないでください
242: uint64 OpSetDelay(uint64 op) const {
243: return op ^ DELAYSLOT;
244: }
245:
246: // ブランチ処理用
247: void EnterBranch();
1.1.1.2 root 248: void DoBranch(uint32 toaddr);
1.1 root 249: void ExitBranch();
250: void ExitDelayBranch();
1.1.1.2 root 251: uint32 nop_counter {}; // STOP 検出用の nop 命令カウンタ
252:
1.1 root 253: // ロードストア命令用の下処理
1.1.1.2 root 254: bool ldst_usr(uint32& usr);
1.1 root 255: uint32 ldst_scale(uint32 size);
256: bool ldst_align(uint32 size, uint32& addr);
257:
258: #define OP_PROTO(name) void __CONCAT(op_,name)()
259: #include "m88100ops.h"
1.1.1.2 root 260: OP_PROTO(illegal);
1.1 root 261: #undef OP_PROTO
262:
263: void op_unimpl() {
264: printf("unimplemented op XIP=%08x opX=%08x\n", xip, (uint32)opX);
265: }
1.1.1.3 ! root 266:
! 267: // 例外名
! 268: static const char * const exception_names[];
1.1 root 269: };
270:
271: // とりあえず
272: static inline uint32
273: op32_to_12(uint32 op)
274: {
275: uint32 op12 = ((op >> 20) & 0x0fc0) | ((op >> 10) & 0x003f);
276: return op12;
277: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.