|
|
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"
12:
13: // MPU に依存しないブランチ履歴。
14: //
15: // count = 0 なら書き込み前の無効エントリを示す。
16: // top がカーソルで、8ビットなので勝手に循環する。
17: // 直近と同じジャンプが連続する場合 count だけを増加させたいため、top は
18: // 次回の書き込み位置ではなく、直近の書き込み位置を指すことに注意。
19: //
20: // BranchHistory クラスはモニタを持つので Object からの継承になっているが
21: // 他の多くの Object 派生クラスと違ってグローバル参照は用意していない。
22: // というのもどの MPU のブランチ履歴かなので、MPU クラスから辿ることにする。
23:
24: class BranchHistory : public Object
25: {
26: struct BranchEntry {
27: uint32 count; // 連続通過回数
28: uint32 from; // ジャンプ元アドレス(VA)
29: uint32 to; // ジャンプ先アドレス(VA)
30: uint32 padding;
31: } __packed;
32:
33: public:
34: BranchHistory();
35: ~BranchHistory() override;
36:
37: bool MonitorUpdate() override;
38:
39: // エントリを追加。
40: // エントリを返す。
41: const BranchEntry& AddEntry(uint32 from, uint32 to) {
42: BranchEntry *e = &entry[top];
43:
44: if (e->from == from && e->to == to) {
45: // 前回と同じなら通過回数++
46: e->count++;
47: } else {
48: // そうでなければ、新規エントリ
49: top++;
50: e = &entry[top];
51: e->count = 1;
52: e->from = from;
53: e->to = to;
54: }
55: return *e;
56: }
57:
58: // 16バイト単位のテーブルなので16バイト境界に整列がよかろう。
59: alignas(16) BranchEntry entry[256] {};
60: // 直近に使用した位置
61: uint8 top {};
62: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.