|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2022 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: //
8: // ベクタテーブル (モニタ)
9: //
10:
11: #include "vectortable.h"
12: #include "mainapp.h"
1.1.1.3 root 13: #include "mainbus.h"
1.1.1.6 ! root 14: #include "monitor.h"
1.1 root 15: #include "mpu.h"
16:
17: // コンストラクタ
1.1.1.2 root 18: VectorTable::VectorTable(VMType vmtype)
1.1.1.3 root 19: : inherited(OBJ_VECTOR_TABLE)
1.1 root 20: {
21: // ログは不要
22: ClearAlias();
23:
24: // 表示名を作成。それぞれ微妙に処理が違う…
25: switch (vmtype) {
1.1.1.2 root 26: case VMType::X68030:
27: case VMType::LUNA1:
1.1.1.3 root 28: case VMType::NEWS:
1.1.1.4 root 29: case VMType::VIRT68K:
1.1.1.6 ! root 30: InitTableM680x0(vmtype);
1.1 root 31: break;
1.1.1.2 root 32: case VMType::LUNA88K:
1.1 root 33: InitTableLuna88k();
34: break;
1.1.1.2 root 35: default:
36: PANIC("invalid vmtype %d", (int)vmtype);
1.1 root 37: }
38:
1.1.1.6 ! root 39: monitor = gMonitorManager->Regist(ID_SUBWIN_VECTOR, this);
! 40: monitor->func = ToMonitorCallback(&VectorTable::MonitorUpdate);
! 41: monitor->SetSize(75, 1 + 32); // ヘッダの1行と全エントリ数
! 42: monitor->SetMaxHeight(1 + Size());
1.1 root 43: }
44:
1.1.1.6 ! root 45: // m68k 機種の表示名テーブル初期化。コンストラクタの一部。
1.1 root 46: void
1.1.1.6 ! root 47: VectorTable::InitTableM680x0(VMType vmtype)
1.1 root 48: {
49: nametable.clear();
50: nametable.resize(256);
51:
1.1.1.6 ! root 52: // まず m680x0 標準の名称で埋める
1.1 root 53: for (int v = 0; v < 64; v++) {
1.1.1.6 ! root 54: if (name_m680x0[v]) {
! 55: nametable[v] = name_m680x0[v];
1.1 root 56: }
57: }
58:
1.1.1.3 root 59: // 機種ごとに必要なところだけ上書き
60: const std::map<int, const char * const> *names;
1.1.1.6 ! root 61: switch (vmtype) {
! 62: case VMType::X68030:
1.1.1.3 root 63: names = &name_x68030;
1.1.1.6 ! root 64: break;
! 65: case VMType::LUNA1:
1.1.1.3 root 66: names = &name_luna1;
1.1.1.6 ! root 67: break;
! 68: case VMType::NEWS:
1.1.1.3 root 69: names = &name_news;
1.1.1.6 ! root 70: break;
! 71: case VMType::VIRT68K:
! 72: names = &name_virt68k;
! 73: break;
! 74: default:
! 75: names = NULL;
! 76: break;
1.1.1.3 root 77: }
1.1.1.6 ! root 78: if (names) {
! 79: for (const auto& p : *names) {
! 80: int v = p.first;
! 81: const char *name = p.second;
! 82: nametable[v] = name;
! 83: }
1.1 root 84: }
85: }
86:
1.1.1.3 root 87: // LUNA-88K の表示名テーブルを初期化。コンストラクタの一部。
1.1 root 88: void
89: VectorTable::InitTableLuna88k()
90: {
91: nametable.clear();
92: nametable.resize(512);
93:
94: // 先頭から10個くらいだけ連続しているのでテーブルからコピー
95: for (int i = 0; i < countof(name_luna88k); i++) {
96: nametable[i] = name_luna88k[i];
97: }
98:
99: // 以降は不連続で、間が空きすぎているので、ここで代入
100:
101: // SFU
102: // (SFU2〜7 はいいか…)
103: // 01234567890123456789012 <- 例外履歴欄の横幅
104: nametable[114] = "SFU1 Precise Exception";
105: nametable[115] = "SFU1 ImpreciseException";
106:
1.1.1.3 root 107: // NetBSD/luna88k
108: nametable[128] = "NetBSD System Call";
109:
1.1 root 110: // OpenBSD
111: // XXX 本来は OpenBSD 稼働時に限定すべきだろうけど、そうする意味もない
112: // 01234567890123456789012
113: nametable[450] = "OpenBSD System Call";
114: nametable[451] = "OpenBSD Cache Flush";
115: nametable[503] = "Division by Zero(GCC)";
116: nametable[504] = "OpenBSD stepbpt";
117: nametable[511] = "OpenBSD userbpt";
118: }
119:
1.1.1.3 root 120: // デストラクタ
121: VectorTable::~VectorTable()
122: {
123: }
124:
125: // 初期化
126: bool
127: VectorTable::Init()
128: {
129: if (inherited::Init() == false) {
130: return false;
131: }
132:
133: mainbus = GetMainbusDevice();
134: mpu = GetMPUDevice();
135:
136: return true;
137: }
138:
1.1 root 139: // 例外名を返す (ベクタテーブル用)。
140: // 名前がなければ "" を返す。
141: const char *
142: VectorTable::GetTableName(int vector) const
143: {
144: assertmsg(0 <= vector && vector < nametable.size(), "vector=%d", vector);
145:
146: return nametable[vector] ?: "";
147: }
148:
149: // 例外名を返す (例外履歴用)。
150: // 名前がなければ NULL を返す。
151: const char *
152: VectorTable::GetExceptionName(int vector) const
153: {
154: assertmsg(0 <= vector && vector < nametable.size(), "vector=%d", vector);
155:
156: if (__predict_false(vector < 2)) {
1.1.1.2 root 157: if (gMainApp.Has(VMCap::M68K)) {
1.1 root 158: // ベクタテーブル的には 0:"Reset(SP)"、1:"Reset(PC)" のほうが
159: // 分かりやすいが、例外の名前は 0 が "Reset Exception" で
160: // 1 は存在しない。
161: if (vector == 0) {
162: return "Reset Exception";
163: } else {
164: return "(vector 1?)";
165: }
166: }
167: }
168:
169: if (__predict_true(nametable[vector] != NULL)) {
170: return nametable[vector];
171: } else {
172: return NULL;
173: }
174: }
175:
176: // モニタ更新
177: void
178: VectorTable::MonitorUpdate(Monitor *, TextScreen& screen)
179: {
1.1.1.5 root 180: // 0 1 2 3 4 5 6 7
181: // 012345678901234567890123456789012345678901234567890123456789012345678901234
182: // No. Offset Address Name >< Count
183: // $02( 2) $0008 $12345678 0123456789012345678901201234567890123456789012345
1.1 root 184:
1.1.1.3 root 185: uint32 vbr = mpu->GetVBR();
1.1 root 186:
187: // userdata が表示開始位置
188: int v = (int)screen.userdata;
189: int row = screen.GetRow();
190: int vend = v + row - 1;
191:
192: screen.Clear();
193:
194: // 最初の1行は常にヘッダ
195: screen.Print(0, 0, "No. Offset Address Name");
1.1.1.5 root 196: screen.Print(70, 0, "Count");
1.1 root 197:
198: for (int y = 1; v < vend; v++, y++) {
1.1.1.5 root 199: screen.Print(0, y, "$%02x(%3u) $%04x", v, v, v * 4);
200: busdata addr = mainbus->Peek4(vbr + v * 4);
1.1.1.4 root 201: if (__predict_false(addr.IsBusErr())) {
1.1 root 202: screen.Print(16, y, "BusErr");
203: } else {
1.1.1.4 root 204: screen.Print(16, y, "$%08x", addr.Data());
1.1 root 205: }
206: screen.Print(26, y, "%-23s", GetTableName(v));
1.1.1.5 root 207: screen.Print(49, y, "%26s",
208: format_number(mpu->excep_counter[v]).c_str());
1.1 root 209: }
210: }
211:
1.1.1.6 ! root 212: // ベクタ名 (MC680x0)。
! 213: // とりあえず CPU の区別はないことにする。
! 214: /*static*/ std::array<const char * const, 64> VectorTable::name_m680x0 = {
1.1 root 215: // 0123456789012345678 <- 例外履歴欄の横幅
216: /* 0 */ "Reset (SP)",
217: /* 1 */ "Reset (PC)",
218: /* 2 */ "Bus Error",
219: /* 3 */ "Address Error",
220: /* 4 */ "Illegal Instruction",
221: /* 5 */ "Zero Divide",
222: /* 6 */ "CHK/CHK2 Insn",
1.1.1.6 ! root 223: /* 7 */ "TRAPV/*TRAPcc Insn",
! 224: /* 8 */ "Privilege Violation",
1.1 root 225: /* 9 */ "Trace",
1.1.1.6 ! root 226: /* 10 */ "Line A emulator",
! 227: /* 11 */ "Line F emulator",
1.1 root 228: /* 12 */ NULL,
1.1.1.6 ! root 229: /* 13 */ "CoproProtoViolation", // 68030 only
1.1 root 230: /* 14 */ "Format Error",
231: /* 15 */ "Uninitialized Intr",
232: /* 16 */ NULL, NULL, NULL, NULL,
233: /* 20 */ NULL, NULL, NULL, NULL,
234: /* 24 */ "Spurious Interrupt",
235: /* 25 */ "Level 1 Interrupt",
236: /* 26 */ "Level 2 Interrupt",
237: /* 27 */ "Level 3 Interrupt",
238: /* 28 */ "Level 4 Interrupt",
239: /* 29 */ "Level 5 Interrupt",
240: /* 30 */ "Level 6 Interrupt",
241: /* 31 */ "Level 7 Interrupt",
242: /* 32 */ "Trap #0",
243: /* 33 */ "Trap #1",
244: /* 34 */ "Trap #2",
245: /* 35 */ "Trap #3",
246: /* 36 */ "Trap #4",
247: /* 37 */ "Trap #5",
248: /* 38 */ "Trap #6",
249: /* 39 */ "Trap #7",
250: /* 40 */ "Trap #8",
251: /* 41 */ "Trap #9",
252: /* 42 */ "Trap #10",
253: /* 43 */ "Trap #11",
254: /* 44 */ "Trap #12",
255: /* 45 */ "Trap #13",
256: /* 46 */ "Trap #14",
257: /* 47 */ "Trap #15",
258: // 0123456789012345678
259: /* 48 */ "FPCP Branch",
260: /* 49 */ "FPCP InexcactResult",
261: /* 50 */ "FPCP Divide by Zero",
262: /* 51 */ "FPCP UnderFlow",
263: /* 52 */ "FPCP Operand Error",
264: /* 53 */ "FPCP OverFlow",
265: /* 54 */ "FPCP Signaling NAN",
1.1.1.6 ! root 266: /* 55 */ "FPCP UnsuppDataType", // 68040 only
! 267: /* 56 */ "MMU Config Error", // 68030 only
1.1 root 268: /* 57 */ NULL,
269: /* 58 */ NULL,
270: /* 59 */ NULL,
271: /* 60 */ NULL,
272: /* 61 */ NULL,
273: /* 62 */ NULL,
274: /* 63 */ NULL,
275: };
276:
277: // ベクタ名 (X68030)
1.1.1.3 root 278: /*static*/ std::map<int, const char * const> VectorTable::name_x68030 = {
279: // 0123456789012345678
280: { 0x40, "MFP Alarm" },
281: { 0x41, "MFP EXPON" },
282: { 0x42, "MFP POWSW" },
283: { 0x43, "MFP FM IRQ" },
284: { 0x44, "MFP Timer-D" },
285: { 0x45, "MFP Timer-C" },
286: { 0x46, "MFP V-Disp" },
287: { 0x47, "MFP GPIP5" },
288: { 0x48, "MFP Timer-B" },
289: { 0x49, "MFP TX Error" },
290: { 0x4a, "MFP TX Empty" },
291: { 0x4b, "MFP RX Error" },
292: { 0x4c, "MFP RX Full" },
293: { 0x4d, "MFP Timer-A" },
294: { 0x4e, "MFP CRTC IRQ" },
295: { 0x4f, "MFP H-Sync" },
296:
297: { 0x50, "SCC#B TX Empty" },
298: { 0x52, "SCC#B E/S" },
299: { 0x54, "SCC#B RX Intr" },
300: { 0x56, "SCC#B SpCond" },
301: { 0x58, "SCC#A TX Empty" },
302: { 0x5a, "SCC#A E/S" },
303: { 0x5c, "SCC#A RX Intr" },
304: { 0x5e, "SCC#A SpCond" },
305:
306: // 0123456789012345678
307: { 0x60, "I/O FDC Intr" },
308: { 0x61, "I/O FDD Intr" },
309: { 0x62, "I/O HDC Intr" },
310: { 0x63, "I/O PRN Intr" },
311: { 0x64, "DMAC#0 Complete" },
312: { 0x65, "DMAC#0 Error" },
313: { 0x66, "DMAC#1 Complete" },
314: { 0x67, "DMAC#1 Error" },
315: { 0x68, "DMAC#2 Complete" },
316: { 0x69, "DMAC#2 Error" },
317: { 0x6a, "DMAC#3 Complete" },
318: { 0x6b, "DMAC#3 Error" },
319: { 0x6c, "SPC Interrupt" },
320:
321: // 0123456789012345678
322: { 0xf0, "PSX16x50 Interrupt" },
323: { 0xf6, "ExSPC Interrupt" },
324: //0xf7, TS-6BSI
325: { 0xf8, "Nereid#1 Interrupt" },
326: { 0xf9, "Neptune-X Interrupt" },
327: { 0xfa, "Nereid#1 USB" },
328: { 0xfb, "Nereid#0 USB" },
329: };
1.1 root 330:
1.1.1.3 root 331: // LUNA-I
332: /*static*/ std::map<int, const char * const> VectorTable::name_luna1 = {
333: // 0123456789012345678 <- 例外履歴欄の横幅
334: { 0x19, "Lv1 Intr (XP Low)" },
335: { 0x1a, "Lv2 Intr (SPC)" },
336: { 0x1b, "Lv3 Intr (Lance)" },
337: { 0x1c, "Lv4 Intr (XP High)" },
338: { 0x1d, "Lv5 Intr (SysClk)" },
339: { 0x1e, "Lv6 Intr (SIO)" },
340: { 0x1f, "Lv7 Intr (NMI)" },
1.1 root 341: };
342:
1.1.1.3 root 343: // NEWS はレベル割り込みと、一部が vectored */
344: /*static*/ std::map<int, const char * const> VectorTable::name_news = {
1.1 root 345: // 0123456789012345678 <- 例外履歴欄の横幅
1.1.1.3 root 346: { 0x19, "Lv1 Intr (AST)" },
347: { 0x1a, "Lv2 Intr" },
348: { 0x1b, "Lv3 Intr" },
349: { 0x1c, "Lv4 Intr (SIC/LAN)" },
350: { 0x1d, "Lv5 Intr (SCC)" },
351: { 0x1e, "Lv6 Intr (SysTimer)" },
352: { 0x1f, "Lv7 Intr" },
353:
354: { 0x40, "SCC" },
1.1 root 355: };
356:
1.1.1.6 ! root 357: // virt-m68k
! 358: /*static*/ std::map<int, const char * const> VectorTable::name_virt68k = {
! 359: // 0123456789012345678 <- 例外履歴欄の横幅
! 360: { 0x19, "Lv1 Intr (GFPIC1)" },
! 361: { 0x1a, "Lv2 Intr (GFPIC2)" },
! 362: { 0x1b, "Lv3 Intr (GFPIC3)" },
! 363: { 0x1c, "Lv4 Intr (GFPIC4)" },
! 364: { 0x1d, "Lv5 Intr (GFPIC5)" },
! 365: { 0x1e, "Lv6 Intr (GFPIC6)" },
! 366: { 0x1f, "Lv7 Intr" },
! 367: };
! 368:
1.1 root 369: // LUNA-88K は先頭11個のみ (残りはコードで処理)
370: /*static*/ std::array<const char * const, 11> VectorTable::name_luna88k = {
1.1.1.3 root 371: // 01234567890123456789012 <- 例外履歴欄の横幅
1.1 root 372: /* 0 */ "Reset Exception",
373: /* 1 */ "Interrupt Exception",
374: /* 2 */ "Inst Access Exception",
375: /* 3 */ "Data Access Exception",
376: /* 4 */ "Misaligned Access Excep",
377: /* 5 */ "Unimplemented Opcode",
378: /* 6 */ "Priv. Violation Excep.",
379: /* 7 */ "Bounds Check Violation",
380: /* 8 */ "Illegal Integer Divide",
381: /* 9 */ "Int Overflow Exception",
382: /* 10 */ "Error Exception",
1.1.1.3 root 383: // 01234567890123456789012
1.1 root 384: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.