|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
5: //
6:
1.1.1.3 root 7: //
1.1 root 8: // ブランチ履歴
1.1.1.3 root 9: //
1.1 root 10:
11: #pragma once
12:
13: #include "object.h"
1.1.1.2 root 14: #include "monitor.h"
1.1 root 15:
1.1.1.4 ! root 16: class VectorTable;
! 17:
1.1 root 18: // MPU に依存しないブランチ履歴。
19: //
20: // count = 0 なら書き込み前の無効エントリを示す。
21: // top がカーソルで、8ビットなので勝手に循環する。
22: // 直近と同じジャンプが連続する場合 count だけを増加させたいため、top は
23: // 次回の書き込み位置ではなく、直近の書き込み位置を指すことに注意。
24: //
25: // BranchHistory クラスはモニタを持つので Object からの継承になっているが
26: // 他の多くの Object 派生クラスと違ってグローバル参照は用意していない。
27: // というのもどの MPU のブランチ履歴かなので、MPU クラスから辿ることにする。
28:
29: class BranchHistory : public Object
30: {
1.1.1.2 root 31: using inherited = Object;
32:
1.1 root 33: protected:
34: struct BranchEntry {
35: uint32 count; // 連続通過回数
36: uint32 from; // ジャンプ元アドレス(VA)
37: uint32 to; // ジャンプ先アドレス(VA)
38: uint32 inst; // ジャンプ元命令や例外情報など (機種による↓)
39: } __packed;
40:
41: public:
42: // 表示系フラグ
1.1.1.2 root 43: static const uint64 BottomToTop = (1ULL << 63); // 新しい方を下に
1.1 root 44:
45: public:
1.1.1.4 ! root 46: BranchHistory(int objid_);
1.1 root 47: virtual ~BranchHistory() override;
48:
49: // 初期化
50: void Clear();
51:
52: // エントリを追加。
53: // エントリを返す。
54: const BranchEntry& AddEntry(uint32 from, uint32 to, uint32 inst) {
55: BranchEntry *e = &entry[top];
56:
57: if (e->from == from && e->to == to) {
58: // 前回と同じなら通過回数++
59: e->count++;
60: } else {
61: // そうでなければ、新規エントリ
62: top++;
63: e = &entry[top];
64: e->count = 1;
65: e->from = from;
66: e->to = to;
67: e->inst = inst;
68: }
69: return *e;
70: }
71:
72: // 使用中のエントリ数を取得する
73: int GetUsed() const;
74:
75: // 16バイト単位のテーブルなので16バイト境界に整列がよかろう。
76: alignas(16) BranchEntry entry[256] {};
77: // 直近に使用した位置
78: uint8 top {};
79:
1.1.1.4 ! root 80: // モニタ (デバッガから直接参照する)
1.1.1.2 root 81: Monitor monitor { this };
82:
1.1 root 83: protected:
1.1.1.4 ! root 84: virtual std::string FormatHeader() const;
1.1 root 85: virtual std::string FormatEntry(const BranchEntry& e) = 0;
1.1.1.2 root 86:
87: DECLARE_MONITOR_CALLBACK(MonitorUpdate);
88:
89: // 例外履歴かどうか。ヘッダ行が違う。
90: bool is_exhist {};
1.1.1.4 ! root 91:
! 92: // カウンタの表示開始座標 (HD64180 だけ違うため)
! 93: int x_count {};
! 94:
! 95: VectorTable *vectortable {};
1.1 root 96: };
97:
98: //
99: // m680x0 ブランチ履歴
100: // (MPU に依存しないとは一体…)
101: //
102: class BranchHistory_m680x0 : public BranchHistory
103: {
104: using inherited = BranchHistory;
105: public:
1.1.1.4 ! root 106: BranchHistory_m680x0(int objid_);
1.1 root 107: virtual ~BranchHistory_m680x0() override;
108:
109: std::string FormatEntry(const BranchEntry& e) override;
110: };
111:
112: //
113: // m88xx0 ブランチ履歴
114: // (MPU に依存しないとは一体…)
115: //
116: class BranchHistory_m88xx0 : public BranchHistory
117: {
118: using inherited = BranchHistory;
119: public:
1.1.1.4 ! root 120: BranchHistory_m88xx0(int objid_);
1.1 root 121: virtual ~BranchHistory_m88xx0() override;
122:
123: std::string FormatEntry(const BranchEntry& e) override;
124: };
1.1.1.4 ! root 125:
! 126: //
! 127: // HD64180 ブランチ履歴
! 128: //
! 129: class BranchHistory_hd64180 : public BranchHistory
! 130: {
! 131: using inherited = BranchHistory;
! 132: public:
! 133: BranchHistory_hd64180(int objid_);
! 134: virtual ~BranchHistory_hd64180() override;
! 135:
! 136: std::string FormatHeader() const override;
! 137: std::string FormatEntry(const BranchEntry& e) override;
! 138:
! 139: private:
! 140: static std::string fstr(int);
! 141: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.