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.
 
 
 
 
 

366 lines
13 KiB

  1. /* Copyright (C) 2014-2015 Ben Kurtovic <ben.kurtovic@gmail.com>
  2. Released under the terms of the MIT License. See LICENSE for details. */
  3. #include <stdarg.h>
  4. #include <stdlib.h>
  5. #include "instructions.h"
  6. #include "inst_args.h"
  7. #include "parse_util.h"
  8. #include "../logging.h"
  9. /* Helper macros for get_inst_parser() */
  10. #define JOIN_(a, b, c, d) ((uint32_t) ((a << 24) + (b << 16) + (c << 8) + d))
  11. #define DISPATCH_(s, z) ( \
  12. (z) == 2 ? JOIN_(s[0], s[1], 0x00, 0x00) : \
  13. (z) == 3 ? JOIN_(s[0], s[1], s[2], 0x00) : \
  14. JOIN_(s[0], s[1], s[2], s[3])) \
  15. #define MAKE_CMP_(s) DISPATCH_(s, sizeof(s) / sizeof(char) - 1)
  16. #define HANDLE(m) if (key == MAKE_CMP_(#m)) return parse_inst_##m;
  17. /* Internal helper macros for instruction parsers */
  18. #define INST_ALLOC_(len) \
  19. *length = len; \
  20. if (!(*bytes = malloc(sizeof(uint8_t) * (len)))) \
  21. OUT_OF_MEMORY()
  22. #define INST_SET_(b, val) ((*bytes)[b] = val)
  23. #define INST_SET1_(b1) INST_SET_(0, b1)
  24. #define INST_SET2_(b1, b2) INST_SET1_(b1), INST_SET_(1, b2)
  25. #define INST_SET3_(b1, b2, b3) INST_SET2_(b1, b2), INST_SET_(2, b3)
  26. #define INST_SET4_(b1, b2, b3, b4) INST_SET3_(b1, b2, b3), INST_SET_(3, b4)
  27. #define INST_DISPATCH_(a, b, c, d, target, ...) target
  28. #define INST_FILL_BYTES_(len, ...) \
  29. ((len > 4) ? fill_bytes_variadic(*bytes, len, __VA_ARGS__) : \
  30. INST_DISPATCH_(__VA_ARGS__, INST_SET4_, INST_SET3_, INST_SET2_, \
  31. INST_SET1_, __VA_ARGS__)(__VA_ARGS__));
  32. #define INST_PREFIX_(reg) \
  33. (((reg) == REG_IX || (reg) == REG_IXH || (reg) == REG_IXL) ? 0xDD : 0xFD)
  34. /* Helper macros for instruction parsers */
  35. #define INST_FUNC(mnemonic) \
  36. static ASMErrorDesc parse_inst_##mnemonic( \
  37. uint8_t **bytes, size_t *length, char **symbol, const char *arg, size_t size)
  38. #define INST_ERROR(desc) return ED_PS_##desc;
  39. #define INST_TAKES_NO_ARGS \
  40. if (arg) \
  41. INST_ERROR(TOO_MANY_ARGS) \
  42. (void) size;
  43. #define INST_TAKES_ARGS(lo, hi) \
  44. if (!arg) \
  45. INST_ERROR(TOO_FEW_ARGS) \
  46. ASMInstArg args[3]; \
  47. size_t nargs = 0; \
  48. ASMErrorDesc err = parse_args(args, &nargs, arg, size); \
  49. if (err) \
  50. return err; \
  51. if (nargs < lo) \
  52. INST_ERROR(TOO_FEW_ARGS) \
  53. if (nargs > hi) \
  54. INST_ERROR(TOO_MANY_ARGS)
  55. #define INST_NARGS nargs
  56. #define INST_TYPE(n) args[n].type
  57. #define INST_REG(n) args[n].data.reg
  58. #define INST_IMM(n) args[n].data.imm
  59. #define INST_INDIRECT(n) args[n].data.indirect
  60. #define INST_INDEX(n) args[n].data.index
  61. #define INST_LABEL(n) args[n].data.label
  62. #define INST_COND(n) args[n].data.cond
  63. #define INST_FORCE_TYPE(n, t) { \
  64. if (INST_TYPE(n) != t) \
  65. INST_ERROR(ARG##n##_TYPE) \
  66. }
  67. #define INST_CHECK_IMM(n, m) { \
  68. if (!(INST_IMM(n).mask & (m))) \
  69. INST_ERROR(ARG##n##_RANGE) \
  70. }
  71. #define INST_INDIRECT_HL_ONLY(n) { \
  72. if (INST_INDIRECT(n).type != AT_REGISTER) \
  73. INST_ERROR(ARG##n##_TYPE) \
  74. if (INST_INDIRECT(n).addr.reg != REG_HL) \
  75. INST_ERROR(ARG##n##_BAD_REG) \
  76. }
  77. #define INST_RETURN(len, ...) { \
  78. (void) symbol; \
  79. INST_ALLOC_(len) \
  80. INST_FILL_BYTES_(len, __VA_ARGS__) \
  81. return ED_NONE; \
  82. }
  83. #define INST_RETURN_WITH_SYMBOL(len, label, ...) { \
  84. *symbol = strdup(label); \
  85. if (!(*symbol)) \
  86. OUT_OF_MEMORY() \
  87. INST_ALLOC_(len) \
  88. INST_FILL_BYTES_(len - 2, __VA_ARGS__) \
  89. return ED_NONE; \
  90. }
  91. #define INST_INDEX_PREFIX(n) INST_PREFIX_(INST_INDEX(n).reg)
  92. #define INST_INDEX_BYTES(n, b) \
  93. INST_INDEX_PREFIX(n), b, INST_INDEX(n).offset
  94. /*
  95. Fill an instruction's byte array with the given data.
  96. This internal function is only called for instructions longer than four
  97. bytes (of which there is only one: the fake emulator debugging/testing
  98. opcode with mnemonic "emu"), so it does not get used in normal situations.
  99. Return the value of the last byte inserted, for compatibility with the
  100. INST_SETn_ family of macros.
  101. */
  102. static uint8_t fill_bytes_variadic(uint8_t *bytes, size_t len, ...)
  103. {
  104. va_list vargs;
  105. va_start(vargs, len);
  106. for (size_t i = 0; i < len; i++)
  107. bytes[i] = va_arg(vargs, unsigned);
  108. va_end(vargs);
  109. return bytes[len - 1];
  110. }
  111. /*
  112. Parse a single instruction argument into an ASMInstArg object.
  113. Return ED_NONE (0) on success or an error code on failure.
  114. */
  115. static ASMErrorDesc parse_arg(
  116. ASMInstArg *arg, const char *str, size_t size, char **symbol)
  117. {
  118. #define USE_PARSER(func, argtype, field) \
  119. if (argparse_##func(&arg->data.field, str, size)) { \
  120. arg->type = argtype; \
  121. return ED_NONE; \
  122. }
  123. DEBUG("parse_arg(): -->%.*s<-- %zu", (int) size, str, size)
  124. USE_PARSER(register, AT_REGISTER, reg)
  125. USE_PARSER(immediate, AT_IMMEDIATE, imm)
  126. USE_PARSER(indirect, AT_INDIRECT, indirect)
  127. // AT_INDEXED
  128. // ASMArgIndexed index;
  129. USE_PARSER(condition, AT_CONDITION, cond)
  130. // AT_LABEL
  131. // ASMArgLabel label;
  132. return ED_PS_ARG_SYNTAX;
  133. #undef USE_PARSER
  134. }
  135. /*
  136. Parse an argument string int ASMInstArg objects.
  137. Return ED_NONE (0) on success or an error code on failure.
  138. */
  139. static ASMErrorDesc parse_args(
  140. ASMInstArg args[3], size_t *nargs, const char *str, size_t size)
  141. {
  142. ASMErrorDesc err;
  143. static char *symbol = NULL;
  144. size_t start = 0, i = 0;
  145. while (i < size) {
  146. char c = str[i];
  147. if (c == ',') {
  148. if (i == start)
  149. return ED_PS_ARG_SYNTAX;
  150. if ((err = parse_arg(&args[*nargs], str + start, i - start, &symbol)))
  151. return err;
  152. (*nargs)++;
  153. i++;
  154. if (i < size && str[i] == ' ')
  155. i++;
  156. start = i;
  157. if (i == size)
  158. return ED_PS_ARG_SYNTAX;
  159. if (*nargs >= 3)
  160. return ED_PS_TOO_MANY_ARGS;
  161. } else {
  162. if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
  163. c == ' ' || c == '+' || c == '-' || c == '(' || c == ')' ||
  164. c == '_' || c == '.')
  165. i++;
  166. else
  167. return ED_PS_ARG_SYNTAX;
  168. }
  169. }
  170. if (i > start) {
  171. if ((err = parse_arg(&args[*nargs], str + start, i - start, &symbol)))
  172. return err;
  173. (*nargs)++;
  174. }
  175. return ED_NONE;
  176. }
  177. /* Instruction parser functions */
  178. INST_FUNC(nop)
  179. {
  180. INST_TAKES_NO_ARGS
  181. INST_RETURN(1, 0x00)
  182. }
  183. INST_FUNC(inc)
  184. {
  185. INST_TAKES_ARGS(1, 1)
  186. switch (INST_TYPE(0)) {
  187. case AT_REGISTER:
  188. switch (INST_REG(0)) {
  189. case REG_A: INST_RETURN(1, 0x3C)
  190. case REG_B: INST_RETURN(1, 0x04)
  191. case REG_C: INST_RETURN(1, 0x0C)
  192. case REG_D: INST_RETURN(1, 0x14)
  193. case REG_E: INST_RETURN(1, 0x1C)
  194. case REG_H: INST_RETURN(1, 0x24)
  195. case REG_L: INST_RETURN(1, 0x2C)
  196. case REG_BC: INST_RETURN(1, 0x03)
  197. case REG_DE: INST_RETURN(1, 0x13)
  198. case REG_HL: INST_RETURN(1, 0x23)
  199. case REG_SP: INST_RETURN(1, 0x33)
  200. case REG_IX: INST_RETURN(2, 0xDD, 0x23)
  201. case REG_IY: INST_RETURN(2, 0xFD, 0x23)
  202. case REG_IXH: INST_RETURN(2, 0xDD, 0x2C)
  203. case REG_IXL: INST_RETURN(2, 0xFD, 0x2C)
  204. case REG_IYH: INST_RETURN(2, 0xDD, 0x2C)
  205. case REG_IYL: INST_RETURN(2, 0xFD, 0x2C)
  206. default: INST_ERROR(ARG0_BAD_REG)
  207. }
  208. case AT_INDIRECT:
  209. INST_INDIRECT_HL_ONLY(0)
  210. INST_RETURN(1, 0x34)
  211. case AT_INDEXED:
  212. INST_RETURN(3, INST_INDEX_BYTES(0, 0x34))
  213. default:
  214. INST_ERROR(ARG0_TYPE)
  215. }
  216. }
  217. INST_FUNC(add)
  218. {
  219. INST_TAKES_ARGS(2, 2)
  220. INST_FORCE_TYPE(0, AT_REGISTER)
  221. switch (INST_REG(0)) {
  222. case REG_A:
  223. switch (INST_TYPE(1)) {
  224. case AT_REGISTER:
  225. switch (INST_REG(1)) {
  226. case REG_A: INST_RETURN(1, 0x87)
  227. case REG_B: INST_RETURN(1, 0x80)
  228. case REG_C: INST_RETURN(1, 0x81)
  229. case REG_D: INST_RETURN(1, 0x82)
  230. case REG_E: INST_RETURN(1, 0x83)
  231. case REG_H: INST_RETURN(1, 0x84)
  232. case REG_L: INST_RETURN(1, 0x85)
  233. case REG_IXH: INST_RETURN(2, 0xDD, 0x84)
  234. case REG_IXL: INST_RETURN(2, 0xDD, 0x85)
  235. case REG_IYH: INST_RETURN(2, 0xFD, 0x84)
  236. case REG_IYL: INST_RETURN(2, 0xFD, 0x85)
  237. default: INST_ERROR(ARG1_BAD_REG)
  238. }
  239. case AT_IMMEDIATE:
  240. INST_CHECK_IMM(1, IMM_U8)
  241. INST_RETURN(2, 0xC6, INST_IMM(1).uval)
  242. case AT_INDIRECT:
  243. INST_INDIRECT_HL_ONLY(1)
  244. INST_RETURN(1, 0x86)
  245. case AT_INDEXED:
  246. INST_RETURN(3, INST_INDEX_BYTES(1, 0x86))
  247. default:
  248. INST_ERROR(ARG1_TYPE)
  249. }
  250. case REG_HL:
  251. INST_FORCE_TYPE(1, AT_REGISTER)
  252. switch (INST_REG(1)) {
  253. case REG_BC: INST_RETURN(1, 0x09)
  254. case REG_DE: INST_RETURN(1, 0x19)
  255. case REG_HL: INST_RETURN(1, 0x29)
  256. case REG_SP: INST_RETURN(1, 0x39)
  257. default: INST_ERROR(ARG1_BAD_REG)
  258. }
  259. case REG_IX:
  260. case REG_IY:
  261. INST_FORCE_TYPE(1, AT_REGISTER)
  262. switch (INST_REG(1)) {
  263. case REG_BC: INST_RETURN(2, INST_INDEX_PREFIX(1), 0x09)
  264. case REG_DE: INST_RETURN(2, INST_INDEX_PREFIX(1), 0x19)
  265. case REG_IX:
  266. case REG_IY:
  267. if (INST_REG(0) != INST_REG(1))
  268. INST_ERROR(ARG1_BAD_REG)
  269. INST_RETURN(2, INST_INDEX_PREFIX(1), 0x29)
  270. case REG_SP: INST_RETURN(2, INST_INDEX_PREFIX(1), 0x39)
  271. default: INST_ERROR(ARG1_BAD_REG)
  272. }
  273. default:
  274. INST_ERROR(ARG0_TYPE)
  275. }
  276. }
  277. /*
  278. INST_FUNC(adc)
  279. {
  280. DEBUG("dispatched to -> ADC")
  281. return ED_PS_TOO_FEW_ARGS;
  282. }
  283. */
  284. INST_FUNC(reti)
  285. {
  286. INST_TAKES_NO_ARGS
  287. INST_RETURN(2, 0xED, 0x4D)
  288. }
  289. INST_FUNC(retn)
  290. {
  291. INST_TAKES_NO_ARGS
  292. INST_RETURN(2, 0xED, 0x45)
  293. }
  294. /*
  295. Return the relevant ASMInstParser function for a given mnemonic.
  296. NULL is returned if the mnemonic is not known.
  297. */
  298. ASMInstParser get_inst_parser(char mstr[MAX_MNEMONIC_SIZE])
  299. {
  300. // Exploit the fact that we can store the entire mnemonic string as a
  301. // single 32-bit value to do fast lookups:
  302. uint32_t key = (mstr[0] << 24) + (mstr[1] << 16) + (mstr[2] << 8) + mstr[3];
  303. DEBUG("get_inst_parser(): -->%.*s<-- 0x%08X", MAX_MNEMONIC_SIZE, mstr, key)
  304. HANDLE(nop)
  305. HANDLE(inc)
  306. HANDLE(add)
  307. // HANDLE(adc)
  308. HANDLE(reti)
  309. HANDLE(retn)
  310. return NULL;
  311. }