gameboy superoptimizer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

869 lines
18 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. from abc import ABC, abstractmethod
  2. from dataclasses import dataclass
  3. from gbso.cpu import CPU
  4. from gbso.regs import R16, R8
  5. class Insn(ABC):
  6. @abstractmethod
  7. def exec(self, cpu: CPU) -> None:
  8. pass
  9. # TODO: Make abstract once all subclasses implement
  10. def pretty(self) -> str:
  11. return ""
  12. @dataclass
  13. class LD_R_R(Insn):
  14. dst: R8
  15. src: R8
  16. def exec(self, cpu: CPU) -> None:
  17. cpu.set_reg8(self.dst, cpu.get_reg8(self.src))
  18. cpu.cycles += 4
  19. def pretty(self) -> str:
  20. return f"LD {self.dst}, {self.src}"
  21. @dataclass
  22. class LD_R_N8(Insn):
  23. dst: R8
  24. imm: int
  25. def exec(self, cpu: CPU) -> None:
  26. cpu.set_reg8(self.dst, self.imm)
  27. cpu.cycles += 8
  28. def pretty(self) -> str:
  29. return f"LD {self.dst}, {hex(self.imm)}"
  30. @dataclass
  31. class LD_R_HL(Insn):
  32. dst: R8
  33. def exec(self, cpu: CPU) -> None:
  34. cpu.set_reg8(self.dst, cpu.get_mem8(cpu.get_reg16(R16.HL)))
  35. cpu.cycles += 8
  36. def pretty(self) -> str:
  37. return f"LD {self.dst}, (HL)"
  38. @dataclass
  39. class LD_HL_R(Insn):
  40. src: R8
  41. def exec(self, cpu: CPU) -> None:
  42. cpu.deref_hl_set(cpu.get_reg8(self.src))
  43. cpu.cycles += 8
  44. def pretty(self) -> str:
  45. return f"LD (HL), {self.src}"
  46. @dataclass
  47. class LD_HL_N(Insn):
  48. imm: int
  49. def exec(self, cpu: CPU) -> None:
  50. cpu.set_mem8(cpu.get_reg16(R16.HL), self.imm)
  51. cpu.cycles += 12
  52. def pretty(self) -> str:
  53. return f"LD (HL), {hex(self.imm & 0xff)}"
  54. @dataclass
  55. class LD_A_BC(Insn):
  56. def exec(self, cpu: CPU) -> None:
  57. cpu.set_reg8(R8.A, cpu.get_mem8(cpu.get_reg16(R16.BC)))
  58. cpu.cycles += 8
  59. def pretty(self) -> str:
  60. return "LD A, (BC)"
  61. @dataclass
  62. class LD_A_DE(Insn):
  63. def exec(self, cpu: CPU) -> None:
  64. cpu.set_reg8(R8.A, cpu.get_mem8(cpu.get_reg16(R16.DE)))
  65. cpu.cycles += 8
  66. def pretty(self) -> str:
  67. return "LD A, (DE)"
  68. @dataclass
  69. class LD_A_NN(Insn):
  70. nn: int
  71. def exec(self, cpu: CPU) -> None:
  72. cpu.set_reg8(R8.A, cpu.get_mem8(self.nn))
  73. cpu.cycles += 16
  74. def pretty(self) -> str:
  75. return f"LD A, ({hex(self.nn)})"
  76. @dataclass
  77. class LD_BC_A(Insn):
  78. def exec(self, cpu: CPU) -> None:
  79. cpu.set_mem8(cpu.get_reg16(R16.BC), cpu.get_reg8(R8.A))
  80. cpu.cycles += 8
  81. def pretty(self) -> str:
  82. return "LD (BC), A"
  83. @dataclass
  84. class LD_DE_A(Insn):
  85. def exec(self, cpu: CPU) -> None:
  86. cpu.set_mem8(cpu.get_reg16(R16.DE), cpu.get_reg8(R8.A))
  87. cpu.cycles += 8
  88. def pretty(self) -> str:
  89. return "LD (DE), A"
  90. @dataclass
  91. class LD_NN_A(Insn):
  92. nn: int
  93. def exec(self, cpu: CPU) -> None:
  94. cpu.set_mem8(self.nn, cpu.get_reg8(R8.A))
  95. cpu.cycles += 16
  96. def pretty(self) -> str:
  97. return f"LD ({hex(self.nn)}), A"
  98. @dataclass
  99. class LD_A_FF_N(Insn):
  100. n: int
  101. def exec(self, cpu: CPU) -> None:
  102. cpu.set_reg8(R8.A, cpu.get_mem8(0xFF00 + self.n))
  103. cpu.cycles += 12
  104. def pretty(self) -> str:
  105. return f"LD A, (0xFF00 + {hex(self.n)})"
  106. @dataclass
  107. class LD_FF_N_A(Insn):
  108. n: int
  109. def exec(self, cpu: CPU) -> None:
  110. cpu.set_mem8(0xFF00 + self.n, cpu.get_reg8(R8.A))
  111. cpu.cycles += 12
  112. def pretty(self) -> str:
  113. return f"LD (0xFF00 + {hex(self.n)}), A"
  114. @dataclass
  115. class LD_A_FF_C(Insn):
  116. def exec(self, cpu: CPU) -> None:
  117. cpu.set_reg8(R8.A, cpu.get_mem8(0xFF00 + cpu.get_reg8(R8.C)))
  118. cpu.cycles += 8
  119. def pretty(self) -> str:
  120. return "LD A, (0xFF00 + C)"
  121. @dataclass
  122. class LD_FF_C_A(Insn):
  123. def exec(self, cpu: CPU) -> None:
  124. cpu.set_mem8(0xFF00 + cpu.get_reg8(R8.C), cpu.get_reg8(R8.A))
  125. cpu.cycles += 8
  126. def pretty(self) -> str:
  127. return "LD (0xFF00 + C), A"
  128. @dataclass
  129. class LDI_HL_A(Insn):
  130. def exec(self, cpu: CPU) -> None:
  131. hl = cpu.get_reg16(R16.HL)
  132. cpu.set_mem8(hl, cpu.get_reg8(R8.A))
  133. cpu.set_reg16(R16.HL, hl + 1)
  134. cpu.cycles += 8
  135. def pretty(self) -> str:
  136. return "LDI (HL), A"
  137. @dataclass
  138. class LDI_A_HL(Insn):
  139. def exec(self, cpu: CPU) -> None:
  140. hl = cpu.get_reg16(R16.HL)
  141. cpu.set_reg8(R8.A, cpu.get_mem8(hl))
  142. cpu.set_reg16(R16.HL, hl + 1)
  143. cpu.cycles += 8
  144. def pretty(self) -> str:
  145. return "LDI A, (HL)"
  146. @dataclass
  147. class LDD_HL_A(Insn):
  148. def exec(self, cpu: CPU) -> None:
  149. hl = cpu.get_reg16(R16.HL)
  150. cpu.set_mem8(hl, cpu.get_reg8(R8.A))
  151. cpu.set_reg16(R16.HL, hl - 1)
  152. cpu.cycles += 8
  153. def pretty(self) -> str:
  154. return "LDD (HL), A"
  155. @dataclass
  156. class LDD_A_HL(Insn):
  157. def exec(self, cpu: CPU) -> None:
  158. hl = cpu.get_reg16(R16.HL)
  159. cpu.set_reg8(R8.A, cpu.get_mem8(hl))
  160. cpu.set_reg16(R16.HL, hl - 1)
  161. cpu.cycles += 8
  162. def pretty(self) -> str:
  163. return "LDD A, (HL)"
  164. @dataclass
  165. class LD_RR_NN(Insn):
  166. rr: R16
  167. nn: int
  168. def exec(self, cpu: CPU) -> None:
  169. cpu.set_reg16(self.rr, self.nn)
  170. def pretty(self) -> str:
  171. return f"LD {self.rr.value}, {hex(self.nn)}"
  172. @dataclass
  173. class LD_NN_SP(Insn):
  174. nn: int
  175. def exec(self, cpu: CPU) -> None:
  176. cpu.set_mem16(self.nn, cpu.get_reg16(R16.SP))
  177. @dataclass
  178. class LD_SP_HL(Insn):
  179. def exec(self, cpu: CPU) -> None:
  180. cpu.set_reg16(R16.SP, cpu.get_reg16(R16.HL))
  181. @dataclass
  182. class PUSH_RR(Insn):
  183. rr: R16
  184. def exec(self, cpu: CPU) -> None:
  185. sp = cpu.get_reg16(R16.SP)
  186. cpu.set_reg16(R16.SP, sp - 2)
  187. cpu.set_mem16(sp - 2, cpu.get_reg16(self.rr))
  188. @dataclass
  189. class POP_RR(Insn):
  190. rr: R16
  191. def exec(self, cpu: CPU) -> None:
  192. sp = cpu.get_reg16(R16.SP)
  193. cpu.set_reg16(self.rr, cpu.get_mem16(sp))
  194. cpu.set_reg16(R16.SP, sp + 2)
  195. @dataclass
  196. class ADD_A_R(Insn):
  197. r: R8
  198. def exec(self, cpu: CPU) -> None:
  199. a = cpu.get_reg8(R8.A) + cpu.get_reg8(self.r)
  200. cpu.carry = 1 if a > 0xFF else 0
  201. cpu.set_reg8(R8.A, a)
  202. @dataclass
  203. class ADD_A_N(Insn):
  204. n: int
  205. def exec(self, cpu: CPU) -> None:
  206. a = cpu.get_reg8(R8.A) + self.n
  207. cpu.carry = 1 if a > 0xFF else 0
  208. cpu.set_reg8(R8.A, a)
  209. @dataclass
  210. class ADD_A_HL(Insn):
  211. def exec(self, cpu: CPU) -> None:
  212. a = cpu.get_reg8(R8.A) + cpu.get_mem8(cpu.get_reg16(R16.HL))
  213. cpu.carry = 1 if a > 0xFF else 0
  214. cpu.set_reg8(R8.A, a)
  215. @dataclass
  216. class ADC_A_R(Insn):
  217. r: R8
  218. def exec(self, cpu: CPU) -> None:
  219. a = cpu.get_reg8(R8.A) + cpu.get_reg8(self.r) + cpu.carry
  220. cpu.carry = 1 if a > 0xFF else 0
  221. cpu.set_reg8(R8.A, a)
  222. @dataclass
  223. class ADC_A_N(Insn):
  224. n: int
  225. def exec(self, cpu: CPU) -> None:
  226. a = cpu.get_reg8(R8.A) + self.n + cpu.carry
  227. cpu.carry = 1 if a > 0xFF else 0
  228. cpu.set_reg8(R8.A, a)
  229. @dataclass
  230. class ADC_A_HL(Insn):
  231. def exec(self, cpu: CPU) -> None:
  232. a = cpu.get_reg8(R8.A) + cpu.get_mem8(cpu.get_reg16(R16.HL)) + cpu.carry
  233. cpu.carry = 1 if a > 0xFF else 0
  234. cpu.set_reg8(R8.A, a)
  235. @dataclass
  236. class SUB_A_R(Insn):
  237. r: R8
  238. def exec(self, cpu: CPU) -> None:
  239. a = cpu.get_reg8(R8.A) - cpu.get_reg8(self.r)
  240. cpu.carry = 1 if a < 0 else 0
  241. cpu.set_reg8(R8.A, a)
  242. @dataclass
  243. class SUB_A_N(Insn):
  244. n: int
  245. def exec(self, cpu: CPU) -> None:
  246. a = cpu.get_reg8(R8.A) - self.n
  247. cpu.carry = 1 if a < 0 else 0
  248. cpu.set_reg8(R8.A, a)
  249. @dataclass
  250. class SUB_A_HL(Insn):
  251. def exec(self, cpu: CPU) -> None:
  252. a = cpu.get_reg8(R8.A) - cpu.get_mem8(cpu.get_reg16(R16.HL))
  253. cpu.carry = 1 if a < 0 else 0
  254. cpu.set_reg8(R8.A, a)
  255. @dataclass
  256. class SBC_A_R(Insn):
  257. r: R8
  258. def exec(self, cpu: CPU) -> None:
  259. a = cpu.get_reg8(R8.A) - cpu.get_reg8(self.r) - cpu.carry
  260. cpu.carry = 1 if a < 0 else 0
  261. cpu.set_reg8(R8.A, a)
  262. @dataclass
  263. class SBC_A_N(Insn):
  264. n: int
  265. def exec(self, cpu: CPU) -> None:
  266. a = cpu.get_reg8(R8.A) - self.n - cpu.carry
  267. cpu.carry = 1 if a < 0 else 0
  268. cpu.set_reg8(R8.A, a)
  269. @dataclass
  270. class SBC_A_HL(Insn):
  271. def exec(self, cpu: CPU) -> None:
  272. a = cpu.get_reg8(R8.A) - cpu.get_mem8(cpu.get_reg16(R16.HL)) - cpu.carry
  273. cpu.carry = 1 if a < 0 else 0
  274. cpu.set_reg8(R8.A, a)
  275. @dataclass
  276. class AND_A_R(Insn):
  277. r: R8
  278. def exec(self, cpu: CPU) -> None:
  279. a = cpu.get_reg8(R8.A) & cpu.get_reg8(self.r)
  280. cpu.set_reg8(R8.A, a)
  281. cpu.carry = 0
  282. @dataclass
  283. class AND_A_N(Insn):
  284. n: int
  285. def exec(self, cpu: CPU) -> None:
  286. a = cpu.get_reg8(R8.A) & self.n
  287. cpu.set_reg8(R8.A, a)
  288. cpu.carry = 0
  289. @dataclass
  290. class AND_A_HL(Insn):
  291. def exec(self, cpu: CPU) -> None:
  292. a = cpu.get_reg8(R8.A) & cpu.get_mem8(cpu.get_reg16(R16.HL))
  293. cpu.set_reg8(R8.A, a)
  294. cpu.carry = 0
  295. def pretty(self) -> str:
  296. return "AND A, (HL)"
  297. @dataclass
  298. class CP_A_R(Insn):
  299. r: R8
  300. def exec(self, cpu: CPU) -> None:
  301. cpu.carry = 1 if cpu.get_reg8(R8.A) < cpu.get_reg8(self.r) else 0
  302. def pretty(self) -> str:
  303. return f"CP A, {self.r.value}"
  304. @dataclass
  305. class CP_A_N(Insn):
  306. n: int
  307. def exec(self, cpu: CPU) -> None:
  308. cpu.carry = 1 if cpu.get_reg8(R8.A) < self.n else 0
  309. def pretty(self) -> str:
  310. return f"CP A, {hex(self.n)}"
  311. @dataclass
  312. class CP_A_HL(Insn):
  313. def exec(self, cpu: CPU) -> None:
  314. cpu.carry = 1 if cpu.get_reg8(R8.A) < cpu.get_mem8(cpu.get_reg16(R16.HL)) else 0
  315. def pretty(self) -> str:
  316. return "CP A, (HL)"
  317. @dataclass
  318. class INC_R(Insn):
  319. r: R8
  320. def exec(self, cpu: CPU) -> None:
  321. cpu.set_reg8(self.r, cpu.get_reg8(self.r) + 1)
  322. def pretty(self) -> str:
  323. return f"INC {self.r.value}"
  324. @dataclass
  325. class INC_HL(Insn):
  326. r: R8
  327. def exec(self, cpu: CPU) -> None:
  328. hl = cpu.get_reg16(R16.HL)
  329. cpu.set_mem8(hl, cpu.get_mem8(hl) + 1)
  330. def pretty(self) -> str:
  331. return "INC (HL)"
  332. @dataclass
  333. class DEC_R(Insn):
  334. r: R8
  335. def exec(self, cpu: CPU) -> None:
  336. cpu.set_reg8(self.r, cpu.get_reg8(self.r) - 1)
  337. def pretty(self) -> str:
  338. return f"DEC {self.r.value}"
  339. @dataclass
  340. class DEC_HL(Insn):
  341. r: R8
  342. def exec(self, cpu: CPU) -> None:
  343. hl = cpu.get_reg16(R16.HL)
  344. cpu.set_mem8(hl, cpu.get_mem8(hl) - 1)
  345. def pretty(self) -> str:
  346. return "DEC (HL)"
  347. @dataclass
  348. class CPL(Insn):
  349. def exec(self, cpu: CPU) -> None:
  350. cpu.set_reg8(R8.A, cpu.get_reg8(R8.A) ^ 0xFF)
  351. @dataclass
  352. class ADD_HL_RR(Insn):
  353. rr: R16
  354. def exec(self, cpu: CPU) -> None:
  355. hl = cpu.get_reg16(R16.HL) + cpu.get_reg16(self.rr)
  356. cpu.carry = 1 if hl > 0xFFFF else 0
  357. cpu.set_reg16(R16.HL, hl)
  358. def pretty(self) -> str:
  359. return f"ADD HL, {self.rr.value}"
  360. @dataclass
  361. class INC_RR(Insn):
  362. rr: R16
  363. def exec(self, cpu: CPU) -> None:
  364. cpu.set_reg16(self.rr, cpu.get_reg16(self.rr) + 1)
  365. def pretty(self) -> str:
  366. return f"INC {self.rr.value}"
  367. @dataclass
  368. class DEC_RR(Insn):
  369. rr: R16
  370. def exec(self, cpu: CPU) -> None:
  371. cpu.set_reg16(self.rr, cpu.get_reg16(self.rr) - 1)
  372. def pretty(self) -> str:
  373. return f"DEC {self.rr.value}"
  374. @dataclass
  375. class ADD_SP_DD(Insn):
  376. dd: int
  377. def exec(self, cpu: CPU) -> None:
  378. sp = cpu.get_reg16(R16.SP) + self.dd
  379. cpu.carry = 1 if sp > 0xFFFF or sp < 0 else 0
  380. cpu.set_reg16(R16.SP, sp)
  381. def pretty(self) -> str:
  382. return f"ADD SP, {self.dd}"
  383. @dataclass
  384. class LD_HL_SP_DD(Insn):
  385. dd: int
  386. def exec(self, cpu: CPU) -> None:
  387. sp = cpu.get_reg16(R16.SP) + self.dd
  388. cpu.carry = 1 if sp > 0xFFFF or sp < 0 else 0
  389. cpu.set_reg16(R16.HL, sp)
  390. def pretty(self) -> str:
  391. return f"LD HL, SP + {self.dd}"
  392. @dataclass
  393. class RLCA(Insn):
  394. def exec(self, cpu: CPU) -> None:
  395. a = cpu.get_reg8(R8.A)
  396. cpu.carry = (a >> 7) & 1
  397. cpu.set_reg8(R8.A, ((a << 1) & 0xFF) | cpu.carry)
  398. def pretty(self) -> str:
  399. return "RLCA"
  400. @dataclass
  401. class RLA(Insn):
  402. def exec(self, cpu: CPU) -> None:
  403. a = cpu.get_reg8(R8.A)
  404. next_carry = (a >> 7) & 1
  405. cpu.set_reg8(R8.A, ((a << 1) & 0xFF) | cpu.carry)
  406. cpu.carry = next_carry
  407. def pretty(self) -> str:
  408. return "RLA"
  409. @dataclass
  410. class RRCA(Insn):
  411. def exec(self, cpu: CPU) -> None:
  412. a = cpu.get_reg8(R8.A)
  413. cpu.carry = a & 1
  414. cpu.set_reg8(R8.A, (a >> 1) | (cpu.carry << 7))
  415. def pretty(self) -> str:
  416. return "RRCA"
  417. @dataclass
  418. class RRA(Insn):
  419. def exec(self, cpu: CPU) -> None:
  420. a = cpu.get_reg8(R8.A)
  421. next_carry = a & 1
  422. cpu.set_reg8(R8.A, (a >> 1) | (cpu.carry << 7))
  423. cpu.carry = next_carry
  424. def pretty(self) -> str:
  425. return "RRA"
  426. @dataclass
  427. class RLC_R(Insn):
  428. r: R8
  429. def exec(self, cpu: CPU) -> None:
  430. r = cpu.get_reg8(self.r)
  431. cpu.carry = (r >> 7) & 1
  432. cpu.set_reg8(self.r, ((r << 1) & 0xFF) | cpu.carry)
  433. def pretty(self) -> str:
  434. return f"RLC {self.r}"
  435. @dataclass
  436. class RLC_HL(Insn):
  437. def exec(self, cpu: CPU) -> None:
  438. hl = cpu.deref_hl()
  439. cpu.carry = (hl >> 7) & 1
  440. cpu.deref_hl_set(((hl << 1) & 0xFF) | cpu.carry)
  441. def pretty(self) -> str:
  442. return f"RLC (HL)"
  443. @dataclass
  444. class RL_R(Insn):
  445. r: R8
  446. def exec(self, cpu: CPU) -> None:
  447. r = cpu.get_reg8(self.r)
  448. next_carry = (r >> 7) & 1
  449. cpu.set_reg8(self.r, ((r << 1) & 0xFF) | cpu.carry)
  450. cpu.carry = next_carry
  451. def pretty(self) -> str:
  452. return f"RL {self.r}"
  453. @dataclass
  454. class RL_HL(Insn):
  455. def exec(self, cpu: CPU) -> None:
  456. hl = cpu.deref_hl()
  457. next_carry = (hl >> 7) & 1
  458. cpu.deref_hl_set(((hl << 1) & 0xFF) | cpu.carry)
  459. cpu.carry = next_carry
  460. def pretty(self) -> str:
  461. return "RL (HL)"
  462. @dataclass
  463. class RRC_R(Insn):
  464. r: R8
  465. def exec(self, cpu: CPU) -> None:
  466. r = cpu.get_reg8(self.r)
  467. cpu.carry = r & 1
  468. cpu.set_reg8(self.r, (r >> 1) | (cpu.carry << 7))
  469. def pretty(self) -> str:
  470. return f"RRC {self.r}"
  471. @dataclass
  472. class RRC_HL(Insn):
  473. def exec(self, cpu: CPU) -> None:
  474. hl = cpu.deref_hl()
  475. cpu.carry = hl & 1
  476. cpu.deref_hl_set((hl >> 1) | (cpu.carry << 7))
  477. def pretty(self) -> str:
  478. return "RRC (HL)"
  479. @dataclass
  480. class RR_R(Insn):
  481. r: R8
  482. def exec(self, cpu: CPU) -> None:
  483. r = cpu.get_reg8(self.r)
  484. next_carry = r & 1
  485. cpu.set_reg8(self.r, (r >> 1) | (cpu.carry << 7))
  486. cpu.carry = next_carry
  487. def pretty(self) -> str:
  488. return f"RR {self.r}"
  489. @dataclass
  490. class RR_HL(Insn):
  491. def exec(self, cpu: CPU) -> None:
  492. hl = cpu.deref_hl()
  493. next_carry = hl & 1
  494. cpu.deref_hl_set((hl >> 1) | (cpu.carry << 7))
  495. cpu.carry = next_carry
  496. def pretty(self) -> str:
  497. return "RR (HL)"
  498. @dataclass
  499. class SLA_R(Insn):
  500. r: R8
  501. def exec(self, cpu: CPU) -> None:
  502. r = cpu.get_reg8(self.r)
  503. cpu.set_reg8(self.r, (r << 1) & 0xFF)
  504. def pretty(self) -> str:
  505. return f"SLA {self.r}"
  506. @dataclass
  507. class SLA_HL(Insn):
  508. def exec(self, cpu: CPU) -> None:
  509. hl = cpu.deref_hl()
  510. cpu.deref_hl_set((hl << 1) & 0xFF)
  511. def pretty(self) -> str:
  512. return "SLA (HL)"
  513. @dataclass
  514. class SWAP_R(Insn):
  515. r: R8
  516. def exec(self, cpu: CPU) -> None:
  517. r = cpu.get_reg8(self.r)
  518. cpu.set_reg8(self.r, ((r << 4) & 0xFF) | (r >> 4))
  519. def pretty(self) -> str:
  520. return f"SWAP {self.r}"
  521. @dataclass
  522. class SWAP_HL(Insn):
  523. def exec(self, cpu: CPU) -> None:
  524. hl = cpu.deref_hl()
  525. cpu.deref_hl_set(((hl << 4) & 0xFF) | (hl >> 4))
  526. def pretty(self) -> str:
  527. return "SWAP (HL)"
  528. @dataclass
  529. class SRA_R(Insn):
  530. r: R8
  531. def exec(self, cpu: CPU) -> None:
  532. r = cpu.get_reg8(self.r)
  533. cpu.set_reg8(self.r, (r >> 1) | (r & (1 << 7)))
  534. def pretty(self) -> str:
  535. return f"SRA {self.r}"
  536. @dataclass
  537. class SRA_HL(Insn):
  538. def exec(self, cpu: CPU) -> None:
  539. hl = cpu.deref_hl()
  540. cpu.deref_hl_set((hl >> 1) | (hl & (1 << 7)))
  541. def pretty(self) -> str:
  542. return "SRA (HL)"
  543. @dataclass
  544. class SRL_R(Insn):
  545. r: R8
  546. def exec(self, cpu: CPU) -> None:
  547. r = cpu.get_reg8(self.r)
  548. cpu.set_reg8(self.r, r >> 1)
  549. def pretty(self) -> str:
  550. return f"SRL {self.r}"
  551. @dataclass
  552. class SRL_HL(Insn):
  553. def exec(self, cpu: CPU) -> None:
  554. hl = cpu.deref_hl()
  555. cpu.deref_hl_set(hl >> 1)
  556. def pretty(self) -> str:
  557. return "SRL (HL)"
  558. # TODO: Remaining rotate and shift instructions
  559. @dataclass
  560. class SET_N_R(Insn):
  561. n: int
  562. r: R8
  563. def exec(self, cpu: CPU) -> None:
  564. cpu.set_reg8(self.r, cpu.get_reg8(self.r) | (1 << self.n))
  565. def pretty(self) -> str:
  566. return f"SET {self.n}, (HL)"
  567. @dataclass
  568. class SET_N_HL(Insn):
  569. n: int
  570. def exec(self, cpu: CPU) -> None:
  571. hl = cpu.get_reg16(R16.HL)
  572. cpu.set_mem8(hl, cpu.get_mem8(hl) | (1 << self.n))
  573. def pretty(self) -> str:
  574. return f"SET {self.n}, (HL)"
  575. @dataclass
  576. class RES_N_R(Insn):
  577. n: int
  578. r: R8
  579. def exec(self, cpu: CPU) -> None:
  580. cpu.set_reg8(self.r, cpu.get_reg8(self.r) & ~(1 << self.n))
  581. def pretty(self) -> str:
  582. return f"RES {self.n}, (HL)"
  583. @dataclass
  584. class RES_N_HL(Insn):
  585. n: int
  586. def exec(self, cpu: CPU) -> None:
  587. hl = cpu.get_reg16(R16.HL)
  588. cpu.set_mem8(hl, cpu.get_mem8(hl) & ~(1 << self.n))
  589. def pretty(self) -> str:
  590. return f"RES {self.n}, (HL)"
  591. @dataclass
  592. class CCF(Insn):
  593. def exec(self, cpu: CPU) -> None:
  594. cpu.carry = cpu.carry ^ 1
  595. def pretty(self) -> str:
  596. return "CCF"
  597. @dataclass
  598. class SCF(Insn):
  599. def exec(self, cpu: CPU) -> None:
  600. cpu.carry = 1
  601. def pretty(self) -> str:
  602. return "SCF"