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.
 
 
 
 
 

187 lines
4.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 <stdlib.h>
  4. #include "state.h"
  5. #include "io.h"
  6. #include "../logging.h"
  7. /*
  8. Initialize default values in an AssemblerState object.
  9. */
  10. void state_init(AssemblerState *state)
  11. {
  12. state->header.offset = DEFAULT_HEADER_OFFSET;
  13. state->header.checksum = true;
  14. state->header.product_code = 0;
  15. state->header.version = 0;
  16. state->header.region = DEFAULT_REGION;
  17. state->header.rom_size = DEFAULT_DECLSIZE;
  18. state->cross_blocks = false;
  19. state->rom_size = 0;
  20. state->lines = NULL;
  21. state->includes = NULL;
  22. state->instructions = NULL;
  23. state->data = NULL;
  24. state->symtable = NULL;
  25. }
  26. /*
  27. Deallocate the contents of an AssemblerState object.
  28. */
  29. void state_free(AssemblerState *state)
  30. {
  31. asm_lines_free(state->lines);
  32. asm_includes_free(state->includes);
  33. asm_instructions_free(state->instructions);
  34. asm_data_free(state->data);
  35. asm_symtable_free(state->symtable);
  36. }
  37. /*
  38. Initialize an ASMSymbolTable and place it in *symtable_ptr.
  39. */
  40. void asm_symtable_init(ASMSymbolTable **symtable_ptr)
  41. {
  42. ASMSymbolTable *symtable;
  43. if (!(symtable = malloc(sizeof(ASMSymbolTable))))
  44. OUT_OF_MEMORY()
  45. for (size_t bucket = 0; bucket < SYMBOL_TABLE_BUCKETS; bucket++)
  46. symtable->buckets[bucket] = NULL;
  47. *symtable_ptr = symtable;
  48. }
  49. /*
  50. Deallocate an ASMLine list.
  51. */
  52. void asm_lines_free(ASMLine *line)
  53. {
  54. while (line) {
  55. ASMLine *temp = line->next;
  56. free(line->data);
  57. free(line);
  58. line = temp;
  59. }
  60. }
  61. /*
  62. Deallocate an ASMInclude list.
  63. */
  64. void asm_includes_free(ASMInclude *include)
  65. {
  66. while (include) {
  67. ASMInclude *temp = include->next;
  68. line_buffer_free(include->lines);
  69. free(include);
  70. include = temp;
  71. }
  72. }
  73. /*
  74. Deallocate an ASMInstruction list.
  75. */
  76. void asm_instructions_free(ASMInstruction *inst)
  77. {
  78. while (inst) {
  79. ASMInstruction *temp = inst->next;
  80. free(inst->bytes);
  81. if (inst->symbol)
  82. free(inst->symbol);
  83. free(inst);
  84. inst = temp;
  85. }
  86. }
  87. /*
  88. Deallocate an ASMData list.
  89. */
  90. void asm_data_free(ASMData *data)
  91. {
  92. while (data) {
  93. ASMData *temp = data->next;
  94. free(data->bytes);
  95. free(data);
  96. data = temp;
  97. }
  98. }
  99. /*
  100. Deallocate an ASMSymbolTable.
  101. */
  102. void asm_symtable_free(ASMSymbolTable *symtable)
  103. {
  104. if (!symtable)
  105. return;
  106. for (size_t bucket = 0; bucket < SYMBOL_TABLE_BUCKETS; bucket++) {
  107. ASMSymbol *sym = symtable->buckets[bucket], *temp;
  108. while (sym) {
  109. temp = sym->next;
  110. free(sym->symbol);
  111. free(sym);
  112. sym = temp;
  113. }
  114. }
  115. free(symtable);
  116. }
  117. /*
  118. Hash a string key into a symbol table bucket index.
  119. This uses the djb2 algorithm: http://www.cse.yorku.ca/~oz/hash.html
  120. */
  121. static inline size_t hash_key(const char *key)
  122. {
  123. size_t hash = 5381;
  124. while (*key)
  125. hash = ((hash << 5) + hash) + *(key++);
  126. return hash % SYMBOL_TABLE_BUCKETS;
  127. }
  128. /*
  129. Search for a key in the symbol table.
  130. Return the corresponding symbol on success and NULL on failure.
  131. */
  132. const ASMSymbol* asm_symtable_find(const ASMSymbolTable *tab, const char *key)
  133. {
  134. ASMSymbol *symbol = tab->buckets[hash_key(key)];
  135. while (symbol) {
  136. if (!strcmp(key, symbol->symbol))
  137. return symbol;
  138. symbol = symbol->next;
  139. }
  140. return NULL;
  141. }
  142. /*
  143. Insert a symbol into the table.
  144. TODO: return boolean on success instead of void.
  145. */
  146. void asm_symtable_insert(ASMSymbolTable *tab, ASMSymbol *symbol)
  147. {
  148. size_t index = hash_key(symbol->symbol);
  149. symbol->next = tab->buckets[index];
  150. tab->buckets[index] = symbol;
  151. }
  152. #ifdef DEBUG_MODE
  153. /*
  154. DEBUG FUNCTION: Print out an ASMLine list to stdout.
  155. */
  156. void asm_lines_print(const ASMLine *line)
  157. {
  158. DEBUG("Dumping ASMLines:")
  159. while (line) {
  160. DEBUG("- %-40.*s [%s:%02zu]", (int) line->length, line->data,
  161. line->filename, line->original->lineno)
  162. line = line->next;
  163. }
  164. }
  165. #endif