@@ -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); | ||||