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