Annotation of nono/m680x0/m68030.h, revision 1.1.1.10

1.1       root        1: //
                      2: // nono
1.1.1.3   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
                      7: #pragma once
                      8: 
                      9: //
                     10: // 外部公開用
                     11: //
                     12: 
1.1.1.3   root       13: #include "branchhistory.h"
1.1       root       14: #include <atomic>
                     15: #include <mutex>
                     16: #include <sys/cdefs.h>
                     17: 
                     18: __BEGIN_DECLS
                     19: #include "fpu_emulate.h"
                     20: __END_DECLS
                     21: 
                     22: class m68kcpu;
                     23: 
                     24: // 外部ループフラグ
                     25: // これらのフラグがいずれも立っていない間、CPU 実行は内側のディスパッチ
                     26: // ループを周り、どれかでも立てばディスパッチループを抜けてフラグを処理
                     27: // してから再びディスパッチループに戻る。
                     28: // それぞれ独立しているためビットを立てる際は代入ではなく OR すること。
                     29: #define CPU_REQ_STOP           (0x00000001)    // ストップ状態
                     30: #define CPU_REQ_HALT           (0x00000002)    // ホールト状態
                     31: #define CPU_REQ_TRACE          (0x00000004)    // デバッガ有効
                     32: #define CPU_REQ_PROMPT         (0x00000008)    // デバッガプロンプト
                     33: #define CPU_REQ_RELEASE                (0x00000010)    // 命令後に CPU 実行中断
                     34: #define CPU_REQ_INTR           (0x00000020)    // 命令後に割り込みチェックが必要
1.1.1.6   root       35: #define CPU_REQ_RESET          (0x00000040)    // リセット例外
1.1       root       36: 
                     37: #define M68K_SR_T      (0xc000)
                     38: #define M68K_SR_S      (0x2000)
                     39: #define M68K_SR_M      (0x1000)
                     40: #define M68K_CCR_X     (0x0010)
                     41: #define M68K_CCR_N     (0x0008)
                     42: #define M68K_CCR_Z     (0x0004)
                     43: #define M68K_CCR_V     (0x0002)
                     44: #define M68K_CCR_C     (0x0001)
                     45: 
                     46: // SSW
                     47: #define SSW_SIZE(x)            (((x) & 0x03) << 4)
                     48: #define SSW_SIZE_BYTE  SSW_SIZE(1)
                     49: #define SSW_SIZE_WORD  SSW_SIZE(2)
                     50: #define SSW_SIZE_3BYTES        SSW_SIZE(3)
                     51: #define SSW_SIZE_LONG  SSW_SIZE(0)
                     52: #define SSW_SIZE_MASK  SSW_SIZE(0x03)
                     53: 
                     54: #define SSW_FC_MASK            (0x0007)        // FC_*
                     55: #define SSW_RW                 (0x0040)        // SSW_BUS_{R,W}
                     56: #define SSW_RM                 (0x0080)
                     57: #define SSW_DF                 (0x0100)        // Data Fault
                     58: #define SSW_RB                 (0x1000)
                     59: #define SSW_RC                 (0x2000)
                     60: #define SSW_FB                 (0x4000)
                     61: #define SSW_FC                 (0x8000)
                     62: 
                     63: #define SSW_BUS_R              (0x0040)
                     64: #define SSW_BUS_W              (0x0000)
                     65: 
                     66: #define FC_DATA                        (1)
                     67: #define FC_PROG                        (2)
                     68: #define FC_USER                        (0)
                     69: #define FC_SUPER               (4)
                     70: #define FC_UD                  (FC_USER  | FC_DATA)
                     71: #define FC_UP                  (FC_USER  | FC_PROG)
                     72: #define FC_SD                  (FC_SUPER | FC_DATA)
                     73: #define FC_SP                  (FC_SUPER | FC_PROG)
                     74: 
1.1.1.10! root       75: #define M68K_CACR_EI   (0x0001)
        !            76: #define M68K_CACR_FI   (0x0002)
        !            77: #define M68K_CACR_CEI  (0x0004)
        !            78: #define M68K_CACR_CI   (0x0008)
        !            79: #define M68K_CACR_IBE  (0x0010)
        !            80: #define M68K_CACR_ED   (0x0100)
        !            81: #define M68K_CACR_FD   (0x0200)
        !            82: #define M68K_CACR_CED  (0x0400)
        !            83: #define M68K_CACR_CD   (0x0800)
        !            84: #define M68K_CACR_DBE  (0x1000)
        !            85: #define M68K_CACR_WA   (0x2000)
        !            86: 
1.1       root       87: #define M68K_FPCR_MASK (0x0000fff0)
                     88: #define M68K_FPSR_MASK (0x0ffffff8)
                     89: 
                     90: #include "m68030ccr.h"
                     91: #include "m68030mmu.h"
                     92: 
                     93: // レジスタイメージを保持する構造体。
                     94: // この構造体はコピーとか比較をするのでポインタとかは置かないこと。
                     95: struct m68kreg {
                     96:  public:
                     97:        uint32 pc;
                     98:        uint32 da[16];
                     99: 
                    100:        m68030ccr ccr;
                    101:        bool s;                         // SR の S ビット
                    102:        bool m;                         // SR の M ビット
                    103:        int  intr_level;        // SR の割り込みレベル (0-7)
                    104: 
1.1.1.10! root      105:        // 現在の SP は常に da[15]。da[15] が示しているときは対応する変数の
        !           106:        // ほうは更新されないため無効。
        !           107:        // ユーザ状態なら da[15] が USP を示し usp は無効、
        !           108:        // isp, msp は ISP, MSP を示して有効。
        !           109:        // スーパバイザ状態で SR_M なら da[15] が MSP を示し msp は無効、
        !           110:        // isp, usp は ISP, USP を示して有効。
        !           111:        // スーパバイザ状態で !SR_M なら da[15] が ISP を示し isp は無効、
        !           112:        // msp, usp は MSP, USP を示して有効。
1.1       root      113:        uint32 usp;
                    114:        uint32 isp;
                    115:        uint32 msp;
                    116: 
                    117:        uint32 vbr;
                    118:        uint32 sfc;
                    119:        uint32 dfc;
                    120: 
                    121:        uint32 cacr;
                    122:        uint32 caar;
                    123: 
                    124:        union64 srp;
                    125:        union64 crp;
                    126:        uint32 tt[2];
                    127:        uint32 tc;
                    128:        uint16 mmusr;
                    129: 
                    130:        struct fpframe fpframe;
                    131: 
1.1.1.7   root      132:        // CPU の実行状態 (SCHED_CPU_*)
1.1       root      133:        uint32 state;
                    134: 
                    135:  public:
                    136:        // SR の上位8ビット部分のみを返す
                    137:        uint16 sr_h() {
                    138:                return (s ? M68K_SR_S : 0) | (m ? M68K_SR_M : 0) | (intr_level << 8);
                    139:        }
                    140: };
                    141: 
                    142: // バス状態
                    143: struct m68kbus {
                    144:        // 論理アドレスと SSW。
                    145:        // SSW はアクセス前に SSW_BUS_{R,W} と FC[012] をセットすること。
                    146:        DEF_UNION64(, ssw_laddr, ssw, laddr);
                    147: 
                    148:        uint32 paddr;                   // 対応する物理アドレス
                    149:        // データバス。
                    150:        // 今の所書き込みだけで使う。読み込みデータは戻り値のみ。
                    151:        uint32 data;
                    152: 
                    153:        // SSW のうち現在の FC2 だけ別途覚えておく。
                    154:        // FC2 が変化するのは SR:S による特権モードが変わった時だけなので。
                    155:        uint16 fc2;
                    156: 
                    157:        // バスが Write なら true を返す
                    158:        bool IsWrite() const { return (ssw & SSW_BUS_R) == 0; }
                    159: 
                    160:        // このへんどうするか
                    161: 
                    162:        // FC2 をキャッシュしておく。
                    163:        void SetFC2(bool newfc2) {
                    164:                fc2 = newfc2 ? 4 : 0;
                    165:        }
                    166:        // FC を取得する。
                    167:        // これは MMU ルーチンから呼ばれる。そのためこの時点ではすでに
                    168:        // FC0/1 と FC2 は ssw に合成済みなので、これでよい。
                    169:        uint GetFC() const { return ssw & SSW_FC_MASK; }
                    170: };
                    171: 
1.1.1.3   root      172: class m68kcpu final {
1.1       root      173:  public:
                    174:        m68kcpu() { }
1.1.1.3   root      175:        ~m68kcpu() { }
1.1       root      176: 
                    177:  public:
                    178:        m68kreg reg {};
1.1.1.5   root      179:        uint32 ppc {};                  // 現在実行中の命令の先頭アドレス
                    180:        uint16 ir {};
                    181:        uint16 ir2 {};
1.1       root      182: 
                    183:        uint32 save_pd[8] {};   // -(An) を保存
                    184:        uint32 save_pi[8] {};   // (An)+ を保存
1.1.1.5   root      185:        uint8  flag_pd {};              // -(An) のどのレジスタを保存したか
                    186:        uint8  flag_pi {};              // (An)+ のどのレジスタを保存したか
1.1       root      187: 
                    188:        // MMU 状態
1.1.1.5   root      189:        bool mmu_enable {};
1.1       root      190:        // SRP
                    191:        void SetSRP(uint32, uint32);
                    192:        uint64 GetSRP()  const { return reg.srp.q; }
                    193:        uint32 GetSRPh() const { return reg.srp.h; }
                    194:        uint32 GetSRPl() const { return reg.srp.l; }
                    195:        // CRP
                    196:        void SetCRP(uint32, uint32);
                    197:        uint64 GetCRP()  const { return reg.crp.q; }
                    198:        uint32 GetCRPh() const { return reg.crp.h; }
                    199:        uint32 GetCRPl() const { return reg.crp.l; }
                    200:        // TT
                    201:        void SetTT(int idx, uint32);
                    202:        uint64 GetTT(int idx) const { return reg.tt[idx]; }
                    203:        // TC
                    204:        bool SetTC(uint32);
                    205:        uint32 GetTC() const { return reg.tc; }
                    206:        // MMUSR
                    207:        void SetMMUSR(uint16);
                    208:        uint16 GetMMUSR() const { return reg.mmusr; }
                    209:        // MMU work
1.1.1.5   root      210:        m68030TT mmu_tt[2] {};
1.1       root      211:        uint8 mmu_tt_quick[256] {};
1.1.1.5   root      212:        m68030TC mmu_tc {};
1.1       root      213:        m68030ATC atc {this};
                    214: 
                    215:  private:
                    216:        void mmu_enable_changed();
                    217: 
                    218:  public:
1.1.1.5   root      219:        int has_fpu {};                 // 0:FPUなし、1:68881、2:68882(?)
                    220:        bool fpu_dirty {};
1.1       root      221:        struct fpemu fe {};
                    222: 
                    223:        std::atomic<uint32> atomic_reqflag {}; // 外部ループ & リクエストフラグ
                    224: 
1.1.1.6   root      225:        // 割り込みペンディングレベル
                    226:        // 外部から入力されている(最も高い)割り込みレベルを保持する。
                    227:        int intr_pending {};
                    228: 
                    229:        // 仮想時刻 [nsec]
                    230:        uint64 total_vtime {};
                    231: 
                    232:        // サイクル数を仮想時間 [nsec] に変換
                    233:        uint64 Cycle2Vtime(int32 cycle) const {
1.1.1.7   root      234:                return (int64)cycle * c2v;
1.1.1.6   root      235:        }
                    236: 
                    237:        // 仮想時間 [nsec] をサイクル数に変換
                    238:        uint32 Vtime2Cycle(uint32 vtime) const {
1.1.1.7   root      239:                return ((uint64)vtime * v2c_factor) >> v2c_shift;
1.1.1.6   root      240:        }
                    241: 
                    242:        uint32 used_cycle {};           // 現在のターンでこれまでに消費したサイクル数
                    243:        uint32 goal_cycle {};           // 現在のターンで消費すべきサイクル数
                    244:        int32 cycle_nocache {};         // ノーキャッシュケースの時の追加分
                    245:        uint32 clock_khz {};            // MPU クロック [kHz]
1.1.1.7   root      246:        uint32 c2v {};                          // サイクル数を nsec に変換する際の係数
                    247:        uint64 v2c_factor {};           // nsec をサイクル数に変換する際の乗算係数
                    248:        uint32 v2c_shift {};            // nsec をサイクル数に変換する際のシフト係数
                    249: 
1.1.1.5   root      250:        uint64 inst_count {};           // 命令実行数
1.1       root      251: 
1.1.1.4   root      252:        // ブランチ履歴 (例外履歴を含む)
1.1.1.9   root      253:        BranchHistory_m680x0 brhist { BranchHistory::BrHist };
1.1.1.4   root      254:        // 例外履歴のみ
1.1.1.9   root      255:        BranchHistory_m680x0 exhist { BranchHistory::ExHistOnly };
1.1       root      256: 
                    257:        // バス
                    258:        m68kbus bus {};
                    259: 
                    260:        // A-Line, F-Line 命令エミュレーションのコールバックとユーザ引数。
                    261:        // ユーザ引数には関与しないので呼び出し側が自由に指定してよい。
                    262:        // コールバック側で処理完了したら true を返す。
                    263:        // デフォルトの処理(すなわちm68k例外)にする場合は false を返す。
1.1.1.5   root      264:        bool (*aline_callback)(m68kcpu *, void *) {};
                    265:        void *aline_arg {};
                    266:        bool (*fline_callback)(m68kcpu *, void *) {};
                    267:        void *fline_arg {};
1.1.1.3   root      268: 
                    269:        // ダブルバスフォールトのコールバックとユーザ引数。
1.1.1.5   root      270:        void (*halt_callback)(void *) {};
                    271:        void *halt_arg {};
1.1       root      272: };
                    273: 
                    274: #define RegD(n)                (cpu->reg.da[(n)])
                    275: #define RegA(n)                (cpu->reg.da[(n) + 8])
                    276: #define RegR(n)                (cpu->reg.da[(n)])
                    277: #define RegPC                  (cpu->reg.pc)
                    278: #define RegPPC                 (cpu->ppc)
                    279: #define RegIR                  (cpu->ir)
                    280: #define RegIR2                 (cpu->ir2)
                    281: #define RegSR                  (cpu->reg.sr_h() | cpu->reg.ccr.Get())
                    282: #define RegVBR                 (cpu->reg.vbr)
                    283: #define RegUSP                 (cpu->reg.usp)
                    284: #define RegISP                 (cpu->reg.isp)
                    285: #define RegMSP                 (cpu->reg.msp)
                    286: #define RegSFC                 (cpu->reg.sfc)
                    287: #define RegDFC                 (cpu->reg.dfc)
                    288: #define RegCACR                (cpu->reg.cacr)
                    289: #define RegCAAR                (cpu->reg.caar)
                    290: 
                    291: #define RegFP(n)       (cpu->reg.fpframe.fpf_regs[n])
                    292: #define RegFPCR                (cpu->reg.fpframe.fpf_fpcr)
                    293: #define RegFPSR                (cpu->reg.fpframe.fpf_fpsr)
                    294: #define RegFPIAR       (cpu->reg.fpframe.fpf_fpiar)
                    295: 
                    296: #define RegIRX                 ((RegIR >> 9) & 7)
                    297: #define RegIRY                 (RegIR & 7)
                    298: #define RegDX                  RegD(RegIRX)
                    299: #define RegAX                  RegA(RegIRX)
                    300: #define RegDY                  RegD(RegIRY)
                    301: #define RegAY                  RegA(RegIRY)
                    302: 
                    303: // 外部公開ルーチン
1.1.1.8   root      304: extern m68kcpu *m68030_init();
1.1.1.6   root      305: extern uint32 m68030_run(m68kcpu *cpu, uint32 delta);
1.1.1.7   root      306: extern void m68030_set_clockspeed(m68kcpu *cpu, uint32 clock_khz);
1.1.1.6   root      307: extern uint64 m68030_get_vtime(m68kcpu *cpu);
1.1.1.8   root      308: extern void m68030_power_on(m68kcpu *cpu);
1.1.1.6   root      309: extern void m68030_request_reset_exception(m68kcpu *cpu);
                    310: extern void m68030_interrupt(m68kcpu *cpu, int level);
1.1.1.5   root      311: extern const char *m68030_get_exception_name(int vector);
1.1       root      312: 
                    313: // 外部で定義されるコールバック
                    314: extern void m68030_reset_inst(m68kcpu *cpu);
1.1.1.6   root      315: extern int  m68030_interrupt_acknowledge(int level);

unix.superglobalmegacorp.com

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