@@ -14,8 +14,6 @@ | |||
#include "rom.h" | |||
#include "util.h" | |||
#define IS_LABEL(line) (line->data[line->length - 1] == ':') | |||
/* Sentinel values for overlap table */ | |||
const ASMLine header_sentinel, bounds_sentinel; | |||
@@ -34,7 +32,7 @@ static ErrorInfo* add_label_to_table( | |||
const ASMSymbol *current = asm_symtable_find(symtable, symbol); | |||
if (current) { | |||
ErrorInfo *ei = error_info_create(line, ET_LAYOUT, ED_LYT_DUPE_LABELS); | |||
ErrorInfo *ei = error_info_create(line, ET_SYMBOL, ED_SYM_DUPE_LABELS); | |||
error_info_append(ei, current->line); | |||
return ei; | |||
} | |||
@@ -43,7 +41,8 @@ static ErrorInfo* add_label_to_table( | |||
if (!label) | |||
OUT_OF_MEMORY() | |||
label->offset = offset; | |||
// TODO: don't assume all ROM gets mapped to slot 2 | |||
label->offset = (offset >= 0xC000) ? ((offset & 0x3FFF) + 0x8000) : offset; | |||
label->symbol = symbol; | |||
label->line = line; | |||
asm_symtable_insert(symtable, label); | |||
@@ -144,7 +143,7 @@ static ErrorInfo* tokenize(AssemblerState *state) | |||
overlap_table[state->header.offset + i] = &header_sentinel; | |||
while (line) { | |||
if (IS_LABEL(line)) { | |||
if (line->is_label) { | |||
if ((ei = add_label_to_table(state->symtable, line, offset))) | |||
goto cleanup; | |||
} | |||
@@ -261,9 +260,31 @@ static ErrorInfo* resolve_defaults(AssemblerState *state) | |||
*/ | |||
static ErrorInfo* resolve_symbols(AssemblerState *state) | |||
{ | |||
// TODO | |||
ErrorInfo *ei; | |||
ASMInstruction *inst = state->instructions; | |||
const ASMSymbol *symbol; | |||
while (inst) { | |||
if (inst->symbol) { | |||
symbol = asm_symtable_find(state->symtable, inst->symbol); | |||
if (!symbol) { | |||
ei = error_info_create(inst->line, ET_SYMBOL, ED_SYM_NO_LABEL); | |||
return ei; | |||
} | |||
(void) state; | |||
if (inst->loc.length == 3) { | |||
inst->b2 = symbol->offset & 0xFF; | |||
inst->b3 = symbol->offset >> 8; | |||
} else { | |||
inst->b3 = symbol->offset & 0xFF; | |||
inst->b4 = symbol->offset >> 8; | |||
} | |||
free(inst->symbol); | |||
inst->symbol = NULL; | |||
} | |||
inst = inst->next; | |||
} | |||
return NULL; | |||
} | |||
@@ -17,6 +17,7 @@ static const char *asm_error_types[] = { | |||
"include directive", // ET_INCLUDE | |||
"preprocessor", // ET_PREPROC | |||
"memory layout", // ET_LAYOUT | |||
"symbol table", // ET_SYMBOL | |||
"instruction parser" // ET_PARSER | |||
}; | |||
@@ -33,11 +34,13 @@ static const char *asm_error_descs[] = { | |||
"header offset exceeds given ROM size", // ED_LYT_HEADER_RANGE | |||
"declared ROM size in header exceeds actual size", // ED_LYT_DECLARE_RANGE | |||
"duplicate definitions for label", // ED_LYT_DUPE_LABELS | |||
"location is out of bounds for the ROM size", // ED_LYT_BOUNDS | |||
"location overlaps with instruction or data", // ED_LYT_OVERLAP | |||
"location overlaps with ROM header", // ED_LYT_OVERLAP_HEAD | |||
"duplicate definitions for label", // ED_SYM_DUPE_LABELS | |||
"undefined reference to label", // ED_SYM_NO_LABEL | |||
"syntax error" // ED_PARSE_SYNTAX | |||
}; | |||
@@ -13,6 +13,7 @@ typedef enum { | |||
ET_INCLUDE, | |||
ET_PREPROC, | |||
ET_LAYOUT, | |||
ET_SYMBOL, | |||
ET_PARSER | |||
} ASMErrorType; | |||
@@ -29,11 +30,13 @@ typedef enum { | |||
ED_LYT_HEADER_RANGE, | |||
ED_LYT_DECLARE_RANGE, | |||
ED_LYT_DUPE_LABELS, | |||
ED_LYT_BOUNDS, | |||
ED_LYT_OVERLAP, | |||
ED_LYT_OVERLAP_HEAD, | |||
ED_SYM_DUPE_LABELS, | |||
ED_SYM_NO_LABEL, | |||
ED_PARSE_SYNTAX | |||
} ASMErrorDesc; | |||
@@ -88,7 +88,7 @@ | |||
static inline bool is_valid_label_char(char c, bool first) | |||
{ | |||
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || | |||
(!first && c >= '0' && c <= '9') || c == '_'; | |||
(!first && c >= '0' && c <= '9') || c == '_' || c == '.'; | |||
} | |||
/* | |||
@@ -125,6 +125,7 @@ static size_t read_labels( | |||
strncpy(line->data, source + start, i - start + 1); | |||
line->length = i - start + 1; | |||
line->is_label = true; | |||
nexti = read_labels(source + i + 1, length - i - 1, &line->next, tail_ptr); | |||
*head_ptr = line; | |||
@@ -136,7 +137,7 @@ static size_t read_labels( | |||
/* | |||
Preprocess a single source line (source, length) into one or more ASMLines. | |||
Only the data, length, and next fields of the ASMLine objects are | |||
Only the data, length, is_label, and next fields of the ASMLine objects are | |||
populated. The normalization process strips comments, makes various | |||
adjustments outside of string literals (converts tabs to spaces, lowercases | |||
all alphabetical characters, and removes runs of multiple spaces), among | |||
@@ -209,6 +210,7 @@ static ASMLine* normalize_line(const char *source, size_t length) | |||
line->data = data; | |||
line->length = di; | |||
line->is_label = false; | |||
line->next = NULL; | |||
if (head) { // Line has labels, so link the main part up | |||
@@ -418,7 +420,7 @@ ErrorInfo* preprocess(AssemblerState *state, const LineBuffer *source) | |||
while ((prev = line, line = next)) { | |||
next = line->next; | |||
if (line->data[0] != DIRECTIVE_MARKER) | |||
if (line->is_label || line->data[0] != DIRECTIVE_MARKER) | |||
continue; | |||
if (IS_LOCAL_DIRECTIVE(line)) | |||
continue; // "Local" directives are handled by the tokenizer | |||
@@ -144,7 +144,7 @@ static inline size_t hash_key(const char *key) | |||
/* | |||
Search for a key in the symbol table. | |||
Return the key on success and NULL on failure. | |||
Return the corresponding symbol on success and NULL on failure. | |||
*/ | |||
const ASMSymbol* asm_symtable_find(const ASMSymbolTable *tab, const char *key) | |||
{ | |||
@@ -159,6 +159,8 @@ const ASMSymbol* asm_symtable_find(const ASMSymbolTable *tab, const char *key) | |||
/* | |||
Insert a symbol into the table. | |||
TODO: return boolean on success instead of void. | |||
*/ | |||
void asm_symtable_insert(ASMSymbolTable *tab, ASMSymbol *symbol) | |||
{ | |||
@@ -22,6 +22,7 @@ struct ASMLine { | |||
size_t length; | |||
const Line *original; | |||
const char *filename; | |||
bool is_label; | |||
struct ASMLine *next; | |||
}; | |||
typedef struct ASMLine ASMLine; | |||
@@ -40,8 +41,8 @@ typedef struct { | |||
struct ASMInstruction { | |||
ASMLocation loc; | |||
uint8_t b1, b2, b3, b4; | |||
uint8_t virtual_byte; | |||
char *symbol; | |||
const ASMLine *line; | |||
struct ASMInstruction *next; | |||
}; | |||
typedef struct ASMInstruction ASMInstruction; | |||
@@ -54,7 +55,7 @@ struct ASMData { | |||
typedef struct ASMData ASMData; | |||
struct ASMSymbol { | |||
size_t offset; | |||
uint16_t offset; | |||
char *symbol; | |||
const ASMLine *line; | |||
struct ASMSymbol *next; | |||