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