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

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: 
                     75: #define M68K_FPCR_MASK (0x0000fff0)
                     76: #define M68K_FPSR_MASK (0x0ffffff8)
                     77: 
                     78: #include "m68030ccr.h"
                     79: #include "m68030mmu.h"
                     80: 
                     81: // レジスタイメージを保持する構造体。
                     82: // この構造体はコピーとか比較をするのでポインタとかは置かないこと。
                     83: struct m68kreg {
                     84:  public:
                     85:        uint32 pc;
                     86:        uint32 da[16];
                     87: 
                     88:        m68030ccr ccr;
                     89:        bool s;                         // SR の S ビット
                     90:        bool m;                         // SR の M ビット
                     91:        int  intr_level;        // SR の割り込みレベル (0-7)
                     92: 
                     93:        // 現在の SP は常に da[15]。現在有効でない残り2つの SP をここに保存。
                     94:        // 例えばユーザ状態なら da[15] が USP、isp/msp は ISP/MSP を示し、
                     95:        // usp の内容は無効。
                     96:        uint32 usp;
                     97:        uint32 isp;
                     98:        uint32 msp;
                     99: 
                    100:        uint32 vbr;
                    101:        uint32 sfc;
                    102:        uint32 dfc;
                    103: 
                    104:        uint32 cacr;
                    105:        uint32 caar;
                    106: 
                    107:        union64 srp;
                    108:        union64 crp;
                    109:        uint32 tt[2];
                    110:        uint32 tc;
                    111:        uint16 mmusr;
                    112: 
                    113:        struct fpframe fpframe;
                    114: 
                    115:        // CPU の実行状態
                    116:        //  0            .. 通常状態
                    117:        //  CPU_REQ_STOP .. STOP 状態
                    118:        //  CPU_REQ_HALT .. HALT 状態
                    119:        uint32 state;
                    120: 
                    121:  public:
                    122:        // SR の上位8ビット部分のみを返す
                    123:        uint16 sr_h() {
                    124:                return (s ? M68K_SR_S : 0) | (m ? M68K_SR_M : 0) | (intr_level << 8);
                    125:        }
                    126: };
                    127: 
                    128: // バス状態
                    129: struct m68kbus {
                    130:        // 論理アドレスと SSW。
                    131:        // SSW はアクセス前に SSW_BUS_{R,W} と FC[012] をセットすること。
                    132:        DEF_UNION64(, ssw_laddr, ssw, laddr);
                    133: 
                    134:        uint32 paddr;                   // 対応する物理アドレス
                    135:        // データバス。
                    136:        // 今の所書き込みだけで使う。読み込みデータは戻り値のみ。
                    137:        uint32 data;
                    138: 
                    139:        // SSW のうち現在の FC2 だけ別途覚えておく。
                    140:        // FC2 が変化するのは SR:S による特権モードが変わった時だけなので。
                    141:        uint16 fc2;
                    142: 
                    143:        // バスが Write なら true を返す
                    144:        bool IsWrite() const { return (ssw & SSW_BUS_R) == 0; }
                    145: 
                    146:        // このへんどうするか
                    147: 
                    148:        // FC2 をキャッシュしておく。
                    149:        void SetFC2(bool newfc2) {
                    150:                fc2 = newfc2 ? 4 : 0;
                    151:        }
                    152:        // FC を取得する。
                    153:        // これは MMU ルーチンから呼ばれる。そのためこの時点ではすでに
                    154:        // FC0/1 と FC2 は ssw に合成済みなので、これでよい。
                    155:        uint GetFC() const { return ssw & SSW_FC_MASK; }
                    156: };
                    157: 
1.1.1.3   root      158: class m68kcpu final {
1.1       root      159:  public:
                    160:        m68kcpu() { }
1.1.1.3   root      161:        ~m68kcpu() { }
1.1       root      162: 
                    163:  public:
                    164:        m68kreg reg {};
1.1.1.5   root      165:        uint32 ppc {};                  // 現在実行中の命令の先頭アドレス
                    166:        uint16 ir {};
                    167:        uint16 ir2 {};
1.1       root      168: 
                    169:        uint32 save_pd[8] {};   // -(An) を保存
                    170:        uint32 save_pi[8] {};   // (An)+ を保存
1.1.1.5   root      171:        uint8  flag_pd {};              // -(An) のどのレジスタを保存したか
                    172:        uint8  flag_pi {};              // (An)+ のどのレジスタを保存したか
1.1       root      173: 
                    174:        // MMU 状態
1.1.1.5   root      175:        bool mmu_enable {};
1.1       root      176:        // SRP
                    177:        void SetSRP(uint32, uint32);
                    178:        uint64 GetSRP()  const { return reg.srp.q; }
                    179:        uint32 GetSRPh() const { return reg.srp.h; }
                    180:        uint32 GetSRPl() const { return reg.srp.l; }
                    181:        // CRP
                    182:        void SetCRP(uint32, uint32);
                    183:        uint64 GetCRP()  const { return reg.crp.q; }
                    184:        uint32 GetCRPh() const { return reg.crp.h; }
                    185:        uint32 GetCRPl() const { return reg.crp.l; }
                    186:        // TT
                    187:        void SetTT(int idx, uint32);
                    188:        uint64 GetTT(int idx) const { return reg.tt[idx]; }
                    189:        // TC
                    190:        bool SetTC(uint32);
                    191:        uint32 GetTC() const { return reg.tc; }
                    192:        // MMUSR
                    193:        void SetMMUSR(uint16);
                    194:        uint16 GetMMUSR() const { return reg.mmusr; }
                    195:        // MMU work
1.1.1.5   root      196:        m68030TT mmu_tt[2] {};
1.1       root      197:        uint8 mmu_tt_quick[256] {};
1.1.1.5   root      198:        m68030TC mmu_tc {};
1.1       root      199:        m68030ATC atc {this};
                    200: 
                    201:  private:
                    202:        void mmu_enable_changed();
                    203: 
                    204:  public:
1.1.1.5   root      205:        int has_fpu {};                 // 0:FPUなし、1:68881、2:68882(?)
                    206:        bool fpu_dirty {};
1.1       root      207:        struct fpemu fe {};
                    208: 
                    209:        std::atomic<uint32> atomic_reqflag {}; // 外部ループ & リクエストフラグ
                    210: 
1.1.1.6 ! root      211:        // 割り込みペンディングレベル
        !           212:        // 外部から入力されている(最も高い)割り込みレベルを保持する。
        !           213:        int intr_pending {};
        !           214: 
        !           215:        // 仮想時刻 [nsec]
        !           216:        uint64 total_vtime {};
        !           217: 
        !           218:        // サイクル数を仮想時間 [nsec] に変換
        !           219:        uint64 Cycle2Vtime(int32 cycle) const {
        !           220:                return (int64)cycle * 1000 * 1000 / clock_khz;
        !           221:        }
        !           222: 
        !           223:        // 仮想時間 [nsec] をサイクル数に変換
        !           224:        uint32 Vtime2Cycle(uint32 vtime) const {
        !           225:                return (uint32)((uint64)vtime * clock_khz / (1000 * 1000));
        !           226:        }
        !           227: 
        !           228:        uint32 used_cycle {};           // 現在のターンでこれまでに消費したサイクル数
        !           229:        uint32 goal_cycle {};           // 現在のターンで消費すべきサイクル数
        !           230:        int32 cycle_nocache {};         // ノーキャッシュケースの時の追加分
        !           231:        uint32 clock_khz {};            // MPU クロック [kHz]
1.1.1.5   root      232:        uint64 inst_count {};           // 命令実行数
1.1       root      233: 
1.1.1.4   root      234:        // ブランチ履歴 (例外履歴を含む)
                    235:        BranchHistory_m680x0 brhist {};
                    236:        // 例外履歴のみ
                    237:        BranchHistory_m680x0 exhist {};
1.1       root      238: 
                    239:        // バス
                    240:        m68kbus bus {};
                    241: 
                    242:        // 手抜きのためリセットベクタ取得アドレスを知っている。
                    243:        // リセット時のためだけにデバイス側に細工を入れるのは実行時の
                    244:        // オーバーヘッドが大きそうなので。
1.1.1.5   root      245:        uint32 reset_vector {};
1.1       root      246: 
                    247:        // A-Line, F-Line 命令エミュレーションのコールバックとユーザ引数。
                    248:        // ユーザ引数には関与しないので呼び出し側が自由に指定してよい。
                    249:        // コールバック側で処理完了したら true を返す。
                    250:        // デフォルトの処理(すなわちm68k例外)にする場合は false を返す。
1.1.1.5   root      251:        bool (*aline_callback)(m68kcpu *, void *) {};
                    252:        void *aline_arg {};
                    253:        bool (*fline_callback)(m68kcpu *, void *) {};
                    254:        void *fline_arg {};
1.1.1.3   root      255: 
                    256:        // ダブルバスフォールトのコールバックとユーザ引数。
1.1.1.5   root      257:        void (*halt_callback)(void *) {};
                    258:        void *halt_arg {};
1.1       root      259: };
                    260: 
                    261: #define RegD(n)                (cpu->reg.da[(n)])
                    262: #define RegA(n)                (cpu->reg.da[(n) + 8])
                    263: #define RegR(n)                (cpu->reg.da[(n)])
                    264: #define RegPC                  (cpu->reg.pc)
                    265: #define RegPPC                 (cpu->ppc)
                    266: #define RegIR                  (cpu->ir)
                    267: #define RegIR2                 (cpu->ir2)
                    268: #define RegSR                  (cpu->reg.sr_h() | cpu->reg.ccr.Get())
                    269: #define RegVBR                 (cpu->reg.vbr)
                    270: #define RegUSP                 (cpu->reg.usp)
                    271: #define RegISP                 (cpu->reg.isp)
                    272: #define RegMSP                 (cpu->reg.msp)
                    273: #define RegSFC                 (cpu->reg.sfc)
                    274: #define RegDFC                 (cpu->reg.dfc)
                    275: #define RegCACR                (cpu->reg.cacr)
                    276: #define RegCAAR                (cpu->reg.caar)
                    277: 
                    278: #define RegFP(n)       (cpu->reg.fpframe.fpf_regs[n])
                    279: #define RegFPCR                (cpu->reg.fpframe.fpf_fpcr)
                    280: #define RegFPSR                (cpu->reg.fpframe.fpf_fpsr)
                    281: #define RegFPIAR       (cpu->reg.fpframe.fpf_fpiar)
                    282: 
                    283: #define RegIRX                 ((RegIR >> 9) & 7)
                    284: #define RegIRY                 (RegIR & 7)
                    285: #define RegDX                  RegD(RegIRX)
                    286: #define RegAX                  RegA(RegIRX)
                    287: #define RegDY                  RegD(RegIRY)
                    288: #define RegAY                  RegA(RegIRY)
                    289: 
                    290: // 外部公開ルーチン
                    291: extern m68kcpu *m68030_init(uint32 reset_vector);
1.1.1.6 ! root      292: extern uint32 m68030_run(m68kcpu *cpu, uint32 delta);
        !           293: extern uint64 m68030_get_vtime(m68kcpu *cpu);
        !           294: extern void m68030_request_reset_exception(m68kcpu *cpu);
        !           295: extern void m68030_interrupt(m68kcpu *cpu, int level);
1.1.1.5   root      296: extern const char *m68030_get_exception_name(int vector);
1.1       root      297: 
                    298: // 外部で定義されるコールバック
                    299: extern void m68030_reset_inst(m68kcpu *cpu);
1.1.1.6 ! root      300: 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.