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.
 
 
 
 
 

156 lignes
7.4 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. #pragma once
  4. #include <stdarg.h>
  5. #include <stdlib.h>
  6. #include "errors.h"
  7. #include "inst_args.h"
  8. #include "parse_util.h"
  9. #include "../util.h"
  10. /* Helper macros for get_inst_parser() */
  11. #define JOIN_(a, b, c, d) ((uint32_t) ((a << 24) + (b << 16) + (c << 8) + d))
  12. #define DISPATCH_(s, z) ( \
  13. (z) == 2 ? JOIN_(s[0], s[1], 0x00, 0x00) : \
  14. (z) == 3 ? JOIN_(s[0], s[1], s[2], 0x00) : \
  15. JOIN_(s[0], s[1], s[2], s[3])) \
  16. #define MAKE_CMP_(s) DISPATCH_(s, sizeof(s) / sizeof(char) - 1)
  17. #define HANDLE(m) if (key == MAKE_CMP_(#m)) return parse_inst_##m;
  18. /* Internal helper macros */
  19. #define INST_ALLOC_(len) \
  20. *length = len; \
  21. *bytes = cr_malloc(sizeof(uint8_t) * (len));
  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_IX_PREFIX_ 0xDD
  33. #define INST_IY_PREFIX_ 0xFD
  34. #define INST_PREFIX_(reg) \
  35. (((reg) == REG_IX || (reg) == REG_IXH || (reg) == REG_IXL) ? \
  36. INST_IX_PREFIX_ : INST_IY_PREFIX_)
  37. #define INST_RETURN_WITH_SYMBOL_(len, label, ...) { \
  38. *symbol = cr_strdup(label.text); \
  39. INST_ALLOC_(len) \
  40. INST_FILL_BYTES_(len - 2, __VA_ARGS__) \
  41. return ED_NONE; \
  42. }
  43. /* Essential/basic helper macros */
  44. #define INST_FUNC(mnemonic) \
  45. static ASMErrorDesc parse_inst_##mnemonic( \
  46. uint8_t **bytes, size_t *length, char **symbol, ASMArgParseInfo ap_info) \
  47. #define INST_ERROR(desc) return ED_PS_##desc;
  48. #define INST_TAKES_NO_ARGS \
  49. if (ap_info.arg) \
  50. INST_ERROR(TOO_MANY_ARGS)
  51. #define INST_TAKES_ARGS(lo, hi) \
  52. if (!ap_info.arg) \
  53. INST_ERROR(TOO_FEW_ARGS) \
  54. ASMInstArg args[3]; \
  55. size_t nargs = 0; \
  56. ASMErrorDesc err = parse_args(args, &nargs, ap_info); \
  57. if (err) \
  58. return err; \
  59. if (nargs < lo) \
  60. INST_ERROR(TOO_FEW_ARGS) \
  61. if (nargs > hi) \
  62. INST_ERROR(TOO_MANY_ARGS)
  63. #define INST_NARGS nargs
  64. #define INST_TYPE(n) args[n].type
  65. #define INST_REG(n) args[n].data.reg
  66. #define INST_IMM(n) args[n].data.imm
  67. #define INST_INDIRECT(n) args[n].data.indirect
  68. #define INST_INDEX(n) args[n].data.index
  69. #define INST_LABEL(n) args[n].data.label
  70. #define INST_COND(n) args[n].data.cond
  71. #define INST_RETURN(len, ...) { \
  72. (void) symbol; \
  73. INST_ALLOC_(len) \
  74. INST_FILL_BYTES_(len, __VA_ARGS__) \
  75. return ED_NONE; \
  76. }
  77. /* Convenience macros */
  78. #define INST_FORCE_TYPE(n, t) { \
  79. if (INST_TYPE(n) != t) \
  80. INST_ERROR(ARG##n##_TYPE) \
  81. }
  82. #define INST_CHECK_IMM(n, m) { \
  83. if (!(INST_IMM(n).mask & (m))) \
  84. INST_ERROR(ARG##n##_RANGE) \
  85. }
  86. #define INST_REG_ONLY(n, reg) { \
  87. if (INST_TYPE(n) != AT_REGISTER) \
  88. INST_ERROR(ARG##n##_TYPE) \
  89. if (INST_REG(n) != reg) \
  90. INST_ERROR(ARG##n##_BAD_REG) \
  91. }
  92. #define INST_INDIRECT_HL_ONLY(n) { \
  93. if (INST_INDIRECT(n).type != AT_REGISTER) \
  94. INST_ERROR(ARG##n##_TYPE) \
  95. if (INST_INDIRECT(n).addr.reg != REG_HL) \
  96. INST_ERROR(ARG##n##_BAD_REG) \
  97. }
  98. #define INST_INDEX_PREFIX(n) INST_PREFIX_(INST_INDEX(n).reg)
  99. #define INST_INDEX_BYTES(n, b) \
  100. INST_INDEX_PREFIX(n), b, INST_INDEX(n).offset
  101. #define INST_INDIRECT_IMM(n) \
  102. INST_INDIRECT(n).addr.imm.uval >> 8, \
  103. INST_INDIRECT(n).addr.imm.uval & 0xFF
  104. #define INST_RETURN_INDIRECT_LABEL(n, len, ...) \
  105. INST_RETURN_WITH_SYMBOL_(len, INST_INDIRECT(n).addr.label, __VA_ARGS__)
  106. #define INST_HANDLE_MAIN_8_BIT_REGS(base) \
  107. case REG_A: INST_RETURN(1, base + 7) \
  108. case REG_B: INST_RETURN(1, base) \
  109. case REG_C: INST_RETURN(1, base + 1) \
  110. case REG_D: INST_RETURN(1, base + 2) \
  111. case REG_E: INST_RETURN(1, base + 3) \
  112. case REG_H: INST_RETURN(1, base + 4) \
  113. case REG_L: INST_RETURN(1, base + 5) \
  114. case REG_IXH: INST_RETURN(2, INST_IX_PREFIX_, base + 4) \
  115. case REG_IXL: INST_RETURN(2, INST_IX_PREFIX_, base + 5) \
  116. case REG_IYH: INST_RETURN(2, INST_IY_PREFIX_, base + 4) \
  117. case REG_IYL: INST_RETURN(2, INST_IY_PREFIX_, base + 5) \
  118. /* Internal functions */
  119. uint8_t fill_bytes_variadic(uint8_t*, size_t, ...);
  120. ASMErrorDesc parse_args(ASMInstArg args[3], size_t*, ASMArgParseInfo);