|
|
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.1.6 ! root 47: ~BranchHistory() override;
1.1 root 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.5 root 106: // inst の分岐種別
107: static const uint32 Normal = 0x00000000; // 通常分岐
108: static const uint32 VectorJump = 0x40000000; // ベクタによる分岐
109: static const uint32 IOCSCall = 0x80000000; // IOCS コール
110: static const uint32 Exception = 0xc0000000; // 例外発生
111: public:
1.1.1.4 root 112: BranchHistory_m680x0(int objid_);
1.1.1.6 ! root 113: ~BranchHistory_m680x0() override;
1.1 root 114:
115: std::string FormatEntry(const BranchEntry& e) override;
116: };
117:
118: //
119: // m88xx0 ブランチ履歴
120: // (MPU に依存しないとは一体…)
121: //
122: class BranchHistory_m88xx0 : public BranchHistory
123: {
124: using inherited = BranchHistory;
125: public:
1.1.1.4 root 126: BranchHistory_m88xx0(int objid_);
1.1.1.6 ! root 127: ~BranchHistory_m88xx0() override;
1.1 root 128:
129: std::string FormatEntry(const BranchEntry& e) override;
130: };
1.1.1.4 root 131:
132: //
133: // HD64180 ブランチ履歴
134: //
135: class BranchHistory_hd64180 : public BranchHistory
136: {
137: using inherited = BranchHistory;
138: public:
139: BranchHistory_hd64180(int objid_);
1.1.1.6 ! root 140: ~BranchHistory_hd64180() override;
1.1.1.4 root 141:
142: std::string FormatHeader() const override;
143: std::string FormatEntry(const BranchEntry& e) override;
144:
145: private:
146: static std::string fstr(int);
147: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.