asm/asm.c
static enum Arg *check_args(
        struct Context *ctx,
        struct Op *op,
        enum Arg *args,
        usize num_args
    ) {
    enum Arg *arg = args, *op_arg = op->args;
    while (arg != &args[num_args]) {
        // too many arguments
        if (op_arg == &op->args[op->num_args]) {
            return &args[num_args - 1];
        }

        bool fail = false;
        fail |= (*op_arg & A_ADDR) && !(*arg & A_IMM);
        fail |= (*op_arg & A_REG) && !(*op_arg & A_IMM) && !(*arg & A_REG);
        fail |= (*op_arg & A_IMM) && !(*op_arg & A_REG) && !(*arg & A_IMM);
        fail |= (*op_arg & A_IMM8) && !(*op_arg & A_IMM16) && (*arg & A_IMM16);

        // TODO: is this check necessary?
        // fail |= !(*op_arg & A_ADDR) && (*arg & A_ADDR);

        if (fail) {
            if (*op_arg & A_HL) {
                // HL indicates argument is optional, retry with next argument
                op_arg++;
                continue;
            } else {
                return arg;
            }
        }

        arg++;
        op_arg++;
    }

    // not enough arguments
    if (op_arg != &op->args[op->num_args] &&
            !(*op_arg & A_HL)) {
        return &args[num_args - 1];
    }

    return NULL;
}
// checks if arguments starting are legal for Op op
// returns NULL if arguments are legal, otherwise returns pointer to erroneous
// argument. returns pointer to last argument if there are too many arguments.
checks if arguments starting are legal for Op op
returns NULL if arguments are legal, otherwise returns pointer to erroneous
argument. returns pointer to last argument if there are too many arguments.
checks if arguments starting are legal for Op op returns NULL if arguments are legal otherwise returns pointer to erroneous argument . returns pointer to last argument if there are too many arguments .
static enum Arg *check_args(
        struct Context *ctx,
        struct Op *op,
        enum Arg *args,
        usize num_args
    ) {
    enum Arg *arg = args, *op_arg = op->args;
    while (arg != &args[num_args]) {
        if (op_arg == &op->args[op->num_args]) {
            return &args[num_args - 1];
        }
        bool fail = false;
        fail |= (*op_arg & A_ADDR) && !(*arg & A_IMM);
        fail |= (*op_arg & A_REG) && !(*op_arg & A_IMM) && !(*arg & A_REG);
        fail |= (*op_arg & A_IMM) && !(*op_arg & A_REG) && !(*arg & A_IMM);
        fail |= (*op_arg & A_IMM8) && !(*op_arg & A_IMM16) && (*arg & A_IMM16);
        if (fail) {
            if (*op_arg & A_HL) {
                op_arg++;
                continue;
            } else {
                return arg;
            }
        }
        arg++;
        op_arg++;
    }
    if (op_arg != &op->args[op->num_args] &&
            !(*op_arg & A_HL)) {
        return &args[num_args - 1];
    }
    return NULL;
}
static enum Arg * check_args ( struct Context * ctx , struct Op * op , enum Arg * args , usize num_args ) { enum Arg * arg = args , * op_arg = op -> args ; while ( arg != & args [ num_args ] ) { if ( op_arg == & op -> args [ op -> num_args ] ) { return & args [ num_args - 1 ] ; } bool fail = false ; fail |= ( * op_arg & A_ADDR ) && ! ( * arg & A_IMM ) ; fail |= ( * op_arg & A_REG ) && ! ( * op_arg & A_IMM ) && ! ( * arg & A_REG ) ; fail |= ( * op_arg & A_IMM ) && ! ( * op_arg & A_REG ) && ! ( * arg & A_IMM ) ; fail |= ( * op_arg & A_IMM8 ) && ! ( * op_arg & A_IMM16 ) && ( * arg & A_IMM16 ) ; if ( fail ) { if ( * op_arg & A_HL ) { op_arg ++ ; continue ; } else { return arg ; } } arg ++ ; op_arg ++ ; } if ( op_arg != & op -> args [ op -> num_args ] && ! ( * op_arg & A_HL ) ) { return & args [ num_args - 1 ] ; } return NULL ; }
checks if arguments starting are legal for Op op
returns NULL if arguments are legal, otherwise returns pointer to erroneous
argument.
checks if arguments starting are legal for Op op returns NULL if arguments are legal otherwise returns pointer to erroneous argument .
// too many arguments // TODO: is this check necessary? // fail |= !(*op_arg & A_ADDR) && (*arg & A_ADDR); // HL indicates argument is optional, retry with next argument // not enough arguments