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.
 
 
 
 
 

99 lines
3.1 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 "inst_support.h"
  4. /* Macro used by parse_arg() */
  5. #define TRY_PARSER(func, argtype, field) \
  6. if (argparse_##func(&arg->data.field, info)) { \
  7. arg->type = argtype; \
  8. return ED_NONE; \
  9. }
  10. /*
  11. Fill an instruction's byte array with the given data.
  12. This internal function is only called for instructions longer than four
  13. bytes (of which there is only one: the fake emulator debugging/testing
  14. opcode with mnemonic "emu"), so it does not get used in normal situations.
  15. Return the value of the last byte inserted, for compatibility with the
  16. INST_SETn_ family of macros.
  17. */
  18. uint8_t fill_bytes_variadic(uint8_t *bytes, size_t len, ...)
  19. {
  20. va_list vargs;
  21. va_start(vargs, len);
  22. for (size_t i = 0; i < len; i++)
  23. bytes[i] = va_arg(vargs, unsigned);
  24. va_end(vargs);
  25. return bytes[len - 1];
  26. }
  27. /*
  28. Parse a single instruction argument into an ASMInstArg object.
  29. Return ED_NONE (0) on success or an error code on failure.
  30. */
  31. static ASMErrorDesc parse_arg(
  32. ASMInstArg *arg, const char *str, size_t size, ASMDefineTable *deftable)
  33. {
  34. ASMArgParseInfo info = {.arg = str, .size = size, .deftable = deftable};
  35. TRY_PARSER(register, AT_REGISTER, reg)
  36. TRY_PARSER(immediate, AT_IMMEDIATE, imm)
  37. TRY_PARSER(indirect, AT_INDIRECT, indirect)
  38. TRY_PARSER(indexed, AT_INDEXED, index)
  39. TRY_PARSER(condition, AT_CONDITION, cond)
  40. TRY_PARSER(label, AT_LABEL, label)
  41. return ED_PS_ARG_SYNTAX;
  42. }
  43. /*
  44. Parse an argument string into ASMInstArg objects.
  45. Return ED_NONE (0) on success or an error code on failure.
  46. */
  47. ASMErrorDesc parse_args(
  48. ASMInstArg args[3], size_t *nargs, ASMArgParseInfo ap_info)
  49. {
  50. ASMErrorDesc err;
  51. ASMDefineTable *dt = ap_info.deftable;
  52. const char *str = ap_info.arg;
  53. size_t size = ap_info.size, start = 0, i = 0;
  54. while (i < size) {
  55. char c = str[i];
  56. if (c == ',') {
  57. if (i == start)
  58. return ED_PS_ARG_SYNTAX;
  59. if ((err = parse_arg(&args[*nargs], str + start, i - start, dt)))
  60. return err;
  61. (*nargs)++;
  62. i++;
  63. if (i < size && str[i] == ' ')
  64. i++;
  65. start = i;
  66. if (i == size)
  67. return ED_PS_ARG_SYNTAX;
  68. if (*nargs >= 3)
  69. return ED_PS_TOO_MANY_ARGS;
  70. } else {
  71. if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
  72. c == ' ' || c == '+' || c == '-' || c == '(' || c == ')' ||
  73. c == '$' || c == '_' || c == '.')
  74. i++;
  75. else
  76. return ED_PS_ARG_SYNTAX;
  77. }
  78. }
  79. if (i > start) {
  80. if ((err = parse_arg(&args[*nargs], str + start, i - start, dt)))
  81. return err;
  82. (*nargs)++;
  83. }
  84. return ED_NONE;
  85. }