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