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.
 
 
 
 
 

101 lines
2.6 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 OV_ADD(lh, rh, res) \
  11. (POS(lh) && POS(rh) && NEG(res) || NEG(lh) && NEG(rh) && POS(res))
  12. #define OV_SUB(lh, rh, res) \
  13. (POS(lh) && NEG(rh) && NEG(res) || NEG(lh) && POS(rh) && POS(res))
  14. #define PARITY(x) (!(__builtin_popcount(x) % 2))
  15. #define F3(x) ((x) & 0x08)
  16. #define F5(x) ((x) & 0x20)
  17. /*
  18. Set the flags for an 8-bit ADD or ADC instruction.
  19. */
  20. static inline void set_flags_add8(Z80 *z80, uint16_t rh)
  21. {
  22. uint8_t lh = z80->regs.a;
  23. uint8_t res = lh + rh;
  24. set_flags(z80, CARRY(lh, +, rh), !SUB, OV_ADD(lh, rh, res), F3(res),
  25. HALF(lh, +, rh), F5(res), ZERO(res), SIGN(res), 0xFF);
  26. }
  27. /*
  28. Set the flags for an 8-bit SUB or SBC instruction.
  29. */
  30. static inline void set_flags_sub8(Z80 *z80, uint16_t rh)
  31. {
  32. uint8_t lh = z80->regs.a;
  33. uint8_t res = lh - rh;
  34. set_flags(z80, CARRY(lh, -, rh), SUB, OV_SUB(lh, rh, res), F3(res),
  35. HALF(lh, -, rh), F5(res), ZERO(res), SIGN(res), 0xFF);
  36. }
  37. /*
  38. Set the flags for a CP instruction.
  39. */
  40. static inline void set_flags_cp(Z80 *z80, uint16_t rh)
  41. {
  42. uint8_t lh = z80->regs.a;
  43. uint8_t res = lh - rh;
  44. set_flags(z80, CARRY(lh, -, rh), SUB, OV_SUB(lh, rh, res), F3(rh),
  45. HALF(lh, -, rh), F5(rh), ZERO(res), SIGN(res), 0xFF);
  46. }
  47. /*
  48. Set the flags for an AND, XOR, or OR instruction.
  49. */
  50. static inline void set_flags_bitwise(Z80 *z80, uint8_t res, bool is_and)
  51. {
  52. set_flags(z80, 0, 0, PARITY(res), F3(res), is_and, F5(res), ZERO(res),
  53. SIGN(res), 0xFF);
  54. }
  55. /*
  56. Set the flags for an 8-bit INC instruction.
  57. */
  58. static inline void set_flags_inc(Z80 *z80, uint8_t val)
  59. {
  60. uint8_t res = val + 1;
  61. set_flags(z80, 0, !SUB, OV_ADD(val, 1, res), F3(res), HALF(val, +, 1),
  62. F5(res), ZERO(res), SIGN(res), 0xFE);
  63. }
  64. /*
  65. Set the flags for an 8-bit DEC instruction.
  66. */
  67. static inline void set_flags_dec(Z80 *z80, uint8_t val)
  68. {
  69. uint8_t res = val - 1;
  70. set_flags(z80, 0, SUB, OV_SUB(val, 1, res), F3(res), HALF(val, -, 1),
  71. F5(res), ZERO(res), SIGN(res), 0xFE);
  72. }
  73. // set_flags(Z80 *z80,
  74. // bool c, bool n, bool pv, bool f3, bool h, bool f5, bool z, bool s,
  75. // uint8_t mask)
  76. #undef POS
  77. #undef NEG
  78. #undef CARRY
  79. #undef HALF
  80. #undef ZERO
  81. #undef SIGN
  82. #undef SUB
  83. #undef OV_ADD
  84. #undef OV_SUB
  85. #undef PARITY
  86. #undef F3
  87. #undef F5