|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2022 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: //
8: // MPU (HD647180)
9: //
10:
11: #pragma once
12:
1.1.1.3 ! root 13: #include "mpu.h"
1.1 root 14: #include "branchhistory.h"
15: #include "event.h"
16: #include "hd64180.h"
17: #include "message.h"
18: #include <array>
19:
20: class PIO0Device;
1.1.1.3 ! root 21: class SSGDevice;
1.1 root 22: class XPbusDevice;
23:
1.1.1.3 ! root 24: class MPU64180Device : public MPUDevice, private HD64180
1.1 root 25: {
1.1.1.3 ! root 26: using inherited = MPUDevice;
1.1 root 27:
28: // タイマー1個分
29: struct XPTimer {
30: uint16 count; // 現在のカウント
31: uint16 reload; // リロードカウント
32: uint16 tmpcount; // 読み出し時用の内部バッファ
33: bool running; // カウントダウン中なら true
34: bool intr_enable; // TIEn ビットの状態 (IEF1 の状態は含まない)
35:
36: // 割り込みフラグ TIFn はカウントが 0 になると立ち、
37: // その後 TCR と TDR をそれぞれ読むことで (AND 条件)、リセットできる。
38: // そのため、tif は 2ビットで管理し、
39: // カウントが 0 になれば $3 をセット、
40: // TCR の読み出しで bit0 をクリア、
41: // TDR の読み出しで bit1 をクリア、
42: // (tif != 0) なら割り込み状態、とする。
43: uint32 tif;
44: };
45:
46: public:
47: MPU64180Device();
1.1.1.2 root 48: ~MPU64180Device() override;
1.1 root 49:
50: void putlogn(const char *fmt, ...) const override;
51: bool Init() override;
52: void ResetHard(bool poweron) override;
53:
54: // 現在実行中の命令先頭の PC を取得
1.1.1.3 ! root 55: uint32 GetPPC() const override { return ppc; }
1.1 root 56:
57: // CPU の動作モードを返す。
58: OpMode GetOpMode() const { return opmode; }
59:
60: // RESET 信号をアサート(true)/ネゲート(false)する。
61: void ChangeRESET(bool);
62: void AssertRESET();
63: void NegateRESET();
64:
65: // プロセッサをリセット
66: void Reset();
67:
68: // INT0 信号線をアサートする (PIO1 から呼ばれる)。
69: // (ネゲートはローカルで行う)
70: void AssertINT0();
71:
72: // ブランチ履歴 (例外履歴を含む)
73: BranchHistory_hd64180 brhist { OBJ_XP_BRHIST };
74: // 例外履歴のみ
75: BranchHistory_hd64180 exhist { OBJ_XP_EXHIST };
76:
77: // I, R レジスタ
78: uint8 GetI() const { return reg_i; }
79: uint8 GetR() const { return reg_r & 0x7f; }
80:
81: bool GetIEF1() const { return ief1; }
82: bool GetIEF2() const { return ief2; }
83:
84: // CPU からの論理メモリアクセス
85: // (MSXDOSDevice からも呼ぶので public にしてある)
1.1.1.3 ! root 86: uint32 Read1(uint32 addr);
! 87: uint32 Write1(uint32 addr, uint32 data);
! 88: uint32 Read2(uint32 addr);
! 89: void Write2(uint32 addr, uint32 data);
1.1 root 90:
91: // アドレス変換 (デバッガ用)
1.1.1.3 ! root 92: uint32 TranslatePeek(uint32) const;
1.1 root 93:
94: // MSXDOS エミュレーションのコールバックを指定する。
95: void SetSYSCALLCallback(void (*callback)(void *), void *arg);
96:
97: hd64180reg reg {};
98:
99: // 割り込み名
100: static std::vector<const char *> InterruptName;
101:
102: private:
103: void EnterNormal();
104: void EnterSleep();
105: void EnterWakeup();
106: void ExecTrace(Event& ev);
107: void ExecNormal(Event& ev);
108: void ExecSleep(Event& ev);
109: void ExecWakeup(Event& ev);
110: void SetExec(EventCallback_t);
111:
112: // トレース設定。デバッガから呼び出される。
113: void SetTrace(bool enable);
114: void TraceMessage(MessageID, uint32);
115:
116: uint32 GetIHL() const;
117: void SetIHL(uint32);
118: uint32 LeaIHL();
119: uint32 GetWW(uint) const;
120: void SetWW(uint, uint32);
121:
1.1.1.3 ! root 122: uint32 Fetch1();
! 123: uint32 Fetch2();
1.1 root 124: void Jump(uint16);
125: void op_illegal(int pos);
126:
127: void ops_ret();
128: void ops_ddfd(ixiy_t);
129: void ops_ldi(int);
130: void ops_cpi(int);
131: void ops_ini(int);
132: void ops_outi(int);
133: void ops_otim(int);
134: void ops_otmr_until();
135:
136: #define OP_PROTO(name) void __CONCAT(op_,name)()
137: #include "hd64180ops.h"
138: #undef OP_PROTO
139:
140: uint32 Translate(uint32) const;
141:
142: void AssertIntmap(int source);
143: void NegateIntmap(int source);
144: void NegateINT0();
145: void DoInterrupt();
146: void ExceptionDirect(int source, uint32 addr);
147: void ExceptionVector(int source);
148:
1.1.1.3 ! root 149: uint32 Peek1(uint32 addr) const;
! 150: uint32 Peek2(uint32 addr) const;
1.1 root 151:
1.1.1.3 ! root 152: void Push2(uint32 data);
! 153: uint32 Pop2();
1.1 root 154:
155: uint32 ReadIO(uint32 addr);
156: uint32 ReadInternalIO(uint32 offset);
157: uint32 ReadExternalIO(uint32 addr);
158: uint32 WriteIO(uint32 addr, uint32 data);
159: uint32 WriteInternalIO(uint32 offset, uint32 data);
160: uint32 WriteExternalIO(uint32 addr, uint32 data);
161: uint32 PeekIO(uint32 addr);
162: uint32 PeekInternalIO(uint32 offset);
163: uint32 PeekExternalIO(uint32 addr);
164: static std::string IOName(uint32 addr);
165:
166: uint32 ReadTMDRL(int ch);
167: uint32 ReadTMDRH(int ch);
168: uint32 ReadTCR();
169:
170: uint32 WriteTMDRL(int ch, uint32 data);
171: uint32 WriteTMDRH(int ch, uint32 data);
172: uint32 WriteRLDRL(int ch, uint32 data);
173: uint32 WriteRLDRH(int ch, uint32 data);
174: uint32 WriteTCR(uint32 data);
175: uint32 WriteDCNTL(uint32 data);
176: uint32 WriteIL(uint32 data);
177: uint32 WriteITC(uint32 data);
178: uint32 WriteRCR(uint32 data);
179: uint32 WriteCBR(uint32 data);
180: uint32 WriteBBR(uint32 data);
181: uint32 WriteCBAR(uint32 data);
182: uint32 WriteICR(uint32 data);
183: uint32 WriteRMCR(uint32 data);
184:
185: uint32 PeekTMDRL(int ch) const;
186: uint32 PeekTMDRH(int ch) const;
187: uint32 PeekRLDRL(int ch) const;
188: uint32 PeekRLDRH(int ch) const;
189: uint32 PeekTCR() const;
190: uint32 PeekFRC() const;
191: uint32 PeekDCNTL() const;
192: uint32 PeekIL() const;
193: uint32 PeekITC() const;
194: uint32 PeekRCR() const;
195: uint32 PeekCBR() const;
196: uint32 PeekBBR() const;
197: uint32 PeekCBAR() const;
198: uint32 PeekICR() const;
199: uint32 PeekRMCR() const;
200:
201: void CYCLE(int n) { used_cycle += n; }
202: void CYCLE_IX(int, int);
203:
204: // タイマー
205: void EnableTimer();
206: void ChangeTimerInterrupt();
207: void TimerCallback(Event& ev);
208: void MakeActiveTimer();
209:
210: uint16 ppc {};
211:
212: uint8 reg_i {}; // I レジスタ
213: uint8 reg_r {}; // R レジスタ
214:
1.1.1.3 ! root 215: uint ixiy {}; // 0=HL, 1=IX, 2=IY
1.1 root 216: // (IX+d)/(IY+d) の d。
217: // 読み込んでない時は (uint32)-1 にしておく。
218: // DD と DD CB で読む位置が違うので。
219: uint32 ixd {};
220:
221: bool ief1 {}; // IEF1: Interrupt Enable Flag1
222: bool ief2 {}; // IEF2: Interrupt Enable Flag2
1.1.1.3 ! root 223: uint int0mode {}; // INT0 mode
1.1 root 224: bool intcheck {}; // この命令後の境界で割り込みチェックするなら true
225:
226: // 割り込み信号線の状態
227: //
228: // bit 31 30 29 27 26 25 24 23 22 21 20 19 18 17 16 15 ... 0
229: // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-- --+
230: // intmap | 0| 0|I0|I1|I2|IC|OC|TV|T0|T1|D0|D1|CS|A0|A1| |
231: // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-- ... --+
232: // 優先順位 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
233: //
234: // intmap (32bit) は最上位から割り込み優先順に 1ビットずつ割り当てる
235: // (ただし TRAP と NMI はここでは使わないので %0 のまま)。
236: // 割り込みが発生していなければ intmap == 0。
237: // 割り込みが発生すれば該当するビットを立てる。割り込みを処理する際は
238: // builtin_clz() で上から判定していく。
239: uint32 intmap {};
240:
241: // 割り込み回数 (アサートのエッジでカウントアップする)
242: // [0] が優先順位 0 (TRAP) の割り込み回数。
243: // [14] が優先順位 14 (ASCI1) の割り込み回数。
244: uint64 int_counter[15] {};
245:
246: // 動作モード。
247: // mode == Reset ならリセット信号アサート中。
248: OpMode opmode {};
249:
250: // 現在の命令列
251: std::vector<uint8> ops {};
252: // 直近の命令語
253: uint8 op {};
254:
255: uint64 clock_nsec {}; // MPU クロック [nsec]
256:
257: // 電源オンからの累積消費サイクル
258: uint64 used_cycle {};
259:
260: // タイマーと Free Running Counter
261: uint64 timer_epoch {};
262: std::array<XPTimer, 2> timer {};
263: std::vector<XPTimer *> active_timer {};
264: uint8 timer_toc {}; // Timer Output Control
265:
266: // DCNTL
267: uint32 memwait {}; // メモリウェイト
268: uint32 iowait {}; // I/O ウェイト
269: uint32 dcntl {}; // DCNTL の残り部分 (未実装)
270:
271: // IL: 割り込みベクタの下位バイト(のうち上位3ビット)。
272: // 書き込み時にマスクする。
273: uint32 intvec_low {};
274: // ITC: 割り込み制御
275: bool itc_trap {};
276: bool itc_ufo {};
277: bool itc_ite0 {}; // INT Enable 0
278: bool itc_ite1 {}; // INT Enable 1
279: bool itc_ite2 {}; // INT Enable 2
280:
281: // RCR
282: uint32 rcr {};
283:
284: // MMU
285: uint32 commbase {}; // Common Base Address
286: uint32 bankbase {}; // Bank Base Address
287: uint32 commarea {}; // Common Area の下限アドレス
288: uint32 bankarea {}; // Bank Area の下限アドレス
289:
290: // ICR
291: uint32 io_address {}; // I/O アドレスの開始番地
292:
293: // SYSCALL 用のコールバック
294: void (*syscall_callback)(void *) = NULL;
295: void *syscall_arg {};
296:
297: PIO0Device *pio0 {};
1.1.1.3 ! root 298: SSGDevice *ssg {};
1.1 root 299: XPbusDevice *xpbus {};
300:
301: // モニター
302: DECLARE_MONITOR_CALLBACK(MonitorUpdateReg);
303: DECLARE_MONITOR_CALLBACK(MonitorUpdateIO);
304: DECLARE_MONITOR_CALLBACK(MonitorUpdateIntr);
305: Monitor reg_monitor { this };
306: Monitor io_monitor { this };
307: Monitor intr_monitor { this };
308:
1.1.1.3 ! root 309: // 実行コールバック
! 310: EventCallback_t exec_func {};
! 311:
1.1 root 312: // イベント
313: Event timer_event { this };
314:
315: // 名前
316: static const char * const opmode_names[];
317: static std::vector<const char *> ionames;
318: };
319:
320: static inline MPU64180Device *GetMPU64180Device() {
321: return Object::GetObject<MPU64180Device>(OBJ_MPUXP);
322: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.