|
|
1.1 root 1: //
2: // nono
1.1.1.2 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
1.1.1.10 root 7: //
8: // MPU (MC68030)
9: //
1.1 root 10:
11: #pragma once
12:
13: #include "mpu.h"
1.1.1.11 root 14: #include "branchhistory.h"
1.1.1.13 root 15: #include "bus.h"
1.1.1.11 root 16: #include "event.h"
1.1.1.15 root 17: #include "m680x0.h"
1.1.1.11 root 18: #include "m68030mmu.h"
1.1.1.15 root 19: #include <array>
1.1.1.11 root 20:
21: class InterruptDevice;
1.1.1.13 root 22: class m68030Cache;
1.1.1.14 root 23: struct m68030CacheLine;
1.1.1.15 root 24: enum class m68030MPUType;
25: class m68040TT;
26: class m68040TC;
27: class m68040ATC;
28: class m68040ATCEntry;
1.1 root 29:
1.1.1.14 root 30: class MPU680x0Device : public MainMPUDevice
1.1 root 31: {
1.1.1.14 root 32: using inherited = MainMPUDevice;
1.1.1.11 root 33: friend class m68030MMU;
34:
35: // CPU の実行状態
36: static const uint32 CPU_STATE_NORMAL = 0;
37: static const uint32 CPU_STATE_STOP = 1;
38: static const uint32 CPU_STATE_HALT = 2;
39:
1.1 root 40: public:
1.1.1.7 root 41: MPU680x0Device();
1.1.1.13 root 42: ~MPU680x0Device() override;
1.1 root 43:
1.1.1.2 root 44: bool Init() override;
1.1.1.10 root 45: void ResetHard(bool poweron) override;
1.1 root 46:
47: // 現在の PPC を取得
1.1.1.11 root 48: uint32 GetPPC() const override { return ppc; }
1.1 root 49:
1.1.1.10 root 50: // 現在の VBR を取得
1.1.1.11 root 51: uint32 GetVBR() const override { return reg.vbr; }
52:
1.1.1.15 root 53: // MPU 種別を取得
54: m680x0MPUType GetMPUType() const { return mpu_type; }
55:
56: // FPU
57: m680x0FPUType GetFPUType() const { return fpu_type; }
58: bool HasFPU() const { return fpu_type.Is4060FPU() || fpu_type.Is6888x(); }
59:
1.1.1.13 root 60: // MPU 名を取得
1.1.1.15 root 61: const char *GetMPUName() const override { return mpu_name; }
1.1.1.13 root 62:
1.1.1.11 root 63: bool IsSuper() const { return reg.s; }
64: bool IsMaster() const { return reg.m; }
65:
66: // CPU の実行状態 (uint32) を返す。
67: uint32 GetState() const { return cpu_state; }
1.1.1.10 root 68:
1.1 root 69: // 現在アクセス中の論理アドレス、物理アドレスを取得。
1.1.1.13 root 70: uint32 GetLaddr() const override { return bus.laddr.Addr(); }
71: uint32 GetPaddr() const override { return bus.paddr.Addr(); }
1.1 root 72:
1.1.1.5 root 73: // 割り込みレベルが変わったことを MPU に通知
74: void Interrupt(int level) override;
1.1 root 75:
76: // A-Line, F-Line 命令エミュレーションのコールバックを指定する。
77: // (Human68k エミュレーションで使用)
1.1.1.11 root 78: void SetALineCallback(bool (*callback)(MPU680x0Device*, void*), void *arg);
79: void SetFLineCallback(bool (*callback)(MPU680x0Device*, void*), void *arg);
1.1 root 80:
1.1.1.14 root 81: // バーストアクセスをサポートするか
82: void EnableBurstAccess(bool enable) { has_burst_access = enable; }
83:
1.1.1.13 root 84: void SetCI() override {
85: bus.ci = true;
86: }
1.1.1.9 root 87:
1.1.1.11 root 88: // ホールト
1.1.1.10 root 89: void Halt();
90:
1.1.1.11 root 91: // 基本アクセス。内部から使用する。
92: // アドレスは論理アドレスで、空間は現在の命令/データ空間。
93: // バスエラーなら C++ の例外をスローする。
1.1.1.15 root 94: virtual uint32 fetch_2() = 0;
95: virtual uint32 fetch_4() = 0;
1.1.1.14 root 96: uint32 read_n(uint32 laddr, uint size) {
97: busaddr addr =
98: busaddr(laddr) | fc_data | BusAddr::R | busaddr::Size(size);
99: return read_data(addr);
100: }
101: void write_n(uint32 laddr, uint size, uint32 data) {
102: busaddr addr =
103: busaddr(laddr) | fc_data | BusAddr::W | busaddr::Size(size);
104: write_data(addr, data);
105: }
106: uint32 read_1(uint32 laddr) { return read_n(laddr, 1); }
107: uint32 read_2(uint32 laddr) { return read_n(laddr, 2); }
108: uint32 read_4(uint32 laddr) { return read_n(laddr, 4); }
109: void write_1(uint32 laddr, uint32 data) { write_n(laddr, 1, data); }
110: void write_2(uint32 laddr, uint32 data) { write_n(laddr, 2, data); }
111: void write_4(uint32 laddr, uint32 data) { write_n(laddr, 4, data); }
1.1.1.11 root 112:
113: // MMU アクセス
1.1.1.15 root 114: virtual busaddr TranslatePeek(busaddr laddr) = 0;
1.1.1.14 root 115: // 統計
1.1.1.15 root 116: virtual void CalcStat() = 0;
1.1.1.11 root 117:
118: // レジスタ
119: uint16 GetIR() const { return ir; }
120: uint16 GetIR2() const { return ir2; }
121: // SR を変更する (Human68k から使う)
122: void SetSR(uint16);
123: uint16 GetSR() const { return reg.GetSR(); }
124:
1.1.1.15 root 125: protected:
1.1.1.10 root 126: // リセット例外コールバック
127: void ResetCallback(Event& ev);
128:
129: // 命令実行系コールバック
130: void ExecShort(Event& ev);
131: void ExecFull(Event& ev);
132: void ExecTrace(Event& ev);
1.1.1.5 root 133:
1.1.1.10 root 134: // トレース設定。デバッガから呼び出される。
135: void SetTrace(bool trace_on) override;
1.1.1.9 root 136:
1.1.1.10 root 137: // 割り込みイベントコールバック
138: void InterruptCallback(Event& ev);
139:
1.1.1.11 root 140: // 動作モード変更
141: void ChangeState(uint32 new_state);
1.1.1.8 root 142:
1.1.1.11 root 143: // 次の実行サイクルを Full にする。
144: void MakeNextFull();
1.1.1.8 root 145:
1.1.1.11 root 146: inline void CYCLE(int cc) {
147: used_cycle += cc;
148: }
149: inline void CYCLE2(int cc, int ncc) {
150: used_cycle += cc;
151: cycle_nocache += ncc - cc;
152: }
153:
154: // PC を addr に変更する。
155: // ベクタへのジャンプはここではなく JumpVector()。
156: inline void Jump(uint32 addr) {
157: // 先にブランチ履歴に記録
1.1.1.12 root 158: brhist.AddEntry(ppc | (IsSuper() ? 1 : 0), addr, ir);
1.1.1.11 root 159:
160: if (__predict_false((addr & 1) != 0)) {
1.1.1.12 root 161: ExceptionBuserr(M68K::EXCEP_ADDRERR);
1.1.1.11 root 162: return;
163: }
164: reg.pc = addr;
165: }
166:
167: // -(An) 実行前にレジスタを保存する。
168: // バスエラーからの復帰用。
169: inline void save_reg_pd(int n) {
170: // 該当ビットのフラグを立てる
171: flag_pd |= (1 << n);
172:
173: // 保存
174: save_pd[n] = reg.A[n];
175: }
176:
177: // (An)+ 実行前にレジスタを保存する。
178: // バスエラーからの復帰用。
179: inline void save_reg_pi(int n) {
180: // 該当ビットのフラグを立てる
181: flag_pi |= (1 << n);
182:
183: // 保存
184: save_pi[n] = reg.A[n];
185: }
186:
1.1.1.14 root 187: // -(An) 実行前にレジスタを(まだ保存してなければ)保存する。
188: // 1命令で同じレジスタを2回 -(An) する可能性がある命令用。
189: inline void save_reg_pd_if(int n) {
190: if ((flag_pd & (1 << n)) == 0) {
191: save_reg_pd(n);
192: }
193: }
194: // (An)+ 実行前にレジスタを(まだ保存してなければ)保存する。
195: // 1命令で同じレジスタを2回 (An)+ する可能性がある命令用。
196: inline void save_reg_pi_if(int n) {
197: if ((flag_pi & (1 << n)) == 0) {
198: save_reg_pi(n);
199: }
200: }
201:
1.1.1.11 root 202: void restore_reg_pi();
203: void restore_reg_pd();
1.1.1.14 root 204: void JumpVector(uint vector, bool from_buserr);
1.1.1.11 root 205:
206: protected:
1.1.1.15 root 207: #include "m680x0ea.h"
1.1.1.11 root 208:
1.1.1.15 root 209: protected:
1.1.1.11 root 210: // 基本アクセスルーチンを使った便利サブルーチン
1.1.1.14 root 211: inline void push_2(uint32 data) {
1.1.1.11 root 212: reg.A[7] -= 2;
1.1.1.14 root 213: write_2(reg.A[7], data);
1.1.1.11 root 214: }
1.1.1.14 root 215: inline void push_4(uint32 data) {
1.1.1.11 root 216: reg.A[7] -= 4;
1.1.1.14 root 217: write_4(reg.A[7], data);
1.1.1.11 root 218: }
1.1.1.14 root 219: inline uint32 pop_2() {
220: uint32 data = read_2(reg.A[7]);
1.1.1.11 root 221: reg.A[7] += 2;
222: return data;
223: }
1.1.1.14 root 224: inline uint32 pop_4() {
225: uint32 data = read_4(reg.A[7]);
1.1.1.11 root 226: reg.A[7] += 4;
227: return data;
228: }
229:
1.1.1.13 root 230: // バスアクセス
1.1.1.15 root 231: virtual uint32 read_data(busaddr addr) = 0;
232: virtual void write_data(busaddr addr, uint32 data) = 0;
1.1.1.14 root 233:
1.1.1.15 root 234: // 物理バスアクセス
1.1.1.14 root 235: busdata read_phys();
236: busdata write_phys(uint32 data);
237: bool read_phys_burst(uint32 *dst);
1.1.1.15 root 238: busdata read_phys_4(uint32 addr);
239: busdata write_phys_4(uint32 addr, uint32 data);
1.1.1.13 root 240:
1.1.1.11 root 241: #define OP_PROTO(name) void __CONCAT(op_,name)()
1.1.1.15 root 242: #include "m680x0ops.h"
1.1.1.11 root 243: #undef OP_PROTO
244:
1.1.1.14 root 245: void ops_divu_32_32(uint r, uint q);
246: void ops_divu_64_32(uint r, uint q);
247: void ops_divs_32_32(uint r, uint q);
248: void ops_divs_64_32(uint r, uint q);
1.1.1.15 root 249: void ops_link(int32 imm);
1.1.1.11 root 250: void ops_movec_rc_rn();
251: void ops_movec_rn_rc();
1.1.1.15 root 252: virtual bool ops_movec_rc_rn_cpu(uint c, uint n) = 0;
253: virtual bool ops_movec_rn_rc_cpu(uint c, uint n) = 0;
1.1.1.11 root 254: void ops_movep();
255: // もともとソース内のテンプレートだった
256: void ops_movem_list_ea(int bytesize);
257: void ops_movem_ea_list(int bytesize);
258: void ops_trapcc(uint cond);
259: inline void ops_bra();
1.1.1.15 root 260: busaddr translate_fc40(busaddr);
1.1.1.11 root 261:
262: void ops_rte();
263: void ops_stop();
264: void ops_reset();
1.1.1.15 root 265: virtual void ops_mmu30() = 0;
266: virtual void ops_mmu40_pflush() = 0;
1.1.1.11 root 267:
1.1.1.15 root 268: void ResetFPU(bool hard);
269: void fpu_init();
270: uint32 cea_fpu(int bytes);
1.1.1.16! root 271: uint32 cea_fpulc(int bytes);
1.1.1.15 root 272: void read_8(uint32 addr, uint32 *data);
273: void read_12(uint32 addr, uint32 *data);
274: void write_8(uint32 addr, const uint32 *data);
275: void write_12(uint32 addr, const uint32 *data);
276:
277: void fpu_op_illg();
278: void fpu_op_illg2();
279:
280: void fpu_op_fgen_reg();
281: void fpu_op_fgen_mem();
282: void fgen(const uint32 *srcdata, uint srcsize_id);
283: void fgen881pre(uint dstnum, const uint32 *srcdata, uint srcsize_id);
284: bool fgen040pre(uint opmode, uint dst, const uint32 *src, uint srcsize);
285: void fpu_op_fmovecr();
286: void fpu_op_fmove_to_mem();
287: void fpu_op_fmove_b_mem();
288: void fpu_op_fmove_w_mem();
289: void fpu_op_fmove_l_mem();
290: void fpu_op_fmove_s_mem();
291: void fpu_op_fmove_d_mem();
292: void fpu_op_fmove_x_mem();
293: void fpu_op_fmove_p_mem();
294: void fpu_op_fmove_ea2ctl();
295: void fpu_op_fmovem_ea2ctl();
296: void fpu_op_fmove_ctl2ea();
297: void fpu_op_fmovem_ctl2ea();
298: void fpu_op_fmovem_ea2reg();
299: void fpu_op_fmovem_reg2ea();
300: void fpu_op_fscc();
301: void fpu_op_fdbcc();
302: void fpu_op_ftrapcc_w();
303: void fpu_op_ftrapcc_l();
304: void fpu_op_ftrapcc();
305: void fpu_op_fbcc_w();
306: void fpu_op_fbcc_l();
307: void fpu_op_fsave();
308: void fpu_op_frestore();
309: void fpu_op_fsave_frame_noimpl(std::array<uint32, 13>&);
310:
311: static struct fpframe initial_fpframe;
312: static const uint32 fsave_frame_null[1];
313: static const uint32 fsave_frame_idle_68881[7];
314: static const uint32 fsave_frame_idle_68040[1];
1.1.1.11 root 315:
1.1.1.13 root 316: // キャッシュ
1.1.1.15 root 317: virtual void SetCACR(uint32) = 0;
1.1.1.11 root 318:
1.1.1.15 root 319: virtual bool TranslateRead() = 0;
320: virtual bool TranslateWrite() = 0;
1.1.1.11 root 321:
322: // 例外
1.1.1.15 root 323: void GenerateExframe0(uint vector, uint16 sr, uint32 pc);
324: void GenerateExframe2(uint vector, uint16 sr, uint32 pc, uint32 addr);
1.1.1.16! root 325: void GenerateExframe4(uint vector, uint16 sr, uint32 ea);
1.1.1.15 root 326: void GenerateExframe7(uint vector, uint16 sr);
1.1.1.14 root 327: void GenerateExframeB(uint vector, uint16 sr);
1.1.1.11 root 328: int ExceptionReset();
1.1.1.14 root 329: void ExceptionBuserr(uint vector);
1.1.1.13 root 330: uint64 ExceptionInterrupt();
1.1.1.12 root 331: void ExceptionTrap15();
1.1.1.15 root 332: void ExceptionFP(uint vector);
1.1.1.16! root 333: void ExceptionFPLC(uint ea);
1.1.1.14 root 334: void Exception(uint vector);
1.1.1.15 root 335: void ExceptionGeneric(uint ext_vector, uint32 inst);
336:
337: // リセット例外の CPU 固有部分。
338: virtual void ResetCache() = 0;
339: virtual void ResetMMU() = 0;
1.1.1.11 root 340:
341: // 二重バスフォールト
342: void DoubleBusFault(const char *where);
343:
344: public:
345: // レジスタ
346: m68kreg reg {};
347: bool mmu_enable {}; // MMU が有効なら true
348:
349: // バス
350: m68kbus bus {};
1.1.1.13 root 351: // 現在の特権状態でのプログラム空間とデータ空間アクセス用。
352: busaddr fc_inst {}; // こっちは R 含む
353: busaddr fc_data {}; // こっちは R/W 含まない
1.1.1.11 root 354:
1.1.1.15 root 355: protected:
1.1.1.11 root 356: uint16 ir {};
357: uint16 ir2 {};
358: // 現在実行中の命令の先頭アドレス
359: uint32 ppc {};
360:
361: // レジスタ(状態保存用)
362: uint32 save_pd[8] {}; // -(An) を保存
363: uint32 save_pi[8] {}; // (An)+ を保存
364: uint8 flag_pd {}; // -(An) のどのレジスタを保存したか
365: uint8 flag_pi {}; // (An)+ のどのレジスタを保存したか
366:
367: // FPU
1.1.1.15 root 368: enum {
369: FPU_STATE_NULL, // 内部状態なし
370: FPU_STATE_IDLE, // FRESTORE 以降に FPU 命令を実行した
371: FPU_STATE_BUSY, // ビジー状態 (実装していない)
372: FPU_STATE_NOIMPL, // 浮動小数点未実装命令
373: } fpu_state {};
1.1.1.11 root 374: struct fpemu fe {};
375:
1.1.1.15 root 376: // 68040 FPU 用の内部状態
377: struct FPU40 {
378: uint32 reg1b; // CMDREG1B
379: uint32 ea; // 計算した EA
380: enum {
381: // NONE は未決定だが Unnormal/Denormal ではないいずれかなので
382: // UNNORMAL より小さい値にしておく。(大小比較する)
383: TAG_NONE = -1,
384: TAG_NORMAL = 0,
385: TAG_ZERO = 1,
386: TAG_INF = 2,
387: TAG_NAN = 3,
388: TAG_UNNORMAL = 4, // .X denormal or unnormal
389: TAG_DENORMAL = 5, // .S/.D denormal
390:
391: // 内部表現 (下位3ビットは維持したまま上位で詳細を区別する)
392: TAG_DENORMAL_S = (0x10 | TAG_DENORMAL),
393: TAG_DENORMAL_D = (0x20 | TAG_DENORMAL),
394: TAG_DENORMAL_X = (0x30 | TAG_UNNORMAL),
395: TAG_UNNORMAL_X = (0x40 | TAG_UNNORMAL),
396: // PACKED のときタグは undefined となっている。仕方ないので 7。
397: TAG_PACKED = 0x07 ,
398: };
399: int32 stag;
400: int32 dtag;
401: uint32 etemp[3];
402: uint32 fptemp[3];
403: enum {
404: E1 = 0x04000000,
405: E3 = 0x02000000,
406: };
407: uint32 eflag;
408: bool post; // T bit, post-op exception
409:
410: // 表示用のフラグ。例外発生から FSAVE の間までが有効。
411: bool enable;
412: } fpu40 {};
413:
1.1.1.11 root 414: // CPU の実行状態
415: uint32 cpu_state {};
1.1.1.7 root 416:
1.1.1.10 root 417: // 割り込みペンディング
418: bool intr_pending {};
419:
1.1.1.11 root 420: // 現在の外部割り込みレベル
421: int intr_level {};
422:
423: // 電源オンからの累積消費サイクル
424: uint64 used_cycle {};
425:
1.1.1.13 root 426: // 今回のバスウェイト [nsec]
427: uint64 buswait {};
428:
1.1.1.14 root 429: // 外部バスがバースト転送に対応していれば true
430: bool has_burst_access {};
431:
1.1.1.15 root 432: // 命令キャッシュ有効 (icache->enable のコピー)
433: bool icache_enable {};
1.1.1.11 root 434: int32 cycle_nocache {}; // ノーキャッシュケースの時の追加分
435:
1.1.1.15 root 436: // MPU/FPU 種別
437: m680x0MPUType mpu_type {};
438: m680x0FPUType fpu_type {};
439: const char *mpu_name {};
440:
1.1.1.11 root 441: // A-Line, F-Line 命令エミュレーションのコールバックとユーザ引数。
442: // ユーザ引数には関与しないので呼び出し側が自由に指定してよい。
443: // コールバック側で処理完了したら true を返す。
444: // デフォルトの処理(すなわちm68k例外)にする場合は false を返す。
445: bool (*aline_callback)(MPU680x0Device *, void *) {};
446: void *aline_arg {};
447: bool (*fline_callback)(MPU680x0Device *, void *) {};
448: void *fline_arg {};
449:
450: // ブランチ履歴 (例外履歴を含む)
451: BranchHistory_m680x0 brhist { OBJ_MPU_BRHIST };
452: // 例外履歴のみ
453: BranchHistory_m680x0 exhist { OBJ_MPU_EXHIST };
454:
455: // 割り込みイベント
456: Event intr_event { this };
457:
1.1.1.10 root 458: // トレースでコールバックを差し替えることができるように
459: // イベントコールバックを変数に入れてある
460: EventCallback_t exec_short {};
461: EventCallback_t exec_full {};
1.1.1.4 root 462:
1.1.1.15 root 463: // モニター
464: void MonitorUpdateRegCommon(TextScreen&, m68kreg&, uint32, uint32);
465: int MonitorUpdateFPU(TextScreen&, int y, m68kreg&);
466: Monitor *reg_monitor {};
467: Monitor *atc_monitor {};
468: Monitor *cache_monitor {};
1.1.1.11 root 469:
1.1.1.15 root 470: InterruptDevice *interruptdev {};
471: VectorTable *vectortable {};
472: };
473:
474: class MPU68030Device : public MPU680x0Device
475: {
476: using inherited = MPU680x0Device;
477:
478: public:
479: MPU68030Device();
480: ~MPU68030Device() override;
481:
482: void SetLogLevel(int loglevel_) override;
1.1.1.11 root 483:
1.1.1.15 root 484: uint64 GetSRP() const { return reg.srp.q; }
485: uint32 GetSRPh() const { return reg.srp.h; }
486: uint32 GetSRPl() const { return reg.srp.l; }
487: uint64 GetCRP() const { return reg.crp.q; }
488: uint32 GetCRPh() const { return reg.crp.h; }
489: uint32 GetCRPl() const { return reg.crp.l; }
490: uint64 GetTT(int idx) const { return reg.tt[idx]; }
491: uint32 GetTC() const { return reg.tc; }
492: uint16 GetMMUSR() const { return reg.mmusr; }
493:
494: busaddr TranslatePeek(busaddr laddr) override;
495: void CalcStat() override;
496:
497: private:
498: // リセット
499: void ResetCache() override;
500: void ResetMMU() override;
501:
502: // 命令
503: bool ops_movec_rc_rn_cpu(uint c, uint n) override;
504: bool ops_movec_rn_rc_cpu(uint c, uint n) override;
505: void ops_mmu30() override;
506: void ops_mmu40_pflush() override;
507: uint32 get_fc();
508: void mmu_op_illg2();
509: void mmu_op_pflush();
510: void mmu_op_pflush_ea();
511: void mmu_op_pload();
512: void mmu_op_ptest();
513:
514: // バスアクセス
515: uint32 fetch_2() override;
516: uint32 fetch_4() override;
517: uint32 read_data(busaddr addr) override;
518: busdata read_nocache(busaddr addr);
519: void write_data(busaddr addr, uint32 data) override;
520:
521: busdata read_cache(m68030Cache *cache, busaddr addr);
522: busdata read_line(m68030CacheLine *, uint32 tag, uint32 opermask);
523: busdata read_single(busdata bd, uint32 readmask, uint32 opermask);
524: busdata write_bus(busaddr addr, uint32 data);
525:
526: // キャッシュ
527: void SetCACR(uint32) override;
528:
529: // MMU
530: bool TranslateRead() override;
531: bool TranslateWrite() override;
532: bool CheckTT();
533:
534: bool SetSRP(uint32, uint32);
535: bool SetCRP(uint32, uint32);
536: void SetTT(int idx, uint32);
537: bool SetTC(uint32);
538: void SetMMUSR(uint16);
539: // MMU 有効状態を更新。(TC と TT の変更で呼ばれる)
540: void mmu_enable_changed();
541:
542: public:
543: // MMU work
544: m68030TT mmu_tt[2] /*{}*/;
545: m68030TC mmu_tc /*{}*/;
546: m68030ATC atc {this};
547:
548: private:
549: DECLARE_MONITOR_CALLBACK(MonitorUpdateReg);
550: DECLARE_MONITOR_CALLBACK(MonitorUpdateATC);
1.1.1.13 root 551: DECLARE_MONITOR_CALLBACK(MonitorUpdateCache);
1.1.1.15 root 552: int MonitorUpdateMMU(TextScreen&, int, m68kreg&);
1.1.1.14 root 553: int MonitorUpdateCache1(TextScreen&, int y, m68030Cache *,
554: char (*)(const m68030CacheLine&));
1.1.1.13 root 555:
1.1.1.15 root 556: // キャッシュ
557: std::unique_ptr<m68030Cache> icache /*{}*/;
558: std::unique_ptr<m68030Cache> dcache /*{}*/;
559: };
560:
561: class MPU68040Device : public MPU680x0Device
562: {
563: using inherited = MPU680x0Device;
564:
565: public:
566: MPU68040Device();
567: ~MPU68040Device() override;
568:
569: uint32 GetITT(int n) const { return reg.itt[n]; }
570: uint32 GetDTT(int n) const { return reg.dtt[n]; }
571: uint32 GetSRP() const { return reg.srp40; }
572: uint32 GetURP() const { return reg.urp40; }
573: uint32 GetTC() const { return reg.tc40; }
574: uint32 GetMMUSR() const { return reg.mmusr40; }
575:
576: busaddr TranslatePeek(busaddr laddr) override;
577: void CalcStat() override;
578:
579: private:
580: // リセット
581: void ResetCache() override;
582: void ResetMMU() override;
583:
584: // 命令
585: bool ops_movec_rc_rn_cpu(uint c, uint n) override;
586: bool ops_movec_rn_rc_cpu(uint c, uint n) override;
587: void ops_mmu30() override;
588: void ops_mmu40_pflush() override;
589:
590: // バスアクセス
591: uint32 fetch_2() override;
592: uint32 fetch_4() override;
593: uint32 read_data(busaddr addr) override;
594: busdata read_nocache(busaddr addr);
595: void write_data(busaddr addr, uint32 data) override;
596:
597: // キャッシュ
598: void SetCACR(uint32) override;
599:
600: // MMU
601: bool TranslateRead() override;
602: bool TranslateWrite() override;
603: m68040TT *CheckTT(std::array<std::unique_ptr<m68040TT>, 2>&) const;
604: bool LookupATC(m68040ATC&);
605: bool Search(m68040ATCEntry *);
606: uint32 PeekDesc(uint32 base, uint32 idx);
607:
608: void SetTT(m68040TT *, uint32);
609: void SetSRP(uint32);
610: void SetURP(uint32);
611: void SetTC(uint32);
612: // MMU 有効状態を更新。(TC と *TTn の変更で呼ばれる)
613: void mmu_enable_changed();
614:
615: DECLARE_MONITOR_CALLBACK(MonitorUpdateReg);
616: DECLARE_MONITOR_CALLBACK(MonitorUpdateATC);
617: int MonitorUpdateMMU(TextScreen&, int, m68kreg&);
618: void MonitorUpdateTT(TextScreen&, int x, int y, const char *, uint32);
619: void MonitorUpdateATC1(TextScreen&, int, const m68040ATC *);
620:
621: // FPU
622: void MonitorUpdateFPU40(TextScreen&, int y, const FPU40&);
623: static std::string GetReg1BName(uint32 opclass, uint32 sz, uint32 cmd);
624: static std::string GetFPUTagName(int32);
625:
626: std::array<std::unique_ptr<m68040TT>, 2> mmu_itt /*{}*/;
627: std::array<std::unique_ptr<m68040TT>, 2> mmu_dtt /*{}*/;
628: std::unique_ptr<m68040TC> mmu_tc /*{}*/;
629:
630: std::unique_ptr<m68040ATC> atc_inst /*{}*/;
631: std::unique_ptr<m68040ATC> atc_data /*{}*/;
1.1 root 632: };
633:
1.1.1.15 root 634: // ブートストラップ
635: extern MPU680x0Device *NewMPU680x0Device();
636:
1.1.1.13 root 637: // これを呼びたい人は mpu を持ってるはず。
638: static inline MPU680x0Device *GetMPU680x0Device(Device *mpu_) {
639: return dynamic_cast<MPU680x0Device*>(mpu_);
1.1.1.11 root 640: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.