| @@ -34,7 +34,8 @@ typedef enum { | |||||
| typedef struct { | typedef struct { | ||||
| ASMArgImmType mask; | ASMArgImmType mask; | ||||
| uint16_t value; | |||||
| uint16_t uval; | |||||
| int16_t sval; | |||||
| } ASMArgImmediate; | } ASMArgImmediate; | ||||
| typedef struct { | typedef struct { | ||||
| @@ -147,35 +147,30 @@ static uint8_t fill_bytes_variadic(uint8_t *bytes, size_t len, ...) | |||||
| static ASMErrorDesc parse_arg( | static ASMErrorDesc parse_arg( | ||||
| ASMInstArg *arg, const char *str, size_t size, char **symbol) | ASMInstArg *arg, const char *str, size_t size, char **symbol) | ||||
| { | { | ||||
| // TODO | |||||
| #define USE_PARSER(func, argtype, field) \ | |||||
| if (argparse_##func(&arg->data.field, str, size)) { \ | |||||
| arg->type = argtype; \ | |||||
| return ED_NONE; \ | |||||
| } | |||||
| // AT_REGISTER | |||||
| // AT_IMMEDIATE | |||||
| // AT_INDIRECT | |||||
| // AT_INDEXED | |||||
| // AT_LABEL | |||||
| // AT_CONDITION | |||||
| DEBUG("parse_arg(): -->%.*s<-- %zu", (int) size, str, size) | |||||
| USE_PARSER(register, AT_REGISTER, reg) | |||||
| USE_PARSER(immediate, AT_IMMEDIATE, imm) | |||||
| // ASMArgRegister reg; | |||||
| // ASMArgImmediate imm; | |||||
| // AT_INDIRECT | |||||
| // ASMArgIndirect indirect; | // ASMArgIndirect indirect; | ||||
| // ASMArgIndexed index; | |||||
| // ASMArgLabel label; | |||||
| // ASMArgCondition cond; | |||||
| DEBUG("parse_arg(): -->%.*s<-- %zu", (int) size, str, size) | |||||
| // AT_INDEXED | |||||
| // ASMArgIndexed index; | |||||
| if (parse_register(&arg->data.reg, str, size)) { | |||||
| arg->type = AT_REGISTER; | |||||
| return ED_NONE; | |||||
| } | |||||
| USE_PARSER(condition, AT_CONDITION, cond) | |||||
| if (parse_condition(&arg->data.cond, str, size)) { | |||||
| arg->type = AT_CONDITION; | |||||
| return ED_NONE; | |||||
| } | |||||
| // AT_LABEL | |||||
| // ASMArgLabel label; | |||||
| return ED_PS_ARG_SYNTAX; | return ED_PS_ARG_SYNTAX; | ||||
| #undef USE_PARSER | |||||
| } | } | ||||
| /* | /* | ||||
| @@ -193,6 +188,8 @@ static ASMErrorDesc parse_args( | |||||
| while (i < size) { | while (i < size) { | ||||
| char c = str[i]; | char c = str[i]; | ||||
| if (c == ',') { | if (c == ',') { | ||||
| if (i == start) | |||||
| return ED_PS_ARG_SYNTAX; | |||||
| if ((err = parse_arg(&args[*nargs], str + start, i - start, &symbol))) | if ((err = parse_arg(&args[*nargs], str + start, i - start, &symbol))) | ||||
| return err; | return err; | ||||
| (*nargs)++; | (*nargs)++; | ||||
| @@ -201,7 +198,9 @@ static ASMErrorDesc parse_args( | |||||
| if (i < size && str[i] == ' ') | if (i < size && str[i] == ' ') | ||||
| i++; | i++; | ||||
| start = i; | start = i; | ||||
| if (*nargs >= 3 && i < size) | |||||
| if (i == size) | |||||
| return ED_PS_ARG_SYNTAX; | |||||
| if (*nargs >= 3) | |||||
| return ED_PS_TOO_MANY_ARGS; | return ED_PS_TOO_MANY_ARGS; | ||||
| } else { | } else { | ||||
| if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || | if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || | ||||
| @@ -177,7 +177,7 @@ bool parse_bytes(uint8_t **result, size_t *length, const char *arg, ssize_t size | |||||
| /* | /* | ||||
| Read in a register argument and store it in *result. | Read in a register argument and store it in *result. | ||||
| */ | */ | ||||
| bool parse_register(ASMArgRegister *result, const char *arg, ssize_t size) | |||||
| bool argparse_register(ASMArgRegister *result, const char *arg, ssize_t size) | |||||
| { | { | ||||
| if (size < 1 || size > 3) | if (size < 1 || size > 3) | ||||
| return false; | return false; | ||||
| @@ -232,7 +232,7 @@ bool parse_register(ASMArgRegister *result, const char *arg, ssize_t size) | |||||
| /* | /* | ||||
| Read in a register argument and store it in *result. | Read in a register argument and store it in *result. | ||||
| */ | */ | ||||
| bool parse_condition(ASMArgCondition *result, const char *arg, ssize_t size) | |||||
| bool argparse_condition(ASMArgCondition *result, const char *arg, ssize_t size) | |||||
| { | { | ||||
| if (size < 1 || size > 2) | if (size < 1 || size > 2) | ||||
| return false; | return false; | ||||
| @@ -265,6 +265,55 @@ bool parse_condition(ASMArgCondition *result, const char *arg, ssize_t size) | |||||
| } | } | ||||
| /* | /* | ||||
| Read in an immediate argument and store it in *result. | |||||
| */ | |||||
| bool argparse_immediate(ASMArgImmediate *result, const char *arg, ssize_t size) | |||||
| { | |||||
| bool negative = false; | |||||
| ssize_t i = 0; | |||||
| if (size <= 0) | |||||
| return false; | |||||
| while (arg[i] == '-' || arg[i] == '+' || arg[i] == ' ') { | |||||
| if (arg[i] == '-') | |||||
| negative = !negative; | |||||
| if (++i >= size) | |||||
| return false; | |||||
| } | |||||
| uint32_t uval; | |||||
| if (parse_uint32_t(&uval, arg, size) && uval > UINT16_MAX) | |||||
| return false; | |||||
| int32_t sval = negative ? uval : -uval; | |||||
| if (sval < INT16_MIN) | |||||
| return false; | |||||
| result->uval = uval; | |||||
| result->sval = sval; | |||||
| result->mask = 0; | |||||
| if (negative) { | |||||
| if (sval >= INT8_MIN && sval <= INT8_MAX) | |||||
| result->mask |= IMM_S8; | |||||
| if (sval >= INT8_MIN + 2 && sval <= INT8_MAX + 2) | |||||
| result->mask |= IMM_REL; | |||||
| } else { | |||||
| result->mask = IMM_U16; | |||||
| if (uval <= UINT8_MAX) | |||||
| result->mask |= IMM_U8; | |||||
| if (uval <= 7) | |||||
| result->mask |= IMM_BIT; | |||||
| if (!(uval & ~0x38)) | |||||
| result->mask |= IMM_RST; | |||||
| if (uval <= 2) | |||||
| result->mask |= IMM_IM; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| /* | |||||
| Read in a boolean argument from the given line and store it in *result. | Read in a boolean argument from the given line and store it in *result. | ||||
| */ | */ | ||||
| DIRECTIVE_PARSE_FUNC(bool, bool) | DIRECTIVE_PARSE_FUNC(bool, bool) | ||||
| @@ -13,19 +13,22 @@ | |||||
| /* Functions */ | /* Functions */ | ||||
| /* General parsers */ | |||||
| bool parse_bool(bool*, const char*, ssize_t); | bool parse_bool(bool*, const char*, ssize_t); | ||||
| bool parse_uint32_t(uint32_t*, const char*, ssize_t); | bool parse_uint32_t(uint32_t*, const char*, ssize_t); | ||||
| bool parse_string(char**, size_t*, const char*, ssize_t); | bool parse_string(char**, size_t*, const char*, ssize_t); | ||||
| bool parse_bytes(uint8_t**, size_t*, const char*, ssize_t); | bool parse_bytes(uint8_t**, size_t*, const char*, ssize_t); | ||||
| bool parse_register(ASMArgRegister*, const char*, ssize_t); | |||||
| bool parse_condition(ASMArgCondition*, const char*, ssize_t); | |||||
| /* Instruction argument parsers */ | |||||
| bool argparse_register(ASMArgRegister*, const char*, ssize_t); | |||||
| bool argparse_condition(ASMArgCondition*, const char*, ssize_t); | |||||
| bool argparse_immediate(ASMArgImmediate*, const char*, ssize_t); | |||||
| /* Preprocessor directive parsers */ | |||||
| bool dparse_bool(bool*, const ASMLine*, const char*); | bool dparse_bool(bool*, const ASMLine*, const char*); | ||||
| bool dparse_uint32_t(uint32_t*, const ASMLine*, const char*); | bool dparse_uint32_t(uint32_t*, const ASMLine*, const char*); | ||||
| bool dparse_uint16_t(uint16_t*, const ASMLine*, const char*); | bool dparse_uint16_t(uint16_t*, const ASMLine*, const char*); | ||||
| bool dparse_uint8_t(uint8_t*, const ASMLine*, const char*); | bool dparse_uint8_t(uint8_t*, const ASMLine*, const char*); | ||||
| bool dparse_rom_size(uint32_t*, const ASMLine*, const char*); | bool dparse_rom_size(uint32_t*, const ASMLine*, const char*); | ||||
| bool dparse_region_string(uint8_t*, const ASMLine*, const char*); | bool dparse_region_string(uint8_t*, const ASMLine*, const char*); | ||||
| bool dparse_size_code(uint8_t*, const ASMLine*, const char*); | bool dparse_size_code(uint8_t*, const ASMLine*, const char*); | ||||
| @@ -63,11 +63,11 @@ static ErrorInfo* add_label_to_table( | |||||
| ASMSymbolTable *symtable, const ASMLine *line, size_t offset, int8_t slot) | ASMSymbolTable *symtable, const ASMLine *line, size_t offset, int8_t slot) | ||||
| { | { | ||||
| ASMArgRegister reg; | ASMArgRegister reg; | ||||
| if (parse_register(®, line->data, line->length - 1)) | |||||
| if (argparse_register(®, line->data, line->length - 1)) | |||||
| return error_info_create(line, ET_SYMBOL, ED_SYM_IS_REGISTER); | return error_info_create(line, ET_SYMBOL, ED_SYM_IS_REGISTER); | ||||
| ASMArgCondition cond; | ASMArgCondition cond; | ||||
| if (parse_condition(&cond, line->data, line->length - 1)) | |||||
| if (argparse_condition(&cond, line->data, line->length - 1)) | |||||
| return error_info_create(line, ET_SYMBOL, ED_SYM_IS_CONDITION); | return error_info_create(line, ET_SYMBOL, ED_SYM_IS_CONDITION); | ||||
| char *symbol = strndup(line->data, line->length - 1); | char *symbol = strndup(line->data, line->length - 1); | ||||