from abc import ABC, abstractmethod
|
|
from dataclasses import dataclass
|
|
|
|
from gbso.cpu import CPU
|
|
from gbso.regs import R16, R8
|
|
|
|
|
|
class Insn(ABC):
|
|
@abstractmethod
|
|
def exec(self, cpu: CPU) -> None:
|
|
pass
|
|
|
|
# TODO: Make abstract once all subclasses implement
|
|
def pretty(self) -> str:
|
|
return ""
|
|
|
|
|
|
@dataclass
|
|
class LD_R_R(Insn):
|
|
dst: R8
|
|
src: R8
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_reg8(self.dst, cpu.get_reg8(self.src))
|
|
|
|
def pretty(self) -> str:
|
|
return f"LD {self.dst}, {self.src}"
|
|
|
|
|
|
@dataclass
|
|
class LD_R_N8(Insn):
|
|
dst: R8
|
|
imm: int
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_reg8(self.dst, self.imm)
|
|
|
|
def pretty(self) -> str:
|
|
return f"LD {self.dst}, {hex(self.imm)}"
|
|
|
|
|
|
@dataclass
|
|
class LD_R_HL(Insn):
|
|
dst: R8
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_reg8(self.dst, cpu.get_mem8(cpu.get_reg16(R16.HL)))
|
|
|
|
def pretty(self) -> str:
|
|
return f"LD {self.dst}, (HL)"
|
|
|
|
|
|
@dataclass
|
|
class LD_HL_R(Insn):
|
|
src: R8
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_mem8(cpu.get_reg16(R16.HL), cpu.get_reg8(self.src))
|
|
|
|
def pretty(self) -> str:
|
|
return f"LD (HL), {self.src}"
|
|
|
|
|
|
@dataclass
|
|
class LD_HL_N(Insn):
|
|
imm: int
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_mem8(cpu.get_reg16(R16.HL), self.imm)
|
|
|
|
def pretty(self) -> str:
|
|
return f"LD (HL), {hex(self.imm & 0xff)}"
|
|
|
|
|
|
@dataclass
|
|
class LD_A_BC(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_reg8(R8.A, cpu.get_mem8(cpu.get_reg16(R16.BC)))
|
|
|
|
def pretty(self) -> str:
|
|
return "LD A, (BC)"
|
|
|
|
|
|
@dataclass
|
|
class LD_A_DE(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_reg8(R8.A, cpu.get_mem8(cpu.get_reg16(R16.DE)))
|
|
|
|
def pretty(self) -> str:
|
|
return "LD A, (DE)"
|
|
|
|
|
|
@dataclass
|
|
class LD_A_NN(Insn):
|
|
nn: int
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_reg8(R8.A, cpu.get_mem8(self.nn))
|
|
|
|
def pretty(self) -> str:
|
|
return f"LD A, ({hex(self.nn)})"
|
|
|
|
|
|
@dataclass
|
|
class LD_BC_A(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_mem8(cpu.get_reg16(R16.BC), cpu.get_reg8(R8.A))
|
|
|
|
|
|
@dataclass
|
|
class LD_DE_A(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_mem8(cpu.get_reg16(R16.DE), cpu.get_reg8(R8.A))
|
|
|
|
|
|
@dataclass
|
|
class LD_NN_A(Insn):
|
|
nn: int
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_mem8(self.nn, cpu.get_reg8(R8.A))
|
|
|
|
|
|
@dataclass
|
|
class LD_A_FF_N(Insn):
|
|
n: int
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_reg8(R8.A, cpu.get_mem8(0xFF00 + self.n))
|
|
|
|
|
|
@dataclass
|
|
class LD_FF_N_A(Insn):
|
|
n: int
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_mem8(0xFF00 + self.n, cpu.get_reg8(R8.A))
|
|
|
|
|
|
@dataclass
|
|
class LD_A_FF_C(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_reg8(R8.A, cpu.get_mem8(0xFF00 + cpu.get_reg8(R8.C)))
|
|
|
|
|
|
@dataclass
|
|
class LD_FF_C_A(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_mem8(0xFF00 + cpu.get_reg8(R8.C), cpu.get_reg8(R8.A))
|
|
|
|
|
|
@dataclass
|
|
class LDI_HL_A(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
hl = cpu.get_reg16(R16.HL)
|
|
cpu.set_mem8(hl, cpu.get_reg8(R8.A))
|
|
cpu.set_reg16(R16.HL, hl + 1)
|
|
|
|
|
|
@dataclass
|
|
class LDI_A_HL(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
hl = cpu.get_reg16(R16.HL)
|
|
cpu.set_reg8(R8.A, cpu.get_mem8(hl))
|
|
cpu.set_reg16(R16.HL, hl + 1)
|
|
|
|
|
|
@dataclass
|
|
class LDD_HL_A(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
hl = cpu.get_reg16(R16.HL)
|
|
cpu.set_mem8(hl, cpu.get_reg8(R8.A))
|
|
cpu.set_reg16(R16.HL, hl - 1)
|
|
|
|
|
|
@dataclass
|
|
class LDD_A_HL(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
hl = cpu.get_reg16(R16.HL)
|
|
cpu.set_reg8(R8.A, cpu.get_mem8(hl))
|
|
cpu.set_reg16(R16.HL, hl - 1)
|
|
|
|
|
|
@dataclass
|
|
class LD_RR_NN(Insn):
|
|
rr: R16
|
|
nn: int
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_reg16(self.rr, self.nn)
|
|
|
|
def pretty(self) -> str:
|
|
return f"LD {self.rr.value}, {hex(self.nn)}"
|
|
|
|
|
|
@dataclass
|
|
class LD_NN_SP(Insn):
|
|
nn: int
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_mem16(self.nn, cpu.get_reg16(R16.SP))
|
|
|
|
|
|
@dataclass
|
|
class LD_SP_HL(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_reg16(R16.SP, cpu.get_reg16(R16.HL))
|
|
|
|
|
|
@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))
|
|
|
|
|
|
@dataclass
|
|
class POP_RR(Insn):
|
|
rr: R16
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
sp = cpu.get_reg16(R16.SP)
|
|
cpu.set_reg16(self.rr, cpu.get_mem16(sp))
|
|
cpu.set_reg16(R16.SP, sp + 2)
|
|
|
|
|
|
@dataclass
|
|
class ADD_A_R(Insn):
|
|
r: R8
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
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)
|
|
|
|
|
|
@dataclass
|
|
class ADD_A_N(Insn):
|
|
n: int
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
a = cpu.get_reg8(R8.A) + self.n
|
|
cpu.carry = 1 if a > 0xFF else 0
|
|
cpu.set_reg8(R8.A, a)
|
|
|
|
|
|
@dataclass
|
|
class ADD_A_HL(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
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)
|
|
|
|
|
|
@dataclass
|
|
class ADC_A_R(Insn):
|
|
r: R8
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
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)
|
|
|
|
|
|
@dataclass
|
|
class ADC_A_N(Insn):
|
|
n: int
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
a = cpu.get_reg8(R8.A) + self.n + cpu.carry
|
|
cpu.carry = 1 if a > 0xFF else 0
|
|
cpu.set_reg8(R8.A, a)
|
|
|
|
|
|
@dataclass
|
|
class ADC_A_HL(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
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)
|
|
|
|
|
|
@dataclass
|
|
class SUB_A_R(Insn):
|
|
r: R8
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
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)
|
|
|
|
|
|
@dataclass
|
|
class SUB_A_N(Insn):
|
|
n: int
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
a = cpu.get_reg8(R8.A) - self.n
|
|
cpu.carry = 1 if a < 0 else 0
|
|
cpu.set_reg8(R8.A, a)
|
|
|
|
|
|
@dataclass
|
|
class SUB_A_HL(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
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)
|
|
|
|
|
|
@dataclass
|
|
class SBC_A_R(Insn):
|
|
r: R8
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
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)
|
|
|
|
|
|
@dataclass
|
|
class SBC_A_N(Insn):
|
|
n: int
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
a = cpu.get_reg8(R8.A) - self.n - cpu.carry
|
|
cpu.carry = 1 if a < 0 else 0
|
|
cpu.set_reg8(R8.A, a)
|
|
|
|
|
|
@dataclass
|
|
class SBC_A_HL(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
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)
|
|
|
|
|
|
@dataclass
|
|
class AND_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
|
|
|
|
|
|
@dataclass
|
|
class AND_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
|
|
|
|
|
|
@dataclass
|
|
class AND_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
|
|
|
|
def pretty(self) -> str:
|
|
return "AND 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
|
|
|
|
def pretty(self) -> str:
|
|
return f"CP A, {self.r.value}"
|
|
|
|
|
|
@dataclass
|
|
class CP_A_N(Insn):
|
|
n: int
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.carry = 1 if cpu.get_reg8(R8.A) < self.n else 0
|
|
|
|
def pretty(self) -> str:
|
|
return f"CP A, {hex(self.n)}"
|
|
|
|
|
|
@dataclass
|
|
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
|
|
|
|
def pretty(self) -> str:
|
|
return "CP A, (HL)"
|
|
|
|
|
|
@dataclass
|
|
class INC_R(Insn):
|
|
r: R8
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_reg8(self.r, cpu.get_reg8(self.r) + 1)
|
|
|
|
def pretty(self) -> str:
|
|
return f"INC {self.r.value}"
|
|
|
|
|
|
@dataclass
|
|
class INC_HL(Insn):
|
|
r: R8
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
hl = cpu.get_reg16(R16.HL)
|
|
cpu.set_mem8(hl, cpu.get_mem8(hl) + 1)
|
|
|
|
def pretty(self) -> str:
|
|
return "INC (HL)"
|
|
|
|
|
|
@dataclass
|
|
class DEC_R(Insn):
|
|
r: R8
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_reg8(self.r, cpu.get_reg8(self.r) - 1)
|
|
|
|
def pretty(self) -> str:
|
|
return f"DEC {self.r.value}"
|
|
|
|
|
|
@dataclass
|
|
class DEC_HL(Insn):
|
|
r: R8
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
hl = cpu.get_reg16(R16.HL)
|
|
cpu.set_mem8(hl, cpu.get_mem8(hl) - 1)
|
|
|
|
def pretty(self) -> str:
|
|
return "DEC (HL)"
|
|
|
|
|
|
@dataclass
|
|
class CPL(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_reg8(R8.A, cpu.get_reg8(R8.A) ^ 0xFF)
|
|
|
|
|
|
@dataclass
|
|
class ADD_HL_RR(Insn):
|
|
rr: R16
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
hl = cpu.get_reg16(R16.HL) + cpu.get_reg16(self.rr)
|
|
cpu.carry = 1 if hl > 0xFFFF else 0
|
|
cpu.set_reg16(R16.HL, hl)
|
|
|
|
def pretty(self) -> str:
|
|
return f"ADD HL, {self.rr.value}"
|
|
|
|
|
|
@dataclass
|
|
class INC_RR(Insn):
|
|
rr: R16
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_reg16(self.rr, cpu.get_reg16(self.rr) + 1)
|
|
|
|
def pretty(self) -> str:
|
|
return f"INC {self.rr.value}"
|
|
|
|
|
|
@dataclass
|
|
class DEC_RR(Insn):
|
|
rr: R16
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_reg16(self.rr, cpu.get_reg16(self.rr) - 1)
|
|
|
|
def pretty(self) -> str:
|
|
return f"DEC {self.rr.value}"
|
|
|
|
|
|
@dataclass
|
|
class ADD_SP_DD(Insn):
|
|
dd: int
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
sp = cpu.get_reg16(R16.SP) + self.dd
|
|
cpu.carry = 1 if sp > 0xFFFF or sp < 0 else 0
|
|
cpu.set_reg16(R16.SP, sp)
|
|
|
|
def pretty(self) -> str:
|
|
return f"ADD SP, {self.dd}"
|
|
|
|
|
|
@dataclass
|
|
class LD_HL_SP_DD(Insn):
|
|
dd: int
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
sp = cpu.get_reg16(R16.SP) + self.dd
|
|
cpu.carry = 1 if sp > 0xFFFF or sp < 0 else 0
|
|
cpu.set_reg16(R16.HL, sp)
|
|
|
|
def pretty(self) -> str:
|
|
return f"LD HL, SP + {self.dd}"
|
|
|
|
|
|
@dataclass
|
|
class RLCA(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
a = cpu.get_reg8(R8.A)
|
|
cpu.carry = (a >> 7) & 1
|
|
cpu.set_reg8(R8.A, ((a << 1) & 0xFF) | cpu.carry)
|
|
|
|
def pretty(self) -> str:
|
|
return "RLCA"
|
|
|
|
|
|
@dataclass
|
|
class RLA(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
a = cpu.get_reg8(R8.A)
|
|
next_carry = (a >> 7) & 1
|
|
cpu.set_reg8(R8.A, ((a << 1) & 0xFF) | cpu.carry)
|
|
cpu.carry = next_carry
|
|
|
|
def pretty(self) -> str:
|
|
return "RLA"
|
|
|
|
|
|
@dataclass
|
|
class RRCA(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
a = cpu.get_reg8(R8.A)
|
|
cpu.carry = a & 1
|
|
cpu.set_reg8(R8.A, (a >> 1) | (cpu.carry << 7))
|
|
|
|
def pretty(self) -> str:
|
|
return "RRCA"
|
|
|
|
|
|
@dataclass
|
|
class RRA(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
a = cpu.get_reg8(R8.A)
|
|
next_carry = a & 1
|
|
cpu.set_reg8(R8.A, (a >> 1) | (cpu.carry << 7))
|
|
cpu.carry = next_carry
|
|
|
|
def pretty(self) -> str:
|
|
return "RRA"
|
|
|
|
|
|
@dataclass
|
|
class RLC_R(Insn):
|
|
r: R8
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
r = cpu.get_reg8(self.r)
|
|
cpu.carry = (r >> 7) & 1
|
|
cpu.set_reg8(self.r, ((r << 1) & 0xFF) | cpu.carry)
|
|
|
|
def pretty(self) -> str:
|
|
return f"RLC {self.r}"
|
|
|
|
|
|
@dataclass
|
|
class RLC_HL(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
hl = cpu.deref_hl()
|
|
cpu.carry = (hl >> 7) & 1
|
|
cpu.deref_hl_set(((hl << 1) & 0xFF) | cpu.carry)
|
|
|
|
def pretty(self) -> str:
|
|
return f"RLC (HL)"
|
|
|
|
|
|
@dataclass
|
|
class RL_R(Insn):
|
|
r: R8
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
r = cpu.get_reg8(self.r)
|
|
next_carry = (r >> 7) & 1
|
|
cpu.set_reg8(self.r, ((r << 1) & 0xFF) | cpu.carry)
|
|
cpu.carry = next_carry
|
|
|
|
def pretty(self) -> str:
|
|
return f"RL {self.r}"
|
|
|
|
|
|
@dataclass
|
|
class RL_HL(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
hl = cpu.deref_hl()
|
|
next_carry = (hl >> 7) & 1
|
|
cpu.deref_hl_set(((hl << 1) & 0xFF) | cpu.carry)
|
|
cpu.carry = next_carry
|
|
|
|
def pretty(self) -> str:
|
|
return "RL (HL)"
|
|
|
|
|
|
@dataclass
|
|
class RRC_R(Insn):
|
|
r: R8
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
r = cpu.get_reg8(self.r)
|
|
cpu.carry = r & 1
|
|
cpu.set_reg8(self.r, (r >> 1) | (cpu.carry << 7))
|
|
|
|
def pretty(self) -> str:
|
|
return f"RRC {self.r}"
|
|
|
|
|
|
@dataclass
|
|
class RRC_HL(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
hl = cpu.deref_hl()
|
|
cpu.carry = hl & 1
|
|
cpu.deref_hl_set((hl >> 1) | (cpu.carry << 7))
|
|
|
|
def pretty(self) -> str:
|
|
return "RRC (HL)"
|
|
|
|
|
|
@dataclass
|
|
class RR_R(Insn):
|
|
r: R8
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
r = cpu.get_reg8(self.r)
|
|
next_carry = r & 1
|
|
cpu.set_reg8(self.r, (r >> 1) | (cpu.carry << 7))
|
|
cpu.carry = next_carry
|
|
|
|
def pretty(self) -> str:
|
|
return f"RR {self.r}"
|
|
|
|
|
|
@dataclass
|
|
class RR_HL(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
hl = cpu.deref_hl()
|
|
next_carry = hl & 1
|
|
cpu.deref_hl_set((hl >> 1) | (cpu.carry << 7))
|
|
cpu.carry = next_carry
|
|
|
|
def pretty(self) -> str:
|
|
return "RR (HL)"
|
|
|
|
|
|
@dataclass
|
|
class SLA_R(Insn):
|
|
r: R8
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
r = cpu.get_reg8(self.r)
|
|
cpu.set_reg8(self.r, (r << 1) & 0xFF)
|
|
|
|
def pretty(self) -> str:
|
|
return f"SLA {self.r}"
|
|
|
|
|
|
@dataclass
|
|
class SLA_HL(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
hl = cpu.deref_hl()
|
|
cpu.deref_hl_set((hl << 1) & 0xFF)
|
|
|
|
def pretty(self) -> str:
|
|
return "SLA (HL)"
|
|
|
|
|
|
@dataclass
|
|
class SWAP_R(Insn):
|
|
r: R8
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
r = cpu.get_reg8(self.r)
|
|
cpu.set_reg8(self.r, ((r << 4) & 0xFF) | (r >> 4))
|
|
|
|
def pretty(self) -> str:
|
|
return f"SWAP {self.r}"
|
|
|
|
|
|
@dataclass
|
|
class SWAP_HL(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
hl = cpu.deref_hl()
|
|
cpu.deref_hl_set(((hl << 4) & 0xFF) | (hl >> 4))
|
|
|
|
def pretty(self) -> str:
|
|
return "SWAP (HL)"
|
|
|
|
|
|
@dataclass
|
|
class SRA_R(Insn):
|
|
r: R8
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
r = cpu.get_reg8(self.r)
|
|
cpu.set_reg8(self.r, (r >> 1) | (r & (1 << 7)))
|
|
|
|
def pretty(self) -> str:
|
|
return f"SRA {self.r}"
|
|
|
|
|
|
@dataclass
|
|
class SRA_HL(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
hl = cpu.deref_hl()
|
|
cpu.deref_hl_set((hl >> 1) | (hl & (1 << 7)))
|
|
|
|
def pretty(self) -> str:
|
|
return "SRA (HL)"
|
|
|
|
|
|
@dataclass
|
|
class SRL_R(Insn):
|
|
r: R8
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
r = cpu.get_reg8(self.r)
|
|
cpu.set_reg8(self.r, r >> 1)
|
|
|
|
def pretty(self) -> str:
|
|
return f"SRL {self.r}"
|
|
|
|
|
|
@dataclass
|
|
class SRL_HL(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
hl = cpu.deref_hl()
|
|
cpu.deref_hl_set(hl >> 1)
|
|
|
|
def pretty(self) -> str:
|
|
return "SRL (HL)"
|
|
|
|
|
|
# TODO: Remaining rotate and shift instructions
|
|
|
|
|
|
@dataclass
|
|
class SET_N_R(Insn):
|
|
n: int
|
|
r: R8
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_reg8(self.r, cpu.get_reg8(self.r) | (1 << self.n))
|
|
|
|
def pretty(self) -> str:
|
|
return f"SET {self.n}, (HL)"
|
|
|
|
|
|
@dataclass
|
|
class SET_N_HL(Insn):
|
|
n: int
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
hl = cpu.get_reg16(R16.HL)
|
|
cpu.set_mem8(hl, cpu.get_mem8(hl) | (1 << self.n))
|
|
|
|
def pretty(self) -> str:
|
|
return f"SET {self.n}, (HL)"
|
|
|
|
|
|
@dataclass
|
|
class RES_N_R(Insn):
|
|
n: int
|
|
r: R8
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.set_reg8(self.r, cpu.get_reg8(self.r) & ~(1 << self.n))
|
|
|
|
def pretty(self) -> str:
|
|
return f"RES {self.n}, (HL)"
|
|
|
|
|
|
@dataclass
|
|
class RES_N_HL(Insn):
|
|
n: int
|
|
|
|
def exec(self, cpu: CPU) -> None:
|
|
hl = cpu.get_reg16(R16.HL)
|
|
cpu.set_mem8(hl, cpu.get_mem8(hl) & ~(1 << self.n))
|
|
|
|
def pretty(self) -> str:
|
|
return f"RES {self.n}, (HL)"
|
|
|
|
|
|
@dataclass
|
|
class CCF(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.carry = cpu.carry ^ 1
|
|
|
|
def pretty(self) -> str:
|
|
return "CCF"
|
|
|
|
|
|
@dataclass
|
|
class SCF(Insn):
|
|
def exec(self, cpu: CPU) -> None:
|
|
cpu.carry = 1
|
|
|
|
def pretty(self) -> str:
|
|
return "SCF"
|