An emulator, assembler, and disassembler for the Sega Game Gear
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 

275 lignes
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