|
@ -10,9 +10,9 @@ class Insn(ABC): |
|
|
def exec(self, cpu: CPU) -> None: |
|
|
def exec(self, cpu: CPU) -> None: |
|
|
pass |
|
|
pass |
|
|
|
|
|
|
|
|
# TODO: Make abstract once all subclasses implement |
|
|
|
|
|
|
|
|
@abstractmethod |
|
|
def pretty(self) -> str: |
|
|
def pretty(self) -> str: |
|
|
return "" |
|
|
|
|
|
|
|
|
pass |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
@ -25,7 +25,7 @@ class LD_R_R(Insn): |
|
|
cpu.cycles += 4 |
|
|
cpu.cycles += 4 |
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
def pretty(self) -> str: |
|
|
return f"LD {self.dst}, {self.src}" |
|
|
|
|
|
|
|
|
return f"LD {self.dst.value}, {self.src.value}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
@ -38,7 +38,7 @@ class LD_R_N8(Insn): |
|
|
cpu.cycles += 8 |
|
|
cpu.cycles += 8 |
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
def pretty(self) -> str: |
|
|
return f"LD {self.dst}, {hex(self.imm)}" |
|
|
|
|
|
|
|
|
return f"LD {self.dst.value}, {hex(self.imm)}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
@ -50,7 +50,7 @@ class LD_R_HL(Insn): |
|
|
cpu.cycles += 8 |
|
|
cpu.cycles += 8 |
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
def pretty(self) -> str: |
|
|
return f"LD {self.dst}, (HL)" |
|
|
|
|
|
|
|
|
return f"LD {self.dst.value}, (HL)" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
@ -62,7 +62,7 @@ class LD_HL_R(Insn): |
|
|
cpu.cycles += 8 |
|
|
cpu.cycles += 8 |
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
def pretty(self) -> str: |
|
|
return f"LD (HL), {self.src}" |
|
|
|
|
|
|
|
|
return f"LD (HL), {self.src.value}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
@ -252,12 +252,18 @@ class LD_NN_SP(Insn): |
|
|
def exec(self, cpu: CPU) -> None: |
|
|
def exec(self, cpu: CPU) -> None: |
|
|
cpu.set_mem16(self.nn, cpu.get_reg16(R16.SP)) |
|
|
cpu.set_mem16(self.nn, cpu.get_reg16(R16.SP)) |
|
|
|
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
|
|
return f"LD ({hex(self.nn)}), SP" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
|
class LD_SP_HL(Insn): |
|
|
class LD_SP_HL(Insn): |
|
|
def exec(self, cpu: CPU) -> None: |
|
|
def exec(self, cpu: CPU) -> None: |
|
|
cpu.set_reg16(R16.SP, cpu.get_reg16(R16.HL)) |
|
|
cpu.set_reg16(R16.SP, cpu.get_reg16(R16.HL)) |
|
|
|
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
|
|
return "LD SP, HL" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
|
class PUSH_RR(Insn): |
|
|
class PUSH_RR(Insn): |
|
@ -268,6 +274,9 @@ class PUSH_RR(Insn): |
|
|
cpu.set_reg16(R16.SP, sp - 2) |
|
|
cpu.set_reg16(R16.SP, sp - 2) |
|
|
cpu.set_mem16(sp - 2, cpu.get_reg16(self.rr)) |
|
|
cpu.set_mem16(sp - 2, cpu.get_reg16(self.rr)) |
|
|
|
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
|
|
return f"PUSH {self.rr.value}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
|
class POP_RR(Insn): |
|
|
class POP_RR(Insn): |
|
@ -278,6 +287,9 @@ class POP_RR(Insn): |
|
|
cpu.set_reg16(self.rr, cpu.get_mem16(sp)) |
|
|
cpu.set_reg16(self.rr, cpu.get_mem16(sp)) |
|
|
cpu.set_reg16(R16.SP, sp + 2) |
|
|
cpu.set_reg16(R16.SP, sp + 2) |
|
|
|
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
|
|
return f"POP {self.rr.value}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
|
class ADD_A_R(Insn): |
|
|
class ADD_A_R(Insn): |
|
@ -288,6 +300,9 @@ class ADD_A_R(Insn): |
|
|
cpu.carry = 1 if a > 0xFF else 0 |
|
|
cpu.carry = 1 if a > 0xFF else 0 |
|
|
cpu.set_reg8(R8.A, a) |
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
|
|
return f"ADD A, {self.r.value}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
|
class ADD_A_N(Insn): |
|
|
class ADD_A_N(Insn): |
|
@ -298,6 +313,9 @@ class ADD_A_N(Insn): |
|
|
cpu.carry = 1 if a > 0xFF else 0 |
|
|
cpu.carry = 1 if a > 0xFF else 0 |
|
|
cpu.set_reg8(R8.A, a) |
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
|
|
return f"ADD A, {hex(self.n)}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
|
class ADD_A_HL(Insn): |
|
|
class ADD_A_HL(Insn): |
|
@ -306,6 +324,9 @@ class ADD_A_HL(Insn): |
|
|
cpu.carry = 1 if a > 0xFF else 0 |
|
|
cpu.carry = 1 if a > 0xFF else 0 |
|
|
cpu.set_reg8(R8.A, a) |
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
|
|
return f"ADD A, (HL)" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
|
class ADC_A_R(Insn): |
|
|
class ADC_A_R(Insn): |
|
@ -316,6 +337,9 @@ class ADC_A_R(Insn): |
|
|
cpu.carry = 1 if a > 0xFF else 0 |
|
|
cpu.carry = 1 if a > 0xFF else 0 |
|
|
cpu.set_reg8(R8.A, a) |
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
|
|
return f"ADC A, {self.r.value}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
|
class ADC_A_N(Insn): |
|
|
class ADC_A_N(Insn): |
|
@ -326,6 +350,9 @@ class ADC_A_N(Insn): |
|
|
cpu.carry = 1 if a > 0xFF else 0 |
|
|
cpu.carry = 1 if a > 0xFF else 0 |
|
|
cpu.set_reg8(R8.A, a) |
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
|
|
return f"ADC A, {hex(self.n)}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
|
class ADC_A_HL(Insn): |
|
|
class ADC_A_HL(Insn): |
|
@ -334,6 +361,9 @@ class ADC_A_HL(Insn): |
|
|
cpu.carry = 1 if a > 0xFF else 0 |
|
|
cpu.carry = 1 if a > 0xFF else 0 |
|
|
cpu.set_reg8(R8.A, a) |
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
|
|
return f"ADC A, (HL)" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
|
class SUB_A_R(Insn): |
|
|
class SUB_A_R(Insn): |
|
@ -344,6 +374,9 @@ class SUB_A_R(Insn): |
|
|
cpu.carry = 1 if a < 0 else 0 |
|
|
cpu.carry = 1 if a < 0 else 0 |
|
|
cpu.set_reg8(R8.A, a) |
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
|
|
return f"SUB A, {self.r.value}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
|
class SUB_A_N(Insn): |
|
|
class SUB_A_N(Insn): |
|
@ -354,6 +387,9 @@ class SUB_A_N(Insn): |
|
|
cpu.carry = 1 if a < 0 else 0 |
|
|
cpu.carry = 1 if a < 0 else 0 |
|
|
cpu.set_reg8(R8.A, a) |
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
|
|
return f"SUB A, {hex(self.n)}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
|
class SUB_A_HL(Insn): |
|
|
class SUB_A_HL(Insn): |
|
@ -362,6 +398,9 @@ class SUB_A_HL(Insn): |
|
|
cpu.carry = 1 if a < 0 else 0 |
|
|
cpu.carry = 1 if a < 0 else 0 |
|
|
cpu.set_reg8(R8.A, a) |
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
|
|
return "SUB A, (HL)" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
|
class SBC_A_R(Insn): |
|
|
class SBC_A_R(Insn): |
|
@ -372,6 +411,9 @@ class SBC_A_R(Insn): |
|
|
cpu.carry = 1 if a < 0 else 0 |
|
|
cpu.carry = 1 if a < 0 else 0 |
|
|
cpu.set_reg8(R8.A, a) |
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
|
|
return f"SBC A, {self.r.value}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
|
class SBC_A_N(Insn): |
|
|
class SBC_A_N(Insn): |
|
@ -382,6 +424,9 @@ class SBC_A_N(Insn): |
|
|
cpu.carry = 1 if a < 0 else 0 |
|
|
cpu.carry = 1 if a < 0 else 0 |
|
|
cpu.set_reg8(R8.A, a) |
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
|
|
return f"SBC A, {hex(self.n)}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
|
class SBC_A_HL(Insn): |
|
|
class SBC_A_HL(Insn): |
|
@ -390,6 +435,9 @@ class SBC_A_HL(Insn): |
|
|
cpu.carry = 1 if a < 0 else 0 |
|
|
cpu.carry = 1 if a < 0 else 0 |
|
|
cpu.set_reg8(R8.A, a) |
|
|
cpu.set_reg8(R8.A, a) |
|
|
|
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
|
|
return "SBC A, (HL)" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
|
class AND_A_R(Insn): |
|
|
class AND_A_R(Insn): |
|
@ -400,6 +448,9 @@ class AND_A_R(Insn): |
|
|
cpu.set_reg8(R8.A, a) |
|
|
cpu.set_reg8(R8.A, a) |
|
|
cpu.carry = 0 |
|
|
cpu.carry = 0 |
|
|
|
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
|
|
return f"AND A, {self.r.value}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
|
class AND_A_N(Insn): |
|
|
class AND_A_N(Insn): |
|
@ -410,6 +461,9 @@ class AND_A_N(Insn): |
|
|
cpu.set_reg8(R8.A, a) |
|
|
cpu.set_reg8(R8.A, a) |
|
|
cpu.carry = 0 |
|
|
cpu.carry = 0 |
|
|
|
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
|
|
return f"AND A, {hex(self.n)}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
|
class AND_A_HL(Insn): |
|
|
class AND_A_HL(Insn): |
|
@ -504,6 +558,9 @@ class CPL(Insn): |
|
|
def exec(self, cpu: CPU) -> None: |
|
|
def exec(self, cpu: CPU) -> None: |
|
|
cpu.set_reg8(R8.A, cpu.get_reg8(R8.A) ^ 0xFF) |
|
|
cpu.set_reg8(R8.A, cpu.get_reg8(R8.A) ^ 0xFF) |
|
|
|
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
|
|
|
return "CPL" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
|
class ADD_HL_RR(Insn): |
|
|
class ADD_HL_RR(Insn): |
|
@ -622,7 +679,7 @@ class RLC_R(Insn): |
|
|
cpu.set_reg8(self.r, ((r << 1) & 0xFF) | cpu.carry) |
|
|
cpu.set_reg8(self.r, ((r << 1) & 0xFF) | cpu.carry) |
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
def pretty(self) -> str: |
|
|
return f"RLC {self.r}" |
|
|
|
|
|
|
|
|
return f"RLC {self.r.value}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
@ -647,7 +704,7 @@ class RL_R(Insn): |
|
|
cpu.carry = next_carry |
|
|
cpu.carry = next_carry |
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
def pretty(self) -> str: |
|
|
return f"RL {self.r}" |
|
|
|
|
|
|
|
|
return f"RL {self.r.value}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
@ -672,7 +729,7 @@ class RRC_R(Insn): |
|
|
cpu.set_reg8(self.r, (r >> 1) | (cpu.carry << 7)) |
|
|
cpu.set_reg8(self.r, (r >> 1) | (cpu.carry << 7)) |
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
def pretty(self) -> str: |
|
|
return f"RRC {self.r}" |
|
|
|
|
|
|
|
|
return f"RRC {self.r.value}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
@ -697,7 +754,7 @@ class RR_R(Insn): |
|
|
cpu.carry = next_carry |
|
|
cpu.carry = next_carry |
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
def pretty(self) -> str: |
|
|
return f"RR {self.r}" |
|
|
|
|
|
|
|
|
return f"RR {self.r.value}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
@ -721,7 +778,7 @@ class SLA_R(Insn): |
|
|
cpu.set_reg8(self.r, (r << 1) & 0xFF) |
|
|
cpu.set_reg8(self.r, (r << 1) & 0xFF) |
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
def pretty(self) -> str: |
|
|
return f"SLA {self.r}" |
|
|
|
|
|
|
|
|
return f"SLA {self.r.value}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
@ -743,7 +800,7 @@ class SWAP_R(Insn): |
|
|
cpu.set_reg8(self.r, ((r << 4) & 0xFF) | (r >> 4)) |
|
|
cpu.set_reg8(self.r, ((r << 4) & 0xFF) | (r >> 4)) |
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
def pretty(self) -> str: |
|
|
return f"SWAP {self.r}" |
|
|
|
|
|
|
|
|
return f"SWAP {self.r.value}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
@ -765,7 +822,7 @@ class SRA_R(Insn): |
|
|
cpu.set_reg8(self.r, (r >> 1) | (r & (1 << 7))) |
|
|
cpu.set_reg8(self.r, (r >> 1) | (r & (1 << 7))) |
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
def pretty(self) -> str: |
|
|
return f"SRA {self.r}" |
|
|
|
|
|
|
|
|
return f"SRA {self.r.value}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
@ -787,7 +844,7 @@ class SRL_R(Insn): |
|
|
cpu.set_reg8(self.r, r >> 1) |
|
|
cpu.set_reg8(self.r, r >> 1) |
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
def pretty(self) -> str: |
|
|
return f"SRL {self.r}" |
|
|
|
|
|
|
|
|
return f"SRL {self.r.value}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
@ -812,7 +869,7 @@ class SET_N_R(Insn): |
|
|
cpu.set_reg8(self.r, cpu.get_reg8(self.r) | (1 << self.n)) |
|
|
cpu.set_reg8(self.r, cpu.get_reg8(self.r) | (1 << self.n)) |
|
|
|
|
|
|
|
|
def pretty(self) -> str: |
|
|
def pretty(self) -> str: |
|
|
return f"SET {self.n}, (HL)" |
|
|
|
|
|
|
|
|
return f"SET {self.n}, {self.r.value}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
@dataclass |
|
|