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