|
|
@ -240,6 +240,7 @@ class LD_RR_NN(Insn): |
|
|
|
|
|
|
|
def exec(self, cpu: CPU) -> None: |
|
|
|
cpu.set_reg16(self.rr, self.nn) |
|
|
|
cpu.cycles += 12 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return f"LD {self.rr.value}, {hex(self.nn)}" |
|
|
@ -251,6 +252,7 @@ class LD_NN_SP(Insn): |
|
|
|
|
|
|
|
def exec(self, cpu: CPU) -> None: |
|
|
|
cpu.set_mem16(self.nn, cpu.get_reg16(R16.SP)) |
|
|
|
cpu.cycles += 20 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return f"LD ({hex(self.nn)}), SP" |
|
|
@ -260,19 +262,23 @@ class LD_NN_SP(Insn): |
|
|
|
class LD_SP_HL(Insn): |
|
|
|
def exec(self, cpu: CPU) -> None: |
|
|
|
cpu.set_reg16(R16.SP, cpu.get_reg16(R16.HL)) |
|
|
|
cpu.cycles += 8 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return "LD SP, HL" |
|
|
|
|
|
|
|
|
|
|
|
# NOTE: Normally we would support PUSH AF, but then non-carry flags could impact |
|
|
|
# the program (by popping or inspecting where F was stored) |
|
|
|
@dataclass |
|
|
|
class PUSH_RR(Insn): |
|
|
|
rr: R16 |
|
|
|
|
|
|
|
def exec(self, cpu: CPU) -> None: |
|
|
|
sp = cpu.get_reg16(R16.SP) |
|
|
|
cpu.set_reg16(R16.SP, sp - 2) |
|
|
|
cpu.set_mem16(sp - 2, cpu.get_reg16(self.rr)) |
|
|
|
sp = cpu.get_reg16(R16.SP) - 2 |
|
|
|
cpu.set_reg16(R16.SP, sp) |
|
|
|
cpu.set_mem16(sp, cpu.get_reg16(self.rr)) |
|
|
|
cpu.cycles += 16 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return f"PUSH {self.rr.value}" |
|
|
@ -286,6 +292,7 @@ class POP_RR(Insn): |
|
|
|
sp = cpu.get_reg16(R16.SP) |
|
|
|
cpu.set_reg16(self.rr, cpu.get_mem16(sp)) |
|
|
|
cpu.set_reg16(R16.SP, sp + 2) |
|
|
|
cpu.cycles += 12 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return f"POP {self.rr.value}" |
|
|
@ -299,6 +306,7 @@ class ADD_A_R(Insn): |
|
|
|
a = cpu.get_reg8(R8.A) + cpu.get_reg8(self.r) |
|
|
|
cpu.carry = 1 if a > 0xFF else 0 |
|
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
cpu.cycles += 4 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return f"ADD A, {self.r.value}" |
|
|
@ -312,6 +320,7 @@ class ADD_A_N(Insn): |
|
|
|
a = cpu.get_reg8(R8.A) + self.n |
|
|
|
cpu.carry = 1 if a > 0xFF else 0 |
|
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
cpu.cycles += 8 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return f"ADD A, {hex(self.n)}" |
|
|
@ -323,6 +332,7 @@ class ADD_A_HL(Insn): |
|
|
|
a = cpu.get_reg8(R8.A) + cpu.get_mem8(cpu.get_reg16(R16.HL)) |
|
|
|
cpu.carry = 1 if a > 0xFF else 0 |
|
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
cpu.cycles += 8 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return f"ADD A, (HL)" |
|
|
@ -336,6 +346,7 @@ class ADC_A_R(Insn): |
|
|
|
a = cpu.get_reg8(R8.A) + cpu.get_reg8(self.r) + cpu.carry |
|
|
|
cpu.carry = 1 if a > 0xFF else 0 |
|
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
cpu.cycles += 4 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return f"ADC A, {self.r.value}" |
|
|
@ -349,6 +360,7 @@ class ADC_A_N(Insn): |
|
|
|
a = cpu.get_reg8(R8.A) + self.n + cpu.carry |
|
|
|
cpu.carry = 1 if a > 0xFF else 0 |
|
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
cpu.cycles += 8 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return f"ADC A, {hex(self.n)}" |
|
|
@ -360,6 +372,7 @@ class ADC_A_HL(Insn): |
|
|
|
a = cpu.get_reg8(R8.A) + cpu.get_mem8(cpu.get_reg16(R16.HL)) + cpu.carry |
|
|
|
cpu.carry = 1 if a > 0xFF else 0 |
|
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
cpu.cycles += 8 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return f"ADC A, (HL)" |
|
|
@ -373,6 +386,7 @@ class SUB_A_R(Insn): |
|
|
|
a = cpu.get_reg8(R8.A) - cpu.get_reg8(self.r) |
|
|
|
cpu.carry = 1 if a < 0 else 0 |
|
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
cpu.cycles += 4 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return f"SUB A, {self.r.value}" |
|
|
@ -386,6 +400,7 @@ class SUB_A_N(Insn): |
|
|
|
a = cpu.get_reg8(R8.A) - self.n |
|
|
|
cpu.carry = 1 if a < 0 else 0 |
|
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
cpu.cycles += 8 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return f"SUB A, {hex(self.n)}" |
|
|
@ -397,6 +412,7 @@ class SUB_A_HL(Insn): |
|
|
|
a = cpu.get_reg8(R8.A) - cpu.get_mem8(cpu.get_reg16(R16.HL)) |
|
|
|
cpu.carry = 1 if a < 0 else 0 |
|
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
cpu.cycles += 8 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return "SUB A, (HL)" |
|
|
@ -410,6 +426,7 @@ class SBC_A_R(Insn): |
|
|
|
a = cpu.get_reg8(R8.A) - cpu.get_reg8(self.r) - cpu.carry |
|
|
|
cpu.carry = 1 if a < 0 else 0 |
|
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
cpu.cycles += 4 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return f"SBC A, {self.r.value}" |
|
|
@ -423,6 +440,7 @@ class SBC_A_N(Insn): |
|
|
|
a = cpu.get_reg8(R8.A) - self.n - cpu.carry |
|
|
|
cpu.carry = 1 if a < 0 else 0 |
|
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
cpu.cycles += 8 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return f"SBC A, {hex(self.n)}" |
|
|
@ -434,6 +452,7 @@ class SBC_A_HL(Insn): |
|
|
|
a = cpu.get_reg8(R8.A) - cpu.get_mem8(cpu.get_reg16(R16.HL)) - cpu.carry |
|
|
|
cpu.carry = 1 if a < 0 else 0 |
|
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
cpu.cycles += 8 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return "SBC A, (HL)" |
|
|
@ -447,6 +466,7 @@ class AND_A_R(Insn): |
|
|
|
a = cpu.get_reg8(R8.A) & cpu.get_reg8(self.r) |
|
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
cpu.carry = 0 |
|
|
|
cpu.cycles += 4 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return f"AND A, {self.r.value}" |
|
|
@ -460,6 +480,7 @@ class AND_A_N(Insn): |
|
|
|
a = cpu.get_reg8(R8.A) & self.n |
|
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
cpu.carry = 0 |
|
|
|
cpu.cycles += 8 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return f"AND A, {hex(self.n)}" |
|
|
@ -471,17 +492,99 @@ class AND_A_HL(Insn): |
|
|
|
a = cpu.get_reg8(R8.A) & cpu.get_mem8(cpu.get_reg16(R16.HL)) |
|
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
cpu.carry = 0 |
|
|
|
cpu.cycles += 8 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return "AND A, (HL)" |
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
|
class XOR_A_R(Insn): |
|
|
|
r: R8 |
|
|
|
|
|
|
|
def exec(self, cpu: CPU) -> None: |
|
|
|
a = cpu.get_reg8(R8.A) ^ cpu.get_reg8(self.r) |
|
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
cpu.carry = 0 |
|
|
|
cpu.cycles += 4 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return f"XOR A, {self.r.value}" |
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
|
class XOR_A_N(Insn): |
|
|
|
n: int |
|
|
|
|
|
|
|
def exec(self, cpu: CPU) -> None: |
|
|
|
a = cpu.get_reg8(R8.A) ^ self.n |
|
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
cpu.carry = 0 |
|
|
|
cpu.cycles += 8 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return f"XOR A, {hex(self.n)}" |
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
|
class XOR_A_HL(Insn): |
|
|
|
def exec(self, cpu: CPU) -> None: |
|
|
|
a = cpu.get_reg8(R8.A) ^ cpu.get_mem8(cpu.get_reg16(R16.HL)) |
|
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
cpu.carry = 0 |
|
|
|
cpu.cycles += 8 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return "XOR A, (HL)" |
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
|
class OR_A_R(Insn): |
|
|
|
r: R8 |
|
|
|
|
|
|
|
def exec(self, cpu: CPU) -> None: |
|
|
|
a = cpu.get_reg8(R8.A) | cpu.get_reg8(self.r) |
|
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
cpu.carry = 0 |
|
|
|
cpu.cycles += 4 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return f"OR A, {self.r.value}" |
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
|
class OR_A_N(Insn): |
|
|
|
n: int |
|
|
|
|
|
|
|
def exec(self, cpu: CPU) -> None: |
|
|
|
a = cpu.get_reg8(R8.A) | self.n |
|
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
cpu.carry = 0 |
|
|
|
cpu.cycles += 8 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return f"OR A, {hex(self.n)}" |
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
|
class OR_A_HL(Insn): |
|
|
|
def exec(self, cpu: CPU) -> None: |
|
|
|
a = cpu.get_reg8(R8.A) | cpu.get_mem8(cpu.get_reg16(R16.HL)) |
|
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
cpu.carry = 0 |
|
|
|
cpu.cycles += 8 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return "OR A, (HL)" |
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
|
class CP_A_R(Insn): |
|
|
|
r: R8 |
|
|
|
|
|
|
|
def exec(self, cpu: CPU) -> None: |
|
|
|
cpu.carry = 1 if cpu.get_reg8(R8.A) < cpu.get_reg8(self.r) else 0 |
|
|
|
cpu.cycles += 4 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return f"CP A, {self.r.value}" |
|
|
@ -493,6 +596,7 @@ class CP_A_N(Insn): |
|
|
|
|
|
|
|
def exec(self, cpu: CPU) -> None: |
|
|
|
cpu.carry = 1 if cpu.get_reg8(R8.A) < self.n else 0 |
|
|
|
cpu.cycles += 8 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return f"CP A, {hex(self.n)}" |
|
|
@ -502,6 +606,7 @@ class CP_A_N(Insn): |
|
|
|
class CP_A_HL(Insn): |
|
|
|
def exec(self, cpu: CPU) -> None: |
|
|
|
cpu.carry = 1 if cpu.get_reg8(R8.A) < cpu.get_mem8(cpu.get_reg16(R16.HL)) else 0 |
|
|
|
cpu.cycles += 8 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return "CP A, (HL)" |
|
|
@ -513,6 +618,7 @@ class INC_R(Insn): |
|
|
|
|
|
|
|
def exec(self, cpu: CPU) -> None: |
|
|
|
cpu.set_reg8(self.r, cpu.get_reg8(self.r) + 1) |
|
|
|
cpu.cycles += 4 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return f"INC {self.r.value}" |
|
|
@ -525,6 +631,7 @@ class INC_HL(Insn): |
|
|
|
def exec(self, cpu: CPU) -> None: |
|
|
|
hl = cpu.get_reg16(R16.HL) |
|
|
|
cpu.set_mem8(hl, cpu.get_mem8(hl) + 1) |
|
|
|
cpu.cycles += 12 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return "INC (HL)" |
|
|
@ -536,6 +643,7 @@ class DEC_R(Insn): |
|
|
|
|
|
|
|
def exec(self, cpu: CPU) -> None: |
|
|
|
cpu.set_reg8(self.r, cpu.get_reg8(self.r) - 1) |
|
|
|
cpu.cycles += 4 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return f"DEC {self.r.value}" |
|
|
@ -548,6 +656,7 @@ class DEC_HL(Insn): |
|
|
|
def exec(self, cpu: CPU) -> None: |
|
|
|
hl = cpu.get_reg16(R16.HL) |
|
|
|
cpu.set_mem8(hl, cpu.get_mem8(hl) - 1) |
|
|
|
cpu.cycles += 12 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return "DEC (HL)" |
|
|
@ -557,6 +666,7 @@ class DEC_HL(Insn): |
|
|
|
class CPL(Insn): |
|
|
|
def exec(self, cpu: CPU) -> None: |
|
|
|
cpu.set_reg8(R8.A, cpu.get_reg8(R8.A) ^ 0xFF) |
|
|
|
cpu.cycles += 4 |
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
return "CPL" |
|
|
|