An emulator, assembler, and disassembler for the Sega Game Gear
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 
 

310 рядки
11 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. /*
  10. TEMP SYNTAX NOTES:
  11. - http://clrhome.org/table/
  12. - http://www.z80.info/z80undoc.htm
  13. - http://www.z80.info/z80code.txt
  14. - http://www.z80.info/z80href.txt
  15. inst := mnemonic [arg[, arg[, arg]]]
  16. mnemonic := [a-z0-9]{2-4}
  17. arg := register | immediate | indirect | indexed | label | condition
  18. register := A | B | C | D | E | AF | BC | DE | HL | H | L | F | I | IX |
  19. IY | PC | R | SP | AF' | IXH | IXL | IYH | IYL
  20. immediate := 16-bit integer
  21. indirect := \( (register | immediate) \)
  22. indexed := \( (IX | IY) + immediate \)
  23. label := string
  24. condition := NZ | N | NC | C | PO | PE | P | M
  25. */
  26. /* Helper macros for get_inst_parser() */
  27. #define JOIN_(a, b, c, d) ((uint32_t) ((a << 24) + (b << 16) + (c << 8) + d))
  28. #define DISPATCH_(s, z) ( \
  29. (z) == 2 ? JOIN_(s[0], s[1], 0x00, 0x00) : \
  30. (z) == 3 ? JOIN_(s[0], s[1], s[2], 0x00) : \
  31. JOIN_(s[0], s[1], s[2], s[3])) \
  32. #define MAKE_CMP_(s) DISPATCH_(s, sizeof(s) / sizeof(char) - 1)
  33. #define HANDLE(m) if (key == MAKE_CMP_(#m)) return parse_inst_##m;
  34. /* Internal helper macros for instruction parsers */
  35. #define INST_ALLOC_(len) \
  36. *length = len; \
  37. if (!(*bytes = malloc(sizeof(uint8_t) * (len)))) \
  38. OUT_OF_MEMORY()
  39. #define INST_SET_(b, val) ((*bytes)[b] = val)
  40. #define INST_SET1_(b1) INST_SET_(0, b1)
  41. #define INST_SET2_(b1, b2) INST_SET1_(b1), INST_SET_(1, b2)
  42. #define INST_SET3_(b1, b2, b3) INST_SET2_(b1, b2), INST_SET_(2, b3)
  43. #define INST_SET4_(b1, b2, b3, b4) INST_SET3_(b1, b2, b3), INST_SET_(3, b4)
  44. #define INST_DISPATCH_(a, b, c, d, target, ...) target
  45. #define INST_FILL_BYTES_(len, ...) \
  46. ((len > 4) ? fill_bytes_variadic(*bytes, len, __VA_ARGS__) : \
  47. INST_DISPATCH_(__VA_ARGS__, INST_SET4_, INST_SET3_, INST_SET2_, \
  48. INST_SET1_, __VA_ARGS__)(__VA_ARGS__));
  49. #define INST_PREFIX_(reg) \
  50. (((reg) == REG_IX || (reg) == REG_IXH || (reg) == REG_IXL) ? 0xDD : 0xFD)
  51. /* Helper macros for instruction parsers */
  52. #define INST_FUNC(mnemonic) \
  53. static ASMErrorDesc parse_inst_##mnemonic( \
  54. uint8_t **bytes, size_t *length, char **symbol, const char *arg, size_t size)
  55. #define INST_ERROR(desc) return ED_PS_##desc;
  56. #define INST_TAKES_NO_ARGS \
  57. if (arg) \
  58. INST_ERROR(TOO_MANY_ARGS) \
  59. (void) size;
  60. #define INST_TAKES_ARGS(lo, hi) \
  61. if (!arg) \
  62. INST_ERROR(TOO_FEW_ARGS) \
  63. ASMInstArg args[3]; \
  64. size_t nargs = 0; \
  65. ASMErrorDesc err = parse_args(args, &nargs, arg, size); \
  66. if (err) \
  67. return err; \
  68. if (nargs < lo) \
  69. INST_ERROR(TOO_FEW_ARGS) \
  70. if (nargs > hi) \
  71. INST_ERROR(TOO_MANY_ARGS)
  72. #define INST_TYPE(n) args[n].type
  73. #define INST_REG(n) args[n].data.reg
  74. #define INST_IMM(n) args[n].data.imm
  75. #define INST_INDIRECT(n) args[n].data.indirect
  76. #define INST_INDEX(n) args[n].data.index
  77. #define INST_LABEL(n) args[n].data.label
  78. #define INST_COND(n) args[n].data.cond
  79. #define INST_REG_PREFIX(n) INST_PREFIX_(INST_REG(n))
  80. #define INST_INDEX_PREFIX(n) INST_PREFIX_(INST_INDEX(n).reg)
  81. #define INST_IND_PREFIX(n) INST_PREFIX_(INST_INDIRECT(n).addr.reg)
  82. #define INST_RETURN(len, ...) { \
  83. (void) symbol; \
  84. INST_ALLOC_(len) \
  85. INST_FILL_BYTES_(len, __VA_ARGS__) \
  86. return ED_NONE; \
  87. }
  88. #define INST_RETURN_WITH_SYMBOL(len, label, ...) { \
  89. *symbol = strdup(label); \
  90. if (!(*symbol)) \
  91. OUT_OF_MEMORY() \
  92. INST_ALLOC_(len) \
  93. INST_FILL_BYTES_(len - 2, __VA_ARGS__) \
  94. return ED_NONE; \
  95. }
  96. /*
  97. Fill an instruction's byte array with the given data.
  98. This internal function is only called for instructions longer than four
  99. bytes (of which there is only one: the fake emulator debugging/testing
  100. opcode with mnemonic "emu"), so it does not get used in normal situations.
  101. Return the value of the last byte inserted, for compatibility with the
  102. INST_SETn_ family of macros.
  103. */
  104. static uint8_t fill_bytes_variadic(uint8_t *bytes, size_t len, ...)
  105. {
  106. va_list vargs;
  107. va_start(vargs, len);
  108. for (size_t i = 0; i < len; i++)
  109. bytes[i] = va_arg(vargs, unsigned);
  110. va_end(vargs);
  111. return bytes[len - 1];
  112. }
  113. /*
  114. Parse a single instruction argument into an ASMInstArg object.
  115. Return ED_NONE (0) on success or an error code on failure.
  116. */
  117. static ASMErrorDesc parse_arg(
  118. ASMInstArg *arg, const char *str, size_t size, char **symbol)
  119. {
  120. #define USE_PARSER(func, argtype, field) \
  121. if (argparse_##func(&arg->data.field, str, size)) { \
  122. arg->type = argtype; \
  123. return ED_NONE; \
  124. }
  125. DEBUG("parse_arg(): -->%.*s<-- %zu", (int) size, str, size)
  126. USE_PARSER(register, AT_REGISTER, reg)
  127. USE_PARSER(immediate, AT_IMMEDIATE, imm)
  128. // AT_INDIRECT
  129. // ASMArgIndirect indirect;
  130. // AT_INDEXED
  131. // ASMArgIndexed index;
  132. USE_PARSER(condition, AT_CONDITION, cond)
  133. // AT_LABEL
  134. // ASMArgLabel label;
  135. return ED_PS_ARG_SYNTAX;
  136. #undef USE_PARSER
  137. }
  138. /*
  139. Parse an argument string int ASMInstArg objects.
  140. Return ED_NONE (0) on success or an error code on failure.
  141. */
  142. static ASMErrorDesc parse_args(
  143. ASMInstArg args[3], size_t *nargs, const char *str, size_t size)
  144. {
  145. ASMErrorDesc err;
  146. static char *symbol = NULL;
  147. size_t start = 0, i = 0;
  148. while (i < size) {
  149. char c = str[i];
  150. if (c == ',') {
  151. if (i == start)
  152. return ED_PS_ARG_SYNTAX;
  153. if ((err = parse_arg(&args[*nargs], str + start, i - start, &symbol)))
  154. return err;
  155. (*nargs)++;
  156. i++;
  157. if (i < size && str[i] == ' ')
  158. i++;
  159. start = i;
  160. if (i == size)
  161. return ED_PS_ARG_SYNTAX;
  162. if (*nargs >= 3)
  163. return ED_PS_TOO_MANY_ARGS;
  164. } else {
  165. if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
  166. c == ' ' || c == '+' || c == '-' || c == '(' || c == ')' ||
  167. c == '_' || c == '.')
  168. i++;
  169. else
  170. return ED_PS_ARG_SYNTAX;
  171. }
  172. }
  173. if (i > start) {
  174. if ((err = parse_arg(&args[*nargs], str + start, i - start, &symbol)))
  175. return err;
  176. (*nargs)++;
  177. }
  178. return ED_NONE;
  179. }
  180. /* Instruction parser functions */
  181. INST_FUNC(nop)
  182. {
  183. INST_TAKES_NO_ARGS
  184. INST_RETURN(1, 0x00)
  185. }
  186. INST_FUNC(inc)
  187. {
  188. INST_TAKES_ARGS(1, 1)
  189. switch (INST_TYPE(0)) {
  190. case AT_REGISTER:
  191. switch (INST_REG(0)) {
  192. case REG_A: INST_RETURN(1, 0x3C)
  193. case REG_B: INST_RETURN(1, 0x04)
  194. case REG_C: INST_RETURN(1, 0x0C)
  195. case REG_D: INST_RETURN(1, 0x14)
  196. case REG_E: INST_RETURN(1, 0x1C)
  197. case REG_H: INST_RETURN(1, 0x24)
  198. case REG_L: INST_RETURN(1, 0x2C)
  199. case REG_BC: INST_RETURN(1, 0x03)
  200. case REG_DE: INST_RETURN(1, 0x13)
  201. case REG_HL: INST_RETURN(1, 0x23)
  202. case REG_SP: INST_RETURN(1, 0x33)
  203. case REG_IX: INST_RETURN(2, 0xDD, 0x23)
  204. case REG_IY: INST_RETURN(2, 0xFD, 0x23)
  205. case REG_IXH: INST_RETURN(2, 0xDD, 0x2C)
  206. case REG_IXL: INST_RETURN(2, 0xFD, 0x2C)
  207. case REG_IYH: INST_RETURN(2, 0xDD, 0x2C)
  208. case REG_IYL: INST_RETURN(2, 0xFD, 0x2C)
  209. default: INST_ERROR(ARG0_BAD_REG)
  210. }
  211. case AT_INDIRECT:
  212. if (INST_INDIRECT(0).type != AT_REGISTER)
  213. INST_ERROR(ARG0_TYPE)
  214. if (INST_INDIRECT(0).addr.reg != REG_HL)
  215. INST_ERROR(ARG0_BAD_REG)
  216. INST_RETURN(2, 0x34)
  217. case AT_INDEXED:
  218. INST_RETURN(3, INST_INDEX_PREFIX(0), 0x34, INST_INDEX(0).offset)
  219. default:
  220. INST_ERROR(ARG0_TYPE)
  221. }
  222. }
  223. /*
  224. INST_FUNC(add)
  225. {
  226. DEBUG("dispatched to -> ADD")
  227. return ED_PS_TOO_FEW_ARGS;
  228. }
  229. INST_FUNC(adc)
  230. {
  231. DEBUG("dispatched to -> ADC")
  232. return ED_PS_TOO_FEW_ARGS;
  233. }
  234. */
  235. INST_FUNC(retn)
  236. {
  237. INST_TAKES_NO_ARGS
  238. INST_RETURN(2, 0xED, 0x45)
  239. }
  240. /*
  241. Return the relevant ASMInstParser function for a given mnemonic.
  242. NULL is returned if the mnemonic is not known.
  243. */
  244. ASMInstParser get_inst_parser(char mstr[MAX_MNEMONIC_SIZE])
  245. {
  246. // Exploit the fact that we can store the entire mnemonic string as a
  247. // single 32-bit value to do fast lookups:
  248. uint32_t key = (mstr[0] << 24) + (mstr[1] << 16) + (mstr[2] << 8) + mstr[3];
  249. DEBUG("get_inst_parser(): -->%.*s<-- 0x%08X", MAX_MNEMONIC_SIZE, mstr, key)
  250. HANDLE(nop)
  251. HANDLE(inc)
  252. // HANDLE(add)
  253. // HANDLE(adc)
  254. HANDLE(retn)
  255. return NULL;
  256. }