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.
 
 
 
 
 

408 lines
12 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. #include "z80.h"
  4. #include "disassembler.h"
  5. #include "logging.h"
  6. #include "util.h"
  7. #define REG_AF 0
  8. #define REG_BC 1
  9. #define REG_DE 2
  10. #define REG_HL 3
  11. #define REG_SP 4
  12. #define REG_AF_ 5
  13. #define REG_BC_ 6
  14. #define REG_DE_ 7
  15. #define REG_HL_ 8
  16. #define FLAG_CARRY 0
  17. #define FLAG_SUBTRACT 1
  18. #define FLAG_PARITY 2
  19. #define FLAG_OVERFLOW 2
  20. #define FLAG_UNDOC_3 3
  21. #define FLAG_HALFCARRY 4
  22. #define FLAG_UNDOC_5 5
  23. #define FLAG_ZERO 6
  24. #define FLAG_SIGN 7
  25. /*
  26. Initialize a Z80 object.
  27. Register values are invalid until z80_power() is called. No other Z80
  28. functions should be called before it.
  29. */
  30. void z80_init(Z80 *z80, MMU *mmu, IO *io)
  31. {
  32. z80->mmu = mmu;
  33. z80->io = io;
  34. z80->except = true;
  35. z80->exc_code = Z80_EXC_NOT_POWERED;
  36. z80->exc_data = 0;
  37. }
  38. /*
  39. Power on the Z80, setting registers to their default values.
  40. This also clears the exception flag, which is necessary before the Z80 can
  41. begin emulation.
  42. */
  43. void z80_power(Z80 *z80)
  44. {
  45. Z80RegFile *regfile = &z80->regfile;
  46. regfile->a = regfile->f = 0xFF;
  47. regfile->b = regfile->c = 0xFF;
  48. regfile->d = regfile->e = 0xFF;
  49. regfile->h = regfile->l = 0xFF;
  50. regfile->a_ = regfile->f_ = 0xFF;
  51. regfile->b_ = regfile->c_ = 0xFF;
  52. regfile->d_ = regfile->e_ = 0xFF;
  53. regfile->h_ = regfile->l_ = 0xFF;
  54. regfile->ix = 0xFFFF;
  55. regfile->iy = 0xFFFF;
  56. regfile->sp = 0xFFF0;
  57. regfile->pc = 0x0000;
  58. regfile->i = 0xFF;
  59. regfile->r = 0xFF;
  60. regfile->im_a = regfile->im_b = 0;
  61. regfile->iff1 = regfile->iff2 = 0;
  62. z80->except = false;
  63. z80->last_index = NULL;
  64. z80->pending_cycles = 0;
  65. z80->trace.fresh = true;
  66. z80->trace.last_addr = 0;
  67. z80->trace.counter = 0;
  68. }
  69. /*
  70. Get the value of a register pair.
  71. */
  72. static inline uint16_t get_pair(Z80 *z80, uint8_t pair)
  73. {
  74. switch (pair) {
  75. case REG_AF: return (z80->regfile.a << 8) + z80->regfile.f;
  76. case REG_BC: return (z80->regfile.b << 8) + z80->regfile.c;
  77. case REG_DE: return (z80->regfile.d << 8) + z80->regfile.e;
  78. case REG_HL: return (z80->regfile.h << 8) + z80->regfile.l;
  79. case REG_AF_: return (z80->regfile.a_ << 8) + z80->regfile.f_;
  80. case REG_BC_: return (z80->regfile.b_ << 8) + z80->regfile.c_;
  81. case REG_DE_: return (z80->regfile.d_ << 8) + z80->regfile.e_;
  82. case REG_HL_: return (z80->regfile.h_ << 8) + z80->regfile.l_;
  83. case REG_SP: return z80->regfile.sp;
  84. }
  85. FATAL("invalid call: get_pair(z80, %u)", pair)
  86. }
  87. /*
  88. Set the value of a register pair.
  89. */
  90. static inline void set_pair(Z80 *z80, uint8_t pair, uint16_t value)
  91. {
  92. switch (pair) {
  93. case REG_AF: z80->regfile.a = value >> 8; z80->regfile.f = value; break;
  94. case REG_BC: z80->regfile.b = value >> 8; z80->regfile.c = value; break;
  95. case REG_DE: z80->regfile.d = value >> 8; z80->regfile.e = value; break;
  96. case REG_HL: z80->regfile.h = value >> 8; z80->regfile.l = value; break;
  97. case REG_AF_: z80->regfile.a_ = value >> 8; z80->regfile.f_ = value; break;
  98. case REG_BC_: z80->regfile.b_ = value >> 8; z80->regfile.c_ = value; break;
  99. case REG_DE_: z80->regfile.d_ = value >> 8; z80->regfile.e_ = value; break;
  100. case REG_HL_: z80->regfile.h_ = value >> 8; z80->regfile.l_ = value; break;
  101. case REG_SP: z80->regfile.sp = value; break;
  102. default:
  103. FATAL("invalid call: set_pair(z80, %u, 0x%04X)", pair, value)
  104. }
  105. }
  106. /*
  107. Return whether a particular flag is set in the F register.
  108. */
  109. static inline bool get_flag(const Z80 *z80, uint8_t flag)
  110. {
  111. return z80->regfile.f & (1 << flag);
  112. }
  113. /*
  114. Return whether a particular flag is set in the F' register.
  115. */
  116. static inline bool get_shadow_flag(const Z80 *z80, uint8_t flag)
  117. {
  118. return z80->regfile.f_ & (1 << flag);
  119. }
  120. /*
  121. Update the F register flags according to the set bits in the mask.
  122. */
  123. static inline void update_flags(Z80 *z80, bool c, bool n, bool pv, bool f3,
  124. bool h, bool f5, bool z, bool s, uint8_t mask)
  125. {
  126. z80->regfile.f = (~mask & z80->regfile.f) | (mask & (
  127. c << FLAG_CARRY |
  128. n << FLAG_SUBTRACT |
  129. pv << FLAG_PARITY |
  130. f3 << FLAG_UNDOC_3 |
  131. h << FLAG_HALFCARRY |
  132. f5 << FLAG_UNDOC_5 |
  133. z << FLAG_ZERO |
  134. s << FLAG_SIGN));
  135. }
  136. /*
  137. Push a two-byte value onto the stack.
  138. */
  139. static inline void stack_push(Z80 *z80, uint16_t value)
  140. {
  141. z80->regfile.sp -= 2;
  142. mmu_write_double(z80->mmu, z80->regfile.sp, value);
  143. }
  144. /*
  145. Pop a two-byte value from the stack.
  146. */
  147. static inline uint16_t stack_pop(Z80 *z80)
  148. {
  149. uint16_t value = mmu_read_double(z80->mmu, z80->regfile.sp);
  150. z80->regfile.sp += 2;
  151. return value;
  152. }
  153. /*
  154. Check for errors after an I/O operation.
  155. */
  156. static void handle_io_errors(Z80 *z80)
  157. {
  158. if (z80->io->except) {
  159. z80->except = true;
  160. z80->exc_code = Z80_EXC_IO_ERROR;
  161. z80->exc_data = z80->io->exc_port;
  162. }
  163. }
  164. /*
  165. Read and return a byte from the given port, and check for errors.
  166. */
  167. static uint8_t read_port(Z80 *z80, uint8_t port)
  168. {
  169. uint8_t value = io_port_read(z80->io, port);
  170. handle_io_errors(z80);
  171. return value;
  172. }
  173. /*
  174. Write a byte to the given port, and check for errors.
  175. */
  176. static void write_port(Z80 *z80, uint8_t port, uint8_t value)
  177. {
  178. io_port_write(z80->io, port, value);
  179. handle_io_errors(z80);
  180. }
  181. /*
  182. Extract an 8-bit register from the given opcode and return a pointer to it.
  183. */
  184. static inline uint8_t* extract_reg(Z80 *z80, uint8_t opcode)
  185. {
  186. switch (opcode & 0x38) {
  187. case 0x00: return &z80->regfile.b;
  188. case 0x08: return &z80->regfile.c;
  189. case 0x10: return &z80->regfile.d;
  190. case 0x18: return &z80->regfile.e;
  191. case 0x20: return &z80->regfile.h;
  192. case 0x28: return &z80->regfile.l;
  193. case 0x38: return &z80->regfile.a;
  194. }
  195. FATAL("invalid call: extract_reg(z80, 0x%02X)", opcode)
  196. }
  197. /*
  198. Extract a register pair from the given opcode and return its identifer.
  199. */
  200. static inline uint8_t extract_pair(uint8_t opcode)
  201. {
  202. switch (opcode & 0x30) {
  203. case 0x00: return REG_BC;
  204. case 0x10: return REG_DE;
  205. case 0x20: return REG_HL;
  206. case 0x30: return REG_SP;
  207. }
  208. FATAL("invalid call: extract_pair(0x%02X)", opcode)
  209. }
  210. /*
  211. Extract a condition from the given opcode.
  212. */
  213. static inline bool extract_cond(const Z80 *z80, uint8_t opcode)
  214. {
  215. switch (opcode & 0x38) {
  216. case 0x00: return !get_flag(z80, FLAG_ZERO);
  217. case 0x08: return get_flag(z80, FLAG_ZERO);
  218. case 0x10: return !get_flag(z80, FLAG_CARRY);
  219. case 0x18: return get_flag(z80, FLAG_CARRY);
  220. case 0x20: return !get_flag(z80, FLAG_PARITY);
  221. case 0x28: return get_flag(z80, FLAG_PARITY);
  222. case 0x30: return !get_flag(z80, FLAG_SIGN);
  223. case 0x38: return get_flag(z80, FLAG_SIGN);
  224. }
  225. FATAL("invalid call: extract_cond(z80, 0x%02X)", opcode)
  226. }
  227. /*
  228. Return the address signified by a indirect index instruction.
  229. */
  230. static inline uint16_t get_index_addr(Z80 *z80, uint16_t offset_addr)
  231. {
  232. return *z80->last_index + ((int8_t) mmu_read_byte(z80->mmu, offset_addr));
  233. }
  234. /*
  235. Return the CPU's current interrupt mode.
  236. */
  237. static inline uint8_t get_interrupt_mode(const Z80 *z80)
  238. {
  239. if (!z80->regfile.im_a)
  240. return 0;
  241. if (!z80->regfile.im_b)
  242. return 1;
  243. return 2;
  244. }
  245. /*
  246. Handle an active IRQ line. Return the number of cycles consumed.
  247. */
  248. static inline uint8_t handle_interrupt(Z80 *z80)
  249. {
  250. TRACE("Z80 triggering mode-%d interrupt", get_interrupt_mode(z80))
  251. z80->regfile.iff1 = z80->regfile.iff2 = 0;
  252. stack_push(z80, z80->regfile.pc);
  253. if (get_interrupt_mode(z80) < 2) {
  254. z80->regfile.pc = 0x0038;
  255. return 13;
  256. } else {
  257. uint16_t addr = (z80->regfile.i << 8) + 0xFF;
  258. z80->regfile.pc = mmu_read_double(z80->mmu, addr);
  259. return 19;
  260. }
  261. }
  262. /*
  263. Increment the refresh counter register, R.
  264. */
  265. static inline void increment_refresh_counter(Z80 *z80)
  266. {
  267. z80->regfile.r = (z80->regfile.r & 0x80) | ((z80->regfile.r + 1) & 0x7F);
  268. }
  269. #include "z80_ops.inc.c"
  270. /*
  271. @TRACE_LEVEL
  272. Trace the instruction about to be executed by the CPU.
  273. */
  274. static inline void trace_instruction(Z80 *z80)
  275. {
  276. if (z80->regfile.pc == z80->trace.last_addr && !z80->trace.fresh) {
  277. z80->trace.counter++;
  278. if (!(z80->trace.counter % (1 << 14)))
  279. TRACE_NOEOL("repeat last: %llu times\r", z80->trace.counter);
  280. return;
  281. }
  282. if (z80->trace.fresh) {
  283. TRACE("PC ADDR P1 P2 OP A1 A2 INSTR\tARGS")
  284. TRACE("------- -------------- -----\t----")
  285. z80->trace.fresh = false;
  286. }
  287. z80->trace.last_addr = z80->regfile.pc;
  288. z80->trace.counter = 0;
  289. uint32_t quad = mmu_read_quad(z80->mmu, z80->regfile.pc);
  290. uint8_t bytes[4] = {quad, quad >> 8, quad >> 16, quad >> 24};
  291. DisasInstr *instr = disassemble_instruction(bytes);
  292. TRACE("0x%04X: %-14s %s",
  293. z80->regfile.pc, instr->bytestr, instr->line)
  294. disas_instr_free(instr);
  295. }
  296. /*
  297. Emulate the given number of cycles of the Z80, or until an exception.
  298. The return value indicates whether the exception flag is set. If it is,
  299. then emulation must be stopped because further calls to z80_do_cycles()
  300. will have no effect. The exception flag can be reset with z80_power().
  301. */
  302. bool z80_do_cycles(Z80 *z80, double cycles)
  303. {
  304. cycles += z80->pending_cycles;
  305. while (cycles > 0 && !z80->except) {
  306. if (io_check_irq(z80->io) && z80->regfile.iff1) {
  307. cycles -= handle_interrupt(z80);
  308. continue;
  309. }
  310. uint8_t opcode = mmu_read_byte(z80->mmu, z80->regfile.pc);
  311. increment_refresh_counter(z80);
  312. if (TRACE_LEVEL)
  313. trace_instruction(z80);
  314. cycles -= (*instruction_table[opcode])(z80, opcode);
  315. }
  316. z80->pending_cycles = cycles;
  317. return z80->except;
  318. }
  319. /*
  320. @DEBUG_LEVEL
  321. Print out all register values to stdout.
  322. */
  323. void z80_dump_registers(const Z80 *z80)
  324. {
  325. const Z80RegFile *rf = &z80->regfile;
  326. DEBUG("Dumping Z80 register values:")
  327. DEBUG("- AF: 0x%02X%02X (%03d, %03d)", rf->a, rf->f, rf->a, rf->f)
  328. DEBUG("- BC: 0x%02X%02X (%03d, %03d)", rf->b, rf->c, rf->b, rf->c)
  329. DEBUG("- DE: 0x%02X%02X (%03d, %03d)", rf->d, rf->e, rf->d, rf->e)
  330. DEBUG("- HL: 0x%02X%02X (%03d, %03d)", rf->h, rf->l, rf->h, rf->l)
  331. DEBUG("- AF': 0x%02X%02X (%03d, %03d)", rf->a_, rf->f_, rf->a_, rf->f_)
  332. DEBUG("- BC': 0x%02X%02X (%03d, %03d)", rf->b_, rf->c_, rf->b_, rf->c_)
  333. DEBUG("- DE': 0x%02X%02X (%03d, %03d)", rf->d_, rf->e_, rf->d_, rf->e_)
  334. DEBUG("- HL': 0x%02X%02X (%03d, %03d)", rf->h_, rf->l_, rf->h_, rf->l_)
  335. DEBUG("- IX: 0x%04X (%05d)", rf->ix, rf->ix)
  336. DEBUG("- IY: 0x%04X (%05d)", rf->iy, rf->iy)
  337. DEBUG("- SP: 0x%04X (%05d)", rf->sp, rf->sp)
  338. DEBUG("- PC: 0x%04X (%05d)", rf->pc, rf->pc)
  339. DEBUG("- I: 0x%2X (%03d)", rf->i, rf->i)
  340. DEBUG("- R: 0x%2X (%03d)", rf->r, rf->r)
  341. DEBUG("- F: "BINARY_FMT" (C: %u, N: %u, P/V: %u, H: %u, Z: %u, S: %u)",
  342. BINARY_VAL(rf->f),
  343. get_flag(z80, FLAG_CARRY),
  344. get_flag(z80, FLAG_SUBTRACT),
  345. get_flag(z80, FLAG_PARITY),
  346. get_flag(z80, FLAG_HALFCARRY),
  347. get_flag(z80, FLAG_ZERO),
  348. get_flag(z80, FLAG_SIGN))
  349. DEBUG("- F': "BINARY_FMT" (C: %u, N: %u, P/V: %u, H: %u, Z: %u, S: %u)",
  350. BINARY_VAL(rf->f_),
  351. get_shadow_flag(z80, FLAG_CARRY),
  352. get_shadow_flag(z80, FLAG_SUBTRACT),
  353. get_shadow_flag(z80, FLAG_PARITY),
  354. get_shadow_flag(z80, FLAG_HALFCARRY),
  355. get_shadow_flag(z80, FLAG_ZERO),
  356. get_shadow_flag(z80, FLAG_SIGN))
  357. DEBUG("- IM: 0b%u%u (mode: %u)", rf->im_a, rf->im_b,
  358. get_interrupt_mode(z80))
  359. DEBUG("- IFF: 1: %u, 2: %u", rf->iff1, rf->iff2)
  360. }