|
|
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);
! 271: void read_8(uint32 addr, uint32 *data);
! 272: void read_12(uint32 addr, uint32 *data);
! 273: void write_8(uint32 addr, const uint32 *data);
! 274: void write_12(uint32 addr, const uint32 *data);
! 275: bool readSRC(int size_id, 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);
! 325: void GenerateExframe7(uint vector, uint16 sr);
1.1.1.14 root 326: void GenerateExframeB(uint vector, uint16 sr);
1.1.1.11 root 327: int ExceptionReset();
1.1.1.14 root 328: void ExceptionBuserr(uint vector);
1.1.1.13 root 329: uint64 ExceptionInterrupt();
1.1.1.12 root 330: void ExceptionTrap15();
1.1.1.15! root 331: void ExceptionFP(uint vector);
1.1.1.14 root 332: void Exception(uint vector);
1.1.1.15! root 333: void ExceptionGeneric(uint ext_vector, uint32 inst);
! 334:
! 335: // リセット例外の CPU 固有部分。
! 336: virtual void ResetCache() = 0;
! 337: virtual void ResetMMU() = 0;
1.1.1.11 root 338:
339: // 二重バスフォールト
340: void DoubleBusFault(const char *where);
341:
342: public:
343: // レジスタ
344: m68kreg reg {};
345: bool mmu_enable {}; // MMU が有効なら true
346:
347: // バス
348: m68kbus bus {};
1.1.1.13 root 349: // 現在の特権状態でのプログラム空間とデータ空間アクセス用。
350: busaddr fc_inst {}; // こっちは R 含む
351: busaddr fc_data {}; // こっちは R/W 含まない
1.1.1.11 root 352:
1.1.1.15! root 353: protected:
1.1.1.11 root 354: uint16 ir {};
355: uint16 ir2 {};
356: // 現在実行中の命令の先頭アドレス
357: uint32 ppc {};
358:
359: // レジスタ(状態保存用)
360: uint32 save_pd[8] {}; // -(An) を保存
361: uint32 save_pi[8] {}; // (An)+ を保存
362: uint8 flag_pd {}; // -(An) のどのレジスタを保存したか
363: uint8 flag_pi {}; // (An)+ のどのレジスタを保存したか
364:
365: // FPU
1.1.1.15! root 366: enum {
! 367: FPU_STATE_NULL, // 内部状態なし
! 368: FPU_STATE_IDLE, // FRESTORE 以降に FPU 命令を実行した
! 369: FPU_STATE_BUSY, // ビジー状態 (実装していない)
! 370: FPU_STATE_NOIMPL, // 浮動小数点未実装命令
! 371: } fpu_state {};
1.1.1.11 root 372: struct fpemu fe {};
373:
1.1.1.15! root 374: // 68040 FPU 用の内部状態
! 375: struct FPU40 {
! 376: uint32 reg1b; // CMDREG1B
! 377: uint32 ea; // 計算した EA
! 378: enum {
! 379: // NONE は未決定だが Unnormal/Denormal ではないいずれかなので
! 380: // UNNORMAL より小さい値にしておく。(大小比較する)
! 381: TAG_NONE = -1,
! 382: TAG_NORMAL = 0,
! 383: TAG_ZERO = 1,
! 384: TAG_INF = 2,
! 385: TAG_NAN = 3,
! 386: TAG_UNNORMAL = 4, // .X denormal or unnormal
! 387: TAG_DENORMAL = 5, // .S/.D denormal
! 388:
! 389: // 内部表現 (下位3ビットは維持したまま上位で詳細を区別する)
! 390: TAG_DENORMAL_S = (0x10 | TAG_DENORMAL),
! 391: TAG_DENORMAL_D = (0x20 | TAG_DENORMAL),
! 392: TAG_DENORMAL_X = (0x30 | TAG_UNNORMAL),
! 393: TAG_UNNORMAL_X = (0x40 | TAG_UNNORMAL),
! 394: // PACKED のときタグは undefined となっている。仕方ないので 7。
! 395: TAG_PACKED = 0x07 ,
! 396: };
! 397: int32 stag;
! 398: int32 dtag;
! 399: uint32 etemp[3];
! 400: uint32 fptemp[3];
! 401: enum {
! 402: E1 = 0x04000000,
! 403: E3 = 0x02000000,
! 404: };
! 405: uint32 eflag;
! 406: bool post; // T bit, post-op exception
! 407:
! 408: // 表示用のフラグ。例外発生から FSAVE の間までが有効。
! 409: bool enable;
! 410: } fpu40 {};
! 411:
1.1.1.11 root 412: // CPU の実行状態
413: uint32 cpu_state {};
1.1.1.7 root 414:
1.1.1.10 root 415: // 割り込みペンディング
416: bool intr_pending {};
417:
1.1.1.11 root 418: // 現在の外部割り込みレベル
419: int intr_level {};
420:
421: // 電源オンからの累積消費サイクル
422: uint64 used_cycle {};
423:
1.1.1.13 root 424: // 今回のバスウェイト [nsec]
425: uint64 buswait {};
426:
1.1.1.14 root 427: // 外部バスがバースト転送に対応していれば true
428: bool has_burst_access {};
429:
1.1.1.15! root 430: // 命令キャッシュ有効 (icache->enable のコピー)
! 431: bool icache_enable {};
1.1.1.11 root 432: int32 cycle_nocache {}; // ノーキャッシュケースの時の追加分
433:
1.1.1.15! root 434: // MPU/FPU 種別
! 435: m680x0MPUType mpu_type {};
! 436: m680x0FPUType fpu_type {};
! 437: const char *mpu_name {};
! 438:
1.1.1.11 root 439: // A-Line, F-Line 命令エミュレーションのコールバックとユーザ引数。
440: // ユーザ引数には関与しないので呼び出し側が自由に指定してよい。
441: // コールバック側で処理完了したら true を返す。
442: // デフォルトの処理(すなわちm68k例外)にする場合は false を返す。
443: bool (*aline_callback)(MPU680x0Device *, void *) {};
444: void *aline_arg {};
445: bool (*fline_callback)(MPU680x0Device *, void *) {};
446: void *fline_arg {};
447:
448: // ブランチ履歴 (例外履歴を含む)
449: BranchHistory_m680x0 brhist { OBJ_MPU_BRHIST };
450: // 例外履歴のみ
451: BranchHistory_m680x0 exhist { OBJ_MPU_EXHIST };
452:
453: // 割り込みイベント
454: Event intr_event { this };
455:
1.1.1.10 root 456: // トレースでコールバックを差し替えることができるように
457: // イベントコールバックを変数に入れてある
458: EventCallback_t exec_short {};
459: EventCallback_t exec_full {};
1.1.1.4 root 460:
1.1.1.15! root 461: // モニター
! 462: void MonitorUpdateRegCommon(TextScreen&, m68kreg&, uint32, uint32);
! 463: int MonitorUpdateFPU(TextScreen&, int y, m68kreg&);
! 464: Monitor *reg_monitor {};
! 465: Monitor *atc_monitor {};
! 466: Monitor *cache_monitor {};
1.1.1.11 root 467:
1.1.1.15! root 468: InterruptDevice *interruptdev {};
! 469: VectorTable *vectortable {};
! 470: };
! 471:
! 472: class MPU68030Device : public MPU680x0Device
! 473: {
! 474: using inherited = MPU680x0Device;
! 475:
! 476: public:
! 477: MPU68030Device();
! 478: ~MPU68030Device() override;
! 479:
! 480: void SetLogLevel(int loglevel_) override;
1.1.1.11 root 481:
1.1.1.15! root 482: uint64 GetSRP() const { return reg.srp.q; }
! 483: uint32 GetSRPh() const { return reg.srp.h; }
! 484: uint32 GetSRPl() const { return reg.srp.l; }
! 485: uint64 GetCRP() const { return reg.crp.q; }
! 486: uint32 GetCRPh() const { return reg.crp.h; }
! 487: uint32 GetCRPl() const { return reg.crp.l; }
! 488: uint64 GetTT(int idx) const { return reg.tt[idx]; }
! 489: uint32 GetTC() const { return reg.tc; }
! 490: uint16 GetMMUSR() const { return reg.mmusr; }
! 491:
! 492: busaddr TranslatePeek(busaddr laddr) override;
! 493: void CalcStat() override;
! 494:
! 495: private:
! 496: // リセット
! 497: void ResetCache() override;
! 498: void ResetMMU() override;
! 499:
! 500: // 命令
! 501: bool ops_movec_rc_rn_cpu(uint c, uint n) override;
! 502: bool ops_movec_rn_rc_cpu(uint c, uint n) override;
! 503: void ops_mmu30() override;
! 504: void ops_mmu40_pflush() override;
! 505: uint32 get_fc();
! 506: void mmu_op_illg2();
! 507: void mmu_op_pflush();
! 508: void mmu_op_pflush_ea();
! 509: void mmu_op_pload();
! 510: void mmu_op_ptest();
! 511:
! 512: // バスアクセス
! 513: uint32 fetch_2() override;
! 514: uint32 fetch_4() override;
! 515: uint32 read_data(busaddr addr) override;
! 516: busdata read_nocache(busaddr addr);
! 517: void write_data(busaddr addr, uint32 data) override;
! 518:
! 519: busdata read_cache(m68030Cache *cache, busaddr addr);
! 520: busdata read_line(m68030CacheLine *, uint32 tag, uint32 opermask);
! 521: busdata read_single(busdata bd, uint32 readmask, uint32 opermask);
! 522: busdata write_bus(busaddr addr, uint32 data);
! 523:
! 524: // キャッシュ
! 525: void SetCACR(uint32) override;
! 526:
! 527: // MMU
! 528: bool TranslateRead() override;
! 529: bool TranslateWrite() override;
! 530: bool CheckTT();
! 531:
! 532: bool SetSRP(uint32, uint32);
! 533: bool SetCRP(uint32, uint32);
! 534: void SetTT(int idx, uint32);
! 535: bool SetTC(uint32);
! 536: void SetMMUSR(uint16);
! 537: // MMU 有効状態を更新。(TC と TT の変更で呼ばれる)
! 538: void mmu_enable_changed();
! 539:
! 540: public:
! 541: // MMU work
! 542: m68030TT mmu_tt[2] /*{}*/;
! 543: m68030TC mmu_tc /*{}*/;
! 544: m68030ATC atc {this};
! 545:
! 546: private:
! 547: DECLARE_MONITOR_CALLBACK(MonitorUpdateReg);
! 548: DECLARE_MONITOR_CALLBACK(MonitorUpdateATC);
1.1.1.13 root 549: DECLARE_MONITOR_CALLBACK(MonitorUpdateCache);
1.1.1.15! root 550: int MonitorUpdateMMU(TextScreen&, int, m68kreg&);
1.1.1.14 root 551: int MonitorUpdateCache1(TextScreen&, int y, m68030Cache *,
552: char (*)(const m68030CacheLine&));
1.1.1.13 root 553:
1.1.1.15! root 554: // キャッシュ
! 555: std::unique_ptr<m68030Cache> icache /*{}*/;
! 556: std::unique_ptr<m68030Cache> dcache /*{}*/;
! 557: };
! 558:
! 559: class MPU68040Device : public MPU680x0Device
! 560: {
! 561: using inherited = MPU680x0Device;
! 562:
! 563: public:
! 564: MPU68040Device();
! 565: ~MPU68040Device() override;
! 566:
! 567: uint32 GetITT(int n) const { return reg.itt[n]; }
! 568: uint32 GetDTT(int n) const { return reg.dtt[n]; }
! 569: uint32 GetSRP() const { return reg.srp40; }
! 570: uint32 GetURP() const { return reg.urp40; }
! 571: uint32 GetTC() const { return reg.tc40; }
! 572: uint32 GetMMUSR() const { return reg.mmusr40; }
! 573:
! 574: busaddr TranslatePeek(busaddr laddr) override;
! 575: void CalcStat() override;
! 576:
! 577: private:
! 578: // リセット
! 579: void ResetCache() override;
! 580: void ResetMMU() override;
! 581:
! 582: // 命令
! 583: bool ops_movec_rc_rn_cpu(uint c, uint n) override;
! 584: bool ops_movec_rn_rc_cpu(uint c, uint n) override;
! 585: void ops_mmu30() override;
! 586: void ops_mmu40_pflush() override;
! 587:
! 588: // バスアクセス
! 589: uint32 fetch_2() override;
! 590: uint32 fetch_4() override;
! 591: uint32 read_data(busaddr addr) override;
! 592: busdata read_nocache(busaddr addr);
! 593: void write_data(busaddr addr, uint32 data) override;
! 594:
! 595: // キャッシュ
! 596: void SetCACR(uint32) override;
! 597:
! 598: // MMU
! 599: bool TranslateRead() override;
! 600: bool TranslateWrite() override;
! 601: m68040TT *CheckTT(std::array<std::unique_ptr<m68040TT>, 2>&) const;
! 602: bool LookupATC(m68040ATC&);
! 603: bool Search(m68040ATCEntry *);
! 604: uint32 PeekDesc(uint32 base, uint32 idx);
! 605:
! 606: void SetTT(m68040TT *, uint32);
! 607: void SetSRP(uint32);
! 608: void SetURP(uint32);
! 609: void SetTC(uint32);
! 610: // MMU 有効状態を更新。(TC と *TTn の変更で呼ばれる)
! 611: void mmu_enable_changed();
! 612:
! 613: DECLARE_MONITOR_CALLBACK(MonitorUpdateReg);
! 614: DECLARE_MONITOR_CALLBACK(MonitorUpdateATC);
! 615: int MonitorUpdateMMU(TextScreen&, int, m68kreg&);
! 616: void MonitorUpdateTT(TextScreen&, int x, int y, const char *, uint32);
! 617: void MonitorUpdateATC1(TextScreen&, int, const m68040ATC *);
! 618:
! 619: // FPU
! 620: void MonitorUpdateFPU40(TextScreen&, int y, const FPU40&);
! 621: static std::string GetReg1BName(uint32 opclass, uint32 sz, uint32 cmd);
! 622: static std::string GetFPUTagName(int32);
! 623:
! 624: std::array<std::unique_ptr<m68040TT>, 2> mmu_itt /*{}*/;
! 625: std::array<std::unique_ptr<m68040TT>, 2> mmu_dtt /*{}*/;
! 626: std::unique_ptr<m68040TC> mmu_tc /*{}*/;
! 627:
! 628: std::unique_ptr<m68040ATC> atc_inst /*{}*/;
! 629: std::unique_ptr<m68040ATC> atc_data /*{}*/;
1.1 root 630: };
631:
1.1.1.15! root 632: // ブートストラップ
! 633: extern MPU680x0Device *NewMPU680x0Device();
! 634:
1.1.1.13 root 635: // これを呼びたい人は mpu を持ってるはず。
636: static inline MPU680x0Device *GetMPU680x0Device(Device *mpu_) {
637: return dynamic_cast<MPU680x0Device*>(mpu_);
1.1.1.11 root 638: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.