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.
 
 
 
 
 

214 lignes
7.8 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 "../util.h"
  8. /* Helper macros for get_inst_parser() and lookup_parser() */
  9. #define JOIN(a, b, c, d) ((uint32_t) ((a << 24) + (b << 16) + (c << 8) + d))
  10. #define DISPATCH_(s, z) ( \
  11. (z) == 2 ? JOIN(s[0], s[1], 0x00, 0x00) : \
  12. (z) == 3 ? JOIN(s[0], s[1], s[2], 0x00) : \
  13. JOIN(s[0], s[1], s[2], s[3])) \
  14. #define MAKE_CMP_(s) DISPATCH_(s, sizeof(s) / sizeof(char) - 1)
  15. #define HANDLE(m) if (key == MAKE_CMP_(#m)) return parse_inst_##m;
  16. /* Helper macro for parse_arg() */
  17. #define TRY_PARSER(func, argtype, field) \
  18. if (mask & argtype && argparse_##func(&arg->data.field, info)) { \
  19. arg->type = argtype; \
  20. return ED_NONE; \
  21. }
  22. /* Internal helper macros */
  23. #define INST_ALLOC_(len) \
  24. *length = len; \
  25. *bytes = cr_malloc(sizeof(uint8_t) * (len));
  26. #define INST_SET_(b, val) ((*bytes)[b] = val)
  27. #define INST_SET1_(b1) INST_SET_(0, b1)
  28. #define INST_SET2_(b1, b2) INST_SET1_(b1), INST_SET_(1, b2)
  29. #define INST_SET3_(b1, b2, b3) INST_SET2_(b1, b2), INST_SET_(2, b3)
  30. #define INST_SET4_(b1, b2, b3, b4) INST_SET3_(b1, b2, b3), INST_SET_(3, b4)
  31. #define INST_DISPATCH_(a, b, c, d, target, ...) target
  32. #define INST_FILL_BYTES_(len, ...) \
  33. ((len > 4) ? fill_bytes_variadic(*bytes, len, __VA_ARGS__) : \
  34. INST_DISPATCH_(__VA_ARGS__, INST_SET4_, INST_SET3_, INST_SET2_, \
  35. INST_SET1_, __VA_ARGS__)(__VA_ARGS__));
  36. #define INST_PREFIX_(reg) \
  37. (((reg) == REG_IX || (reg) == REG_IXH || (reg) == REG_IXL) ? \
  38. INST_IX_PREFIX : INST_IY_PREFIX)
  39. /* Helper macros for instruction parsers */
  40. #define INST_FUNC(mnemonic) \
  41. static ASMErrorDesc parse_inst_##mnemonic( \
  42. uint8_t **bytes, size_t *length, char **symbol, ASMArgParseInfo ap_info) \
  43. #define INST_ERROR(desc) return ED_PS_##desc;
  44. #define INST_TAKES_NO_ARGS \
  45. if (ap_info.arg) \
  46. INST_ERROR(TOO_MANY_ARGS)
  47. #define INST_TAKES_ARGS(a0, a1, a2) \
  48. ASMInstArg args[3]; \
  49. size_t nargs; \
  50. ASMArgType masks[] = {a0, a1, a2}; \
  51. ASMErrorDesc err = parse_args(args, &nargs, ap_info, masks); \
  52. if (err) \
  53. return err; \
  54. #define INST_NARGS nargs
  55. #define INST_TYPE(n) args[n].type
  56. #define INST_REG(n) args[n].data.reg
  57. #define INST_IMM(n) args[n].data.imm
  58. #define INST_INDIRECT(n) args[n].data.indirect
  59. #define INST_INDEX(n) args[n].data.index
  60. #define INST_COND(n) args[n].data.cond
  61. #define INST_PORT(n) args[n].data.port
  62. #define INST_IX_PREFIX 0xDD
  63. #define INST_IY_PREFIX 0xFD
  64. #define INST_RETURN(len, ...) { \
  65. (void) symbol; \
  66. INST_ALLOC_(len) \
  67. INST_FILL_BYTES_(len, __VA_ARGS__) \
  68. return ED_NONE; \
  69. }
  70. #define INST_IMM_U16_B1(imm) \
  71. ((imm).is_label ? \
  72. (*symbol = cr_strdup((imm).label), 0) : \
  73. (imm).uval & 0xFF)
  74. #define INST_IMM_U16_B2(imm) \
  75. ((imm).is_label ? 0 : (imm).uval >> 8)
  76. #define INST_INDEX_PREFIX(n) INST_PREFIX_(INST_INDEX(n).reg)
  77. /*
  78. Fill an instruction's byte array with the given data.
  79. This internal function is only called for instructions longer than four
  80. bytes (of which there is only one: the fake emulator debugging/testing
  81. opcode with mnemonic "emu"), so it does not get used in normal situations.
  82. Return the value of the last byte inserted, for compatibility with the
  83. INST_SETn_ family of macros.
  84. */
  85. static uint8_t fill_bytes_variadic(uint8_t *bytes, size_t len, ...)
  86. {
  87. va_list vargs;
  88. va_start(vargs, len);
  89. for (size_t i = 0; i < len; i++)
  90. bytes[i] = va_arg(vargs, unsigned);
  91. va_end(vargs);
  92. return bytes[len - 1];
  93. }
  94. /*
  95. Parse a single instruction argument into an ASMInstArg object.
  96. Return ED_NONE (0) on success or an error code on failure.
  97. */
  98. static ASMErrorDesc parse_arg(
  99. ASMInstArg *arg, const char *str, size_t size, ASMDefineTable *deftable,
  100. ASMArgType mask)
  101. {
  102. ASMArgParseInfo info = {.arg = str, .size = size, .deftable = deftable};
  103. TRY_PARSER(register, AT_REGISTER, reg)
  104. TRY_PARSER(condition, AT_CONDITION, cond)
  105. TRY_PARSER(indexed, AT_INDEXED, index)
  106. TRY_PARSER(indirect, AT_INDIRECT, indirect)
  107. TRY_PARSER(port, AT_PORT, port)
  108. TRY_PARSER(immediate, AT_IMMEDIATE, imm)
  109. return ED_PS_ARG_SYNTAX;
  110. }
  111. /*
  112. Parse an argument string into ASMInstArg objects.
  113. Return ED_NONE (0) on success or an error code on failure.
  114. */
  115. static ASMErrorDesc parse_args(
  116. ASMInstArg args[3], size_t *nargs, ASMArgParseInfo ap_info,
  117. ASMArgType masks[3])
  118. {
  119. ASMErrorDesc err;
  120. ASMDefineTable *dt = ap_info.deftable;
  121. const char *str = ap_info.arg;
  122. size_t size = ap_info.size, start = 0, i = 0, n = 0;
  123. while (i < size) {
  124. char c = str[i];
  125. if (c == ',') {
  126. if (i == start)
  127. return ED_PS_ARG_SYNTAX;
  128. if (masks[n] == AT_NONE)
  129. return ED_PS_TOO_MANY_ARGS;
  130. err = parse_arg(&args[n], str + start, i - start, dt, masks[n]);
  131. if (err)
  132. return err;
  133. n++;
  134. i++;
  135. if (i < size && str[i] == ' ')
  136. i++;
  137. start = i;
  138. if (i == size)
  139. return ED_PS_ARG_SYNTAX;
  140. if (n >= 3)
  141. return ED_PS_TOO_MANY_ARGS;
  142. } else {
  143. if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
  144. c == ' ' || c == '+' || c == '-' || c == '(' || c == ')' ||
  145. c == '$' || c == '_' || c == '.')
  146. i++;
  147. else
  148. return ED_PS_ARG_SYNTAX;
  149. }
  150. }
  151. if (i > start) {
  152. if (masks[n] == AT_NONE)
  153. return ED_PS_TOO_MANY_ARGS;
  154. if ((err = parse_arg(&args[n], str + start, i - start, dt, masks[n])))
  155. return err;
  156. n++;
  157. }
  158. if (n < 3 && masks[n] != AT_NONE && !(masks[n] & AT_OPTIONAL))
  159. return ED_PS_TOO_FEW_ARGS;
  160. *nargs = n;
  161. return ED_NONE;
  162. }
  163. #include "instructions.inc.c"
  164. /*
  165. Return the relevant ASMInstParser function for a given mnemonic.
  166. NULL is returned if the mnemonic is not known.
  167. */
  168. ASMInstParser get_inst_parser(char mstr[MAX_MNEMONIC_SIZE])
  169. {
  170. // Exploit the fact that we can store the entire mnemonic string as a
  171. // single 32-bit value to do fast lookups:
  172. uint32_t key = JOIN(mstr[0], mstr[1], mstr[2], mstr[3]);
  173. return lookup_parser(key);
  174. }