File:  [Isaki's NoNo m68k/m88k emulator] / nono / hd64180 / hd64180disasm.cpp
Revision 1.1.1.5 (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
//

//
// HD64180 逆アセンブラ
//

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

#define OP_DEF(name)	void __CONCAT(hd64180disasm::op_,name)()
#define OP_FUNC(name)	__CONCAT(op_,name)()

// コンストラクタ
hd64180disasm::hd64180disasm()
{
}

// デストラクタ
hd64180disasm::~hd64180disasm()
{
}

// 逆アセンブルを実行
bool
hd64180disasm::Exec(DebuggerMemoryStream *mem_)
{
	ExecInit(mem_);

	name.clear();
	arg1.clear();
	arg2.clear();

	ppc = mem->laddr.Addr();
	ixiy = USE_HL;
	ixd = (uint32)-1;
	// 1バイト目処理
	op = fetch1();
	switch (op) {
#include "hd64180switch_00.inc"
	 default:
		__unreachable();
	}

	// 出力文字列(ダンプ)
	dump = string_format("%02x ", bin[0]);
	for (int i = 1; i < bin.size(); i++) {
		dump += string_format("%02x ", bin[i]);
	}
	if (bin.size() < 5) {
		dump += std::string(15 - bin.size() * 3, ' ');
	}

	// 出力文字列(命令)
	text = name;

	// arg2 だけがあるという状態は認めないが、
	// ここでシフトしておけばいいか。
	if (__predict_false(!arg2.empty() && arg1.empty())) {
		arg1 = arg2;
		arg2.clear();
	}

	// arg1 があればインデントして追加
	if (!arg1.empty()) {
		uint len = text.length();
		if (len < 8) {
			text += std::string(8 - len, ' ');
		} else {
			text += ' ';
		}

		text += arg1;
	}

	// arg2 があればカンマで区切って追加
	if (!arg2.empty()) {
		text += ",";
		text += arg2;
	}

	return true;
}

// バイトフェッチ
uint8
hd64180disasm::fetch1()
{
	uint8 data = mem->Read(1);
	bin.push_back(data);
	return data;
}

// ワードフェッチ
uint16
hd64180disasm::fetch2()
{
	uint16 data;

	data  = fetch1();
	data |= fetch1() << 8;

	return data;
}


// ixiy に応じて HL/IX/IY のレジスタ名を返す。
std::string
hd64180disasm::HL()
{
	static const char *hlname[] = {
		"HL",
		"IX",
		"IY",
	};
	return hlname[(uint)ixiy];
}

// (HL)/(IX+d)/(IY+d) を出力する。
std::string
hd64180disasm::HLin()
{
	if (ixiy) {
		// ixd を読むタイミングが DD CB の時だけ違う。
		if ((int32)ixd < 0) {
			ixd = fetch1();
		}
		if (ixd < 0x80) {
			return string_format("(%s+%02XH)", HL().c_str(), ixd);
		} else {
			int v = -(int)(int8)ixd;
			return string_format("(%s-%02XH)", HL().c_str(), v);
		}
	} else {
		return "(HL)";
	}
}

#define op_ww	(((op) >> 4) & 3)
#define op_zz	(((op) >> 4) & 3)
#define op_fff	(((op) >> 3) & 7)
#define op_bbb	(((op) >> 3) & 7)
#define op_rrr	(((op) >> 3) & 7)
#define op_sss	( (op)       & 7)

// ww のレジスタ名を返す。HL は必要に応じて IX, IY を出力する。
std::string
hd64180disasm::ww()
{
	static const char * const wwnames[] = {
		"BC",
		"DE",
		"HL?",	// 参照されないはず
		"SP",
	};

	uint r = op_ww;
	if (r == 2) {
		return HL();
	} else {
		return std::string(wwnames[r]);
	}
}

// ww のレジスタ間接名 ("(BC)"形式) を返す。
// (HL) は必要に応じて (IX+d)、(IY+d) を出力する。
std::string
hd64180disasm::wwin()
{
	uint r = op_ww;
	if (r == 2) {
		return HLin();
	} else {
		return "(" + ww() + ")";
	}
}

// zz レジスタの "BC", "DE", "HL" を返す。
// "AF" は独立してるのでここでは扱わない。
std::string
hd64180disasm::zz()
{
	static const char * const zznames[] = {
		"BC",
		"DE",
		// HL は参照されないはず
	};

	uint r = op_zz;
	if (r == 2) {
		return HL();
	} else {
		return std::string(zznames[r]);
	}
}

// rrr (!=%110) のレジスタ名を返す。
std::string
hd64180disasm::rrr()
{
	return rrrsss(op_rrr);
}

// sss (!=%110) のレジスタ名を返す。
std::string
hd64180disasm::sss()
{
	return rrrsss(op_sss);
}

// rrr/sss (!=%110) のレジスタ名を返す。
std::string
hd64180disasm::rrrsss(uint r)
{
	static const char rrrnames[] = "BCDEHL?A";

	if (__predict_true(ixiy == USE_HL)) {
		return std::string(1, rrrnames[r]);
	} else {
		switch (r) {
		 case 4:	return HL() + "H";
		 case 5:	return HL() + "L";
		 default:	return std::string(1, rrrnames[r]);
		}
	}
}

std::string
hd64180disasm::fff() const
{
	static const char *fffname[] = {
		"NZ",
		"Z",
		"NC",
		"C",
		"PO",
		"PE",
		"P",
		"M",
	};
	uint r = op_fff;
	return fffname[r];
}

std::string
hd64180disasm::bbb() const
{
	uint b = op_bbb;
	return std::string(1, '0' + b);
}

std::string
hd64180disasm::imm8()
{
	uint8 imm = fetch1();
	if (imm < 0xa0) {
		return string_format("%02XH", imm);
	} else {
		return string_format("0%02XH", imm);
	}
}

std::string
hd64180disasm::imm16()
{
	uint16 imm = fetch2();
	if (imm < 0xa000) {
		return string_format("%04XH", imm);
	} else {
		return string_format("0%04XH", imm);
	}
}

std::string
hd64180disasm::disp8()
{
	int8 disp = (int8)fetch1();
	// 外部的な表記はこの命令位置 + 2 となっているが、実際には
	// disp をフェッチした後の PC が起点になっているということのはず。
	uint32 pc = mem->laddr.Addr();
	uint32 addr = pc + disp;
	if (addr < 0xa000) {
		return string_format("%04XH", addr);
	} else {
		return string_format("0%04XH", addr);
	}
}

// 不当命令
OP_DEF(illegal)
{
	name = "<illegal instruction>";
}

// エミュレータ的未実装
OP_DEF(undef)
{
	name = "<not implemented?>";
}

// 00000000: 01R:	NOP
OP_DEF(nop)
{
	name = "NOP";
}

//    00ww0001: 01R:	LD ww,nn
// DD:00100001: 01R:	LD IX,nn
OP_DEF(ld_ww_nn)
{
	name = "LD";
	arg1 = ww();
	arg2 = imm16();
}

// 00ww0010: 01R:	LD (ww),A
OP_DEF(ld_wwin_a)
{
	name = "LD";
	arg1 = wwin();
	arg2 = "A";
}

//    00ww0011: 01R:	INC ww
// DD:00100011: 01R:	INC IX
OP_DEF(inc_ww)
{
	name = "INC";
	arg1 = ww();
}

// 00rrr100: 01R:	INC r
OP_DEF(inc_r)
{
	name = "INC";
	arg1 = rrr();
}

// 00rrr101: 01R:	DEC r
OP_DEF(dec_r)
{
	name = "DEC";
	arg1 = rrr();
}

// 00rrr110: 01R:	LD r,n
OP_DEF(ld_r_n)
{
	name = "LD";
	arg1 = rrr();
	arg2 = imm8();
}

// 00000111: 01R:	RLCA
OP_DEF(rlca)
{
	name = "RLCA";
}

// 00001000: 01R:	EX AF,AF'
OP_DEF(ex_af_af)
{
	name = "EX";
	arg1 = "AF";
	arg2 = "AF'";
}

//    00ww1001: 01R:	ADD HL,ww
// DD:00ww1001: 01R:	ADD IX,ww
OP_DEF(add_hl_ww)
{
	name = "ADD";
	arg1 = HL();
	arg2 = ww();
}

// 00ww1010: 01R:	LD A,(ww)
OP_DEF(ld_a_wwin)
{
	name = "LD";
	arg1 = "A";
	arg2 = wwin();
}

//    00ww1011: 01R:	DEC ww
// DD:00101011: 01R:	DEC IX
OP_DEF(dec_ww)
{
	name = "DEC";
	arg1 = ww();
}

// 00001111: 01R:	RRCA
OP_DEF(rrca)
{
	name = "RRCA";
}

// 00010000: 01R:	DJNZ n
OP_DEF(djnz)
{
	name = "DJNZ";
	arg1 = disp8();
}

// 00010111: 01R:	RLA
OP_DEF(rla)
{
	name = "RLA";
}

// 00011000: 01R:	JR n
OP_DEF(jr)
{
	name = "JR";
	arg1 = disp8();
}

// 00011111: 01R:	RRA
OP_DEF(rra)
{
	name = "RRA";
}

// 00100000: 01R:	JR NZ,n
OP_DEF(jr_nz)
{
	name = "JR";
	arg1 = "NZ";
	arg2 = disp8();
}

//    00100010: 01R:	LD (nn),HL
// DD:00100010: 01R:	LD (nn),IX
OP_DEF(ld_nnin_hl)
{
	name = "LD";
	arg1 = "(" + imm16() + ")";
	arg2 = HL();
}

// 00100111: 01R:	DAA
OP_DEF(daa)
{
	name = "DAA";
}

// 00101000: 01R:	JR Z,n
OP_DEF(jr_z)
{
	name = "JR";
	arg1 = "Z";
	arg2 = disp8();
}

//    00101010: 01R:	LD HL,(nn)
// DD:00101010: 01R:	LD IX,(nn)
OP_DEF(ld_hl_nnin)
{
	name = "LD";
	arg1 = HL();
	arg2 = "(" + imm16() + ")";
}

// 00101111: 01R:	CPL
OP_DEF(cpl)
{
	name = "CPL";
}

// 00110000: 01R:	JR NC,n
OP_DEF(jr_nc)
{
	name = "JR";
	arg1 = "NC";
	arg2 = disp8();
}

// 00110010: 01R:	LD (nn),A
OP_DEF(ld_nnin_a)
{
	name = "LD";
	arg1 = "(" + imm16() + ")";
	arg2 = "A";
}

//    00110100: 01R:	INC (HL)
// DD:00110100: 01R:	INC (IX+d)
OP_DEF(inc_hlin)
{
	name = "INC";
	arg1 = HLin();
}

//    00110101: 01R:	DEC (HL)
// DD:00110101: 01R:	DEC (IX+d)
OP_DEF(dec_hlin)
{
	name = "DEC";
	arg1 = HLin();
}

//    00110110: 01R:	LD (HL),n
// DD:00110110: 01R:	LD (IX+d),n
OP_DEF(ld_hlin_n)
{
	name = "LD";
	arg1 = HLin();
	arg2 = imm8();
}

// 00110111: 01R:	SCF
OP_DEF(scf)
{
	name = "SCF";
}

// 00111000: 01R:	JR C,n
OP_DEF(jr_c)
{
	name = "JR";
	arg1 = "C";
	arg2 = disp8();
}

// 00111010: 01R:	LD A,(nn)
OP_DEF(ld_a_nnin)
{
	name = "LD";
	arg1 = "A";
	arg2 = "(" + imm16() + ")";
}

// 00111111: 01R:	CCF
OP_DEF(ccf)
{
	name = "CCF";
}

// 01rrrsss: 01R:	LD r,s
OP_DEF(ld_r_s)
{
	name = "LD";
	arg1 = rrr();
	arg2 = sss();
}

//    01rrr110: 01R:	LD r,(HL)
// DD:01rrr110: 01R:	LD r,(IX+d)
OP_DEF(ld_r_hlin)
{
	name = "LD";
	arg1 = rrr();
	arg2 = HLin();
}

//    01110sss: 01R:	LD (HL),s
// DD:01110sss: 01R:	LD (IX+d),s
OP_DEF(ld_hlin_s)
{
	name = "LD";
	arg1 = HLin();
	arg2 = sss();
}

// 01110110: 01R:	HALT
OP_DEF(halt)
{
	name = "HALT";
}

// 10000rrr: 01R:	ADD A,r
OP_DEF(add_a_r)
{
	name = "ADD";
	arg1 = "A";
	arg2 = sss();
}

//    10000110: 01R:	ADD A,(HL)
// DD:10000110: 01R:	ADD A,(IX+d)
OP_DEF(add_a_hlin)
{
	name = "ADD";
	arg1 = "A";
	arg2 = HLin();
}

// 10001rrr: 01R:	ADC A,r
OP_DEF(adc_a_r)
{
	name = "ADC";
	arg1 = "A";
	arg2 = sss();
}

//    10001110: 01R:	ADC A,(HL)
// DD:10001110: 01R:	ADC A,(IX+d)
OP_DEF(adc_a_hlin)
{
	name = "ADC";
	arg1 = "A";
	arg2 = HLin();
}

// 10010rrr: 01R:	SUB r
OP_DEF(sub_r)
{
	name = "SUB";
	arg1 = sss();
}

//    10010110: 01R:	SUB (HL)
// DD:10010110: 01R:	SUB (IX+d)
OP_DEF(sub_hlin)
{
	name = "SUB";
	arg1 = HLin();
}

// 10011rrr: 01R:	SBC A,r
OP_DEF(sbc_a_r)
{
	name = "SBC";
	arg1 = "A";
	arg2 = sss();
}

//    10011110: 01R:	SBC A,(HL)
// DD:10011110: 01R:	SBC A,(IX+d)
OP_DEF(sbc_a_hlin)
{
	name = "SBC";
	arg1 = "A";
	arg2 = HLin();
}

// 10100rrr: 01R:	AND r
OP_DEF(and_r)
{
	name = "AND";
	arg1 = sss();
}

//    10100110: 01R:	AND (HL)
// DD:10100110: 01R:	AND (IX+d)
OP_DEF(and_hlin)
{
	name = "AND";
	arg1 = HLin();
}

// 10101rrr: 01R:	XOR r
OP_DEF(xor_r)
{
	name = "XOR";
	arg1 = sss();
}

//    10101110: 01R:	XOR (HL)
// DD:10101110: 01R:	XOR (IX+d)
OP_DEF(xor_hlin)
{
	name = "XOR";
	arg1 = HLin();
}

// 10110rrr: 01R:	OR r
OP_DEF(or_r)
{
	name = "OR";
	arg1 = sss();
}

//    10110110: 01R:	OR (HL)
// DD:10110110: 01R:	OR (IX+d)
OP_DEF(or_hlin)
{
	name = "OR";
	arg1 = HLin();
}

// 10111rrr: 01R:	CP r
OP_DEF(cp_r)
{
	name = "CP";
	arg1 = sss();
}

//    10111110: 01R:	CP (HL)
// DD:10111110: 01R:	CP (IX+d)
OP_DEF(cp_hlin)
{
	name = "CP";
	arg1 = HLin();
}

// 11fff000: 01R:	RET f
OP_DEF(ret_f)
{
	name = "RET";
	arg1 = fff();
}

//    11zz0001: 01R:	POP zz
// DD:11100001: 01R:	POP IX
OP_DEF(pop_zz)
{
	name = "POP";
	arg1 = zz();
}

// 11fff010: 01R:	JP f,nn
OP_DEF(jp_f_nn)
{
	name = "JP";
	arg1 = fff();
	arg2 = imm16();
}

// 11000011: 01R:	JP nn
OP_DEF(jp_nn)
{
	name = "JP";
	arg1 = imm16();
}

// 11fff100: 01R:	CALL f,nn
OP_DEF(call_f_nn)
{
	name = "CALL";
	arg1 = fff();
	arg2 = imm16();
}

//    11zz0101: 01R:	PUSH zz
// DD:11100101: 01R:	PUSH IX
OP_DEF(push_zz)
{
	name = "PUSH";
	arg1 = zz();
}

// 11000110: 01R:	ADD A,n
OP_DEF(add_a_n)
{
	name = "ADD";
	arg1 = "A";
	arg2 = imm8();
}

// 11vvv111: 01R:	RST v
OP_DEF(rst)
{
	uint v = (op >> 3) & 7;
	name = "RST";
	arg1 = string_format("%02xH", v * 8);
}

// 11001001: 01R:	RET
OP_DEF(ret)
{
	name = "RET";
}

// 11001011: 01R:	op_CB
OP_DEF(cb)
{
	op = fetch1();
	switch (op) {
#include "hd64180switch_cb.inc"
	 default:
		OP_FUNC(illegal);
		break;
	}
}

// 11001101: 01R:	CALL nn
OP_DEF(call)
{
	name = "CALL";
	arg1 = imm16();
}

// 11001110: 01R:	ADC A,n
OP_DEF(adc_a_n)
{
	name = "ADC";
	arg1 = "A";
	arg2 = imm8();
}

// 11010011: 01R:	OUT (n),A
OP_DEF(out_n_a)
{
	name = "OUT";
	arg1 = "(" + imm8() + ")";
	arg2 = "A";
}

// 11010110: 01R:	SUB n
OP_DEF(sub_n)
{
	name = "SUB";
	arg1 = imm8();
}

// 11011001: 01R:	EXX
OP_DEF(exx)
{
	name = "EXX";
}

// 11011011: 01R:	IN A,(n)
OP_DEF(in_a_n)
{
	name = "IN";
	arg1 = "A";
	arg2 = "(" + imm8() + ")";
}

// DD/FD の共通部
void
hd64180disasm::ops_ddfd(ixiy_t xy)
{
	ixiy = xy;

	// 2バイト目をフェッチ
	op = fetch1();
	// で分岐
	switch (op) {
#include "hd64180switch_dd.inc"
	 default:
		OP_FUNC(illegal);
		break;
	}
}

// 11011101: 01R:	op_DD
OP_DEF(dd)
{
	ops_ddfd(USE_IX);
}

// 11011110: 01R:	SBC A,n
OP_DEF(sbc_a_n)
{
	name = "SBC";
	arg1 = "A";
	arg2 = imm8();
}

//    11100011: 01R:	EX (SP),HL
// DD:11100011: 01R:	EX (SP),IX
OP_DEF(ex_sp_hl)
{
	name = "EX";
	arg1 = "(SP)";
	arg2 = HL();
}

// 11100110: 01R:	AND n
OP_DEF(and_n)
{
	name = "AND";
	arg1 = imm8();
}

//    11101001: 01R:	JP (HL)
// DD:11101001: 01R:	JP (IX)
OP_DEF(jp_hl)
{
	// これは DD/FD の時に (IX+d)/(IY+d) ではなく (IX)/(IY) になる
	name = "JP";
	arg1 = "(" + HL() + ")";
}

// 11101011: 01R:	EX DE,HL
OP_DEF(ex_de_hl)
{
	name = "EX";
	arg1 = "DE";
	arg2 = "HL";
}

// 11101101: 01R:	op_ED
OP_DEF(ed)
{
	op = fetch1();
	switch (op) {
#include "hd64180switch_ed.inc"
	 default:
		OP_FUNC(illegal);
		break;
	}
}

// 11101110: 01R:	XOR n
OP_DEF(xor_n)
{
	name = "XOR";
	arg1 = imm8();
}

// 11110001: 01R:	POP AF
OP_DEF(pop_af)
{
	name = "POP";
	arg1 = "AF";
}

// 11110011: 01R:	DI
OP_DEF(di)
{
	name = "DI";
}

// 11110101: 01R:	PUSH AF
OP_DEF(push_af)
{
	name = "PUSH";
	arg1 = "AF";
}

// 11110110: 01R:	OR n
OP_DEF(or_n)
{
	name = "OR";
	arg1 = imm8();
}

//    11111001: 01R:	LD SP,HL
// DD:11111001: 01R:	LD SP,IX
OP_DEF(ld_sp_hl)
{
	name = "LD";
	arg1 = "SP";
	arg2 = HL();
}

// 11111011: 01R:	EI
OP_DEF(ei)
{
	name = "EI";
}

// 11111101: 01R:	op_FD
OP_DEF(fd)
{
	ops_ddfd(USE_IY);
}

// 11111110: 01R:	CP n
OP_DEF(cp_n)
{
	name = "CP";
	arg1 = imm8();
}

// CB:00000rrr: 01R:	RLC r
OP_DEF(rlc_r)
{
	name = "RLC";
	arg1 = sss();
}

//    CB:00000110: 01R:	RLC (HL)
// DD_CB:00000110: 01R:	RLC (IX+d)
OP_DEF(rlc_hlin)
{
	name = "RLC";
	arg1 = HLin();
}

// CB:00001rrr: 01R:	RRC r
OP_DEF(rrc_r)
{
	name = "RRC";
	arg1 = sss();
}

//    CB:00001110: 01R:	RRC (HL)
// DD_CB:00001110: 01R:	RRC (IX+d)
OP_DEF(rrc_hlin)
{
	name = "RRC";
	arg1 = HLin();
}

// CB:00010rrr: 01R:	RL r
OP_DEF(rl_r)
{
	name = "RL";
	arg1 = sss();
}

//    CB:00010110: 01R:	RL (HL)
// DD_CB:00010110: 01R:	RL (IX+d)
OP_DEF(rl_hlin)
{
	name = "RL";
	arg1 = HLin();
}

// CB:00011rrr: 01R:	RR r
OP_DEF(rr_r)
{
	name = "RR";
	arg1 = sss();
}

//    CB:00011110: 01R:	RR (HL)
// DD_CB:00011110: 01R:	RR (IX+d)
OP_DEF(rr_hlin)
{
	name = "RR";
	arg1 = HLin();
}

// CB:00100rrr: 01R:	SLA r
OP_DEF(sla_r)
{
	name = "SLA";
	arg1 = sss();
}

//    CB:00100110: 01R:	SLA (HL)
// DD_CB:00100110: 01R:	SLA (IX+d)
OP_DEF(sla_hlin)
{
	name = "SLA";
	arg1 = HLin();
}

// CB:00101rrr: 01R:	SRA r
OP_DEF(sra_r)
{
	name = "SRA";
	arg1 = sss();
}

//    CB:00101110: 01R:	SRA (HL)
// DD_CB:00101110: 01R:	SRA (IX+d)
OP_DEF(sra_hlin)
{
	name = "SRA";
	arg1 = HLin();
}

// CB:00110rrr: Z--:	SLL
OP_DEF(sll_r)
{
	name = "SLL";
	arg1 = sss();
}

//    CB:00110110: Z--:	SLL (HL)
// DD_CB:00110110: Z--:	SLL (IX+d)
OP_DEF(sll_hlin)
{
	name = "SLL";
	arg1 = HLin();
}

// CB:00111rrr: 01R:	SRL r
OP_DEF(srl_r)
{
	name = "SRL";
	arg1 = sss();
}

//    CB:00111110: 01R:	SRL (HL)
// DD_CB:00111110: 01R:	SRL (IX+d)
OP_DEF(srl_hlin)
{
	name = "SRL";
	arg1 = HLin();
}

// CB:01bbbrrr: 01R:	BIT b,r
OP_DEF(bit_r)
{
	name = "BIT";
	arg1 = bbb();
	arg2 = sss();
}

//    CB:01bbb110: 01R:	BIT b,(HL)
// DD_CB:01bbb110: 01R:	BIT b,(IX+d)
OP_DEF(bit_hlin)
{
	name = "BIT";
	arg1 = bbb();
	arg2 = HLin();
}

// CB:10bbbrrr: 01R:	RES b,r
OP_DEF(res_r)
{
	name = "RES";
	arg1 = bbb();
	arg2 = sss();
}

//    CB:10bbb110: 01R:	RES b,(HL)
// DD_CB:10bbb110: 01R:	RES b,(IX+d)
OP_DEF(res_hlin)
{
	name = "RES";
	arg1 = bbb();
	arg2 = HLin();
}

// CB:11bbbrrr: 01R:	SET b,r
OP_DEF(set_r)
{
	name = "SET";
	arg1 = bbb();
	arg2 = sss();
}

//    CB:11bbb110: 01R:	SET b,(HL)
// DD_CB:11bbb110: 01R:	SET b,(IX+d)
OP_DEF(set_hlin)
{
	name = "SET";
	arg1 = bbb();
	arg2 = HLin();
}

// ED:00rrr000: -1-:	IN0 r,(n)
OP_DEF(in0_r_n)
{
	name = "IN0";
	arg1 = rrr();
	arg2 = "(" + imm8() + ")";
}

// ED:00rrr001: -1-:	OUT0 (n),r
OP_DEF(out0_n_r)
{
	name = "OUT0";
	arg1 = "(" + imm8() + ")";
	arg2 = rrr();
}

// ED:00rrr100: -1-:	TST r
OP_DEF(tst_r)
{
	name = "TST";
	arg1 = rrr();
}

// ED:00110000: -1-:	IN0 F,(n)
OP_DEF(in0_f_n)
{
	name = "IN0";
	arg1 = "F";
	arg2 = "(" + imm8() + ")";
}

// ED:00110100: -1-:	TST (HL)
OP_DEF(tst_hlin)
{
	name = "TST";
	arg1 = HLin();
}

// ED:01rrr000: 01R:	IN r,(C)
OP_DEF(in_r_c)
{
	name = "IN";
	arg1 = rrr();
	arg2 = "(C)";
}

// ED:01rrr001: 01R:	OUT (C),r
OP_DEF(out_c_r)
{
	name = "OUT";
	arg1 = "(C)";
	arg2 = rrr();
}

// ED:01ww0010: 01R:	SBC HL,ww
OP_DEF(sbc_hl_ww)
{
	name = "SBC";
	arg1 = HL();
	arg2 = ww();
}

// ED:01ww0011: 01R:	LD (nn),ww
OP_DEF(ld_nnin_ww)
{
	name = "LD";
	arg1 = "(" + imm16() + ")";
	arg2 = ww();
}

// ED:01000100: 01R:	NEG
OP_DEF(neg)
{
	name = "NEG";
}

// ED:01000101: 01R:	RETN
OP_DEF(retn)
{
	name = "RETN";
}

// ED:01000110: 01R:	IM 0
OP_DEF(im_0)
{
	name = "IM";
	arg1 = "0";
}

// ED:01000111: 01R:	LD I,A
OP_DEF(ld_i_a)
{
	name = "LD";
	arg1 = "I";
	arg2 = "A";
}

// ED:01ww1010: 01R:	ADC HL,ww
OP_DEF(adc_hl_ww)
{
	name = "ADC";
	arg1 = HL();
	arg2 = ww();
}

// ED:01ww1011: 01R:	LD ww,(nn)
OP_DEF(ld_ww_nnin)
{
	name = "LD";
	arg1 = ww();
	arg2 = "(" + imm16() + ")";
}

// ED:01ww1100: -1-:	MLT ww
OP_DEF(mlt)
{
	name = "MLT";
	arg1 = ww();
}

// ED:01001101: 01R:	RETI
OP_DEF(reti)
{
	name = "RETI";
}

// ED:01001111: 01R:	LD R,A
OP_DEF(ld_r_a)
{
	name = "LD";
	arg1 = "R";
	arg2 = "A";
}

// ED:01010110: 01R:	IM 1
OP_DEF(im_1)
{
	name = "IM";
	arg1 = "1";
}

// ED:01010111: 01R:	LD A,I
OP_DEF(ld_a_i)
{
	name = "LD";
	arg1 = "A";
	arg2 = "I";
}

// ED:01011110: 01R:	IM 2
OP_DEF(im_2)
{
	name = "IM";
	arg1 = "2";
}

// ED:01011111: 01R:	LD A,R
OP_DEF(ld_a_r)
{
	name = "LD";
	arg1 = "A";
	arg2 = "R";
}

// ED:01100100: -1-:	TST n
OP_DEF(tst_n)
{
	name = "TST";
	arg1 = imm8();
}

// ED:01100111: 01R:	RRD
OP_DEF(rrd)
{
	name = "RRD";
}

// ED:01101111: 01R:	RLD
OP_DEF(rld)
{
	name = "RLD";
}

// ED:01110000: 01R:	IN F,(C)
OP_DEF(in_f_c)
{
	name = "IN";
	arg1 = "F";
	arg2 = "(C)";
}

// ED:01110100: -1-:	TSTIO n
OP_DEF(tstio_n)
{
	name = "TSTIO";
	arg1 = imm8();
}

// ED:01110110: -1-:	SLP
OP_DEF(slp)
{
	name = "SLP";
}

// ED:10000011: -1-:	OTIM
OP_DEF(otim)
{
	name = "OTIM";
}

// ED:10001011: -1-:	OTDM
OP_DEF(otdm)
{
	name = "OTDM";
}

// ED:10010011: -1-:	OTIMR
OP_DEF(otimr)
{
	name = "OTIMR";
}

// ED:10011011: -1-:	OTDMR
OP_DEF(otdmr)
{
	name = "OTDMR";
}

// ED:10100000: 01R:	LDI
OP_DEF(ldi)
{
	name = "LDI";
}

// ED:10100001: 01R:	CPI
OP_DEF(cpi)
{
	name = "CPI";
}

// ED:10100010: 01R:	INI
OP_DEF(ini)
{
	name = "INI";
}

// ED:10100011: 01R:	OUTI
OP_DEF(outi)
{
	name = "OUTI";
}

// ED:10101000: 01R:	LDD
OP_DEF(ldd)
{
	name = "LDD";
}

// ED:10101001: 01R:	CPD
OP_DEF(cpd)
{
	name = "CPD";
}

// ED:10101010: 01R:	IND
OP_DEF(ind)
{
	name = "IND";
}

// ED:10101011: 01R:	OUTD
OP_DEF(outd)
{
	name = "OUTD";
}

// ED:10110000: 01R:	LDIR
OP_DEF(ldir)
{
	name = "LDIR";
}

// ED:10110001: 01R:	CPIR
OP_DEF(cpir)
{
	name = "CPIR";
}

// ED:10110010: 01R:	INIR
OP_DEF(inir)
{
	name = "INIR";
}

// ED:10110011: 01R:	OTIR
OP_DEF(otir)
{
	name = "OTIR";
}

// ED:10111000: 01R:	LDDR
OP_DEF(lddr)
{
	name = "LDDR";
}

// ED:10111001: 01R:	CPDR
OP_DEF(cpdr)
{
	name = "CPDR";
}

// ED:10111010: 01R:	INDR
OP_DEF(indr)
{
	name = "INDR";
}

// ED:10111011: 01R:	OTDR
OP_DEF(otdr)
{
	name = "OTDR";
}

// ED:11rrr001: --R:	MULUB A,r
OP_DEF(mulub_a_r)
{
	name = "MULUB";
	arg1 = "A";
	arg2 = rrr();
}

// ED:11000011: --R:	MULUB HL,BC
OP_DEF(mulub_hl_bc)
{
	name = "MULUB";
	arg1 = "HL";
	arg2 = "BC";
}

// ED:11110011: --R:	MULUB HL,SP
OP_DEF(mulub_hl_sp)
{
	name = "MULUB";
	arg1 = "HL";
	arg2 = "SP";
}

// ED:11111111: -N-:	SYSCALL
OP_DEF(syscall)
{
	name = "SYSCALL";
}

// DD:00rrr100: Z-Z:	INC ixr
OP_DEF(inc_ixr)
{
	OP_FUNC(inc_r);
}

// DD:00rrr101: Z-Z:	DEC ixr
OP_DEF(dec_ixr)
{
	OP_FUNC(dec_r);
}

// DD:00rrr110: Z-Z:	LD ixr,n
OP_DEF(ld_ixr_n)
{
	OP_FUNC(ld_r_n);
}

// DD:01rrrsss: Z-Z:	LD r,ixs
OP_DEF(ld_r_ixs)
{
	OP_FUNC(ld_r_s);
}

// DD:10000rrr: Z-Z:	ADD A,ixr
OP_DEF(add_a_ixr)
{
	OP_FUNC(add_a_r);
}

// DD:10001rrr: Z-Z:	ADC A,ixr
OP_DEF(adc_a_ixr)
{
	OP_FUNC(adc_a_r);
}

// DD:10010rrr: Z-Z:	SUB ixr
OP_DEF(sub_ixr)
{
	OP_FUNC(sub_r);
}

// DD:10011rrr: Z-Z:	SBC A,ixr
OP_DEF(sbc_a_ixr)
{
	OP_FUNC(sbc_a_r);
}

// DD:10100rrr: Z-Z:	AND ixr
OP_DEF(and_ixr)
{
	OP_FUNC(and_r);
}

// DD:10101rrr: Z-Z:	XOR ixr
OP_DEF(xor_ixr)
{
	OP_FUNC(xor_r);
}

// DD:10110rrr: Z-Z:	OR ixr
OP_DEF(or_ixr)
{
	OP_FUNC(or_r);
}

// DD:10111rrr: Z-Z:	CP ixr
OP_DEF(cp_ixr)
{
	OP_FUNC(cp_r);
}

// DD:11001011: 01R:	op_DD_CB
OP_DEF(dd_cb)
{
	// DD/FD CB の場合は 3バイト目が <d> で 4バイト目が命令語の順。
	// どうして…。
	ixd = fetch1();

	op = fetch1();
	switch (op) {
#include "hd64180switch_dd_cb.inc"
	 default:
		OP_FUNC(illegal);
		break;
	}
}

unix.superglobalmegacorp.com

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