diff --git a/src/assembler/instructions.c b/src/assembler/instructions.c index 54ff6ef..714e890 100644 --- a/src/assembler/instructions.c +++ b/src/assembler/instructions.c @@ -156,10 +156,7 @@ static ASMErrorDesc parse_arg( USE_PARSER(register, AT_REGISTER, reg) USE_PARSER(immediate, AT_IMMEDIATE, imm) USE_PARSER(indirect, AT_INDIRECT, indirect) - - // AT_INDEXED - // ASMArgIndexed index; - + USE_PARSER(indexed, AT_INDEXED, index) USE_PARSER(condition, AT_CONDITION, cond) // AT_LABEL @@ -202,7 +199,7 @@ static ASMErrorDesc parse_args( } else { if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == ' ' || c == '+' || c == '-' || c == '(' || c == ')' || - c == '_' || c == '.') + c == '$' || c == '_' || c == '.') i++; else return ED_PS_ARG_SYNTAX; @@ -352,8 +349,6 @@ ASMInstParser get_inst_parser(char mstr[MAX_MNEMONIC_SIZE]) // single 32-bit value to do fast lookups: uint32_t key = (mstr[0] << 24) + (mstr[1] << 16) + (mstr[2] << 8) + mstr[3]; - DEBUG("get_inst_parser(): -->%.*s<-- 0x%08X", MAX_MNEMONIC_SIZE, mstr, key) - HANDLE(nop) HANDLE(inc) HANDLE(add) diff --git a/src/assembler/parse_util.c b/src/assembler/parse_util.c index 3c9f3bb..d69f792 100644 --- a/src/assembler/parse_util.c +++ b/src/assembler/parse_util.c @@ -25,6 +25,37 @@ */ /* + Adjust *arg_ptr / *size_ptr for an indirect argument, like (hl) or (ix+*). + + *size_ptr must be > 2 to begin with, and is assured to be > 0 on success. + The two arguments are not modified on failure. +*/ +static bool adjust_for_indirection(const char **arg_ptr, ssize_t *size_ptr) +{ + const char *arg = *arg_ptr; + ssize_t size = *size_ptr; + + if (arg[0] != '(' || arg[size - 1] != ')') + return false; + arg++; + size -= 2; + + if (arg[0] == ' ') { + arg++; + if (--size <= 0) + return false; + } + if (arg[size - 1] == ' ') { + if (--size <= 0) + return false; + } + + *arg_ptr = arg; + *size_ptr = size; + return true; +} + +/* Read in a boolean value and store it in *result. */ bool parse_bool(bool *result, const char *arg, ssize_t size) @@ -283,10 +314,10 @@ bool argparse_immediate(ASMArgImmediate *result, const char *arg, ssize_t size) } uint32_t uval; - if (!parse_uint32_t(&uval, arg, size) || uval > UINT16_MAX) + if (!parse_uint32_t(&uval, arg + i, size - i) || uval > UINT16_MAX) return false; - int32_t sval = negative ? uval : -uval; + int32_t sval = negative ? -uval : uval; if (sval < INT16_MIN) return false; @@ -294,15 +325,19 @@ bool argparse_immediate(ASMArgImmediate *result, const char *arg, ssize_t size) result->sval = sval; result->mask = 0; - if (negative) { - if (sval >= INT8_MIN && sval <= INT8_MAX) + if (sval < 0) { + if (sval >= INT8_MIN) result->mask |= IMM_S8; - if (sval >= INT8_MIN + 2 && sval <= INT8_MAX + 2) + if (sval >= INT8_MIN + 2) result->mask |= IMM_REL; } else { result->mask = IMM_U16; if (uval <= UINT8_MAX) result->mask |= IMM_U8; + if (uval <= INT8_MAX) + result->mask |= IMM_S8; + if (uval <= INT8_MAX + 2) + result->mask |= IMM_REL; if (uval <= 7) result->mask |= IMM_BIT; if (!(uval & ~0x38)) @@ -318,12 +353,8 @@ bool argparse_immediate(ASMArgImmediate *result, const char *arg, ssize_t size) */ bool argparse_indirect(ASMArgIndirect *result, const char *arg, ssize_t size) { - if (size < 3) - return false; - if (arg[0] != '(' || arg[size - 1] != ')') + if (size < 3 || !adjust_for_indirection(&arg, &size)) return false; - arg++; - size -= 2; ASMArgRegister reg; ASMArgImmediate imm; @@ -344,6 +375,43 @@ bool argparse_indirect(ASMArgIndirect *result, const char *arg, ssize_t size) } /* + Read in an indexed argument and store it in *result. +*/ +bool argparse_indexed(ASMArgIndexed *result, const char *arg, ssize_t size) +{ + if (size < 4 || !adjust_for_indirection(&arg, &size) || size < 2) + return false; + + ASMArgRegister reg; + if (arg[0] != 'i') + return false; + if (arg[1] == 'x') + reg = REG_IX; + else if (arg[1] == 'y') + reg = REG_IY; + else + return false; + + arg += 2; + size -= 2; + if (size > 0 && arg[0] == ' ') { + arg++; + size--; + } + + if (size > 0) { + ASMArgImmediate imm; + if (!argparse_immediate(&imm, arg, size) || !(imm.mask & IMM_S8)) + return false; + result->offset = imm.sval; + } else { + result->offset = 0; + } + result->reg = reg; + return true; +} + +/* Read in a boolean argument from the given line and store it in *result. */ DIRECTIVE_PARSE_FUNC(bool, bool) diff --git a/src/assembler/parse_util.h b/src/assembler/parse_util.h index 588220d..85bdf86 100644 --- a/src/assembler/parse_util.h +++ b/src/assembler/parse_util.h @@ -24,6 +24,7 @@ bool argparse_register(ASMArgRegister*, const char*, ssize_t); bool argparse_condition(ASMArgCondition*, const char*, ssize_t); bool argparse_immediate(ASMArgImmediate*, const char*, ssize_t); bool argparse_indirect(ASMArgIndirect*, const char*, ssize_t); +bool argparse_indexed(ASMArgIndexed*, const char*, ssize_t); /* Preprocessor directive parsers */ bool dparse_bool(bool*, const ASMLine*, const char*);