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