diff --git a/src/assembler.c b/src/assembler.c index 44c1045..15bcb80 100644 --- a/src/assembler.c +++ b/src/assembler.c @@ -9,6 +9,8 @@ #include "assembler/preprocessor.h" #include "assembler/state.h" #include "logging.h" +#include "rom.h" +#include "util.h" /* Tokenize ASMLines into ASMInstructions. @@ -48,17 +50,21 @@ static ErrorInfo* tokenize(AssemblerState *state) */ static ErrorInfo* resolve_defaults(AssemblerState *state) { - // TODO + if (!state->rom_size) { + state->rom_size = 32 << 10; - // if (!state.rom_size) - // set to max possible >= 32 KB (max of instructions, offset, and state.header.rom_size) + // TODO: use highest instruction too - // if (!state.header.rom_size) - // set to actual rom size using util's size_bytes_to_code() + if (state->header.rom_size != INVALID_SIZE_CODE) { + size_t decl_size = size_code_to_bytes(state->header.rom_size); + if (decl_size > state->rom_size) + state->rom_size = decl_size; + } + } - state->rom_size = 8; + if (state->header.rom_size == INVALID_SIZE_CODE) + state->header.rom_size = size_bytes_to_code(state->rom_size); - (void) state; return NULL; } diff --git a/src/assembler/parse_util.c b/src/assembler/parse_util.c index 3f89355..26a2600 100644 --- a/src/assembler/parse_util.c +++ b/src/assembler/parse_util.c @@ -202,7 +202,7 @@ PARSE_FUNC_HEADER(size_code, uint8_t) } uint8_t code = size_bytes_to_code(bytes); - if (code) + if (code != INVALID_SIZE_CODE) return (*result = code), true; return false; } diff --git a/src/assembler/preprocessor.c b/src/assembler/preprocessor.c index bf41671..ab06ee4 100644 --- a/src/assembler/preprocessor.c +++ b/src/assembler/preprocessor.c @@ -51,7 +51,7 @@ if (CALL_PARSER_(arg_type)) {true_part} else {false_part} #define SAVE_LINE(target) \ - target = line; + if (!dir_is_auto) target = line; #define BEGIN_DIRECTIVE_BLOCK \ ssize_t first_ctr = -1; \ @@ -63,7 +63,8 @@ FAIL_ON_COND_(!DIRECTIVE_HAS_ARG(line, directive), ED_PP_NO_ARG) \ arg_type arg = 0; \ arg_type* dest = &(dest_loc); \ - if (DIRECTIVE_IS_AUTO(line, directive)) { \ + bool dir_is_auto = DIRECTIVE_IS_AUTO(line, directive); \ + if (dir_is_auto) { \ arg = auto_val; \ } else { @@ -311,6 +312,14 @@ static ErrorInfo* build_asm_lines( } /* + Return whether the given ROM size is valid. +*/ +static inline bool is_rom_size_valid(size_t size) +{ + return size_bytes_to_code(size) != INVALID_SIZE_CODE; +} + +/* Return whether the given header offset is a valid location. */ static inline bool is_header_offset_valid(uint16_t offset) @@ -365,7 +374,7 @@ ErrorInfo* preprocess(AssemblerState *state, const LineBuffer *source) PARSER_BRANCH(uint32_t, {}, { USE_PARSER(uint32_t, rom_size) }) - VALIDATE(size_bytes_to_code) + VALIDATE(is_rom_size_valid) SAVE_LINE(rom_size_line) END_DIRECTIVE @@ -397,7 +406,7 @@ ErrorInfo* preprocess(AssemblerState *state, const LineBuffer *source) }) END_DIRECTIVE - BEGIN_DIRECTIVE(DIR_ROM_DECLSIZE, uint8_t, state->header.rom_size, 0) + BEGIN_DIRECTIVE(DIR_ROM_DECLSIZE, uint8_t, state->header.rom_size, DEFAULT_DECLSIZE) PARSER_BRANCH(uint8_t, { CHECK_RANGE(0x10) VALIDATE(size_code_to_bytes) @@ -416,18 +425,21 @@ ErrorInfo* preprocess(AssemblerState *state, const LineBuffer *source) line = prev; } - if (state->rom_size && state->header.offset + HEADER_SIZE > state->rom_size) { + if (rom_size_line && state->header.offset + HEADER_SIZE > state->rom_size) { ei = error_info_create(rom_size_line, ET_PREPROC, ED_PP_HEADER_RANGE); goto cleanup; } - if (state->rom_size && state->header.rom_size && + if (rom_size_line && rom_declsize_line && size_code_to_bytes(state->header.rom_size) > state->rom_size) { ei = error_info_create(rom_size_line, ET_PREPROC, ED_PP_DECLARE_RANGE); error_info_append(ei, rom_declsize_line); goto cleanup; } + if (!rom_declsize_line) // Mark as undefined, for resolve_defaults() + state->header.rom_size = INVALID_SIZE_CODE; + cleanup: asm_lines_free(condemned); state->lines = dummy.next; // Fix list head if first line was a directive diff --git a/src/assembler/state.c b/src/assembler/state.c index 5b79fde..a62e97f 100644 --- a/src/assembler/state.c +++ b/src/assembler/state.c @@ -17,7 +17,7 @@ void state_init(AssemblerState *state) state->header.product_code = 0; state->header.version = 0; state->header.region = DEFAULT_REGION; - state->header.rom_size = 0; + state->header.rom_size = DEFAULT_DECLSIZE; state->optimizer = false; state->rom_size = 0; diff --git a/src/assembler/state.h b/src/assembler/state.h index 477186a..de0c2c5 100644 --- a/src/assembler/state.h +++ b/src/assembler/state.h @@ -11,6 +11,7 @@ #define DEFAULT_HEADER_OFFSET 0x7FF0 #define DEFAULT_REGION 6 // GG Export +#define DEFAULT_DECLSIZE 0xC // 32 KB #define SYMBOL_TABLE_BUCKETS 128 diff --git a/src/util.c b/src/util.c index 857bcb0..050c7a9 100644 --- a/src/util.c +++ b/src/util.c @@ -121,7 +121,7 @@ size_t size_code_to_bytes(uint8_t code) /* Given the number of bytes in a ROM image, return the size code. - 0 is returned if the size is invalid. + INVALID_SIZE_CODE is returned if the size is invalid. */ uint8_t size_bytes_to_code(size_t bytes) { @@ -138,6 +138,6 @@ uint8_t size_bytes_to_code(size_t bytes) case 256: return 0x0; case 512: return 0x1; case 1024: return 0x2; - default: return 0; + default: return INVALID_SIZE_CODE; } } diff --git a/src/util.h b/src/util.h index b82df0c..237ad21 100644 --- a/src/util.h +++ b/src/util.h @@ -5,6 +5,8 @@ #include +#define INVALID_SIZE_CODE 0x8 + /* Functions */ uint8_t bcd_decode(uint8_t);