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.
 
 
 
 
 

90 lines
2.5 KiB

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # Copyright (C) 2014-2015 Ben Kurtovic <ben.kurtovic@gmail.com>
  4. # Released under the terms of the MIT License. See LICENSE for details.
  5. """
  6. This script generates 'src/assembler/instructions.inc.c' from
  7. 'src/assembler/instructions.yml'. It should be run automatically by make
  8. when the latter is modified, but can also be run manually.
  9. """
  10. from __future__ import print_function
  11. import re
  12. import time
  13. SOURCE = "src/assembler/instructions.yml"
  14. DEST = "src/assembler/instructions.inc.c"
  15. ENCODING = "utf8"
  16. TAB = " " * 4
  17. try:
  18. import yaml
  19. except ImportError:
  20. print("Error: PyYAML is required (https://pypi.python.org/pypi/PyYAML)\n"
  21. "If you don't want to rebuild {0}, do:\n`make -t {0}`".format(DEST))
  22. exit(1)
  23. re_date = re.compile(r"^(\s*@AUTOGEN_DATE\s*)(.*?)$", re.M)
  24. re_inst = re.compile(
  25. r"(/\* @AUTOGEN_INST_BLOCK_START \*/\n*)(.*?)"
  26. r"(\n*/\* @AUTOGEN_INST_BLOCK_END \*/)", re.S)
  27. re_lookup = re.compile(
  28. r"(/\* @AUTOGEN_LOOKUP_BLOCK_START \*/\n*)(.*?)"
  29. r"(\n*/\* @AUTOGEN_LOOKUP_BLOCK_END \*/)", re.S)
  30. def build_inst(name, data):
  31. """
  32. Convert data for an individual instruction into a C parse function.
  33. """
  34. # TODO
  35. return "INST_FUNC({0})\n{{\n}}".format(name)
  36. def build_inst_block(data):
  37. """
  38. Return the instruction parser block, given instruction data.
  39. """
  40. return "\n\n".join(build_inst(k, v) for k, v in sorted(data.items()))
  41. def build_lookup_block(data):
  42. """
  43. Return the instruction lookup block, given instruction data.
  44. """
  45. macro = TAB + "HANDLE({0})"
  46. return "\n".join(macro.format(inst) for inst in sorted(data.keys()))
  47. def process(template, data):
  48. """
  49. Return C code generated from a source template and instruction data.
  50. """
  51. inst_block = build_inst_block(data)
  52. lookup_block = build_lookup_block(data)
  53. date = time.asctime(time.gmtime())
  54. result = re_date.sub(r"\1{0} UTC".format(date), template)
  55. result = re_inst.sub(r"\1{0}\3".format(inst_block), result)
  56. result = re_lookup.sub(r"\1{0}\3".format(lookup_block), result)
  57. return result
  58. def main():
  59. """
  60. Main script entry point.
  61. """
  62. with open(SOURCE, "r") as fp:
  63. text = fp.read().decode(ENCODING)
  64. with open(DEST, "r") as fp:
  65. template = fp.read().decode(ENCODING)
  66. data = yaml.load(text)
  67. result = process(template, data)
  68. # with open(DEST, "w") as fp:
  69. # fp.write(result.encode(ENCODING))
  70. print(result) # TODO: remove me!
  71. if __name__ == "__main__":
  72. main()