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

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