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