| @@ -34,7 +34,8 @@ typedef enum { | |||
| typedef struct { | |||
| ASMArgImmType mask; | |||
| uint16_t value; | |||
| uint16_t uval; | |||
| int16_t sval; | |||
| } ASMArgImmediate; | |||
| typedef struct { | |||
| @@ -147,35 +147,30 @@ static uint8_t fill_bytes_variadic(uint8_t *bytes, size_t len, ...) | |||
| static ASMErrorDesc parse_arg( | |||
| 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; | |||
| // 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; | |||
| #undef USE_PARSER | |||
| } | |||
| /* | |||
| @@ -193,6 +188,8 @@ static ASMErrorDesc parse_args( | |||
| while (i < size) { | |||
| char c = str[i]; | |||
| if (c == ',') { | |||
| if (i == start) | |||
| return ED_PS_ARG_SYNTAX; | |||
| if ((err = parse_arg(&args[*nargs], str + start, i - start, &symbol))) | |||
| return err; | |||
| (*nargs)++; | |||
| @@ -201,7 +198,9 @@ static ASMErrorDesc parse_args( | |||
| if (i < size && str[i] == ' ') | |||
| 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; | |||
| } else { | |||
| 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. | |||
| */ | |||
| 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) | |||
| 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. | |||
| */ | |||
| 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) | |||
| 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. | |||
| */ | |||
| DIRECTIVE_PARSE_FUNC(bool, bool) | |||
| @@ -13,19 +13,22 @@ | |||
| /* Functions */ | |||
| /* General parsers */ | |||
| bool parse_bool(bool*, 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_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_uint32_t(uint32_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_rom_size(uint32_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*); | |||
| @@ -63,11 +63,11 @@ static ErrorInfo* add_label_to_table( | |||
| ASMSymbolTable *symtable, const ASMLine *line, size_t offset, int8_t slot) | |||
| { | |||
| 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); | |||
| 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); | |||
| char *symbol = strndup(line->data, line->length - 1); | |||