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.

преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  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 ? (*symbol = cr_strdup((imm).label), 0) : (imm).uval >> 8)
  72. #define INST_IMM_U16_B2(imm) \
  73. ((imm).is_label ? 0 : (imm).uval & 0xFF)
  74. #define INST_INDEX_PREFIX(n) INST_PREFIX_(INST_INDEX(n).reg)
  75. /*
  76. Fill an instruction's byte array with the given data.
  77. This internal function is only called for instructions longer than four
  78. bytes (of which there is only one: the fake emulator debugging/testing
  79. opcode with mnemonic "emu"), so it does not get used in normal situations.
  80. Return the value of the last byte inserted, for compatibility with the
  81. INST_SETn_ family of macros.
  82. */
  83. static uint8_t fill_bytes_variadic(uint8_t *bytes, size_t len, ...)
  84. {
  85. va_list vargs;
  86. va_start(vargs, len);
  87. for (size_t i = 0; i < len; i++)
  88. bytes[i] = va_arg(vargs, unsigned);
  89. va_end(vargs);
  90. return bytes[len - 1];
  91. }
  92. /*
  93. Parse a single instruction argument into an ASMInstArg object.
  94. Return ED_NONE (0) on success or an error code on failure.
  95. */
  96. static ASMErrorDesc parse_arg(
  97. ASMInstArg *arg, const char *str, size_t size, ASMDefineTable *deftable,
  98. ASMArgType mask)
  99. {
  100. ASMArgParseInfo info = {.arg = str, .size = size, .deftable = deftable};
  101. TRY_PARSER(register, AT_REGISTER, reg)
  102. TRY_PARSER(condition, AT_CONDITION, cond)
  103. TRY_PARSER(indexed, AT_INDEXED, index)
  104. TRY_PARSER(indirect, AT_INDIRECT, indirect)
  105. TRY_PARSER(port, AT_PORT, port)
  106. TRY_PARSER(immediate, AT_IMMEDIATE, imm)
  107. return ED_PS_ARG_SYNTAX;
  108. }
  109. /*
  110. Parse an argument string into ASMInstArg objects.
  111. Return ED_NONE (0) on success or an error code on failure.
  112. */
  113. static ASMErrorDesc parse_args(
  114. ASMInstArg args[3], size_t *nargs, ASMArgParseInfo ap_info,
  115. ASMArgType masks[3])
  116. {
  117. ASMErrorDesc err;
  118. ASMDefineTable *dt = ap_info.deftable;
  119. const char *str = ap_info.arg;
  120. size_t size = ap_info.size, start = 0, i = 0, n = 0;
  121. while (i < size) {
  122. char c = str[i];
  123. if (c == ',') {
  124. if (i == start)
  125. return ED_PS_ARG_SYNTAX;
  126. if (masks[n] == AT_NONE)
  127. return ED_PS_TOO_MANY_ARGS;
  128. err = parse_arg(&args[n], str + start, i - start, dt, masks[n]);
  129. if (err)
  130. return err;
  131. n++;
  132. i++;
  133. if (i < size && str[i] == ' ')
  134. i++;
  135. start = i;
  136. if (i == size)
  137. return ED_PS_ARG_SYNTAX;
  138. if (n >= 3)
  139. return ED_PS_TOO_MANY_ARGS;
  140. } else {
  141. if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
  142. c == ' ' || c == '+' || c == '-' || c == '(' || c == ')' ||
  143. c == '$' || c == '_' || c == '.')
  144. i++;
  145. else
  146. return ED_PS_ARG_SYNTAX;
  147. }
  148. }
  149. if (i > start) {
  150. if (masks[n] == AT_NONE)
  151. return ED_PS_TOO_MANY_ARGS;
  152. if ((err = parse_arg(&args[n], str + start, i - start, dt, masks[n])))
  153. return err;
  154. n++;
  155. }
  156. if (n < 3 && masks[n] != AT_NONE && !(masks[n] & AT_OPTIONAL))
  157. return ED_PS_TOO_FEW_ARGS;
  158. *nargs = n;
  159. return ED_NONE;
  160. }
  161. #include "instructions.inc.c"
  162. /*
  163. Return the relevant ASMInstParser function for a given mnemonic.
  164. NULL is returned if the mnemonic is not known.
  165. */
  166. ASMInstParser get_inst_parser(char mstr[MAX_MNEMONIC_SIZE])
  167. {
  168. // Exploit the fact that we can store the entire mnemonic string as a
  169. // single 32-bit value to do fast lookups:
  170. uint32_t key = JOIN(mstr[0], mstr[1], mstr[2], mstr[3]);
  171. return lookup_parser(key);
  172. }