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.
 
 
 
 
 

345 lines
14 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. /*
  4. This file contains code to implement the Z80 instruction set. Since there
  5. are a lot of functions, it is kept separate from the main z80.c file. It is
  6. included in the middle of z80.c and should not be compiled separately.
  7. Most of this information can be found in the Z80 User Manual, Revision 06.
  8. Undocumented opcodes, flags, and some additional details come from:
  9. - http://clrhome.org/table/
  10. - http://www.z80.info/z80sflag.htm
  11. */
  12. /*
  13. Unimplemented opcode handler.
  14. */
  15. static uint8_t z80_inst_unimplemented(Z80 *z80, uint8_t opcode)
  16. {
  17. z80->except = true;
  18. z80->exc_code = Z80_EXC_UNIMPLEMENTED_OPCODE;
  19. z80->exc_data = opcode;
  20. return 2;
  21. }
  22. /*
  23. NOP (0x00):
  24. No operation is performed.
  25. */
  26. static uint8_t z80_inst_nop(Z80 *z80, uint8_t opcode)
  27. {
  28. (void) opcode;
  29. z80->regfile.pc++;
  30. return 4;
  31. }
  32. /*
  33. INC r (0x04, 0x0C, 0x14, 0x1C, 0x24, 0x2C, 0x3C):
  34. Increment the 8-bit register encoded in the opcode.
  35. */
  36. static uint8_t z80_inst_inc_r(Z80 *z80, uint8_t opcode)
  37. {
  38. uint8_t *reg;
  39. switch(opcode) {
  40. case 0x3C: reg = &z80->regfile.a; break;
  41. case 0x04: reg = &z80->regfile.b; break;
  42. case 0x0C: reg = &z80->regfile.c; break;
  43. case 0x14: reg = &z80->regfile.d; break;
  44. case 0x1C: reg = &z80->regfile.e; break;
  45. case 0x24: reg = &z80->regfile.h; break;
  46. case 0x2C: reg = &z80->regfile.l; break;
  47. }
  48. bool halfcarry = !!(((*reg & 0x0F) + 1) & 0x10);
  49. (*reg)++;
  50. update_flags(z80, 0, 0, *reg == 0x80, !!(*reg & 0x08), halfcarry,
  51. !!(*reg & 0x20), *reg == 0, !!(*reg & 0x80), 0xFE);
  52. z80->regfile.pc++;
  53. return 4;
  54. }
  55. /*
  56. INC ss (0x03, 0x13, 0x23, 0x33):
  57. Increment the 16-bit register encoded in the opcode.
  58. */
  59. static uint8_t z80_inst_inc_ss(Z80 *z80, uint8_t opcode)
  60. {
  61. if (opcode == 0x33) {
  62. z80->regfile.sp++;
  63. } else {
  64. uint8_t pair;
  65. switch(opcode) {
  66. case 0x03: pair = REG_BC; break;
  67. case 0x13: pair = REG_DE; break;
  68. case 0x23: pair = REG_HL; break;
  69. }
  70. set_pair(z80, pair, get_pair(z80, pair) + 1);
  71. }
  72. z80->regfile.pc++;
  73. return 6;
  74. }
  75. static uint8_t (*instruction_lookup_table[256])(Z80*, uint8_t) = {
  76. [0x00] = z80_inst_nop,
  77. [0x01] = z80_inst_unimplemented, // TODO
  78. [0x02] = z80_inst_unimplemented, // TODO
  79. [0x03] = z80_inst_inc_ss,
  80. [0x04] = z80_inst_inc_r,
  81. [0x05] = z80_inst_unimplemented, // TODO
  82. [0x06] = z80_inst_unimplemented, // TODO
  83. [0x07] = z80_inst_unimplemented, // TODO
  84. [0x08] = z80_inst_unimplemented, // TODO
  85. [0x09] = z80_inst_unimplemented, // TODO
  86. [0x0A] = z80_inst_unimplemented, // TODO
  87. [0x0B] = z80_inst_unimplemented, // TODO
  88. [0x0C] = z80_inst_inc_r,
  89. [0x0D] = z80_inst_unimplemented, // TODO
  90. [0x0E] = z80_inst_unimplemented, // TODO
  91. [0x0F] = z80_inst_unimplemented, // TODO
  92. [0x10] = z80_inst_unimplemented, // TODO
  93. [0x11] = z80_inst_unimplemented, // TODO
  94. [0x12] = z80_inst_unimplemented, // TODO
  95. [0x13] = z80_inst_inc_ss,
  96. [0x14] = z80_inst_inc_r,
  97. [0x15] = z80_inst_unimplemented, // TODO
  98. [0x16] = z80_inst_unimplemented, // TODO
  99. [0x17] = z80_inst_unimplemented, // TODO
  100. [0x18] = z80_inst_unimplemented, // TODO
  101. [0x19] = z80_inst_unimplemented, // TODO
  102. [0x1A] = z80_inst_unimplemented, // TODO
  103. [0x1B] = z80_inst_unimplemented, // TODO
  104. [0x1C] = z80_inst_inc_r,
  105. [0x1D] = z80_inst_unimplemented, // TODO
  106. [0x1E] = z80_inst_unimplemented, // TODO
  107. [0x1F] = z80_inst_unimplemented, // TODO
  108. [0x20] = z80_inst_unimplemented, // TODO
  109. [0x21] = z80_inst_unimplemented, // TODO
  110. [0x22] = z80_inst_unimplemented, // TODO
  111. [0x23] = z80_inst_inc_ss,
  112. [0x24] = z80_inst_inc_r,
  113. [0x25] = z80_inst_unimplemented, // TODO
  114. [0x26] = z80_inst_unimplemented, // TODO
  115. [0x27] = z80_inst_unimplemented, // TODO
  116. [0x28] = z80_inst_unimplemented, // TODO
  117. [0x29] = z80_inst_unimplemented, // TODO
  118. [0x2A] = z80_inst_unimplemented, // TODO
  119. [0x2B] = z80_inst_unimplemented, // TODO
  120. [0x2C] = z80_inst_inc_r,
  121. [0x2D] = z80_inst_unimplemented, // TODO
  122. [0x2E] = z80_inst_unimplemented, // TODO
  123. [0x2F] = z80_inst_unimplemented, // TODO
  124. [0x30] = z80_inst_unimplemented, // TODO
  125. [0x31] = z80_inst_unimplemented, // TODO
  126. [0x32] = z80_inst_unimplemented, // TODO
  127. [0x33] = z80_inst_inc_ss,
  128. [0x34] = z80_inst_unimplemented, // TODO
  129. [0x35] = z80_inst_unimplemented, // TODO
  130. [0x36] = z80_inst_unimplemented, // TODO
  131. [0x37] = z80_inst_unimplemented, // TODO
  132. [0x38] = z80_inst_unimplemented, // TODO
  133. [0x39] = z80_inst_unimplemented, // TODO
  134. [0x3A] = z80_inst_unimplemented, // TODO
  135. [0x3B] = z80_inst_unimplemented, // TODO
  136. [0x3C] = z80_inst_inc_r,
  137. [0x3D] = z80_inst_unimplemented, // TODO
  138. [0x3E] = z80_inst_unimplemented, // TODO
  139. [0x3F] = z80_inst_unimplemented, // TODO
  140. [0x40] = z80_inst_unimplemented, // TODO
  141. [0x41] = z80_inst_unimplemented, // TODO
  142. [0x42] = z80_inst_unimplemented, // TODO
  143. [0x43] = z80_inst_unimplemented, // TODO
  144. [0x44] = z80_inst_unimplemented, // TODO
  145. [0x45] = z80_inst_unimplemented, // TODO
  146. [0x46] = z80_inst_unimplemented, // TODO
  147. [0x47] = z80_inst_unimplemented, // TODO
  148. [0x48] = z80_inst_unimplemented, // TODO
  149. [0x49] = z80_inst_unimplemented, // TODO
  150. [0x4A] = z80_inst_unimplemented, // TODO
  151. [0x4B] = z80_inst_unimplemented, // TODO
  152. [0x4C] = z80_inst_unimplemented, // TODO
  153. [0x4D] = z80_inst_unimplemented, // TODO
  154. [0x4E] = z80_inst_unimplemented, // TODO
  155. [0x4F] = z80_inst_unimplemented, // TODO
  156. [0x50] = z80_inst_unimplemented, // TODO
  157. [0x51] = z80_inst_unimplemented, // TODO
  158. [0x52] = z80_inst_unimplemented, // TODO
  159. [0x53] = z80_inst_unimplemented, // TODO
  160. [0x54] = z80_inst_unimplemented, // TODO
  161. [0x55] = z80_inst_unimplemented, // TODO
  162. [0x56] = z80_inst_unimplemented, // TODO
  163. [0x57] = z80_inst_unimplemented, // TODO
  164. [0x58] = z80_inst_unimplemented, // TODO
  165. [0x59] = z80_inst_unimplemented, // TODO
  166. [0x5A] = z80_inst_unimplemented, // TODO
  167. [0x5B] = z80_inst_unimplemented, // TODO
  168. [0x5C] = z80_inst_unimplemented, // TODO
  169. [0x5D] = z80_inst_unimplemented, // TODO
  170. [0x5E] = z80_inst_unimplemented, // TODO
  171. [0x5F] = z80_inst_unimplemented, // TODO
  172. [0x60] = z80_inst_unimplemented, // TODO
  173. [0x61] = z80_inst_unimplemented, // TODO
  174. [0x62] = z80_inst_unimplemented, // TODO
  175. [0x63] = z80_inst_unimplemented, // TODO
  176. [0x64] = z80_inst_unimplemented, // TODO
  177. [0x65] = z80_inst_unimplemented, // TODO
  178. [0x66] = z80_inst_unimplemented, // TODO
  179. [0x67] = z80_inst_unimplemented, // TODO
  180. [0x68] = z80_inst_unimplemented, // TODO
  181. [0x69] = z80_inst_unimplemented, // TODO
  182. [0x6A] = z80_inst_unimplemented, // TODO
  183. [0x6B] = z80_inst_unimplemented, // TODO
  184. [0x6C] = z80_inst_unimplemented, // TODO
  185. [0x6D] = z80_inst_unimplemented, // TODO
  186. [0x6E] = z80_inst_unimplemented, // TODO
  187. [0x6F] = z80_inst_unimplemented, // TODO
  188. [0x70] = z80_inst_unimplemented, // TODO
  189. [0x71] = z80_inst_unimplemented, // TODO
  190. [0x72] = z80_inst_unimplemented, // TODO
  191. [0x73] = z80_inst_unimplemented, // TODO
  192. [0x74] = z80_inst_unimplemented, // TODO
  193. [0x75] = z80_inst_unimplemented, // TODO
  194. [0x76] = z80_inst_unimplemented, // TODO
  195. [0x77] = z80_inst_unimplemented, // TODO
  196. [0x78] = z80_inst_unimplemented, // TODO
  197. [0x79] = z80_inst_unimplemented, // TODO
  198. [0x7A] = z80_inst_unimplemented, // TODO
  199. [0x7B] = z80_inst_unimplemented, // TODO
  200. [0x7C] = z80_inst_unimplemented, // TODO
  201. [0x7D] = z80_inst_unimplemented, // TODO
  202. [0x7E] = z80_inst_unimplemented, // TODO
  203. [0x7F] = z80_inst_unimplemented, // TODO
  204. [0x80] = z80_inst_unimplemented, // TODO
  205. [0x81] = z80_inst_unimplemented, // TODO
  206. [0x82] = z80_inst_unimplemented, // TODO
  207. [0x83] = z80_inst_unimplemented, // TODO
  208. [0x84] = z80_inst_unimplemented, // TODO
  209. [0x85] = z80_inst_unimplemented, // TODO
  210. [0x86] = z80_inst_unimplemented, // TODO
  211. [0x87] = z80_inst_unimplemented, // TODO
  212. [0x88] = z80_inst_unimplemented, // TODO
  213. [0x89] = z80_inst_unimplemented, // TODO
  214. [0x8A] = z80_inst_unimplemented, // TODO
  215. [0x8B] = z80_inst_unimplemented, // TODO
  216. [0x8C] = z80_inst_unimplemented, // TODO
  217. [0x8D] = z80_inst_unimplemented, // TODO
  218. [0x8E] = z80_inst_unimplemented, // TODO
  219. [0x8F] = z80_inst_unimplemented, // TODO
  220. [0x90] = z80_inst_unimplemented, // TODO
  221. [0x91] = z80_inst_unimplemented, // TODO
  222. [0x92] = z80_inst_unimplemented, // TODO
  223. [0x93] = z80_inst_unimplemented, // TODO
  224. [0x94] = z80_inst_unimplemented, // TODO
  225. [0x95] = z80_inst_unimplemented, // TODO
  226. [0x96] = z80_inst_unimplemented, // TODO
  227. [0x97] = z80_inst_unimplemented, // TODO
  228. [0x98] = z80_inst_unimplemented, // TODO
  229. [0x99] = z80_inst_unimplemented, // TODO
  230. [0x9A] = z80_inst_unimplemented, // TODO
  231. [0x9B] = z80_inst_unimplemented, // TODO
  232. [0x9C] = z80_inst_unimplemented, // TODO
  233. [0x9D] = z80_inst_unimplemented, // TODO
  234. [0x9E] = z80_inst_unimplemented, // TODO
  235. [0x9F] = z80_inst_unimplemented, // TODO
  236. [0xA0] = z80_inst_unimplemented, // TODO
  237. [0xA1] = z80_inst_unimplemented, // TODO
  238. [0xA2] = z80_inst_unimplemented, // TODO
  239. [0xA3] = z80_inst_unimplemented, // TODO
  240. [0xA4] = z80_inst_unimplemented, // TODO
  241. [0xA5] = z80_inst_unimplemented, // TODO
  242. [0xA6] = z80_inst_unimplemented, // TODO
  243. [0xA7] = z80_inst_unimplemented, // TODO
  244. [0xA8] = z80_inst_unimplemented, // TODO
  245. [0xA9] = z80_inst_unimplemented, // TODO
  246. [0xAA] = z80_inst_unimplemented, // TODO
  247. [0xAB] = z80_inst_unimplemented, // TODO
  248. [0xAC] = z80_inst_unimplemented, // TODO
  249. [0xAD] = z80_inst_unimplemented, // TODO
  250. [0xAE] = z80_inst_unimplemented, // TODO
  251. [0xAF] = z80_inst_unimplemented, // TODO
  252. [0xB0] = z80_inst_unimplemented, // TODO
  253. [0xB1] = z80_inst_unimplemented, // TODO
  254. [0xB2] = z80_inst_unimplemented, // TODO
  255. [0xB3] = z80_inst_unimplemented, // TODO
  256. [0xB4] = z80_inst_unimplemented, // TODO
  257. [0xB5] = z80_inst_unimplemented, // TODO
  258. [0xB6] = z80_inst_unimplemented, // TODO
  259. [0xB7] = z80_inst_unimplemented, // TODO
  260. [0xB8] = z80_inst_unimplemented, // TODO
  261. [0xB9] = z80_inst_unimplemented, // TODO
  262. [0xBA] = z80_inst_unimplemented, // TODO
  263. [0xBB] = z80_inst_unimplemented, // TODO
  264. [0xBC] = z80_inst_unimplemented, // TODO
  265. [0xBD] = z80_inst_unimplemented, // TODO
  266. [0xBE] = z80_inst_unimplemented, // TODO
  267. [0xBF] = z80_inst_unimplemented, // TODO
  268. [0xC0] = z80_inst_unimplemented, // TODO
  269. [0xC1] = z80_inst_unimplemented, // TODO
  270. [0xC2] = z80_inst_unimplemented, // TODO
  271. [0xC3] = z80_inst_unimplemented, // TODO
  272. [0xC4] = z80_inst_unimplemented, // TODO
  273. [0xC5] = z80_inst_unimplemented, // TODO
  274. [0xC6] = z80_inst_unimplemented, // TODO
  275. [0xC7] = z80_inst_unimplemented, // TODO
  276. [0xC8] = z80_inst_unimplemented, // TODO
  277. [0xC9] = z80_inst_unimplemented, // TODO
  278. [0xCA] = z80_inst_unimplemented, // TODO
  279. [0xCB] = z80_inst_unimplemented, // TODO
  280. [0xCC] = z80_inst_unimplemented, // TODO
  281. [0xCD] = z80_inst_unimplemented, // TODO
  282. [0xCE] = z80_inst_unimplemented, // TODO
  283. [0xCF] = z80_inst_unimplemented, // TODO
  284. [0xD0] = z80_inst_unimplemented, // TODO
  285. [0xD1] = z80_inst_unimplemented, // TODO
  286. [0xD2] = z80_inst_unimplemented, // TODO
  287. [0xD3] = z80_inst_unimplemented, // TODO
  288. [0xD4] = z80_inst_unimplemented, // TODO
  289. [0xD5] = z80_inst_unimplemented, // TODO
  290. [0xD6] = z80_inst_unimplemented, // TODO
  291. [0xD7] = z80_inst_unimplemented, // TODO
  292. [0xD8] = z80_inst_unimplemented, // TODO
  293. [0xD9] = z80_inst_unimplemented, // TODO
  294. [0xDA] = z80_inst_unimplemented, // TODO
  295. [0xDB] = z80_inst_unimplemented, // TODO
  296. [0xDC] = z80_inst_unimplemented, // TODO
  297. [0xDD] = z80_inst_unimplemented, // TODO
  298. [0xDE] = z80_inst_unimplemented, // TODO
  299. [0xDF] = z80_inst_unimplemented, // TODO
  300. [0xE0] = z80_inst_unimplemented, // TODO
  301. [0xE1] = z80_inst_unimplemented, // TODO
  302. [0xE2] = z80_inst_unimplemented, // TODO
  303. [0xE3] = z80_inst_unimplemented, // TODO
  304. [0xE4] = z80_inst_unimplemented, // TODO
  305. [0xE5] = z80_inst_unimplemented, // TODO
  306. [0xE6] = z80_inst_unimplemented, // TODO
  307. [0xE7] = z80_inst_unimplemented, // TODO
  308. [0xE8] = z80_inst_unimplemented, // TODO
  309. [0xE9] = z80_inst_unimplemented, // TODO
  310. [0xEA] = z80_inst_unimplemented, // TODO
  311. [0xEB] = z80_inst_unimplemented, // TODO
  312. [0xEC] = z80_inst_unimplemented, // TODO
  313. [0xED] = z80_inst_unimplemented, // TODO
  314. [0xEE] = z80_inst_unimplemented, // TODO
  315. [0xEF] = z80_inst_unimplemented, // TODO
  316. [0xF0] = z80_inst_unimplemented, // TODO
  317. [0xF1] = z80_inst_unimplemented, // TODO
  318. [0xF2] = z80_inst_unimplemented, // TODO
  319. [0xF3] = z80_inst_unimplemented, // TODO
  320. [0xF4] = z80_inst_unimplemented, // TODO
  321. [0xF5] = z80_inst_unimplemented, // TODO
  322. [0xF6] = z80_inst_unimplemented, // TODO
  323. [0xF7] = z80_inst_unimplemented, // TODO
  324. [0xF8] = z80_inst_unimplemented, // TODO
  325. [0xF9] = z80_inst_unimplemented, // TODO
  326. [0xFA] = z80_inst_unimplemented, // TODO
  327. [0xFB] = z80_inst_unimplemented, // TODO
  328. [0xFC] = z80_inst_unimplemented, // TODO
  329. [0xFD] = z80_inst_unimplemented, // TODO
  330. [0xFE] = z80_inst_unimplemented, // TODO
  331. [0xFF] = z80_inst_unimplemented // TODO
  332. };