|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2022 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: #include "hd64180disasm.h"
8: #include "debugger_memory.h"
9: #include "mpu64180.h"
10: #include "mystring.h"
11:
12: #define T(inp, exp) { __LINE__, #inp, exp }
13: #define ILLEGAL "<illegal instruction>"
14:
15: struct {
16: int line;
17: std::string inp;
18: std::string exp;
19: } table[] = {
20: // inst exp
21: T(00, "NOP"),
22: T(011234, "LD BC,3412H"),
23: T(02, "LD (BC),A"),
24: T(03, "INC BC"),
25: T(04, "INC B"),
26: T(05, "DEC B"),
27: T(0612, "LD B,12H"),
28: T(07, "RLCA"),
29: T(08, "EX AF,AF'"),
30: T(09, "ADD HL,BC"),
31: T(0a, "LD A,(BC)"),
32: T(0b, "DEC BC"),
33: T(0c, "INC C"),
34: T(0d, "DEC C"),
35: T(0e12, "LD C,12H"),
36: T(0f, "RRCA"),
37:
38: T(1012, "DJNZ 0114H"),
39: T(111234, "LD DE,3412H"),
40: T(17, "RLA"),
41: T(1812, "JR 0114H"),
42: T(1f, "RRA"),
43:
44: T(2012, "JR NZ,0114H"),
45: T(211234, "LD HL,3412H"),
46: T(221234, "LD (3412H),HL"),
47: T(27, "DAA"),
48: T(2812, "JR Z,0114H"),
49: T(2a1234, "LD HL,(3412H)"),
50: T(2f, "CPL"),
51:
52: T(3012, "JR NC,0114H"),
53: T(311234, "LD SP,3412H"),
54: T(321234, "LD (3412H),A"),
55: T(37, "SCF"),
56: T(3812, "JR C,0114H"),
57: T(39, "ADD HL,SP"),
58: T(3a1234, "LD A,(3412H)"),
59: T(3f, "CCF"),
60:
61: T(40, "LD B,B"),
62: T(46, "LD B,(HL)"),
63: T(48, "LD C,B"),
64: T(4e, "LD C,(HL)"),
65: T(70, "LD (HL),B"),
66: T(76, "HALT"),
67: T(77, "LD (HL),A"),
68: T(7e, "LD A,(HL)"),
69:
70: T(80, "ADD A,B"),
71: T(89, "ADC A,C"),
72: T(92, "SUB D"),
73: T(9b, "SBC A,E"),
74: T(a4, "AND H"),
75: T(ad, "XOR L"),
76: T(b6, "OR (HL)"),
77: T(bf, "CP A"),
78:
79: T(c0, "RET NZ"),
80: T(c1, "POP BC"),
81: T(c21234, "JP NZ,3412H"),
82: T(c31234, "JP 3412H"),
83: T(c41234, "CALL NZ,3412H"),
84: T(c5, "PUSH BC"),
85: T(c612, "ADD A,12H"),
86: T(c7, "RST 00H"),
87: T(c9, "RET"),
88: T(cd1234, "CALL 3412H"),
89: T(ce12, "ADC A,12H"),
90:
91: T(d312, "OUT (12H),A"),
92: T(d612, "SUB 12H"),
93: T(d9, "EXX"),
94: T(db12, "IN A,(12H)"),
95: T(de12, "SBC A,12H"),
96:
97: T(e3, "EX (SP),HL"),
98: T(e612, "AND 12H"),
99: T(e9, "JP (HL)"),
100: T(eb, "EX DE,HL"),
101: T(ee12, "XOR 12H"),
102:
103: T(f3, "DI"),
104: T(f612, "OR 12H"),
105: T(f9, "LD SP,HL"),
106: T(fb, "EI"),
107: T(fe12, "CP 12H"),
108:
109: // ww
110: T(13, "INC DE"),
111: T(23, "INC HL"),
112: T(33, "INC SP"),
113:
114: // fff
115: T(c8, "RET Z"),
116: T(d0, "RET NC"),
117: T(d8, "RET C"),
118: T(e0, "RET PO"),
119: T(e8, "RET PE"),
120: T(f0, "RET P"),
121: T(f8, "RET M"),
122:
123: // zzz
124: T(d1, "POP DE"),
125: T(e1, "POP HL"),
126: T(f1, "POP AF"),
127:
128: // vvv
129: T(cf, "RST 08H"),
130: T(d7, "RST 10H"),
131: T(df, "RST 18H"),
132: T(e7, "RST 20H"),
133: T(ef, "RST 28H"),
134: T(f7, "RST 30H"),
135: T(ff, "RST 38H"),
136:
137: //
138: // CB
139: //
140:
141: T(cb00, "RLC B"),
142: T(cb08, "RRC B"),
143: T(cb10, "RL B"),
144: T(cb18, "RR B"),
145: T(cb20, "SLA B"),
146: T(cb28, "SRA B"),
147: T(cb38, "SRL B"),
148:
149: T(cb7f, "BIT 7,A"),
150: T(cbbf, "RES 7,A"),
151: T(cbff, "SET 7,A"),
152:
153: // bbb
154: T(cb41, "BIT 0,C"),
155: T(cb49, "BIT 1,C"),
156: T(cb51, "BIT 2,C"),
157: T(cb59, "BIT 3,C"),
158: T(cb61, "BIT 4,C"),
159: T(cb69, "BIT 5,C"),
160: T(cb71, "BIT 6,C"),
161: T(cb79, "BIT 7,C"),
162:
163: //
164: // ED
165: //
166:
167: T(ed0012, "IN0 B,(12H)"),
168: T(ed0112, "OUT0 (12H),B"),
169: T(ed04, "TST B"),
170: T(ed3012, "IN0 F,(12H)"), // 公式表記は不明だが定義動作
171: T(ed31, ILLEGAL), // OUT0 (HL),n はない
172: T(ed34, "TST (HL)"),
173:
174: T(ed40, "IN B,(C)"),
175: T(ed41, "OUT (C),B"),
176: T(ed42, "SBC HL,BC"),
177: T(ed431234, "LD (3412H),BC"),
178: T(ed44, "NEG"),
179: T(ed45, "RETN"),
180: T(ed46, "IM 0"),
181: T(ed47, "LD I,A"),
182: T(ed4a, "ADC HL,BC"),
183: T(ed4b1234, "LD BC,(3412H)"),
184: T(ed4c, "MLT BC"),
185: T(ed4d, "RETI"),
186: T(ed4f, "LD R,A"),
187:
188: T(ed56, "IM 1"),
189: T(ed57, "LD A,I"),
190: T(ed5e, "IM 2"),
191: T(ed5f, "LD A,R"),
192:
193: T(ed6412, "TST 12H"),
194: T(ed67, "RRD"),
195: T(ed6f, "RLD"),
196:
197: T(ed70, "IN F,(C)"), // 公式表記は不明だが定義動作
198: T(ed71, ILLEGAL), // OUT (C),(HL) はない
199: T(ed72, "SBC HL,SP"),
200: T(ed731234, "LD (3412H),SP"),
201: T(ed7412, "TSTIO 12H"),
202: T(ed76, "SLP"),
203: T(ed7c, "MLT SP"),
204:
205: T(ed83, "OTIM"),
206: T(ed8b, "OTDM"),
207: T(ed93, "OTIMR"),
208: T(ed9b, "OTDMR"),
209:
210: T(eda0, "LDI"),
211: T(eda1, "CPI"),
212: T(eda2, "INI"),
213: T(eda3, "OUTI"),
214: T(eda8, "LDD"),
215: T(eda9, "CPD"),
216: T(edaa, "IND"),
217: T(edab, "OUTD"),
218:
219: T(edb0, "LDIR"),
220: T(edb1, "CPIR"),
221: T(edb2, "INIR"),
222: T(edb3, "OTIR"),
223: T(edb8, "LDDR"),
224: T(edb9, "CPDR"),
225: T(edba, "INDR"),
226: T(edbb, "OTDR"),
227:
228: T(edc9, "MULUB A,C"), // R800
229: T(edc3, "MULUB HL,BC"), // R800
230: T(edf3, "MULUB HL,SP"), // R800
231:
232: T(edff, "SYSCALL"),
233:
234: //
235: // DD/FD
236: //
237:
238: // XXX fd00 は nop になるかとか
239: // XXX ddfd23 とかどうなるかとか
240: T(fd09, "ADD IY,BC"),
241: T(fd29, "ADD IY,IY"),
242: T(fd0c, "INC C"), // Z80
243: T(fd2c, "INC IYL"), // Z80
244: T(fd0d, "DEC C"), // Z80
245: T(fd2d, "DEC IYL"), // Z80
246: T(fd211234, "LD IY,3412H"),
247: T(fd221234, "LD (3412H),IY"),
248: T(fd23, "INC IY"),
249: T(fd3412, "INC (IY+12H)"),
250: T(fd3512, "DEC (IY+12H)"),
251: T(fd361234, "LD (IY+12H),34H"),
252: T(fd4612, "LD B,(IY+12H)"),
253: T(fd7112, "LD (IY+12H),C"),
254: T(fd4a, "LD C,D"), // Z80
255: T(fd4d, "LD C,IYL"), // Z80
256: T(fd69, "LD IYL,C"), // Z80
257: T(fd8612, "ADD A,(IY+12H)"),
258: T(fd8e12, "ADC A,(IY+12H)"),
259: T(fd9612, "SUB (IY+12H)"),
260: T(fd9e12, "SBC A,(IY+12H)"),
261: T(fda612, "AND (IY+12H)"),
262: T(fdae12, "XOR (IY+12H)"),
263: T(fdb612, "OR (IY+12H)"),
264: T(fdbe12, "CP (IY+12H)"),
265: T(fd81, "ADD A,C"), // Z80
266: T(fd85, "ADD A,IYL"), // Z80
267: T(fd8d, "ADC A,IYL"), // Z80
268: T(fd95, "SUB IYL"), // Z80
269: T(fd9d, "SBC A,IYL"), // Z80
270: T(fda5, "AND IYL"), // Z80
271: T(fdad, "XOR IYL"), // Z80
272: T(fdb5, "OR IYL"), // Z80
273: T(fdbd, "CP IYL"), // Z80
274: T(fde1, "POP IY"),
275: T(fde3, "EX (SP),IY"), // EX (SP),HL は IX/IY 可
276: T(fde5, "PUSH IY"),
277: T(fde9, "JP (IY)"), // JP (HL) は (IX)/(IY) になる
278: T(fdeb, ILLEGAL), // EX DE,HL は IX/IY 不可
279: T(fdf9, "LD SP,IY"),
280:
281: T(ddcb1206, "RLC (IX+12H)"),
282: T(ddcb12fe, "SET 7,(IX+12H)"),
283:
284: // XXX ED 以下は DD/FD で HL が変化する?しない?
285: };
286:
287: static uint8 ram[1024];
288: static int failed;
289:
290: #include "test_debugger_memory.cpp"
291:
292: // リンカを通すためのダミー
293: DisasmLine::~DisasmLine() { }
294: DebuggerMD::~DebuggerMD() { }
1.1.1.4 ! root 295: uint32 DebuggerMD::GetNextPC() { return 0; }
! 296: void DebuggerMD::PrintExceptionFrame(FILE *, busaddr) { }
1.1 root 297:
298: int
299: main(int ac, char *av[])
300: {
1.1.1.2 root 301: busaddr saddr;
1.1 root 302:
303: // DebuggerMD (の継承クラス)を用意するのは芋づる式に大変なので、
304: // 中でアクセスする変数だけ強引に用意する。
1.1.1.3 root 305: DebuggerMD *md = (DebuggerMD *)calloc(1, sizeof(DebuggerMD));
1.1 root 306: md->inst_bytes = 1;
307:
308: for (int i = 0; i < countof(table); i++) {
309: int line = table[i].line;
310: std::string inp = table[i].inp;
311: std::string exp = table[i].exp;
312:
313: // エラー表示用
314: std::string inst_str = string_format("%d: %s", line, inp.c_str());
315:
316: // 入力ダンプ文字列を 16進数列にする
317: std::vector<uint8> bin;
318: for (int j = 0; j < inp.length(); j += 2) {
319: std::string hex = inp.substr(j, 2);
320: char *end;
321: errno = 0;
322: uint32 r = strtoul(hex.c_str(), &end, 16);
323: if (errno != 0) {
324: err(1, "strtoul");
325: }
326: bin.push_back(r);
327: }
328: // テーブルの期待値は入力手間を省くためタブ区切りだが実際は空白。
329: // ここでタブを空白に変換する。
330: std::string exp2;
331: for (int j = 0; j < exp.length(); j++) {
332: if (exp[j] == '\t') {
333: if (j < 8) {
334: exp2 += std::string(8 - j, ' ');
335: } else {
336: exp2 += ' ';
337: }
338: } else {
339: exp2 += exp[j];
340: }
341: }
342: exp = exp2;
343:
344: // 全体を初期化
345: memset(ram, 0x99, sizeof(ram));
346: // 100番地から命令列を書き込む
347: for (int j = 0; j < bin.size(); j++) {
348: ram[HB(0x100 + j)] = bin[j];
349: }
350: // 検査
1.1.1.3 root 351: saddr = busaddr(0x100);
1.1 root 352: hd64180disasm dis;
353: DebuggerMemoryStream mem(NULL, saddr);
354: dis.Exec(&mem);
355: // 照合
356: if (dis.text != exp) {
357: printf("%s expects \"%s\" but \"%s\"\n", inst_str.c_str(),
358: exp.c_str(), dis.text.c_str());
359: failed++;
360: continue;
361: }
362: // PC を照合
363: uint32 exppc = 0x100 + bin.size();
364: if (mem.paddr != exppc) {
365: printf("%s expects PC +$%x but +$%x\n", inst_str.c_str(),
366: exppc - 0x100, mem.paddr - 0x100);
367: failed++;
368: continue;
369: }
370: }
371:
372: int total = countof(table);
373: printf("%d tests, %d success", total, total - failed);
374: if (failed > 0) {
375: printf(", %d failed", failed);
376: }
377: printf("\n");
378: return 0;
379: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.