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