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.
 
 
 
 
 

156 lines
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);