An emulator, assembler, and disassembler for the Sega Game Gear
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 

311 lignes
10 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. // TODO
  121. // AT_REGISTER
  122. // AT_IMMEDIATE
  123. // AT_INDIRECT
  124. // AT_INDEXED
  125. // AT_LABEL
  126. // AT_CONDITION
  127. // ASMArgRegister reg;
  128. // ASMArgImmediate imm;
  129. // ASMArgIndirect indirect;
  130. // ASMArgIndexed index;
  131. // ASMArgLabel label;
  132. // ASMArgCondition cond;
  133. DEBUG("parse_arg(): -->%.*s<-- %zu", (int) size, str, size)
  134. if (parse_register(&arg->data.reg, str, size)) {
  135. arg->type = AT_REGISTER;
  136. return ED_NONE;
  137. }
  138. if (parse_condition(&arg->data.cond, str, size)) {
  139. arg->type = AT_CONDITION;
  140. return ED_NONE;
  141. }
  142. return ED_PS_ARG_SYNTAX;
  143. }
  144. /*
  145. Parse an argument string int ASMInstArg objects.
  146. Return ED_NONE (0) on success or an error code on failure.
  147. */
  148. static ASMErrorDesc parse_args(
  149. ASMInstArg args[3], size_t *nargs, const char *str, size_t size)
  150. {
  151. ASMErrorDesc err;
  152. static char *symbol = NULL;
  153. size_t start = 0, i = 0;
  154. while (i < size) {
  155. char c = str[i];
  156. if (c == ',') {
  157. if ((err = parse_arg(&args[*nargs], str + start, i - start, &symbol)))
  158. return err;
  159. (*nargs)++;
  160. i++;
  161. if (i < size && str[i] == ' ')
  162. i++;
  163. start = i;
  164. if (*nargs >= 3 && i < size)
  165. return ED_PS_TOO_MANY_ARGS;
  166. } else {
  167. if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
  168. c == ' ' || c == '+' || c == '-' || c == '(' || c == ')' ||
  169. c == '_' || c == '.')
  170. i++;
  171. else
  172. return ED_PS_ARG_SYNTAX;
  173. }
  174. }
  175. if (i > start) {
  176. if ((err = parse_arg(&args[*nargs], str + start, i - start, &symbol)))
  177. return err;
  178. (*nargs)++;
  179. }
  180. return ED_NONE;
  181. }
  182. /* Instruction parser functions */
  183. INST_FUNC(nop)
  184. {
  185. INST_TAKES_NO_ARGS
  186. INST_RETURN(1, 0x00)
  187. }
  188. INST_FUNC(inc)
  189. {
  190. INST_TAKES_ARGS(1, 1)
  191. switch (INST_TYPE(0)) {
  192. case AT_REGISTER:
  193. switch (INST_REG(0)) {
  194. case REG_A: INST_RETURN(1, 0x3C)
  195. case REG_B: INST_RETURN(1, 0x04)
  196. case REG_C: INST_RETURN(1, 0x0C)
  197. case REG_D: INST_RETURN(1, 0x14)
  198. case REG_E: INST_RETURN(1, 0x1C)
  199. case REG_H: INST_RETURN(1, 0x24)
  200. case REG_L: INST_RETURN(1, 0x2C)
  201. case REG_BC: INST_RETURN(1, 0x03)
  202. case REG_DE: INST_RETURN(1, 0x13)
  203. case REG_HL: INST_RETURN(1, 0x23)
  204. case REG_SP: INST_RETURN(1, 0x33)
  205. case REG_IX: INST_RETURN(2, 0xDD, 0x23)
  206. case REG_IY: INST_RETURN(2, 0xFD, 0x23)
  207. case REG_IXH: INST_RETURN(2, 0xDD, 0x2C)
  208. case REG_IXL: INST_RETURN(2, 0xFD, 0x2C)
  209. case REG_IYH: INST_RETURN(2, 0xDD, 0x2C)
  210. case REG_IYL: INST_RETURN(2, 0xFD, 0x2C)
  211. default: INST_ERROR(ARG0_BAD_REG)
  212. }
  213. case AT_INDIRECT:
  214. if (INST_INDIRECT(0).type != AT_REGISTER)
  215. INST_ERROR(ARG0_TYPE)
  216. if (INST_INDIRECT(0).addr.reg != REG_HL)
  217. INST_ERROR(ARG0_BAD_REG)
  218. INST_RETURN(2, 0x34)
  219. case AT_INDEXED:
  220. INST_RETURN(3, INST_INDEX_PREFIX(0), 0x34, INST_INDEX(0).offset)
  221. default:
  222. INST_ERROR(ARG0_TYPE)
  223. }
  224. }
  225. /*
  226. INST_FUNC(add)
  227. {
  228. DEBUG("dispatched to -> ADD")
  229. return ED_PS_TOO_FEW_ARGS;
  230. }
  231. INST_FUNC(adc)
  232. {
  233. DEBUG("dispatched to -> ADC")
  234. return ED_PS_TOO_FEW_ARGS;
  235. }
  236. */
  237. INST_FUNC(retn)
  238. {
  239. INST_TAKES_NO_ARGS
  240. INST_RETURN(2, 0xED, 0x45)
  241. }
  242. /*
  243. Return the relevant ASMInstParser function for a given mnemonic.
  244. NULL is returned if the mnemonic is not known.
  245. */
  246. ASMInstParser get_inst_parser(char mstr[MAX_MNEMONIC_SIZE])
  247. {
  248. // Exploit the fact that we can store the entire mnemonic string as a
  249. // single 32-bit value to do fast lookups:
  250. uint32_t key = (mstr[0] << 24) + (mstr[1] << 16) + (mstr[2] << 8) + mstr[3];
  251. DEBUG("get_inst_parser(): -->%.*s<-- 0x%08X", MAX_MNEMONIC_SIZE, mstr, key)
  252. HANDLE(nop)
  253. HANDLE(inc)
  254. // HANDLE(add)
  255. // HANDLE(adc)
  256. HANDLE(retn)
  257. return NULL;
  258. }