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.
 
 
 
 
 

173 lignes
4.5 KiB

  1. /* Copyright (C) 2014-2016 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 NEG instruction.
  132. */
  133. static inline void set_flags_neg(Z80 *z80)
  134. {
  135. uint8_t val = z80->regs.a;
  136. uint8_t res = -val;
  137. set_flags(z80, CARRY(0, -, val), SUB, OV_SUB(0, val, res), F3(res),
  138. HALF(0, -, val), F5(res), ZERO(res), SIGN(res), 0xFF);
  139. }
  140. #undef POS
  141. #undef NEG
  142. #undef CARRY
  143. #undef HALF
  144. #undef ZERO
  145. #undef SIGN
  146. #undef SUB
  147. #undef CARRY2
  148. #undef OV_ADD
  149. #undef OV_SUB
  150. #undef PARITY
  151. #undef F3
  152. #undef F5