|
|
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:
1.1.1.4 ! root 132: // SFU1(FPU)が有効なら true
! 133: bool IsFPUEnable() const { return (psr & PSR_SFD1) == 0; }
! 134:
1.1 root 135: // MXM (Misaligned Access Enable) なら true
136: bool IsMXM() const { return (psr & PSR_MXM) != 0; }
137:
138: // キャリーフラグが立っていれば 1 を返す
139: uint32 GetCY() const { return (psr >> 28) & 1; }
1.1.1.4 ! root 140:
! 141: // キャリーフラグをセットする。
! 142: // cy のうち最下位ビットのみ参照する (呼び出し側はマスクせず渡してよい)
1.1 root 143: void SetCY(uint cy) {
144: psr &= ~PSR_C;
145: psr |= ((cy & 1) << 28);
146: }
147:
148: static const char * const sipname[3];
1.1.1.2 root 149: static const char * const dmt_en_str[16];
1.1 root 150: };
151:
152: class m88kcpu : public m88100reg
153: {
1.1.1.4 ! root 154: static const uint64 DELAYSLOT = 1ULL << 62;
! 155:
! 156: enum ExceptionKind
! 157: {
! 158: NORMAL,
! 159: DATA,
! 160: ERROR,
! 161: INTR,
! 162: TRAP,
! 163: };
! 164:
1.1 root 165: public:
166: m88kcpu();
167: virtual ~m88kcpu();
168:
169: void Reset(uint32 reset_vector);
170: uint32 Run(uint64 request);
171: void Release();
172:
173: void Interrupt();
174:
1.1.1.2 root 175: // PID.VERSION を設定する (初期化時に呼ぶ)
176: void SetVersion(uint32 version);
177:
1.1.1.4 ! root 178: // クラス外部からの xip 取得
! 179: uint32 GetXIP() const { return xip; }
1.1 root 180:
181: // op が>=0ならバスエラーは起きていない
182: // そのときに DELAYSLOT bit が 0 ならば通常
183: // bit32 が 1 ならば遅延スロット命令
184: // op が負数ならバスエラーが起きた
185: // そのときに DELAYSLOT bit が 1 ならば通常バスエラー
186: // bit32 が 0 ならば遅延スロットでのバスエラー
187: // バスエラーかどうかのチェックのほうが回数が多いため、
188: // バスエラー優先にしたい。
189:
1.1.1.4 ! root 190: static bool OpIsBusErr(uint64 op) {
1.1 root 191: return (int64)op < 0;
192: }
1.1.1.4 ! root 193:
! 194: // op が DelaySlot 実行なら true を返す。デバッガで表示用に使う。
! 195: static bool OpIsDelay(uint64 op) {
1.1 root 196: return (OpIsBusErr(op) ? ~op : op) & DELAYSLOT;
197: }
198:
1.1.1.4 ! root 199: // 積算実行サイクル数を取得
! 200: uint64 GetTotalCycle() const { return total_cycle; }
! 201:
! 202: // サイクルを加算 (m88200 から使う)
! 203: // 今は単純に加算しているだけで正確ではない
! 204: void AddCycle(uint64 cycle) { total_cycle += cycle; }
! 205:
! 206: std::atomic<uint32> atomic_reqflag {}; // リクエストフラグ
! 207:
! 208: // [0] 命令バス
! 209: // [1] データバス
! 210: m88200 cmmu[2] {};
! 211:
! 212: // ブランチ履歴 (例外履歴を含む)
! 213: BranchHistory_m88xx0 brhist {};
! 214: // 例外履歴のみ
! 215: BranchHistory_m88xx0 exhist {};
! 216:
! 217: // 例外名を返す
! 218: static const char *GetExceptionName(int vector);
! 219:
! 220: private:
! 221: uint64 fetch() {
! 222: nip = fip;
! 223: opF = cmmu[0].load_32(fip);
! 224: fip += 4;
! 225: return opF;
! 226: }
! 227:
! 228: // PSR を newpsr に変更する。
1.1.1.2 root 229: // CY ビットは特別にこの関数を経由しないで変更してよいことにする。
230: void SetPSR(uint32 newpsr)
231: {
232: psr = newpsr;
1.1.1.4 ! root 233: SetPSR();
! 234: }
! 235: // 更新された psr に基づいて、PSR 変更によって必要な処理をする。
! 236: // CY ビットを変更した場合は呼ばなくてよいことにする。
! 237: void SetPSR()
! 238: {
1.1.1.2 root 239: // CMMU に S/U 信号を出す
240: cmmu[0].SetSuper(IsSuper());
241: cmmu[1].SetSuper(IsSuper());
242: }
243:
1.1 root 244: void Exception(int vec);
245: void ExceptionCore(int vec, ExceptionKind cause);
246: void ReadDataException(uint32 addr, uint32 flag);
247: void WriteDataException(uint32 addr, uint32 data, uint32 flag);
1.1.1.2 root 248: void XmemDataException(uint32 addr, uint32 data, uint32 flag);
249:
1.1 root 250: // ブランチ処理用
1.1.1.4 ! root 251: void EnterBranch(uint32 toaddr);
1.1 root 252: void ExitBranch();
253: void ExitDelayBranch();
1.1.1.2 root 254: uint32 nop_counter {}; // STOP 検出用の nop 命令カウンタ
255:
1.1 root 256: // ロードストア命令用の下処理
1.1.1.2 root 257: bool ldst_usr(uint32& usr);
1.1 root 258: uint32 ldst_scale(uint32 size);
259: bool ldst_align(uint32 size, uint32& addr);
260:
261: #define OP_PROTO(name) void __CONCAT(op_,name)()
262: #include "m88100ops.h"
1.1.1.2 root 263: OP_PROTO(illegal);
1.1 root 264: #undef OP_PROTO
265:
266: void op_unimpl() {
267: printf("unimplemented op XIP=%08x opX=%08x\n", xip, (uint32)opX);
268: }
1.1.1.4 ! root 269: void fpu_unimpl();
! 270:
! 271: // 32bit 命令コードからディスパッチ用の 12bit に変換。
! 272: static uint32 op32_to_12(uint32 op) {
! 273: return ((op >> 20) & 0x0fc0) | ((op >> 10) & 0x003f);
! 274: }
! 275:
! 276: // 積算実行サイクル数
! 277: // 今のところ正確に実装するのは無理なので、適当に全部積み上げてある。
! 278: uint64 total_cycle {};
1.1.1.3 root 279:
280: // 例外名
281: static const char * const exception_names[];
1.1 root 282: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.