|
|
nono 1.1.0
#include "hd64180acc.h"
#define ACC (*(hd64180acc*)®.f)
// LDIR, LDDR のリピート系命令の雛形。
// いずれも OP(name) を実行して BC == 0 になるまでこの PC を繰り返すもの。
// ジャンプする際には 2クロック追加で消費する。
// フラグも OP(name) が変更した以上にはここでは変更しない。
#define REPEAT_LD(name) do { \
OP_FUNC(name); \
if (reg.f.IsV()) { \
reg.pc -= 2; \
CYCLE(2); \
} \
} while (0)
// INIR, INDR, OTIR, OTDR 用。
#define REPEAT_IO(name) do { \
OP_FUNC(name); \
if (reg.f.IsZ() == false) { \
reg.pc -= 2; \
CYCLE(2); \
} \
} while (0)
// CPIR, CPDR 用。
#define REPEAT_CP(name) do { \
OP_FUNC(name); \
if (reg.f.IsZ() == false && reg.f.IsV()) { \
reg.pc -= 2; \
CYCLE(2); \
} \
} while (0)
void
MPU64180Device::Push2(uint32 data)
{
reg.sp -= 2;
Write2(reg.sp, data);
}
uint32
MPU64180Device::Pop2()
{
uint16 data = Read2(reg.sp);
reg.sp += 2;
return data;
}
// HL (もしくは IX/IY) の値を取得する。
uint32
MPU64180Device::GetIHL() const
{
switch (ixiy) {
case USE_HL: return reg.GetHL(); break;
case USE_IX: return reg.ix; break;
case USE_IY: return reg.iy; break;
default:
PANIC("invalid ixiy = %u", (uint)ixiy);
}
}
// HL (もしくは IX/IY) に値を代入する。
void
MPU64180Device::SetIHL(uint32 data)
{
switch (ixiy) {
case USE_HL: reg.SetHL(data); break;
case USE_IX: reg.ix = data; break;
case USE_IY: reg.iy = data; break;
default:
PANIC("invalid ixiy = %u", (uint)ixiy);
}
}
// (HL) 用に HL のアドレスを取得する。
// IX/IY の時は (IX/IY + d) のアドレスを取得する。
uint32
MPU64180Device::LeaIHL()
{
uint32 addr = GetIHL();
if (ixiy != USE_HL) {
// DD と DD CB で +d をフェッチする順序が違う。
if ((int32)ixd < 0) {
ixd = Fetch1();
}
addr += (int32)(int8)ixd;
}
return addr;
}
// ww (BC, DE, HL, SP) の値を取得する。
// ixiy なら HL の代わりに IX/IY の値を取得する。
uint32
MPU64180Device::GetWW(uint ww) const
{
switch (ww) {
case 0: return reg.GetBC();
case 1: return reg.GetDE();
case 2: return GetIHL();
case 3: return reg.sp;
default:
PANIC("invalid ww = %u", ww);
}
}
// ww (BC, DE, HL, SP) に値を代入する。
// ixiy なら HL の代わりに IX/IY に値を取得する。
void
MPU64180Device::SetWW(uint ww, uint32 data)
{
switch (ww) {
case 0: reg.SetBC(data); break;
case 1: reg.SetDE(data); break;
case 2: SetIHL(data); break;
case 3: reg.sp = data; break;
default:
PANIC("invalid ww = %u", ww);
}
}
// ここから命令
// 00000000: 01R: NOP
OP_DEF(nop)
{
CYCLE(3);
}
// 00ww0001: 01R: LD ww,nn
// DD:00100001: 01R: LD IX,nn
OP_DEF(ld_ww_nn)
{
uint32 nn = Fetch2();
uint ww = (op >> 4) & 3;
SetWW(ww, nn);
CYCLE_IX(9, 12);
}
// 00ww0010: 01R: LD (ww),A
OP_DEF(ld_wwin_a)
{
uint ww = op >> 4;
uint32 addr = GetWW(ww); // ww は BC, DE のみ
Write1(addr, reg.a);
CYCLE_IX(7, 15);
}
// 00ww0011: 01R: INC ww
// DD:00100011: 01R: INC IX
OP_DEF(inc_ww)
{
uint ww = op >> 4;
uint32 data = GetWW(ww);
data++;
SetWW(ww, data);
CYCLE_IX(4, 7);
}
// 00rrr100: 01R: INC r
OP_DEF(inc_r)
{
uint r = op >> 3;
reg.r[r] = ACC.inc_8(reg.r[r]);
CYCLE(4);
}
// 00rrr101: 01R: DEC r
OP_DEF(dec_r)
{
uint r = op >> 3;
reg.r[r] = ACC.dec_8(reg.r[r]);
CYCLE(4);
}
// 00rrr110: 01R: LD r,n
OP_DEF(ld_r_n)
{
uint r = op >> 3;
reg.r[r] = Fetch1();
CYCLE(6);
}
// 00000111: 01R: RLCA
OP_DEF(rlca)
{
reg.a = ACC.rlc_8(reg.a);
CYCLE(3);
}
// 00001000: 01R: EX AF,AF'
OP_DEF(ex_af_af)
{
uint8 tmpa = reg.a;
uint8 tmpf = reg.f.Get();
reg.a = reg.ex.a;
reg.f.Set(reg.ex.f.Get());
reg.ex.a = tmpa;
reg.ex.f.Set(tmpf);
CYCLE(4);
}
// 00ww1001: 01R: ADD HL,ww
// DD:00ww1001: 01R: ADD IX,ww
OP_DEF(add_hl_ww)
{
uint ww = op >> 4;
uint32 src = GetWW(ww);
uint32 dst = GetIHL();
dst = ACC.add_16(dst, src);
SetIHL(dst);
CYCLE_IX(7, 10);
}
// 00ww1010: 01R: LD A,(ww)
OP_DEF(ld_a_wwin)
{
uint ww = op >> 4;
uint32 addr = GetWW(ww); // ww は BC, DE のみ
reg.a = Read1(addr);
CYCLE(6);
}
// 00ww1011: 01R: DEC ww
// DD:00101011: 01R: DEC IX
OP_DEF(dec_ww)
{
uint ww = op >> 4;
uint32 data = GetWW(ww);
data--;
SetWW(ww, data);
CYCLE_IX(4, 7);
}
// 00001111: 01R: RRCA
OP_DEF(rrca)
{
reg.a = ACC.rrc_8(reg.a);
CYCLE(3);
}
// 00010000: 01R: DJNZ n
OP_DEF(djnz)
{
int8 n = Fetch1();
reg.b--;
if (reg.b != 0) {
Jump(reg.pc + n);
CYCLE(9);
} else {
CYCLE(7);
}
}
// 00010111: 01R: RLA
OP_DEF(rla)
{
reg.a = ACC.rl_8(reg.a);
CYCLE(3);
}
// 00011000: 01R: JR n
OP_DEF(jr)
{
int8 n = Fetch1();
Jump(reg.pc + n);
CYCLE(8);
}
// 00011111: 01R: RRA
OP_DEF(rra)
{
reg.a = ACC.rr_8(reg.a);
CYCLE(3);
}
// 00100000: 01R: JR NZ,n
OP_DEF(jr_nz)
{
int8 n = Fetch1();
if (reg.f.IsZ() == false) {
Jump(reg.pc + n);
CYCLE(8);
} else {
CYCLE(6);
}
}
// 00100010: 01R: LD (nn),HL
// DD:00100010: 01R: LD (nn),IX
OP_DEF(ld_nnin_hl)
{
uint32 nn = Fetch2();
Write2(nn, GetIHL());
CYCLE_IX(16, 19);
}
// 00100111: 01R: DAA
OP_DEF(daa)
{
reg.a = ACC.daa_8(reg.a);
CYCLE(4);
}
// 00101000: 01R: JR Z,n
OP_DEF(jr_z)
{
int8 n = Fetch1();
if (reg.f.IsZ()) {
Jump(reg.pc + n);
CYCLE(8);
} else {
CYCLE(6);
}
}
// 00101010: 01R: LD HL,(nn)
// DD:00101010: 01R: LD IX,(nn)
OP_DEF(ld_hl_nnin)
{
uint32 nn = Fetch2();
uint32 src = Read2(nn);
SetIHL(src);
CYCLE_IX(15, 18);
}
// 00101111: 01R: CPL
OP_DEF(cpl)
{
reg.a = ~reg.a;
reg.f.SetH(true);
reg.f.SetN(true);
CYCLE(3);
}
// 00110000: 01R: JR NC,n
OP_DEF(jr_nc)
{
int8 n = Fetch1();
if (reg.f.IsC() == false) {
Jump(reg.pc + n);
CYCLE(8);
} else {
CYCLE(6);
}
}
// 00110010: 01R: LD (nn),A
OP_DEF(ld_nnin_a)
{
uint32 addr = Fetch2();
Write1(addr, reg.a);
CYCLE(13);
}
// 00110100: 01R: INC (HL)
// DD:00110100: 01R: INC (IX+d)
OP_DEF(inc_hlin)
{
uint32 addr = LeaIHL();
uint32 src = Read1(addr);
uint32 dst = ACC.inc_8(src);
Write1(addr, dst);
CYCLE_IX(10, 18);
}
// 00110101: 01R: DEC (HL)
// DD:00110101: 01R: DEC (IX+d)
OP_DEF(dec_hlin)
{
uint32 addr = LeaIHL();
uint32 src = Read1(addr);
uint32 dst = ACC.dec_8(src);
Write1(addr, dst);
CYCLE_IX(10, 18);
}
// 00110110: 01R: LD (HL),n
// DD:00110110: 01R: LD (IX+d),n
OP_DEF(ld_hlin_n)
{
uint32 addr = LeaIHL();
uint32 src = Fetch1();
Write1(addr, src);
CYCLE_IX(9, 15);
}
// 00110111: 01R: SCF
OP_DEF(scf)
{
reg.f.SetC(true);
reg.f.SetH(false);
reg.f.SetN(false);
CYCLE(3);
}
// 00111000: 01R: JR C,n
OP_DEF(jr_c)
{
int8 n = Fetch1();
if (reg.f.IsC()) {
Jump(reg.pc + n);
CYCLE(8);
} else {
CYCLE(6);
}
}
// 00111010: 01R: LD A,(nn)
OP_DEF(ld_a_nnin)
{
uint32 nn = Fetch2();
reg.a = Read1(nn);
CYCLE(12);
}
// 00111111: 01R: CCF
OP_DEF(ccf)
{
reg.f.SetC(!reg.f.IsC());
reg.f.SetH(false);
reg.f.SetN(false);
CYCLE(3);
}
// 01rrrsss: 01R: LD r,s
OP_DEF(ld_r_s)
{
uint d = (op >> 3) & 7;
uint s = op & 7;
reg.r[d] = reg.r[s];
CYCLE(4);
}
// 01rrr110: 01R: LD r,(HL)
// DD:01rrr110: 01R: LD r,(IX+d)
OP_DEF(ld_r_hlin)
{
uint d = (op >> 3) & 7;
uint16 addr = LeaIHL();
reg.r[d] = Read1(addr);
CYCLE_IX(6, 14);
}
// 01110sss: 01R: LD (HL),s
// DD:01110sss: 01R: LD (IX+d),s
OP_DEF(ld_hlin_s)
{
uint s = op & 7;
uint32 addr = LeaIHL();
Write1(addr, reg.r[s]);
CYCLE_IX(7, 15);
}
// 01110110: 01R: HALT
OP_DEF(halt)
{
opmode = OpMode::Halt;
putlog(1, "Halt");
CYCLE(3);
}
// 10000rrr: 01R: ADD A,r
OP_DEF(add_a_r)
{
uint r = op & 7;
reg.a = ACC.add_8(reg.a, reg.r[r]);
CYCLE(4);
}
// 10000110: 01R: ADD A,(HL)
// DD:10000110: 01R: ADD A,(IX+d)
OP_DEF(add_a_hlin)
{
uint32 addr = LeaIHL();
uint32 src = Read1(addr);
reg.a = ACC.add_8(reg.a, src);
CYCLE_IX(6, 14);
}
// 10001rrr: 01R: ADC A,r
OP_DEF(adc_a_r)
{
uint r = op & 7;
reg.a = ACC.adc_8(reg.a, reg.r[r]);
CYCLE(4);
}
// 10001110: 01R: ADC A,(HL)
// DD:10001110: 01R: ADC A,(IX+d)
OP_DEF(adc_a_hlin)
{
uint32 addr = LeaIHL();
uint32 src = Read1(addr);
reg.a = ACC.adc_8(reg.a, src);
CYCLE_IX(6, 14);
}
// 10010rrr: 01R: SUB r
OP_DEF(sub_r)
{
uint r = op & 7;
reg.a = ACC.sub_8(reg.a, reg.r[r]);
CYCLE(4);
}
// 10010110: 01R: SUB (HL)
// DD:10010110: 01R: SUB (IX+d)
OP_DEF(sub_hlin)
{
uint32 addr = LeaIHL();
uint32 src = Read1(addr);
reg.a = ACC.sub_8(reg.a, src);
CYCLE_IX(6, 14);
}
// 10011rrr: 01R: SBC A,r
OP_DEF(sbc_a_r)
{
uint r = op & 7;
reg.a = ACC.sbc_8(reg.a, reg.r[r]);
CYCLE(4);
}
// 10011110: 01R: SBC A,(HL)
// DD:10011110: 01R: SBC A,(IX+d)
OP_DEF(sbc_a_hlin)
{
uint32 addr = LeaIHL();
uint32 src = Read1(addr);
reg.a = ACC.sbc_8(reg.a, src);
CYCLE_IX(6, 14);
}
// 10100rrr: 01R: AND r
OP_DEF(and_r)
{
uint r = op & 7;
reg.a = ACC.and_8(reg.a, reg.r[r]);
CYCLE(4);
}
// 10100110: 01R: AND (HL)
// DD:10100110: 01R: AND (IX+d)
OP_DEF(and_hlin)
{
uint16 addr = LeaIHL();
uint32 src = Read1(addr);
reg.a = ACC.and_8(reg.a, src);
CYCLE_IX(6, 14);
}
// 10101rrr: 01R: XOR r
OP_DEF(xor_r)
{
uint r = op & 7;
reg.a = ACC.xor_8(reg.a, reg.r[r]);
CYCLE(4);
}
// 10101110: 01R: XOR (HL)
// DD:10101110: 01R: XOR (IX+d)
OP_DEF(xor_hlin)
{
uint16 addr = LeaIHL();
uint32 src = Read1(addr);
reg.a = ACC.xor_8(reg.a, src);
CYCLE_IX(6, 14);
}
// 10110rrr: 01R: OR r
OP_DEF(or_r)
{
uint r = op & 7;
reg.a = ACC.or_8(reg.a, reg.r[r]);
CYCLE(4);
}
// 10110110: 01R: OR (HL)
// DD:10110110: 01R: OR (IX+d)
OP_DEF(or_hlin)
{
uint16 addr = LeaIHL();
uint32 src = Read1(addr);
reg.a = ACC.or_8(reg.a, src);
CYCLE_IX(6, 14);
}
// 10111rrr: 01R: CP r
OP_DEF(cp_r)
{
uint r = op & 7;
ACC.sub_8(reg.a, reg.r[r]);
CYCLE(4);
}
// 10111110: 01R: CP (HL)
// DD:10111110: 01R: CP (IX+d)
OP_DEF(cp_hlin)
{
uint16 addr = LeaIHL();
uint32 src = Read1(addr);
ACC.sub_8(reg.a, src);
CYCLE_IX(6, 14);
}
void
MPU64180Device::ops_ret()
{
uint16 addr = Pop2();
Jump(addr);
}
// 11fff000: 01R: RET f
OP_DEF(ret_f)
{
uint fff = (op >> 3) & 7;
if (reg.f.IsCond(fff)) {
ops_ret();
CYCLE(10);
} else {
CYCLE(5);
}
}
// 11zz0001: 01R: POP zz
// DD:11100001: 01R: POP IX
OP_DEF(pop_zz)
{
// ここでは zz のうち BC, DE, HL のみなので ww が使える
uint zz = (op >> 4) & 3;
uint16 data = Pop2();
SetWW(zz, data);
CYCLE_IX(9, 12);
}
// 11fff010: 01R: JP f,nn
OP_DEF(jp_f_nn)
{
uint fff = (op >> 3) & 7;
uint16 addr = Fetch2();
if (reg.f.IsCond(fff)) {
Jump(addr);
CYCLE(9);
} else {
CYCLE(6);
}
}
// 11000011: 01R: JP nn
OP_DEF(jp_nn)
{
uint32 addr = Fetch2();
Jump(addr);
CYCLE(9);
}
// 11fff100: 01R: CALL f,nn
OP_DEF(call_f_nn)
{
uint fff = (op >> 3) & 7;
uint16 nn = Fetch2();
if (reg.f.IsCond(fff)) {
Push2(reg.pc);
Jump(nn);
CYCLE(16);
} else {
CYCLE(6);
}
}
// 11zz0101: 01R: PUSH zz
// DD:11100101: 01R: PUSH IX
OP_DEF(push_zz)
{
// ここでは zz のうち BC, DE, HL のみなので ww が使える
uint zz = (op >> 4) & 3;
uint16 data = GetWW(zz);
Push2(data);
CYCLE_IX(11, 14);
}
// 11000110: 01R: ADD A,n
OP_DEF(add_a_n)
{
uint32 n = Fetch1();
reg.a = ACC.add_8(reg.a, n);
CYCLE(6);
}
// 11vvv111: 01R: RST v
OP_DEF(rst)
{
Push2(reg.pc);
uint v = op & 0x38;
Jump(v);
CYCLE(11);
}
// 11001001: 01R: RET
OP_DEF(ret)
{
ops_ret();
CYCLE(9);
}
// 11001011: 01R: op_CB
OP_DEF(cb)
{
// 2バイト目をフェッチ
op = Fetch1();
// で分岐
switch (op) {
#include "hd64180switch_cb.inc"
default:
op_illegal(2);
break;
}
}
// 11001101: 01R: CALL nn
OP_DEF(call)
{
uint16 nn = Fetch2();
Push2(reg.pc);
Jump(nn);
CYCLE(16);
}
// 11001110: 01R: ADC A,n
OP_DEF(adc_a_n)
{
uint32 n = Fetch1();
reg.a = ACC.adc_8(reg.a, n);
CYCLE(6);
}
// 11010011: 01R: OUT (n),A
OP_DEF(out_n_a)
{
uint32 n = Fetch1();
// バスの上位には A が出る
uint32 addr = (reg.a << 8) | n;
WriteIO(addr, reg.a);
CYCLE(10);
}
// 11010110: 01R: SUB n
OP_DEF(sub_n)
{
uint32 n = Fetch1();
reg.a = ACC.sub_8(reg.a, n);
CYCLE(6);
}
// 11011001: 01R: EXX
OP_DEF(exx)
{
uint8 tmpb = reg.b;
uint8 tmpc = reg.c;
uint8 tmpd = reg.d;
uint8 tmpe = reg.e;
uint8 tmph = reg.h;
uint8 tmpl = reg.l;
reg.b = reg.ex.b;
reg.c = reg.ex.c;
reg.d = reg.ex.d;
reg.e = reg.ex.e;
reg.h = reg.ex.h;
reg.l = reg.ex.l;
reg.ex.b = tmpb;
reg.ex.c = tmpc;
reg.ex.d = tmpd;
reg.ex.e = tmpe;
reg.ex.h = tmph;
reg.ex.l = tmpl;
CYCLE(3);
}
// 11011011: 01R: IN A,(n)
OP_DEF(in_a_n)
{
uint32 n = Fetch1();
// バスの上位には A が出る
uint32 addr = (reg.a << 8) | n;
reg.a = ReadIO(addr);
CYCLE(9);
}
// DD/FD の共通部
void
MPU64180Device::ops_ddfd(ixiy_t xy)
{
ixiy = xy;
// 2バイト目をフェッチ
op = Fetch1();
// で分岐
switch (op) {
#include "hd64180switch_dd.inc"
default:
op_illegal(2);
break;
}
}
// 11011101: 01R: op_DD
OP_DEF(dd)
{
ops_ddfd(USE_IX);
}
// 11011110: 01R: SBC A,n
OP_DEF(sbc_a_n)
{
uint32 n = Fetch1();
reg.a = ACC.sbc_8(reg.a, n);
CYCLE(6);
}
// 11100011: 01R: EX (SP),HL
// DD:11100011: 01R: EX (SP),IX
OP_DEF(ex_sp_hl)
{
uint32 tmp = Read2(reg.sp);
Write2(reg.sp, GetIHL());
SetIHL(tmp);
CYCLE_IX(16, 19);
}
// 11100110: 01R: AND n
OP_DEF(and_n)
{
uint32 src = Fetch1();
reg.a = ACC.and_8(reg.a, src);
CYCLE(6);
}
// 11101001: 01R: JP (HL)
// DD:11101001: 01R: JP (IX)
OP_DEF(jp_hl)
{
Jump(GetIHL());
CYCLE_IX(3, 6);
}
// 11101011: 01R: EX DE,HL
OP_DEF(ex_de_hl)
{
uint16 tmp = reg.GetDE();
reg.SetDE(reg.GetHL());
reg.SetHL(tmp);
CYCLE(3);
}
// 11101101: 01R: op_ED
OP_DEF(ed)
{
op = Fetch1();
switch (op) {
#include "hd64180switch_ed.inc"
default:
op_illegal(2);
break;
}
}
// 11101110: 01R: XOR n
OP_DEF(xor_n)
{
uint32 src = Fetch1();
reg.a = ACC.xor_8(reg.a, src);
CYCLE(6);
}
// 11110001: 01R: POP AF
OP_DEF(pop_af)
{
uint16 data = Pop2();
reg.a = data >> 8;
reg.f.Set(data & 0xff);
CYCLE(9);
}
// 11110011: 01R: DI
OP_DEF(di)
{
ief1 = false;
ief2 = false;
// DI 命令の直後は割り込みをサンプルしない。HD647180.pdf, p.205
intcheck = false;
CYCLE(3);
}
// 11110101: 01R: PUSH AF
OP_DEF(push_af)
{
uint16 data;
data = reg.a << 8;
data |= reg.f.Get();
Push2(data);
CYCLE(11);
}
// 11110110: 01R: OR n
OP_DEF(or_n)
{
uint32 src = Fetch1();
reg.a = ACC.or_8(reg.a, src);
CYCLE(6);
}
// 11111001: 01R: LD SP,HL
// DD:11111001: 01R: LD SP,IX
OP_DEF(ld_sp_hl)
{
reg.sp = GetIHL();
CYCLE_IX(4, 7);
}
// 11111011: 01R: EI
OP_DEF(ei)
{
ief1 = true;
ief2 = true;
// EI 命令の直後は割り込みをサンプルしない。HD647180.pdf, p.205
intcheck = false;
CYCLE(3);
}
// 11111101: 01R: op_FD
OP_DEF(fd)
{
ops_ddfd(USE_IY);
}
// 11111110: 01R: CP n
OP_DEF(cp_n)
{
uint32 n = Fetch1();
ACC.sub_8(reg.a, n);
CYCLE(6);
}
// CB:00000rrr: 01R: RLC r
OP_DEF(rlc_r)
{
uint r = op & 7;
reg.r[r] = ACC.in_8(ACC.rlc_8(reg.r[r]));
CYCLE(7);
}
// CB:00000110: 01R: RLC (HL)
// DD_CB:00000110: 01R: RLC (IX+d)
OP_DEF(rlc_hlin)
{
uint32 addr = LeaIHL();
uint32 src = Read1(addr);
uint32 res = ACC.in_8(ACC.rlc_8(src));
Write1(addr, res);
CYCLE_IX(13, 19);
}
// CB:00001rrr: 01R: RRC r
OP_DEF(rrc_r)
{
uint r = op & 7;
reg.r[r] = ACC.in_8(ACC.rrc_8(reg.r[r]));
CYCLE(7);
}
// CB:00001110: 01R: RRC (HL)
// DD_CB:00001110: 01R: RRC (IX+d)
OP_DEF(rrc_hlin)
{
uint32 addr = LeaIHL();
uint32 src = Read1(addr);
uint32 res = ACC.in_8(ACC.rrc_8(src));
Write1(addr, res);
CYCLE_IX(13, 19);
}
// CB:00010rrr: 01R: RL r
OP_DEF(rl_r)
{
uint r = op & 7;
reg.r[r] = ACC.in_8(ACC.rl_8(reg.r[r]));
CYCLE(7);
}
// CB:00010110: 01R: RL (HL)
// DD_CB:00010110: 01R: RL (IX+d)
OP_DEF(rl_hlin)
{
uint32 addr = LeaIHL();
uint32 src = Read1(addr);
uint32 res = ACC.in_8(ACC.rl_8(src));
Write1(addr, res);
CYCLE_IX(13, 19);
}
// CB:00011rrr: 01R: RR r
OP_DEF(rr_r)
{
uint r = op & 7;
reg.r[r] = ACC.in_8(ACC.rr_8(reg.r[r]));
CYCLE(7);
}
// CB:00011110: 01R: RR (HL)
// DD_CB:00011110: 01R: RR (IX+d)
OP_DEF(rr_hlin)
{
uint32 addr = LeaIHL();
uint32 src = Read1(addr);
uint32 res = ACC.in_8(ACC.rr_8(src));
Write1(addr, res);
CYCLE_IX(13, 19);
}
// CB:00100rrr: 01R: SLA r
OP_DEF(sla_r)
{
uint r = op & 7;
reg.r[r] = ACC.in_8(ACC.sla_8(reg.r[r]));
CYCLE(7);
}
// CB:00100110: 01R: SLA (HL)
// DD_CB:00100110: 01R: SLA (IX+d)
OP_DEF(sla_hlin)
{
uint32 addr = LeaIHL();
uint32 src = Read1(addr);
uint32 res = ACC.in_8(ACC.sla_8(src));
Write1(addr, res);
CYCLE_IX(13, 19);
}
// CB:00101rrr: 01R: SRA r
OP_DEF(sra_r)
{
uint r = op & 7;
reg.r[r] = ACC.in_8(ACC.sra_8(reg.r[r]));
CYCLE(7);
}
// CB:00101110: 01R: SRA (HL)
// DD_CB:00101110: 01R: SRA (IX+d)
OP_DEF(sra_hlin)
{
uint32 addr = LeaIHL();
uint32 src = Read1(addr);
uint32 res = ACC.in_8(ACC.sra_8(src));
Write1(addr, res);
CYCLE_IX(13, 19);
}
// CB:00110rrr: Z--: SLL
OP_DEF(sll_r)
{
if (1) {
op_illegal(2);
} else {
uint r = op & 7;
reg.r[r] = ACC.in_8(ACC.sll_8(reg.r[r]));
CYCLE(7);
}
}
// CB:00110110: Z--: SLL (HL)
// DD_CB:00110110: Z--: SLL (IX+d)
OP_DEF(sll_hlin)
{
if (1) {
if (ixiy == USE_HL) {
op_illegal(2);
} else {
op_illegal(3);
}
} else {
uint32 addr = LeaIHL();
uint32 src = Read1(addr);
uint32 res = ACC.in_8(ACC.sll_8(src));
Write1(addr, res);
CYCLE_IX(13, 19);
}
}
// CB:00111rrr: 01R: SRL r
OP_DEF(srl_r)
{
uint r = op & 7;
reg.r[r] = ACC.in_8(ACC.srl_8(reg.r[r]));
CYCLE(7);
}
// CB:00111110: 01R: SRL (HL)
// DD_CB:00111110: 01R: SRL (IX+d)
OP_DEF(srl_hlin)
{
uint32 addr = LeaIHL();
uint32 src = Read1(addr);
uint32 res = ACC.in_8(ACC.srl_8(src));
Write1(addr, res);
CYCLE_IX(13, 19);
}
// CB:01bbbrrr: 01R: BIT b,r
OP_DEF(bit_r)
{
uint b = (op >> 3) & 7;
uint r = op & 7;
ACC.bit_8(b, reg.r[r]);
CYCLE(6);
}
// CB:01bbb110: 01R: BIT b,(HL)
// DD_CB:01bbb110: 01R: BIT b,(IX+d)
OP_DEF(bit_hlin)
{
uint b = (op >> 3) & 7;
uint32 addr = LeaIHL();
uint32 data = Read1(addr);
ACC.bit_8(b, data);
CYCLE_IX(9, 15);
}
// CB:10bbbrrr: 01R: RES b,r
OP_DEF(res_r)
{
uint b = (op >> 3) & 7;
uint r = op & 7;
reg.r[r] &= ~(1U << b);
CYCLE(7);
}
// CB:10bbb110: 01R: RES b,(HL)
// DD_CB:10bbb110: 01R: RES b,(IX+d)
OP_DEF(res_hlin)
{
uint b = (op >> 3) & 7;
uint32 addr = LeaIHL();
uint32 data = Read1(addr);
data &= ~(1U << b);
Write1(addr, data);
CYCLE_IX(13, 19);
}
// CB:11bbbrrr: 01R: SET b,r
OP_DEF(set_r)
{
uint b = (op >> 3) & 7;
uint r = op & 7;
reg.r[r] |= 1U << b;
CYCLE(7);
}
// CB:11bbb110: 01R: SET b,(HL)
// DD_CB:11bbb110: 01R: SET b,(IX+d)
OP_DEF(set_hlin)
{
uint b = (op >> 3) & 7;
uint32 addr = LeaIHL();
uint32 data = Read1(addr);
data |= 1U << b;
Write1(addr, data);
CYCLE_IX(13, 19);
}
// ED:00rrr000: -1-: IN0 r,(n)
OP_DEF(in0_r_n)
{
uint32 n = Fetch1();
uint32 src = ReadIO(n);
uint r = op >> 3;
reg.r[r] = ACC.in_8(src);
CYCLE(12);
}
// ED:00rrr001: -1-: OUT0 (n),r
OP_DEF(out0_n_r)
{
uint32 n = Fetch1();
uint32 r = op >> 3;
WriteIO(n, reg.r[r]);
CYCLE(13);
}
// ED:00rrr100: -1-: TST r
OP_DEF(tst_r)
{
uint r = op & 7;
ACC.tst_8(reg.a, reg.r[r]);
CYCLE(7);
}
// ED:00110000: -1-: IN0 F,(n)
OP_DEF(in0_f_n)
{
uint32 n = Fetch1();
uint32 src = ReadIO(n);
ACC.in_8(src);
CYCLE(12);
}
// ED:00110100: -1-: TST (HL)
OP_DEF(tst_hlin)
{
uint16 addr = reg.GetHL();
uint32 src = Read1(addr);
ACC.tst_8(reg.a, src);
CYCLE(10);
}
// ED:01rrr000: 01R: IN r,(C)
OP_DEF(in_r_c)
{
uint r = (op >> 3) & 7;
// バスの上位には B が出る
uint32 addr = reg.GetBC();
uint32 data = ReadIO(addr);
reg.r[r] = ACC.in_8(data);
CYCLE(9);
}
// ED:01rrr001: 01R: OUT (C),r
OP_DEF(out_c_r)
{
uint r = (op >> 3) & 7;
// バスの上位には B が出る
uint32 addr = reg.GetBC();
WriteIO(addr, reg.r[r]);
CYCLE(10);
}
// ED:01ww0010: 01R: SBC HL,ww
OP_DEF(sbc_hl_ww)
{
uint ww = (op >> 4) & 3;
uint32 src = GetWW(ww);
uint32 dst = reg.GetHL();
dst = ACC.sbc_16(dst, src);
reg.SetHL(dst);
CYCLE(10);
}
// ED:01ww0011: 01R: LD (nn),ww
OP_DEF(ld_nnin_ww)
{
uint ww = (op >> 4) & 3;
uint32 src = GetWW(ww);
uint32 nn = Fetch2();
Write2(nn, src);
CYCLE(19);
}
// ED:01000100: 01R: NEG
OP_DEF(neg)
{
reg.a = ACC.sub_8(0, reg.a);
CYCLE(6);
}
// ED:01000101: 01R: RETN
OP_DEF(retn)
{
ief1 = ief2;
Jump(Pop2());
}
// ED:01000110: 01R: IM 0
OP_DEF(im_0)
{
int0mode = 0;
putlog(1, "IM %u", int0mode);
CYCLE(6);
}
// ED:01000111: 01R: LD I,A
OP_DEF(ld_i_a)
{
reg_i = reg.a;
CYCLE(6);
}
// ED:01ww1010: 01R: ADC HL,ww
OP_DEF(adc_hl_ww)
{
uint ww = (op >> 4) & 3;
uint32 src = GetWW(ww);
uint32 dst = reg.GetHL();
dst = ACC.adc_16(dst, src);
reg.SetHL(dst);
CYCLE(10);
}
// ED:01ww1011: 01R: LD ww,(nn)
OP_DEF(ld_ww_nnin)
{
uint ww = (op >> 4) & 3;
uint32 nn = Fetch2();
uint32 src = Read2(nn);
SetWW(ww, src);
CYCLE(18);
}
// ED:01ww1100: -1-: MLT ww
OP_DEF(mlt)
{
uint ww = (op >> 4) & 3;
uint32 src = GetWW(ww);
uint32 dst = (src >> 8) * (src & 0xff);
SetWW(ww, dst);
// フラグ変化なし
CYCLE(17);
}
// ED:01001101: 01R: RETI
OP_DEF(reti)
{
ops_ret();
CYCLE(12);
}
// ED:01001111: 01R: LD R,A
OP_DEF(ld_r_a)
{
reg_r = reg.a;
CYCLE(6);
}
// ED:01010110: 01R: IM 1
OP_DEF(im_1)
{
int0mode = 1;
putlog(1, "IM %u", int0mode);
CYCLE(6);
}
// ED:01010111: 01R: LD A,I
OP_DEF(ld_a_i)
{
reg.a = ACC.ld_ir8(reg_i);
// IEF2 を P/V にコピー。P でも V でもないので一応 V にしておく。
reg.f.SetV(GetIEF2());
// HD64180 ではこの命令の終わりで割り込みをサンプルしない。
intcheck = false;
CYCLE(6);
}
// ED:01011110: 01R: IM 2
OP_DEF(im_2)
{
int0mode = 2;
putlog(1, "IM %u", int0mode);
CYCLE(6);
}
// ED:01011111: 01R: LD A,R
OP_DEF(ld_a_r)
{
reg.a = ACC.ld_ir8(GetR());
// IEF2 を P/V にコピー。P でも V でもないので一応 V にしておく。
reg.f.SetV(GetIEF2());
// HD64180 ではこの命令の終わりで割り込みをサンプルしない。
intcheck = false;
CYCLE(6);
}
// ED:01100100: -1-: TST n
OP_DEF(tst_n)
{
uint32 src = Fetch1();
ACC.and_8(reg.a, src);
CYCLE(9);
}
// ED:01100111: 01R: RRD
OP_DEF(rrd)
{
// +-----------+ +---+
// | v | v
// +-----+-----+ +-----+-----+
// A | 7654 3210 | (HL) | 7654 3210 |
// +-----+-----+ +-----+-----+
// ^ |
// +-------------------+
uint32 hl = reg.GetHL();
uint32 m = Read1(hl);
uint32 a = (reg.a & 0xf0) | (m & 0x0f);
uint32 b = (reg.a << 4) | (m >> 4);
Write1(hl, b);
reg.a = ACC.in_8(a);
CYCLE(16);
}
// ED:01101111: 01R: RLD
OP_DEF(rld)
{
// +-------------------+
// | v
// +-----+-----+ +-----+-----+
// A | 7654 3210 | (HL) | 7654 3210 |
// +-----+-----+ +-----+-----+
// ^ | ^ |
// +-----------+ +---+
uint32 hl = reg.GetHL();
uint32 m = Read1(hl);
uint32 a = (reg.a & 0xf0) | (m >> 4);
uint32 b = (m << 4) | (reg.a & 0x0f);
Write1(hl, b);
reg.a = ACC.in_8(a);
CYCLE(16);
}
// ED:01110000: 01R: IN F,(C)
OP_DEF(in_f_c)
{
// バスの上位には B が出る
uint32 addr = reg.GetBC();
uint32 data = ReadIO(addr);
ACC.in_8(data);
CYCLE(9);
}
// ED:01110100: -1-: TSTIO n
OP_DEF(tstio_n)
{
// バスの上位は 0 になる
uint32 n = Fetch1();
uint32 dst = ReadIO(reg.c);
ACC.tst_8(dst, n);
CYCLE(12);
}
// ED:01110110: -1-: SLP
OP_DEF(slp)
{
putlog(0, "SLP (NOT IMPLEMENTED)");
EnterSleep();
CYCLE(8);
}
// OTIM/OTDM の共通部分
void
MPU64180Device::ops_otim(int inc)
{
uint32 hl = reg.GetHL();
uint32 src = Read1(hl);
// バスの上位は 0 になる
WriteIO(reg.c, src);
reg.c += inc;
hl += inc;
reg.SetHL(hl);
reg.b = ACC.outm_8(src, reg.b);
CYCLE(14);
}
// ED:10000011: -1-: OTIM
OP_DEF(otim)
{
ops_otim(+1);
}
// ED:10001011: -1-: OTDM
OP_DEF(otdm)
{
ops_otim(-1);
}
// OTIMR/OTDMR の終了条件の共通部分。
// 他のリピート系命令とはフラグ変化が異なる。
void
MPU64180Device::ops_otmr_until()
{
if (reg.b != 0) {
reg.pc -= 2;
CYCLE(2);
} else {
// 終了時はフラグ変化が違う。
// S:0 Z:1 H:0 P/V:1 N:* C:0
// このうち S, Z, H, N, C はセットされているままでよい。
// パリティだけセット。
reg.f.SetP(true);
}
}
// ED:10010011: -1-: OTIMR
OP_DEF(otimr)
{
OP_FUNC(otim);
ops_otmr_until();
}
// ED:10011011: -1-: OTDMR
OP_DEF(otdmr)
{
OP_FUNC(otdm);
ops_otmr_until();
}
// LDI/LDD の共通部分
void
MPU64180Device::ops_ldi(int inc)
{
uint32 hl = reg.GetHL();
uint32 de = reg.GetDE();
uint32 bc = reg.GetBC();
uint32 data = Read1(hl);
Write1(de, data);
hl += inc;
de += inc;
bc--;
reg.SetHL(hl);
reg.SetDE(de);
reg.SetBC(bc);
reg.f.SetV((bc != 0));
reg.f.SetN(false);
reg.f.SetH(false);
CYCLE(12);
}
// ED:10100000: 01R: LDI
OP_DEF(ldi)
{
ops_ldi(+1);
}
// CPI/CPD の共通部分
void
MPU64180Device::ops_cpi(int inc)
{
uint32 hl = reg.GetHL();
uint32 bc = reg.GetBC();
uint32 src = Read1(hl);
ACC.sub_8(reg.a, src, true);
hl += inc;
bc--;
reg.SetHL(hl);
reg.SetBC(bc);
reg.f.SetV(bc != 0);
CYCLE(12);
}
// ED:10100001: 01R: CPI
OP_DEF(cpi)
{
ops_cpi(+1);
}
// INI/IND の共通部分
void
MPU64180Device::ops_ini(int inc)
{
uint32 hl = reg.GetHL();
// バスの上位には B が出る
uint32 addr = reg.GetBC();
uint32 data = ReadIO(addr);
Write1(hl, data);
hl += inc;
reg.b--;
reg.SetHL(hl);
// XXX S,H,P/V,C は本当は不定
reg.f.SetZ(reg.b == 0);
reg.f.SetN((int8)data < 0);
CYCLE(12);
}
// ED:10100010: 01R: INI
OP_DEF(ini)
{
ops_ini(+1);
}
// OUTI/OUTD の共通部分
void
MPU64180Device::ops_outi(int inc)
{
uint32 hl = reg.GetHL();
// バスの上位には B が出る
uint32 addr = reg.GetBC();
uint32 data = Read1(hl);
WriteIO(addr, data);
hl += inc;
reg.b--;
reg.SetHL(hl);
// XXX S,H,P/V,C は本当は不定
reg.f.SetZ(reg.b == 0);
reg.f.SetN((int8)data < 0);
CYCLE(12);
}
// ED:10100011: 01R: OUTI
OP_DEF(outi)
{
ops_outi(+1);
}
// ED:10101000: 01R: LDD
OP_DEF(ldd)
{
ops_ldi(-1);
}
// ED:10101001: 01R: CPD
OP_DEF(cpd)
{
ops_cpi(-1);
}
// ED:10101010: 01R: IND
OP_DEF(ind)
{
ops_ini(-1);
}
// ED:10101011: 01R: OUTD
OP_DEF(outd)
{
ops_outi(-1);
}
// ED:10110000: 01R: LDIR
OP_DEF(ldir)
{
REPEAT_LD(ldi);
}
// ED:10110001: 01R: CPIR
OP_DEF(cpir)
{
REPEAT_CP(cpi);
}
// ED:10110010: 01R: INIR
OP_DEF(inir)
{
REPEAT_IO(ini);
}
// ED:10110011: 01R: OTIR
OP_DEF(otir)
{
REPEAT_IO(outi);
}
// ED:10111000: 01R: LDDR
OP_DEF(lddr)
{
REPEAT_LD(ldd);
}
// ED:10111001: 01R: CPDR
OP_DEF(cpdr)
{
REPEAT_CP(cpd);
}
// ED:10111010: 01R: INDR
OP_DEF(indr)
{
REPEAT_IO(ind);
}
// ED:10111011: 01R: OTDR
OP_DEF(otdr)
{
REPEAT_IO(outd);
}
// ED:11rrr001: --R: MULUB A,r
OP_DEF(mulub_a_r)
{
op_illegal(2);
}
// ED:11000011: --R: MULUB HL,BC
OP_DEF(mulub_hl_bc)
{
op_illegal(2);
}
// ED:11110011: --R: MULUB HL,SP
OP_DEF(mulub_hl_sp)
{
op_illegal(2);
}
// ED:11111111: -N-: SYSCALL
OP_DEF(syscall)
{
// MSX-DOS エミュレーションのような何か。
// 通常の DOSCALL と同様、コール番号は C レジスタに入っている。
if (gMainApp.msxdos_mode) {
// MSX-DOS エミュレーションなら DOS コールを処理する
assert(syscall_callback != NULL);
syscall_callback(syscall_arg);
CYCLE(3);
} else {
// 通常時は他の ED 系列と同じく不当命令例外。
op_illegal(2);
}
}
// DD:00rrr100: Z-Z: INC ixr
OP_DEF(inc_ixr)
{
op_illegal(2);
}
// DD:00rrr101: Z-Z: DEC ixr
OP_DEF(dec_ixr)
{
op_illegal(2);
}
// DD:00rrr110: Z-Z: LD ixr,n
OP_DEF(ld_ixr_n)
{
op_illegal(2);
}
// DD:01rrrsss: Z-Z: LD r,ixs
OP_DEF(ld_r_ixs)
{
op_illegal(2);
}
// DD:10000rrr: Z-Z: ADD A,ixr
OP_DEF(add_a_ixr)
{
op_illegal(2);
}
// DD:10001rrr: Z-Z: ADC A,ixr
OP_DEF(adc_a_ixr)
{
op_illegal(2);
}
// DD:10010rrr: Z-Z: SUB ixr
OP_DEF(sub_ixr)
{
op_illegal(2);
}
// DD:10011rrr: Z-Z: SBC A,ixr
OP_DEF(sbc_a_ixr)
{
op_illegal(2);
}
// DD:10100rrr: Z-Z: AND ixr
OP_DEF(and_ixr)
{
op_illegal(2);
}
// DD:10101rrr: Z-Z: XOR ixr
OP_DEF(xor_ixr)
{
op_illegal(2);
}
// DD:10110rrr: Z-Z: OR ixr
OP_DEF(or_ixr)
{
op_illegal(2);
}
// DD:10111rrr: Z-Z: CP ixr
OP_DEF(cp_ixr)
{
op_illegal(2);
}
// DD:11001011: 01R: op_DD_CB
OP_DEF(dd_cb)
{
// DD CB の場合は 3バイト目が d で、4バイト目が命令語。
ixd = Fetch1();
// 4バイト目をフェッチ
op = Fetch1();
// で分岐
switch (op) {
#include "hd64180switch_dd_cb.inc"
default:
op_illegal(3);
break;
}
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.