An emulator, assembler, and disassembler for the Sega Game Gear
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.
 
 
 
 
 

275 lines
6.9 KiB

  1. /* Copyright (C) 2014-2019 Ben Kurtovic <ben.kurtovic@gmail.com>
  2. Released under the terms of the MIT License. See LICENSE for details. */
  3. #define POS(x) (!((x) & 0x80))
  4. #define NEG(x) ((x) & 0x80)
  5. #define CARRY(lh, op, rh) (((lh) op (rh)) & 0x100)
  6. #define HALF(lh, op, rh) ((((lh) & 0x0F) op ((rh) & 0x0F)) & 0x10)
  7. #define ZERO(x) ((x) == 0)
  8. #define SIGN(x) NEG(x)
  9. #define SUB 1
  10. #define CARRY2(lh, op, rh) (((lh) op (rh)) & 0x10000)
  11. #define OV_ADD(lh, rh, res) \
  12. (POS(lh) && POS(rh) && NEG(res) || NEG(lh) && NEG(rh) && POS(res))
  13. #define OV_SUB(lh, rh, res) \
  14. (POS(lh) && NEG(rh) && NEG(res) || NEG(lh) && POS(rh) && POS(res))
  15. #define PARITY(x) (!(__builtin_popcount(x) % 2))
  16. #define F3(x) ((x) & 0x08)
  17. #define F5(x) ((x) & 0x20)
  18. /*
  19. Set the flags for an 8-bit ADD or ADC instruction.
  20. */
  21. static inline void set_flags_add8(Z80 *z80, uint16_t rh)
  22. {
  23. uint8_t lh = z80->regs.a;
  24. uint8_t res = lh + rh;
  25. set_flags(z80, CARRY(lh, +, rh), !SUB, OV_ADD(lh, rh, res), F3(res),
  26. HALF(lh, +, rh), F5(res), ZERO(res), SIGN(res), 0xFF);
  27. }
  28. /*
  29. Set the flags for an 8-bit SUB or SBC instruction.
  30. */
  31. static inline void set_flags_sub8(Z80 *z80, uint16_t rh)
  32. {
  33. uint8_t lh = z80->regs.a;
  34. uint8_t res = lh - rh;
  35. set_flags(z80, CARRY(lh, -, rh), SUB, OV_SUB(lh, rh, res), F3(res),
  36. HALF(lh, -, rh), F5(res), ZERO(res), SIGN(res), 0xFF);
  37. }
  38. /*
  39. Set the flags for a CP instruction.
  40. */
  41. static inline void set_flags_cp(Z80 *z80, uint16_t rh)
  42. {
  43. uint8_t lh = z80->regs.a;
  44. uint8_t res = lh - rh;
  45. set_flags(z80, CARRY(lh, -, rh), SUB, OV_SUB(lh, rh, res), F3(rh),
  46. HALF(lh, -, rh), F5(rh), ZERO(res), SIGN(res), 0xFF);
  47. }
  48. /*
  49. Set the flags for an AND, XOR, or OR instruction.
  50. */
  51. static inline void set_flags_bitwise(Z80 *z80, uint8_t res, bool is_and)
  52. {
  53. set_flags(z80, 0, 0, PARITY(res), F3(res), is_and, F5(res), ZERO(res),
  54. SIGN(res), 0xFF);
  55. }
  56. /*
  57. Set the flags for an 8-bit INC instruction.
  58. */
  59. static inline void set_flags_inc(Z80 *z80, uint8_t val)
  60. {
  61. uint8_t res = val + 1;
  62. set_flags(z80, 0, !SUB, OV_ADD(val, 1, res), F3(res), HALF(val, +, 1),
  63. F5(res), ZERO(res), SIGN(res), 0xFE);
  64. }
  65. /*
  66. Set the flags for an 8-bit DEC instruction.
  67. */
  68. static inline void set_flags_dec(Z80 *z80, uint8_t val)
  69. {
  70. uint8_t res = val - 1;
  71. set_flags(z80, 0, SUB, OV_SUB(val, 1, res), F3(res), HALF(val, -, 1),
  72. F5(res), ZERO(res), SIGN(res), 0xFE);
  73. }
  74. /*
  75. Set the flags for a 16-bit ADD instruction.
  76. */
  77. static inline void set_flags_add16(Z80 *z80, uint16_t lh, uint16_t rh)
  78. {
  79. uint16_t res = lh + rh;
  80. set_flags(z80, CARRY2(lh, +, rh), !SUB, 0, F3(res >> 8),
  81. HALF(lh >> 8, +, rh >> 8), F5(res >> 8), 0, 0, 0x3B);
  82. }
  83. /*
  84. Set the flags for a 16-bit ADC instruction.
  85. */
  86. static inline void set_flags_adc16(Z80 *z80, uint16_t lh, uint32_t rh)
  87. {
  88. uint16_t res = lh + rh;
  89. set_flags(z80, CARRY2(lh, +, rh), !SUB, OV_ADD(lh >> 8, rh >> 8, res >> 8),
  90. F3(res >> 8), HALF(lh >> 8, +, rh >> 8), F5(res >> 8), ZERO(res),
  91. SIGN(res >> 8), 0xFF);
  92. }
  93. /*
  94. Set the flags for a 16-bit SBC instruction.
  95. */
  96. static inline void set_flags_sbc16(Z80 *z80, uint16_t lh, uint32_t rh)
  97. {
  98. uint16_t res = lh - rh;
  99. set_flags(z80, CARRY2(lh, -, rh), SUB, OV_SUB(lh >> 8, rh >> 8, res >> 8),
  100. F3(res >> 8), HALF(lh >> 8, -, rh >> 8), F5(res >> 8), ZERO(res),
  101. SIGN(res >> 8), 0xFF);
  102. }
  103. /*
  104. Set the flags for a BIT instruction.
  105. */
  106. static inline void set_flags_bit(Z80 *z80, uint8_t val, uint8_t bit)
  107. {
  108. bool z = ZERO((val >> bit) & 1);
  109. if (z)
  110. set_flags(z80, 0, 0, z, 0, 1, 0, z, 0, 0xFE);
  111. else
  112. set_flags(z80, 0, 0, z, bit == 3, 1, bit == 5, z, bit == 7, 0xFE);
  113. }
  114. /*
  115. Set the flags for a RLCA/RLA/RRCA/RRA instruction.
  116. */
  117. static inline void set_flags_bitrota(Z80 *z80, uint8_t bit)
  118. {
  119. uint8_t a = z80->regs.a;
  120. set_flags(z80, bit, 0, 0, F3(a), 0, F5(a), 0, 0, 0x3B);
  121. }
  122. /*
  123. Set the flags for a RLC/RL/RRC/RR/SLA/SRA/SL1/SRL instruction.
  124. */
  125. static inline void set_flags_bitshift(Z80 *z80, uint8_t res, uint8_t bit)
  126. {
  127. set_flags(z80, bit, 0, PARITY(res), F3(res), 0, F5(res), ZERO(res),
  128. SIGN(res), 0xFF);
  129. }
  130. /*
  131. Set the flags for a RLD or RRD instruction.
  132. */
  133. static inline void set_flags_rd(Z80 *z80)
  134. {
  135. uint8_t a = z80->regs.a;
  136. set_flags(z80, 0, 0, PARITY(a), F3(a), 0, F5(a), ZERO(a), SIGN(a), 0xFE);
  137. }
  138. /*
  139. Set the flags for a DAA instruction.
  140. */
  141. static inline void set_flags_daa(Z80 *z80, uint8_t old, uint8_t adjust)
  142. {
  143. uint8_t res = z80->regs.a;
  144. bool c = adjust >= 0x60;
  145. bool h = get_flag(z80, FLAG_SUBTRACT) ?
  146. (get_flag(z80, FLAG_HALFCARRY) && (old & 0x0F) < 0x06) :
  147. ((old & 0x0F) > 0x09);
  148. set_flags(z80, c, 0, PARITY(res), F3(res), h, F5(res), ZERO(res),
  149. SIGN(res), 0xFD);
  150. }
  151. /*
  152. Set the flags for a CPL instruction.
  153. */
  154. static inline void set_flags_cpl(Z80 *z80)
  155. {
  156. uint8_t res = z80->regs.a;
  157. set_flags(z80, 0, 1, 0, F3(res), 1, F5(res), 0, 0, 0x3A);
  158. }
  159. /*
  160. Set the flags for a NEG instruction.
  161. */
  162. static inline void set_flags_neg(Z80 *z80)
  163. {
  164. uint8_t res = z80->regs.a;
  165. uint8_t val = -res;
  166. set_flags(z80, CARRY(0, -, val), SUB, OV_SUB(0, val, res), F3(res),
  167. HALF(0, -, val), F5(res), ZERO(res), SIGN(res), 0xFF);
  168. }
  169. /*
  170. Set the flags for a CCF instruction.
  171. */
  172. static inline void set_flags_ccf(Z80 *z80)
  173. {
  174. uint8_t val = z80->regs.a;
  175. bool c = get_flag(z80, FLAG_CARRY);
  176. set_flags(z80, 1 - c, 0, 0, F3(val), c, F5(val), 0, 0, 0x3B);
  177. }
  178. /*
  179. Set the flags for a SCF instruction.
  180. */
  181. static inline void set_flags_scf(Z80 *z80)
  182. {
  183. uint8_t val = z80->regs.a;
  184. set_flags(z80, 1, 0, 0, F3(val), 0, F5(val), 0, 0, 0x3B);
  185. }
  186. /*
  187. Set the flags for a LD A, I/R instruction.
  188. */
  189. static inline void set_flags_ld_a_ir(Z80 *z80)
  190. {
  191. uint8_t val = z80->regs.a;
  192. set_flags(z80, 0, 0, z80->regs.iff2, F3(val), 0, F5(val), ZERO(val), SIGN(val), 0xFE);
  193. }
  194. /*
  195. Set the flags for a LDI/LDIR/LDD/LDDR instruction.
  196. */
  197. static inline void set_flags_blockxfer(Z80 *z80, uint8_t val)
  198. {
  199. bool pv = z80->regs.bc != 0;
  200. uint8_t res = val + z80->regs.a;
  201. set_flags(z80, 0, 0, pv, res & 0x08, 0, res & 0x02, 0, 0, 0x3E);
  202. }
  203. /*
  204. Set the flags for a CPI/CPIR/CPD/CPDR instruction.
  205. */
  206. static inline void set_flags_blockcp(Z80 *z80, uint16_t rh)
  207. {
  208. uint8_t lh = z80->regs.a;
  209. bool pv = z80->regs.bc != 0;
  210. bool h = HALF(lh, -, rh);
  211. uint8_t res = lh - rh;
  212. uint8_t resh = res - h;
  213. set_flags(z80, 0, 1, pv, F3(resh), h, F5(resh), ZERO(res), SIGN(res), 0xFE);
  214. }
  215. /*
  216. Set the flags for an IN instruction.
  217. */
  218. static inline void set_flags_in(Z80 *z80, uint8_t val)
  219. {
  220. set_flags(z80, 0, 0, PARITY(val), F3(val), 0, F5(val), ZERO(val),
  221. SIGN(val), 0xFE);
  222. }
  223. /*
  224. Set the flags for an INI/INIR/IND/INDR/OUTI/OTIR/OUTD/OTDR instruction.
  225. */
  226. static inline void set_flags_blockio(Z80 *z80)
  227. {
  228. set_flags_dec(z80, z80->regs.b);
  229. }
  230. #undef POS
  231. #undef NEG
  232. #undef CARRY
  233. #undef HALF
  234. #undef ZERO
  235. #undef SIGN
  236. #undef SUB
  237. #undef CARRY2
  238. #undef OV_ADD
  239. #undef OV_SUB
  240. #undef PARITY
  241. #undef F3
  242. #undef F5