File:  [Isaki's NoNo m68k/m88k emulator] / nono / hd64180 / testdis.cpp
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:06:02 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v027, HEAD
nono 1.7.0

//
// nono
// Copyright (C) 2022 nono project
// Licensed under nono-license.txt
//

#include "hd64180disasm.h"
#include "debugger_memory.h"
#include "mpu64180.h"
#include "mystring.h"

#define T(inp, exp)	{ __LINE__, #inp, exp }
#define ILLEGAL	"<illegal instruction>"

struct {
	int line;
	std::string inp;
	std::string exp;
} table[] = {
	// inst			exp
	T(00,			 "NOP"),
	T(011234,		 "LD	BC,3412H"),
	T(02,			 "LD	(BC),A"),
	T(03,			 "INC	BC"),
	T(04,			 "INC	B"),
	T(05,			 "DEC	B"),
	T(0612,			 "LD	B,12H"),
	T(07,			 "RLCA"),
	T(08,			 "EX	AF,AF'"),
	T(09,			 "ADD	HL,BC"),
	T(0a,			 "LD	A,(BC)"),
	T(0b,			 "DEC	BC"),
	T(0c,			 "INC	C"),
	T(0d,			 "DEC	C"),
	T(0e12,			 "LD	C,12H"),
	T(0f,			 "RRCA"),

	T(1012,			 "DJNZ	0114H"),
	T(111234,		 "LD	DE,3412H"),
	T(17,			 "RLA"),
	T(1812,			 "JR	0114H"),
	T(1f,			 "RRA"),

	T(2012,			 "JR	NZ,0114H"),
	T(211234,		 "LD	HL,3412H"),
	T(221234,		 "LD	(3412H),HL"),
	T(27,			 "DAA"),
	T(2812,			 "JR	Z,0114H"),
	T(2a1234,		 "LD	HL,(3412H)"),
	T(2f,			 "CPL"),

	T(3012,			 "JR	NC,0114H"),
	T(311234,		 "LD	SP,3412H"),
	T(321234,		 "LD	(3412H),A"),
	T(37,			 "SCF"),
	T(3812,			 "JR	C,0114H"),
	T(39,			 "ADD	HL,SP"),
	T(3a1234,		 "LD	A,(3412H)"),
	T(3f,			 "CCF"),

	T(40,			 "LD	B,B"),
	T(46,			 "LD	B,(HL)"),
	T(48,			 "LD	C,B"),
	T(4e,			 "LD	C,(HL)"),
	T(70,			 "LD	(HL),B"),
	T(76,			 "HALT"),
	T(77,			 "LD	(HL),A"),
	T(7e,			 "LD	A,(HL)"),

	T(80,			 "ADD	A,B"),
	T(89,			 "ADC	A,C"),
	T(92,			 "SUB	D"),
	T(9b,			 "SBC	A,E"),
	T(a4,			 "AND	H"),
	T(ad,			 "XOR	L"),
	T(b6,			 "OR	(HL)"),
	T(bf,			 "CP	A"),

	T(c0,			 "RET	NZ"),
	T(c1,			 "POP	BC"),
	T(c21234,		 "JP	NZ,3412H"),
	T(c31234,		 "JP	3412H"),
	T(c41234,		 "CALL	NZ,3412H"),
	T(c5,			 "PUSH	BC"),
	T(c612,			 "ADD	A,12H"),
	T(c7,			 "RST	00H"),
	T(c9,			 "RET"),
	T(cd1234,		 "CALL	3412H"),
	T(ce12,			 "ADC	A,12H"),

	T(d312,			 "OUT	(12H),A"),
	T(d612,			 "SUB	12H"),
	T(d9,			 "EXX"),
	T(db12,			 "IN	A,(12H)"),
	T(de12,			 "SBC	A,12H"),

	T(e3,			 "EX	(SP),HL"),
	T(e612,			 "AND	12H"),
	T(e9,			 "JP	(HL)"),
	T(eb,			 "EX	DE,HL"),
	T(ee12,			 "XOR	12H"),

	T(f3,			 "DI"),
	T(f612,			 "OR	12H"),
	T(f9,			 "LD	SP,HL"),
	T(fb,			 "EI"),
	T(fe12,			 "CP	12H"),

	// ww
	T(13,			 "INC	DE"),
	T(23,			 "INC	HL"),
	T(33,			 "INC	SP"),

	// fff
	T(c8,			 "RET	Z"),
	T(d0,			 "RET	NC"),
	T(d8,			 "RET	C"),
	T(e0,			 "RET	PO"),
	T(e8,			 "RET	PE"),
	T(f0,			 "RET	P"),
	T(f8,			 "RET	M"),

	// zzz
	T(d1,			 "POP	DE"),
	T(e1,			 "POP	HL"),
	T(f1,			 "POP	AF"),

	// vvv
	T(cf,			 "RST	08H"),
	T(d7,			 "RST	10H"),
	T(df,			 "RST	18H"),
	T(e7,			 "RST	20H"),
	T(ef,			 "RST	28H"),
	T(f7,			 "RST	30H"),
	T(ff,			 "RST	38H"),

	//
	// CB
	//

	T(cb00,			 "RLC	B"),
	T(cb08,			 "RRC	B"),
	T(cb10,			 "RL	B"),
	T(cb18,			 "RR	B"),
	T(cb20,			 "SLA	B"),
	T(cb28,			 "SRA	B"),
	T(cb38,			 "SRL	B"),

	T(cb7f,			 "BIT	7,A"),
	T(cbbf,			 "RES	7,A"),
	T(cbff,			 "SET	7,A"),

	// bbb
	T(cb41,			 "BIT	0,C"),
	T(cb49,			 "BIT	1,C"),
	T(cb51,			 "BIT	2,C"),
	T(cb59,			 "BIT	3,C"),
	T(cb61,			 "BIT	4,C"),
	T(cb69,			 "BIT	5,C"),
	T(cb71,			 "BIT	6,C"),
	T(cb79,			 "BIT	7,C"),

	//
	// ED
	//

	T(ed0012,		 "IN0	B,(12H)"),
	T(ed0112,		 "OUT0	(12H),B"),
	T(ed04,			 "TST	B"),
	T(ed3012,		 "IN0	F,(12H)"),	// 公式表記は不明だが定義動作
	T(ed31,			 ILLEGAL),			// OUT0 (HL),n はない
	T(ed34,			 "TST	(HL)"),

	T(ed40,			 "IN	B,(C)"),
	T(ed41,			 "OUT	(C),B"),
	T(ed42,			 "SBC	HL,BC"),
	T(ed431234,		 "LD	(3412H),BC"),
	T(ed44,			 "NEG"),
	T(ed45,			 "RETN"),
	T(ed46,			 "IM	0"),
	T(ed47,			 "LD	I,A"),
	T(ed4a,			 "ADC	HL,BC"),
	T(ed4b1234,		 "LD	BC,(3412H)"),
	T(ed4c,			 "MLT	BC"),
	T(ed4d,			 "RETI"),
	T(ed4f,			 "LD	R,A"),

	T(ed56,			 "IM	1"),
	T(ed57,			 "LD	A,I"),
	T(ed5e,			 "IM	2"),
	T(ed5f,			 "LD	A,R"),

	T(ed6412,		 "TST	12H"),
	T(ed67,			 "RRD"),
	T(ed6f,			 "RLD"),

	T(ed70,			 "IN	F,(C)"),	// 公式表記は不明だが定義動作
	T(ed71,			 ILLEGAL),			// OUT (C),(HL) はない
	T(ed72,			 "SBC	HL,SP"),
	T(ed731234,		 "LD	(3412H),SP"),
	T(ed7412,		 "TSTIO	12H"),
	T(ed76,			 "SLP"),
	T(ed7c,			 "MLT	SP"),

	T(ed83,			 "OTIM"),
	T(ed8b,			 "OTDM"),
	T(ed93,			 "OTIMR"),
	T(ed9b,			 "OTDMR"),

	T(eda0,			 "LDI"),
	T(eda1,			 "CPI"),
	T(eda2,			 "INI"),
	T(eda3,			 "OUTI"),
	T(eda8,			 "LDD"),
	T(eda9,			 "CPD"),
	T(edaa,			 "IND"),
	T(edab,			 "OUTD"),

	T(edb0,			 "LDIR"),
	T(edb1,			 "CPIR"),
	T(edb2,			 "INIR"),
	T(edb3,			 "OTIR"),
	T(edb8,			 "LDDR"),
	T(edb9,			 "CPDR"),
	T(edba,			 "INDR"),
	T(edbb,			 "OTDR"),

	T(edc9,			 "MULUB	A,C"),			// R800
	T(edc3,			 "MULUB	HL,BC"),		// R800
	T(edf3,			 "MULUB	HL,SP"),		// R800

	T(edff,			 "SYSCALL"),

	//
	// DD/FD
	//

	// XXX fd00 は nop になるかとか
	// XXX ddfd23 とかどうなるかとか
	T(fd09,			 "ADD	IY,BC"),
	T(fd29,			 "ADD	IY,IY"),
	T(fd0c,			 "INC	C"),			// Z80
	T(fd2c,			 "INC	IYL"),			// Z80
	T(fd0d,			 "DEC	C"),			// Z80
	T(fd2d,			 "DEC	IYL"),			// Z80
	T(fd211234,		 "LD	IY,3412H"),
	T(fd221234,		 "LD	(3412H),IY"),
	T(fd23,			 "INC	IY"),
	T(fd3412,		 "INC	(IY+12H)"),
	T(fd3512,		 "DEC	(IY+12H)"),
	T(fd361234,		 "LD	(IY+12H),34H"),
	T(fd4612,		 "LD	B,(IY+12H)"),
	T(fd7112,		 "LD	(IY+12H),C"),
	T(fd4a,			 "LD	C,D"),			// Z80
	T(fd4d,			 "LD	C,IYL"),		// Z80
	T(fd69,			 "LD	IYL,C"),		// Z80
	T(fd8612,		 "ADD	A,(IY+12H)"),
	T(fd8e12,		 "ADC	A,(IY+12H)"),
	T(fd9612,		 "SUB	(IY+12H)"),
	T(fd9e12,		 "SBC	A,(IY+12H)"),
	T(fda612,		 "AND	(IY+12H)"),
	T(fdae12,		 "XOR	(IY+12H)"),
	T(fdb612,		 "OR	(IY+12H)"),
	T(fdbe12,		 "CP	(IY+12H)"),
	T(fd81,			 "ADD	A,C"),			// Z80
	T(fd85,			 "ADD	A,IYL"),		// Z80
	T(fd8d,			 "ADC	A,IYL"),		// Z80
	T(fd95,			 "SUB	IYL"),			// Z80
	T(fd9d,			 "SBC	A,IYL"),		// Z80
	T(fda5,			 "AND	IYL"),			// Z80
	T(fdad,			 "XOR	IYL"),			// Z80
	T(fdb5,			 "OR	IYL"),			// Z80
	T(fdbd,			 "CP	IYL"),			// Z80
	T(fde1,			 "POP	IY"),
	T(fde3,			 "EX	(SP),IY"),		// EX (SP),HL は IX/IY 可
	T(fde5,			 "PUSH	IY"),
	T(fde9,			 "JP	(IY)"),			// JP (HL) は (IX)/(IY) になる
	T(fdeb,			 ILLEGAL),				// EX DE,HL は IX/IY 不可
	T(fdf9,			 "LD	SP,IY"),

	T(ddcb1206,		 "RLC	(IX+12H)"),
	T(ddcb12fe,		 "SET	7,(IX+12H)"),

	// XXX ED 以下は DD/FD で HL が変化する?しない?
};

static uint8 ram[1024];
static int failed;

#include "test_debugger_memory.cpp"

// リンカを通すためのダミー
DisasmLine::~DisasmLine() { }
DebuggerMD::~DebuggerMD() { }
uint32 DebuggerMD::GetNextPC() { return 0; }
void DebuggerMD::PrintExceptionFrame(FILE *, busaddr) { }

int
main(int ac, char *av[])
{
	busaddr saddr;

	// DebuggerMD (の継承クラス)を用意するのは芋づる式に大変なので、
	// 中でアクセスする変数だけ強引に用意する。
	DebuggerMD *md = (DebuggerMD *)calloc(1, sizeof(DebuggerMD));
	md->inst_bytes = 1;

	for (int i = 0; i < countof(table); i++) {
		int line = table[i].line;
		std::string inp = table[i].inp;
		std::string exp = table[i].exp;

		// エラー表示用
		std::string inst_str = string_format("%d: %s", line, inp.c_str());

		// 入力ダンプ文字列を 16進数列にする
		std::vector<uint8> bin;
		for (int j = 0; j < inp.length(); j += 2) {
			std::string hex = inp.substr(j, 2);
			char *end;
			errno = 0;
			uint32 r = strtoul(hex.c_str(), &end, 16);
			if (errno != 0) {
				err(1, "strtoul");
			}
			bin.push_back(r);
		}
		// テーブルの期待値は入力手間を省くためタブ区切りだが実際は空白。
		// ここでタブを空白に変換する。
		std::string exp2;
		for (int j = 0; j < exp.length(); j++) {
			if (exp[j] == '\t') {
				if (j < 8) {
					exp2 += std::string(8 - j, ' ');
				} else {
					exp2 += ' ';
				}
			} else {
				exp2 += exp[j];
			}
		}
		exp = exp2;

		// 全体を初期化
		memset(ram, 0x99, sizeof(ram));
		// 100番地から命令列を書き込む
		for (int j = 0; j < bin.size(); j++) {
			ram[HB(0x100 + j)] = bin[j];
		}
		// 検査
		saddr = busaddr(0x100);
		hd64180disasm dis;
		DebuggerMemoryStream mem(NULL, saddr);
		dis.Exec(&mem);
		// 照合
		if (dis.text != exp) {
			printf("%s expects \"%s\" but \"%s\"\n", inst_str.c_str(),
				exp.c_str(), dis.text.c_str());
			failed++;
			continue;
		}
		// PC を照合
		uint32 exppc = 0x100 + bin.size();
		if (mem.paddr != exppc) {
			printf("%s expects PC +$%x but +$%x\n", inst_str.c_str(),
				exppc - 0x100, mem.paddr - 0x100);
			failed++;
			continue;
		}
	}

	int total = countof(table);
	printf("%d tests, %d success", total, total - failed);
	if (failed > 0) {
		printf(", %d failed", failed);
	}
	printf("\n");
	return 0;
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.