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