|
|
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:
13: #include "device.h"
14: #include "branchhistory.h"
15: #include "event.h"
16: #include "hd64180.h"
17: #include "message.h"
18: #include <array>
19:
20: class Debugger;
21: class PIO0Device;
22: class XPbusDevice;
23:
24: class MPU64180Device : public Device, private HD64180
25: {
26: using inherited = Device;
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 を取得
55: uint32 GetPPC() const { return ppc; }
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 にしてある)
86: uint32 Read8(uint32 addr);
87: uint32 Write8(uint32 addr, uint32 data);
88: uint32 Read16(uint32 addr);
89: void Write16(uint32 addr, uint32 data);
90:
91: // アドレス変換 (デバッガ用)
1.1.1.2 ! root 92: busaddr 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:
122: uint32 Fetch8();
123: uint32 Fetch16();
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:
149: uint32 Peek8(uint32 addr) const;
150: uint32 Peek16(uint32 addr) const;
151:
152: void Push16(uint32 data);
153: uint32 Pop16();
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:
215: int ixiy {}; // 0=HL, 1=IX, 2=IY
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
223: int int0mode {}; // INT0 mode
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: Debugger *debugger {};
298: PIO0Device *pio0 {};
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:
309: // イベント
310: EventCallback_t exec_func {}; // 実行コールバック
311: Event exec_event { this };
312: Event timer_event { this };
313:
314: // 名前
315: static const char * const opmode_names[];
316: static std::vector<const char *> ionames;
317: };
318:
319: static inline MPU64180Device *GetMPU64180Device() {
320: return Object::GetObject<MPU64180Device>(OBJ_MPUXP);
321: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.