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

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