|
|
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(); ! 48: virtual ~MPU64180Device() override; ! 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: // アドレス変換 (デバッガ用) ! 92: uint64 TranslatePeek(uint32) const; ! 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.