|
|
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);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.