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.
 
 
 
 
 

162 lines
4.3 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. #undef POS
  131. #undef NEG
  132. #undef CARRY
  133. #undef HALF
  134. #undef ZERO
  135. #undef SIGN
  136. #undef SUB
  137. #undef CARRY2
  138. #undef OV_ADD
  139. #undef OV_SUB
  140. #undef PARITY
  141. #undef F3
  142. #undef F5