|
|
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;
}
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.