|
|
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"
14:
1.1.1.4 root 15: class VectorTable;
16:
1.1 root 17: // MPU に依存しないブランチ履歴。
18: //
19: // count = 0 なら書き込み前の無効エントリを示す。
20: // top がカーソルで、8ビットなので勝手に循環する。
21: // 直近と同じジャンプが連続する場合 count だけを増加させたいため、top は
22: // 次回の書き込み位置ではなく、直近の書き込み位置を指すことに注意。
23: //
24: // BranchHistory クラスはモニタを持つので Object からの継承になっているが
25: // 他の多くの Object 派生クラスと違ってグローバル参照は用意していない。
26: // というのもどの MPU のブランチ履歴かなので、MPU クラスから辿ることにする。
27:
28: class BranchHistory : public Object
29: {
1.1.1.2 root 30: using inherited = Object;
31:
1.1 root 32: protected:
33: struct BranchEntry {
34: uint32 count; // 連続通過回数
35: uint32 from; // ジャンプ元アドレス(VA)
36: uint32 to; // ジャンプ先アドレス(VA)
1.1.1.9 root 37: uint32 info; // ジャンプ元命令や例外情報など (機種による)
1.1 root 38: } __packed;
39:
40: public:
41: // 表示系フラグ
1.1.1.2 root 42: static const uint64 BottomToTop = (1ULL << 63); // 新しい方を下に
1.1 root 43:
44: public:
1.1.1.7 root 45: explicit BranchHistory(uint objid_);
1.1.1.6 root 46: ~BranchHistory() override;
1.1 root 47:
48: // 初期化
49: void Clear();
50:
51: // エントリを追加。
52: // エントリを返す。
1.1.1.9 root 53: const BranchEntry& AddEntry(uint32 from, uint32 to, uint32 info) {
1.1 root 54: BranchEntry *e = &entry[top];
55:
1.1.1.10! root 56: if (e->from == from && e->to == to && e->info == info) {
1.1 root 57: // 前回と同じなら通過回数++
58: e->count++;
59: } else {
60: // そうでなければ、新規エントリ
61: top++;
62: e = &entry[top];
63: e->count = 1;
64: e->from = from;
65: e->to = to;
1.1.1.9 root 66: e->info = info;
1.1 root 67: }
68: return *e;
69: }
70:
71: // 使用中のエントリ数を取得する
72: int GetUsed() const;
73:
74: // 16バイト単位のテーブルなので16バイト境界に整列がよかろう。
75: alignas(16) BranchEntry entry[256] {};
76: // 直近に使用した位置
77: uint8 top {};
78:
1.1.1.4 root 79: // モニタ (デバッガから直接参照する)
1.1.1.8 root 80: Monitor *monitor {};
1.1.1.2 root 81:
1.1 root 82: protected:
1.1.1.4 root 83: virtual std::string FormatHeader() const;
1.1 root 84: virtual std::string FormatEntry(const BranchEntry& e) = 0;
1.1.1.2 root 85:
1.1.1.10! root 86: DECLARE_MONITOR_SCREEN(MonitorScreen);
1.1.1.2 root 87:
88: // 例外履歴かどうか。ヘッダ行が違う。
89: bool is_exhist {};
1.1.1.4 root 90:
91: // カウンタの表示開始座標 (HD64180 だけ違うため)
92: int x_count {};
93:
94: VectorTable *vectortable {};
1.1 root 95: };
96:
97: //
98: // m680x0 ブランチ履歴
99: // (MPU に依存しないとは一体…)
100: //
101: class BranchHistory_m680x0 : public BranchHistory
102: {
103: using inherited = BranchHistory;
1.1.1.9 root 104:
105: // info の分岐種別
106: static constexpr uint32 NORMAL = 0x00000000; // 通常分岐
107: static constexpr uint32 VECTORJUMP = 0x40000000; // ベクタによる分岐
1.1.1.10! root 108: static constexpr uint32 SERVICECALL_HUMAN = 0x80000000; // IOCS/DOS call
! 109: static constexpr uint32 SERVICECALL_NETBSD = 0x80010000; // NetBSD syscall
1.1.1.9 root 110: static constexpr uint32 EXCEPTION = 0xc0000000; // 例外発生
111:
1.1.1.5 root 112: public:
1.1.1.7 root 113: explicit BranchHistory_m680x0(uint objid_);
1.1.1.6 root 114: ~BranchHistory_m680x0() override;
1.1 root 115:
1.1.1.9 root 116: static constexpr uint32 InfoNormal(uint16 inst) {
117: return NORMAL | inst;
118: }
119: static constexpr uint32 InfoVectorJump() {
120: return VECTORJUMP;
121: }
122: static constexpr uint32 InfoException(uint8 vector) {
123: return EXCEPTION | vector;
124: }
125: static constexpr uint32 InfoIOCSCall(uint8 num) {
1.1.1.10! root 126: return SERVICECALL_HUMAN | num;
1.1.1.9 root 127: }
128: static constexpr uint32 InfoDOSCall(uint16 ir) {
1.1.1.10! root 129: return SERVICECALL_HUMAN | ir;
! 130: }
! 131: static constexpr uint32 InfoNetBSDSyscall(uint16 syscall) {
! 132: return SERVICECALL_NETBSD | syscall;
1.1.1.9 root 133: }
134:
1.1 root 135: std::string FormatEntry(const BranchEntry& e) override;
136: };
137:
138: //
139: // m88xx0 ブランチ履歴
140: // (MPU に依存しないとは一体…)
141: //
142: class BranchHistory_m88xx0 : public BranchHistory
143: {
144: using inherited = BranchHistory;
145: public:
1.1.1.7 root 146: explicit BranchHistory_m88xx0(uint objid_);
1.1.1.6 root 147: ~BranchHistory_m88xx0() override;
1.1 root 148:
149: std::string FormatEntry(const BranchEntry& e) override;
150: };
1.1.1.4 root 151:
152: //
153: // HD64180 ブランチ履歴
154: //
155: class BranchHistory_hd64180 : public BranchHistory
156: {
157: using inherited = BranchHistory;
158: public:
1.1.1.7 root 159: explicit BranchHistory_hd64180(uint objid_);
1.1.1.6 root 160: ~BranchHistory_hd64180() override;
1.1.1.4 root 161:
162: std::string FormatHeader() const override;
163: std::string FormatEntry(const BranchEntry& e) override;
164:
165: private:
166: static std::string fstr(int);
167: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.