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