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

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:        // ブランチ履歴 (例外履歴を含む)
1.1.1.9 ! root      236:        BranchHistory_m680x0 brhist { BranchHistory::BrHist };
1.1.1.4   root      237:        // 例外履歴のみ
1.1.1.9 ! root      238:        BranchHistory_m680x0 exhist { BranchHistory::ExHistOnly };
1.1       root      239: 
                    240:        // バス
                    241:        m68kbus bus {};
                    242: 
                    243:        // A-Line, F-Line 命令エミュレーションのコールバックとユーザ引数。
                    244:        // ユーザ引数には関与しないので呼び出し側が自由に指定してよい。
                    245:        // コールバック側で処理完了したら true を返す。
                    246:        // デフォルトの処理(すなわちm68k例外)にする場合は false を返す。
1.1.1.5   root      247:        bool (*aline_callback)(m68kcpu *, void *) {};
                    248:        void *aline_arg {};
                    249:        bool (*fline_callback)(m68kcpu *, void *) {};
                    250:        void *fline_arg {};
1.1.1.3   root      251: 
                    252:        // ダブルバスフォールトのコールバックとユーザ引数。
1.1.1.5   root      253:        void (*halt_callback)(void *) {};
                    254:        void *halt_arg {};
1.1       root      255: };
                    256: 
                    257: #define RegD(n)                (cpu->reg.da[(n)])
                    258: #define RegA(n)                (cpu->reg.da[(n) + 8])
                    259: #define RegR(n)                (cpu->reg.da[(n)])
                    260: #define RegPC                  (cpu->reg.pc)
                    261: #define RegPPC                 (cpu->ppc)
                    262: #define RegIR                  (cpu->ir)
                    263: #define RegIR2                 (cpu->ir2)
                    264: #define RegSR                  (cpu->reg.sr_h() | cpu->reg.ccr.Get())
                    265: #define RegVBR                 (cpu->reg.vbr)
                    266: #define RegUSP                 (cpu->reg.usp)
                    267: #define RegISP                 (cpu->reg.isp)
                    268: #define RegMSP                 (cpu->reg.msp)
                    269: #define RegSFC                 (cpu->reg.sfc)
                    270: #define RegDFC                 (cpu->reg.dfc)
                    271: #define RegCACR                (cpu->reg.cacr)
                    272: #define RegCAAR                (cpu->reg.caar)
                    273: 
                    274: #define RegFP(n)       (cpu->reg.fpframe.fpf_regs[n])
                    275: #define RegFPCR                (cpu->reg.fpframe.fpf_fpcr)
                    276: #define RegFPSR                (cpu->reg.fpframe.fpf_fpsr)
                    277: #define RegFPIAR       (cpu->reg.fpframe.fpf_fpiar)
                    278: 
                    279: #define RegIRX                 ((RegIR >> 9) & 7)
                    280: #define RegIRY                 (RegIR & 7)
                    281: #define RegDX                  RegD(RegIRX)
                    282: #define RegAX                  RegA(RegIRX)
                    283: #define RegDY                  RegD(RegIRY)
                    284: #define RegAY                  RegA(RegIRY)
                    285: 
                    286: // 外部公開ルーチン
1.1.1.8   root      287: extern m68kcpu *m68030_init();
1.1.1.6   root      288: extern uint32 m68030_run(m68kcpu *cpu, uint32 delta);
1.1.1.7   root      289: extern void m68030_set_clockspeed(m68kcpu *cpu, uint32 clock_khz);
1.1.1.6   root      290: extern uint64 m68030_get_vtime(m68kcpu *cpu);
1.1.1.8   root      291: extern void m68030_power_on(m68kcpu *cpu);
1.1.1.6   root      292: extern void m68030_request_reset_exception(m68kcpu *cpu);
                    293: extern void m68030_interrupt(m68kcpu *cpu, int level);
1.1.1.5   root      294: extern const char *m68030_get_exception_name(int vector);
1.1       root      295: 
                    296: // 外部で定義されるコールバック
                    297: extern void m68030_reset_inst(m68kcpu *cpu);
1.1.1.6   root      298: 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.