|
|
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.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:
1.1 root 35: public:
1.1.1.7 root 36: MPU680x0Device();
1.1.1.13 root 37: ~MPU680x0Device() override;
1.1 root 38:
1.1.1.2 root 39: bool Init() override;
1.1.1.10 root 40: void ResetHard(bool poweron) override;
1.1 root 41:
42: // 現在の PPC を取得
1.1.1.11 root 43: uint32 GetPPC() const override { return ppc; }
1.1 root 44:
1.1.1.10 root 45: // 現在の VBR を取得
1.1.1.11 root 46: uint32 GetVBR() const override { return reg.vbr; }
47:
1.1.1.15 root 48: // MPU 種別を取得
49: m680x0MPUType GetMPUType() const { return mpu_type; }
50:
51: // FPU
52: m680x0FPUType GetFPUType() const { return fpu_type; }
53: bool HasFPU() const { return fpu_type.Is4060FPU() || fpu_type.Is6888x(); }
54:
1.1.1.13 root 55: // MPU 名を取得
1.1.1.15 root 56: const char *GetMPUName() const override { return mpu_name; }
1.1.1.13 root 57:
1.1.1.11 root 58: bool IsSuper() const { return reg.s; }
59: bool IsMaster() const { return reg.m; }
60:
1.1 root 61: // 現在アクセス中の論理アドレス、物理アドレスを取得。
1.1.1.13 root 62: uint32 GetLaddr() const override { return bus.laddr.Addr(); }
63: uint32 GetPaddr() const override { return bus.paddr.Addr(); }
1.1 root 64:
1.1.1.5 root 65: // 割り込みレベルが変わったことを MPU に通知
66: void Interrupt(int level) override;
1.1 root 67:
68: // A-Line, F-Line 命令エミュレーションのコールバックを指定する。
69: // (Human68k エミュレーションで使用)
1.1.1.11 root 70: void SetALineCallback(bool (*callback)(MPU680x0Device*, void*), void *arg);
71: void SetFLineCallback(bool (*callback)(MPU680x0Device*, void*), void *arg);
1.1 root 72:
1.1.1.14 root 73: // バーストアクセスをサポートするか
74: void EnableBurstAccess(bool enable) { has_burst_access = enable; }
75:
1.1.1.13 root 76: void SetCI() override {
77: bus.ci = true;
78: }
1.1.1.9 root 79:
1.1.1.11 root 80: // ホールト
1.1.1.10 root 81: void Halt();
82:
1.1.1.11 root 83: // 基本アクセス。内部から使用する。
84: // アドレスは論理アドレスで、空間は現在の命令/データ空間。
85: // バスエラーなら C++ の例外をスローする。
1.1.1.15 root 86: virtual uint32 fetch_2() = 0;
87: virtual uint32 fetch_4() = 0;
1.1.1.14 root 88: uint32 read_n(uint32 laddr, uint size) {
89: busaddr addr =
90: busaddr(laddr) | fc_data | BusAddr::R | busaddr::Size(size);
91: return read_data(addr);
92: }
93: void write_n(uint32 laddr, uint size, uint32 data) {
94: busaddr addr =
95: busaddr(laddr) | fc_data | BusAddr::W | busaddr::Size(size);
96: write_data(addr, data);
97: }
98: uint32 read_1(uint32 laddr) { return read_n(laddr, 1); }
99: uint32 read_2(uint32 laddr) { return read_n(laddr, 2); }
100: uint32 read_4(uint32 laddr) { return read_n(laddr, 4); }
101: void write_1(uint32 laddr, uint32 data) { write_n(laddr, 1, data); }
102: void write_2(uint32 laddr, uint32 data) { write_n(laddr, 2, data); }
103: void write_4(uint32 laddr, uint32 data) { write_n(laddr, 4, data); }
1.1.1.11 root 104:
105: // MMU アクセス
1.1.1.15 root 106: virtual busaddr TranslatePeek(busaddr laddr) = 0;
1.1.1.14 root 107: // 統計
1.1.1.15 root 108: virtual void CalcStat() = 0;
1.1.1.11 root 109:
110: // レジスタ
111: uint16 GetIR() const { return ir; }
112: uint16 GetIR2() const { return ir2; }
113: // SR を変更する (Human68k から使う)
114: void SetSR(uint16);
115: uint16 GetSR() const { return reg.GetSR(); }
116:
1.1.1.15 root 117: protected:
1.1.1.10 root 118: // リセット例外コールバック
119: void ResetCallback(Event& ev);
120:
121: // 命令実行系コールバック
122: void ExecShort(Event& ev);
123: void ExecFull(Event& ev);
124: void ExecTrace(Event& ev);
1.1.1.5 root 125:
1.1.1.10 root 126: // トレース設定。デバッガから呼び出される。
1.1.1.17! root 127: void SetTrace(bool enable) override;
1.1.1.9 root 128:
1.1.1.10 root 129: // 割り込みイベントコールバック
130: void InterruptCallback(Event& ev);
131:
1.1.1.11 root 132: // 次の実行サイクルを Full にする。
133: void MakeNextFull();
1.1.1.8 root 134:
1.1.1.11 root 135: inline void CYCLE(int cc) {
136: used_cycle += cc;
137: }
1.1.1.17! root 138: // 副作用前提のマクロなので do-while にしない。
! 139: #define CYCLE3(name) used_cycle += cycle_table[__CONCAT(cycidx_,name)]
1.1.1.11 root 140:
141: // PC を addr に変更する。
142: // ベクタへのジャンプはここではなく JumpVector()。
143: inline void Jump(uint32 addr) {
144: // 先にブランチ履歴に記録
1.1.1.12 root 145: brhist.AddEntry(ppc | (IsSuper() ? 1 : 0), addr, ir);
1.1.1.11 root 146:
147: if (__predict_false((addr & 1) != 0)) {
1.1.1.12 root 148: ExceptionBuserr(M68K::EXCEP_ADDRERR);
1.1.1.11 root 149: return;
150: }
151: reg.pc = addr;
152: }
153:
154: // -(An) 実行前にレジスタを保存する。
155: // バスエラーからの復帰用。
156: inline void save_reg_pd(int n) {
157: // 該当ビットのフラグを立てる
158: flag_pd |= (1 << n);
159:
160: // 保存
161: save_pd[n] = reg.A[n];
162: }
163:
164: // (An)+ 実行前にレジスタを保存する。
165: // バスエラーからの復帰用。
166: inline void save_reg_pi(int n) {
167: // 該当ビットのフラグを立てる
168: flag_pi |= (1 << n);
169:
170: // 保存
171: save_pi[n] = reg.A[n];
172: }
173:
1.1.1.14 root 174: // -(An) 実行前にレジスタを(まだ保存してなければ)保存する。
175: // 1命令で同じレジスタを2回 -(An) する可能性がある命令用。
176: inline void save_reg_pd_if(int n) {
177: if ((flag_pd & (1 << n)) == 0) {
178: save_reg_pd(n);
179: }
180: }
181: // (An)+ 実行前にレジスタを(まだ保存してなければ)保存する。
182: // 1命令で同じレジスタを2回 (An)+ する可能性がある命令用。
183: inline void save_reg_pi_if(int n) {
184: if ((flag_pi & (1 << n)) == 0) {
185: save_reg_pi(n);
186: }
187: }
188:
1.1.1.11 root 189: void restore_reg_pi();
190: void restore_reg_pd();
1.1.1.14 root 191: void JumpVector(uint vector, bool from_buserr);
1.1.1.11 root 192:
193: protected:
1.1.1.15 root 194: #include "m680x0ea.h"
1.1.1.11 root 195:
1.1.1.15 root 196: protected:
1.1.1.11 root 197: // 基本アクセスルーチンを使った便利サブルーチン
1.1.1.14 root 198: inline void push_2(uint32 data) {
1.1.1.11 root 199: reg.A[7] -= 2;
1.1.1.14 root 200: write_2(reg.A[7], data);
1.1.1.11 root 201: }
1.1.1.14 root 202: inline void push_4(uint32 data) {
1.1.1.11 root 203: reg.A[7] -= 4;
1.1.1.14 root 204: write_4(reg.A[7], data);
1.1.1.11 root 205: }
1.1.1.14 root 206: inline uint32 pop_2() {
207: uint32 data = read_2(reg.A[7]);
1.1.1.11 root 208: reg.A[7] += 2;
209: return data;
210: }
1.1.1.14 root 211: inline uint32 pop_4() {
212: uint32 data = read_4(reg.A[7]);
1.1.1.11 root 213: reg.A[7] += 4;
214: return data;
215: }
216:
1.1.1.13 root 217: // バスアクセス
1.1.1.15 root 218: virtual uint32 read_data(busaddr addr) = 0;
219: virtual void write_data(busaddr addr, uint32 data) = 0;
1.1.1.14 root 220:
1.1.1.15 root 221: // 物理バスアクセス
1.1.1.14 root 222: busdata read_phys();
223: busdata write_phys(uint32 data);
224: bool read_phys_burst(uint32 *dst);
1.1.1.15 root 225: busdata read_phys_4(uint32 addr);
226: busdata write_phys_4(uint32 addr, uint32 data);
1.1.1.13 root 227:
1.1.1.11 root 228: #define OP_PROTO(name) void __CONCAT(op_,name)()
1.1.1.15 root 229: #include "m680x0ops.h"
1.1.1.11 root 230: #undef OP_PROTO
231:
1.1.1.14 root 232: void ops_divu_32_32(uint r, uint q);
233: void ops_divu_64_32(uint r, uint q);
234: void ops_divs_32_32(uint r, uint q);
235: void ops_divs_64_32(uint r, uint q);
1.1.1.15 root 236: void ops_link(int32 imm);
1.1.1.11 root 237: void ops_movec_rc_rn();
238: void ops_movec_rn_rc();
1.1.1.15 root 239: virtual bool ops_movec_rc_rn_cpu(uint c, uint n) = 0;
240: virtual bool ops_movec_rn_rc_cpu(uint c, uint n) = 0;
1.1.1.11 root 241: void ops_movep();
242: // もともとソース内のテンプレートだった
243: void ops_movem_list_ea(int bytesize);
244: void ops_movem_ea_list(int bytesize);
245: void ops_trapcc(uint cond);
246: inline void ops_bra();
1.1.1.15 root 247: busaddr translate_fc40(busaddr);
1.1.1.11 root 248:
249: void ops_rte();
250: void ops_stop();
251: void ops_reset();
1.1.1.15 root 252: virtual void ops_mmu30() = 0;
253: virtual void ops_mmu40_pflush() = 0;
1.1.1.11 root 254:
1.1.1.15 root 255: void ResetFPU(bool hard);
256: void fpu_init();
257: uint32 cea_fpu(int bytes);
1.1.1.16 root 258: uint32 cea_fpulc(int bytes);
1.1.1.15 root 259: void read_8(uint32 addr, uint32 *data);
260: void read_12(uint32 addr, uint32 *data);
261: void write_8(uint32 addr, const uint32 *data);
262: void write_12(uint32 addr, const uint32 *data);
263:
264: void fpu_op_illg();
265: void fpu_op_illg2();
266:
267: void fpu_op_fgen_reg();
268: void fpu_op_fgen_mem();
269: void fgen(const uint32 *srcdata, uint srcsize_id);
270: void fgen881pre(uint dstnum, const uint32 *srcdata, uint srcsize_id);
271: bool fgen040pre(uint opmode, uint dst, const uint32 *src, uint srcsize);
272: void fpu_op_fmovecr();
273: void fpu_op_fmove_to_mem();
274: void fpu_op_fmove_b_mem();
275: void fpu_op_fmove_w_mem();
276: void fpu_op_fmove_l_mem();
277: void fpu_op_fmove_s_mem();
278: void fpu_op_fmove_d_mem();
279: void fpu_op_fmove_x_mem();
280: void fpu_op_fmove_p_mem();
281: void fpu_op_fmove_ea2ctl();
282: void fpu_op_fmovem_ea2ctl();
283: void fpu_op_fmove_ctl2ea();
284: void fpu_op_fmovem_ctl2ea();
285: void fpu_op_fmovem_ea2reg();
286: void fpu_op_fmovem_reg2ea();
287: void fpu_op_fscc();
288: void fpu_op_fdbcc();
289: void fpu_op_ftrapcc_w();
290: void fpu_op_ftrapcc_l();
291: void fpu_op_ftrapcc();
292: void fpu_op_fbcc_w();
293: void fpu_op_fbcc_l();
294: void fpu_op_fsave();
295: void fpu_op_frestore();
296: void fpu_op_fsave_frame_noimpl(std::array<uint32, 13>&);
297:
298: static struct fpframe initial_fpframe;
299: static const uint32 fsave_frame_null[1];
300: static const uint32 fsave_frame_idle_68881[7];
301: static const uint32 fsave_frame_idle_68040[1];
1.1.1.11 root 302:
1.1.1.13 root 303: // キャッシュ
1.1.1.15 root 304: virtual void SetCACR(uint32) = 0;
1.1.1.11 root 305:
1.1.1.15 root 306: virtual bool TranslateRead() = 0;
307: virtual bool TranslateWrite() = 0;
1.1.1.11 root 308:
309: // 例外
1.1.1.15 root 310: void GenerateExframe0(uint vector, uint16 sr, uint32 pc);
311: void GenerateExframe2(uint vector, uint16 sr, uint32 pc, uint32 addr);
1.1.1.16 root 312: void GenerateExframe4(uint vector, uint16 sr, uint32 ea);
1.1.1.15 root 313: void GenerateExframe7(uint vector, uint16 sr);
1.1.1.14 root 314: void GenerateExframeB(uint vector, uint16 sr);
1.1.1.11 root 315: int ExceptionReset();
1.1.1.14 root 316: void ExceptionBuserr(uint vector);
1.1.1.13 root 317: uint64 ExceptionInterrupt();
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:
442: // 割り込みイベント
443: Event intr_event { this };
444:
1.1.1.10 root 445: // トレースでコールバックを差し替えることができるように
446: // イベントコールバックを変数に入れてある
447: EventCallback_t exec_short {};
448: EventCallback_t exec_full {};
1.1.1.4 root 449:
1.1.1.15 root 450: // モニター
451: void MonitorUpdateRegCommon(TextScreen&, m68kreg&, uint32, uint32);
452: int MonitorUpdateFPU(TextScreen&, int y, m68kreg&);
453: Monitor *reg_monitor {};
454: Monitor *atc_monitor {};
455: Monitor *cache_monitor {};
1.1.1.11 root 456:
1.1.1.15 root 457: InterruptDevice *interruptdev {};
458: VectorTable *vectortable {};
459: };
460:
461: class MPU68030Device : public MPU680x0Device
462: {
463: using inherited = MPU680x0Device;
464:
465: public:
466: MPU68030Device();
467: ~MPU68030Device() override;
468:
469: void SetLogLevel(int loglevel_) override;
1.1.1.11 root 470:
1.1.1.15 root 471: uint64 GetSRP() const { return reg.srp.q; }
472: uint32 GetSRPh() const { return reg.srp.h; }
473: uint32 GetSRPl() const { return reg.srp.l; }
474: uint64 GetCRP() const { return reg.crp.q; }
475: uint32 GetCRPh() const { return reg.crp.h; }
476: uint32 GetCRPl() const { return reg.crp.l; }
477: uint64 GetTT(int idx) const { return reg.tt[idx]; }
478: uint32 GetTC() const { return reg.tc; }
479: uint16 GetMMUSR() const { return reg.mmusr; }
480:
481: busaddr TranslatePeek(busaddr laddr) override;
482: void CalcStat() override;
483:
484: private:
485: // リセット
486: void ResetCache() override;
487: void ResetMMU() override;
488:
489: // 命令
490: bool ops_movec_rc_rn_cpu(uint c, uint n) override;
491: bool ops_movec_rn_rc_cpu(uint c, uint n) override;
492: void ops_mmu30() override;
493: void ops_mmu40_pflush() override;
494: uint32 get_fc();
495: void mmu_op_illg2();
496: void mmu_op_pflush();
497: void mmu_op_pflush_ea();
498: void mmu_op_pload();
499: void mmu_op_ptest();
500:
501: // バスアクセス
502: uint32 fetch_2() override;
503: uint32 fetch_4() override;
504: uint32 read_data(busaddr addr) override;
505: busdata read_nocache(busaddr addr);
506: void write_data(busaddr addr, uint32 data) override;
507:
508: busdata read_cache(m68030Cache *cache, busaddr addr);
509: busdata read_line(m68030CacheLine *, uint32 tag, uint32 opermask);
510: busdata read_single(busdata bd, uint32 readmask, uint32 opermask);
511: busdata write_bus(busaddr addr, uint32 data);
512:
513: // キャッシュ
514: void SetCACR(uint32) override;
515:
516: // MMU
517: bool TranslateRead() override;
518: bool TranslateWrite() override;
519: bool CheckTT();
520:
521: bool SetSRP(uint32, uint32);
522: bool SetCRP(uint32, uint32);
523: void SetTT(int idx, uint32);
524: bool SetTC(uint32);
525: void SetMMUSR(uint16);
526: // MMU 有効状態を更新。(TC と TT の変更で呼ばれる)
527: void mmu_enable_changed();
528:
529: public:
530: // MMU work
531: m68030TT mmu_tt[2] /*{}*/;
532: m68030TC mmu_tc /*{}*/;
533: m68030ATC atc {this};
534:
535: private:
536: DECLARE_MONITOR_CALLBACK(MonitorUpdateReg);
537: DECLARE_MONITOR_CALLBACK(MonitorUpdateATC);
1.1.1.13 root 538: DECLARE_MONITOR_CALLBACK(MonitorUpdateCache);
1.1.1.15 root 539: int MonitorUpdateMMU(TextScreen&, int, m68kreg&);
1.1.1.14 root 540: int MonitorUpdateCache1(TextScreen&, int y, m68030Cache *,
541: char (*)(const m68030CacheLine&));
1.1.1.13 root 542:
1.1.1.15 root 543: // キャッシュ
544: std::unique_ptr<m68030Cache> icache /*{}*/;
545: std::unique_ptr<m68030Cache> dcache /*{}*/;
546: };
547:
548: class MPU68040Device : public MPU680x0Device
549: {
550: using inherited = MPU680x0Device;
551:
552: public:
553: MPU68040Device();
554: ~MPU68040Device() override;
555:
556: uint32 GetITT(int n) const { return reg.itt[n]; }
557: uint32 GetDTT(int n) const { return reg.dtt[n]; }
558: uint32 GetSRP() const { return reg.srp40; }
559: uint32 GetURP() const { return reg.urp40; }
560: uint32 GetTC() const { return reg.tc40; }
561: uint32 GetMMUSR() const { return reg.mmusr40; }
562:
563: busaddr TranslatePeek(busaddr laddr) override;
564: void CalcStat() override;
565:
566: private:
567: // リセット
568: void ResetCache() override;
569: void ResetMMU() override;
570:
571: // 命令
572: bool ops_movec_rc_rn_cpu(uint c, uint n) override;
573: bool ops_movec_rn_rc_cpu(uint c, uint n) override;
574: void ops_mmu30() override;
575: void ops_mmu40_pflush() override;
576:
577: // バスアクセス
578: uint32 fetch_2() override;
579: uint32 fetch_4() override;
580: uint32 read_data(busaddr addr) override;
581: busdata read_nocache(busaddr addr);
582: void write_data(busaddr addr, uint32 data) override;
583:
584: // キャッシュ
585: void SetCACR(uint32) override;
586:
587: // MMU
588: bool TranslateRead() override;
589: bool TranslateWrite() override;
590: m68040TT *CheckTT(std::array<std::unique_ptr<m68040TT>, 2>&) const;
591: bool LookupATC(m68040ATC&);
1.1.1.17! root 592: void Search(m68040ATCEntry *);
1.1.1.15 root 593: uint32 PeekDesc(uint32 base, uint32 idx);
594:
595: void SetTT(m68040TT *, uint32);
596: void SetSRP(uint32);
597: void SetURP(uint32);
598: void SetTC(uint32);
599: // MMU 有効状態を更新。(TC と *TTn の変更で呼ばれる)
600: void mmu_enable_changed();
601:
602: DECLARE_MONITOR_CALLBACK(MonitorUpdateReg);
603: DECLARE_MONITOR_CALLBACK(MonitorUpdateATC);
604: int MonitorUpdateMMU(TextScreen&, int, m68kreg&);
605: void MonitorUpdateTT(TextScreen&, int x, int y, const char *, uint32);
606: void MonitorUpdateATC1(TextScreen&, int, const m68040ATC *);
607:
608: // FPU
609: void MonitorUpdateFPU40(TextScreen&, int y, const FPU40&);
610: static std::string GetReg1BName(uint32 opclass, uint32 sz, uint32 cmd);
611: static std::string GetFPUTagName(int32);
612:
613: std::array<std::unique_ptr<m68040TT>, 2> mmu_itt /*{}*/;
614: std::array<std::unique_ptr<m68040TT>, 2> mmu_dtt /*{}*/;
615: std::unique_ptr<m68040TC> mmu_tc /*{}*/;
616:
617: std::unique_ptr<m68040ATC> atc_inst /*{}*/;
618: std::unique_ptr<m68040ATC> atc_data /*{}*/;
1.1 root 619: };
620:
1.1.1.15 root 621: // ブートストラップ
622: extern MPU680x0Device *NewMPU680x0Device();
623:
1.1.1.13 root 624: // これを呼びたい人は mpu を持ってるはず。
625: static inline MPU680x0Device *GetMPU680x0Device(Device *mpu_) {
626: return dynamic_cast<MPU680x0Device*>(mpu_);
1.1.1.11 root 627: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.