瀏覽代碼

Properly implement slots in the tokenizer.

master
Ben Kurtovic 9 年之前
父節點
當前提交
0903955e48
共有 3 個文件被更改,包括 97 次插入24 次删除
  1. +2
    -1
      src/assembler/errors.c
  2. +2
    -1
      src/assembler/errors.h
  3. +93
    -22
      src/assembler/tokenizer.c

+ 2
- 1
src/assembler/errors.c 查看文件

@@ -34,8 +34,9 @@ static const char *asm_error_descs[] = {


"header offset exceeds given ROM size", // ED_LYT_HEADER_RANGE "header offset exceeds given ROM size", // ED_LYT_HEADER_RANGE
"declared ROM size in header exceeds actual size", // ED_LYT_DECLARE_RANGE "declared ROM size in header exceeds actual size", // ED_LYT_DECLARE_RANGE
"block zero cannot be mapped into a nonzero slot", // ED_LYT_BLOCK0
"location is out of bounds for the ROM size", // ED_LYT_BOUNDS "location is out of bounds for the ROM size", // ED_LYT_BOUNDS
"block zero cannot be mapped into a nonzero slot", // ED_LYT_BLOCK0
"multiple slot declarations for block directive", // ED_LYT_SLOTS
"location overlaps with instruction or data", // ED_LYT_OVERLAP "location overlaps with instruction or data", // ED_LYT_OVERLAP
"location overlaps with ROM header", // ED_LYT_OVERLAP_HEAD "location overlaps with ROM header", // ED_LYT_OVERLAP_HEAD




+ 2
- 1
src/assembler/errors.h 查看文件

@@ -30,8 +30,9 @@ typedef enum {


ED_LYT_HEADER_RANGE, ED_LYT_HEADER_RANGE,
ED_LYT_DECLARE_RANGE, ED_LYT_DECLARE_RANGE,
ED_LYT_BLOCK0,
ED_LYT_BOUNDS, ED_LYT_BOUNDS,
ED_LYT_BLOCK0,
ED_LYT_SLOTS,
ED_LYT_OVERLAP, ED_LYT_OVERLAP,
ED_LYT_OVERLAP_HEAD, ED_LYT_OVERLAP_HEAD,




+ 93
- 22
src/assembler/tokenizer.c 查看文件

@@ -8,19 +8,44 @@
#include "directives.h" #include "directives.h"
#include "parse_util.h" #include "parse_util.h"
#include "../logging.h" #include "../logging.h"
#include "../mmu.h"
#include "../rom.h" #include "../rom.h"


/* Internal structs */

typedef struct {
int8_t slots[MMU_NUM_ROM_BANKS];
const ASMLine *lines[MMU_NUM_ROM_BANKS];
} ASMSlotInfo;

/* Sentinel values for overlap table */ /* Sentinel values for overlap table */

const ASMLine header_sentinel, bounds_sentinel; const ASMLine header_sentinel, bounds_sentinel;


/* /*
Return the address of a given ROM offset when mapped into the given slot.
*/
static inline uint16_t map_into_slot(size_t offset, int8_t slot)
{
return (slot * MMU_ROM_BANK_SIZE) + (offset & (MMU_ROM_BANK_SIZE - 1));
}

/*
Return the default slot associated with a given memory bank.
*/
static inline int8_t default_bank_slot(size_t bank)
{
return bank > 2 ? 2 : bank;
}

/*
Add a given line, representing a label, to the symbol table. Add a given line, representing a label, to the symbol table.


Return NULL on success and an ErrorInfo object on failure (in the case of Return NULL on success and an ErrorInfo object on failure (in the case of
duplicate labels). duplicate labels).
*/ */
static ErrorInfo* add_label_to_table( static ErrorInfo* add_label_to_table(
ASMSymbolTable *symtable, const ASMLine *line, size_t offset, ssize_t slot)
ASMSymbolTable *symtable, const ASMLine *line, size_t offset, int8_t slot)
{ {
char *symbol = strndup(line->data, line->length - 1); char *symbol = strndup(line->data, line->length - 1);
if (!symbol) if (!symbol)
@@ -37,9 +62,8 @@ static ErrorInfo* add_label_to_table(
if (!label) if (!label)
OUT_OF_MEMORY() OUT_OF_MEMORY()


size_t block_offset = offset & 0x3FFF;
label->offset = slot >= 0 ? (block_offset + slot * 0x4000) :
(offset >= 0xC000 ? (block_offset + 0x8000) : offset);
label->offset = map_into_slot(offset,
(slot >= 0) ? slot : default_bank_slot(offset / MMU_ROM_BANK_SIZE));
label->symbol = symbol; label->symbol = symbol;
label->line = line; label->line = line;
asm_symtable_insert(symtable, label); asm_symtable_insert(symtable, label);
@@ -47,12 +71,11 @@ static ErrorInfo* add_label_to_table(
} }


/* /*
Handle an origin directive by updating the offset and (maybe) the slot.
Handle an origin directive by updating the offset.


Return NULL on success and an ErrorInfo object on failure. Return NULL on success and an ErrorInfo object on failure.
*/ */
static ErrorInfo* handle_origin_directive(
const ASMLine *line, size_t *offset, ssize_t *slot)
static ErrorInfo* handle_origin_directive(const ASMLine *line, size_t *offset)
{ {
if (!DIRECTIVE_HAS_ARG(line, DIR_ORIGIN)) if (!DIRECTIVE_HAS_ARG(line, DIR_ORIGIN))
return error_info_create(line, ET_PREPROC, ED_PP_NO_ARG); return error_info_create(line, ET_PREPROC, ED_PP_NO_ARG);
@@ -61,8 +84,10 @@ static ErrorInfo* handle_origin_directive(
if (!dparse_uint32_t(&arg, line, DIR_ORIGIN)) if (!dparse_uint32_t(&arg, line, DIR_ORIGIN))
return error_info_create(line, ET_PREPROC, ED_PP_BAD_ARG); return error_info_create(line, ET_PREPROC, ED_PP_BAD_ARG);


if (arg >= MMU_NUM_ROM_BANKS * MMU_ROM_BANK_SIZE)
return error_info_create(line, ET_PREPROC, ED_PP_ARG_RANGE);

*offset = arg; *offset = arg;
// TODO: if different block, *slot <-- slot lookup table for this block
return NULL; return NULL;
} }


@@ -72,27 +97,41 @@ static ErrorInfo* handle_origin_directive(
Return NULL on success and an ErrorInfo object on failure. Return NULL on success and an ErrorInfo object on failure.
*/ */
static ErrorInfo* handle_block_directive( static ErrorInfo* handle_block_directive(
const ASMLine *line, size_t *offset, ssize_t *slot)
const ASMLine *line, size_t *offset, ASMSlotInfo *si)
{ {
if (!DIRECTIVE_HAS_ARG(line, DIR_BLOCK)) if (!DIRECTIVE_HAS_ARG(line, DIR_BLOCK))
return error_info_create(line, ET_PREPROC, ED_PP_NO_ARG); return error_info_create(line, ET_PREPROC, ED_PP_NO_ARG);


uint8_t *args;
uint8_t *args, bank, slot;
size_t dir_offset = DIRECTIVE_OFFSET(line, DIR_BLOCK) + 1, nargs; size_t dir_offset = DIRECTIVE_OFFSET(line, DIR_BLOCK) + 1, nargs;


if (!parse_bytes(&args, &nargs, line->data + dir_offset, if (!parse_bytes(&args, &nargs, line->data + dir_offset,
line->length - dir_offset)) line->length - dir_offset))
return error_info_create(line, ET_PREPROC, ED_PP_BAD_ARG); return error_info_create(line, ET_PREPROC, ED_PP_BAD_ARG);
if (nargs < 1 || nargs > 2)
return free(args), error_info_create(line, ET_PREPROC, ED_PP_BAD_ARG);


if (nargs < 1 || nargs > 2 || args[0] >= 64 || (nargs == 2 && args[1] > 2))
return error_info_create(line, ET_PREPROC, ED_PP_BAD_ARG);
bank = args[0];
slot = nargs == 2 ? args[1] : default_bank_slot(bank);
free(args);


if (nargs == 2 && args[0] == 0 && args[1] != 0)
return error_info_create(line, ET_LAYOUT, ED_LYT_BLOCK0);
if (bank >= MMU_NUM_ROM_BANKS || slot >= MMU_NUM_SLOTS)
return error_info_create(line, ET_PREPROC, ED_PP_ARG_RANGE);


*offset = args[0] * (16 << 10);
*slot = nargs == 2 ? args[1] : -1;
free(args);
if (nargs == 2) {
if (bank == 0 && slot != 0)
return error_info_create(line, ET_LAYOUT, ED_LYT_BLOCK0);
if (si->slots[bank] >= 0 && si->slots[bank] != slot) {
ErrorInfo *ei = error_info_create(line, ET_LAYOUT, ED_LYT_SLOTS);
error_info_append(ei, si->lines[bank]);
return ei;
}
}

*offset = bank * MMU_ROM_BANK_SIZE;
si->slots[bank] = slot;
if (!si->lines[bank])
si->lines[bank] = line;
return NULL; return NULL;
} }


@@ -108,7 +147,19 @@ static ErrorInfo* parse_data(
// TODO // TODO
DEBUG("parse_data(): %.*s", (int) line->length, line->data) DEBUG("parse_data(): %.*s", (int) line->length, line->data)


return error_info_create(line, ET_PARSER, ED_PARSE_SYNTAX);
// return error_info_create(line, ET_PARSER, ED_PARSE_SYNTAX);

ASMData *data = malloc(sizeof(ASMData));
if (!data)
OUT_OF_MEMORY()

data->loc.offset = offset;
data->loc.length = 6;
data->data = (uint8_t*) strdup("foobar");
data->next = NULL;

*data_ptr = data;
return NULL;
} }


/* /*
@@ -123,7 +174,21 @@ static ErrorInfo* parse_instruction(
// TODO // TODO
DEBUG("parse_instruction(): %.*s", (int) line->length, line->data) DEBUG("parse_instruction(): %.*s", (int) line->length, line->data)


return error_info_create(line, ET_PARSER, ED_PARSE_SYNTAX);
// return error_info_create(line, ET_PARSER, ED_PARSE_SYNTAX);

ASMInstruction *inst = malloc(sizeof(ASMInstruction));
if (!inst)
OUT_OF_MEMORY()

inst->loc.offset = offset;
inst->loc.length = 1;
inst->b1 = 0x3C;
inst->symbol = NULL;
inst->line = line;
inst->next = NULL;

*inst_ptr = inst;
return NULL;
} }


/* /*
@@ -186,24 +251,30 @@ ErrorInfo* tokenize(AssemblerState *state)
ASMData dummy_data = {.next = NULL}, *data, *prev_data = &dummy_data; ASMData dummy_data = {.next = NULL}, *data, *prev_data = &dummy_data;
const ASMLine *line = state->lines, *origin = NULL; const ASMLine *line = state->lines, *origin = NULL;
size_t offset = 0; size_t offset = 0;
ssize_t slot = -1;
ASMSlotInfo si = {.lines = {0}};


for (size_t i = 0; i < HEADER_SIZE; i++) for (size_t i = 0; i < HEADER_SIZE; i++)
overlap_table[state->header.offset + i] = &header_sentinel; overlap_table[state->header.offset + i] = &header_sentinel;
memset(si.slots, -1, MMU_NUM_ROM_BANKS);


while (line) { while (line) {
if (line->is_label) { if (line->is_label) {
if (offset >= size) {
ei = error_info_create(line, ET_LAYOUT, ED_LYT_BOUNDS);
goto cleanup;
}
int8_t slot = si.slots[offset / MMU_NUM_ROM_BANKS];
if ((ei = add_label_to_table(state->symtable, line, offset, slot))) if ((ei = add_label_to_table(state->symtable, line, offset, slot)))
goto cleanup; goto cleanup;
} }
else if (IS_LOCAL_DIRECTIVE(line)) { else if (IS_LOCAL_DIRECTIVE(line)) {
if (IS_DIRECTIVE(line, DIR_ORIGIN)) { if (IS_DIRECTIVE(line, DIR_ORIGIN)) {
if ((ei = handle_origin_directive(line, &offset, &slot)))
if ((ei = handle_origin_directive(line, &offset)))
goto cleanup; goto cleanup;
origin = line; origin = line;
} }
else if (IS_DIRECTIVE(line, DIR_BLOCK)) { else if (IS_DIRECTIVE(line, DIR_BLOCK)) {
if ((ei = handle_block_directive(line, &offset, &slot)))
if ((ei = handle_block_directive(line, &offset, &si)))
goto cleanup; goto cleanup;
origin = line; origin = line;
} }


Loading…
取消
儲存