|
|
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.