Annotation of nono/vm/mpu64180.h, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.