diff --git a/makefile b/makefile index 57346bc..fdf785b 100644 --- a/makefile +++ b/makefile @@ -12,6 +12,7 @@ CFLAGS = $(shell sdl2-config --cflags) LIBS = $(shell sdl2-config --libs) MKDIR = mkdir -p RM = rm -rf +ASM_UP = scripts/update_asm_instructions.py MODE = release BNRY = $(PROGRAM) @@ -23,7 +24,7 @@ DIRS = $(sort $(dir $(OBJS))) ifdef DEBUG BNRY := $(BNRY)$(DEVEXT) - FLAGS += -g -fsanitize=address -DDEBUG_MODE + FLAGS += -g -DDEBUG_MODE MODE = debug endif @@ -47,6 +48,10 @@ $(BUILD)/$(MODE)/%.o: %.c -include $(DEPS) +ASM_INST = $(SOURCES)/assembler/instructions +$(ASM_INST).inc.c: $(ASM_INST).yml $(ASM_UP) + python $(ASM_UP) + test: test-all test-z80 test-asm test-dasm test-all: diff --git a/scripts/update_asm_instructions.py b/scripts/update_asm_instructions.py new file mode 100755 index 0000000..94f9608 --- /dev/null +++ b/scripts/update_asm_instructions.py @@ -0,0 +1,406 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (C) 2014-2015 Ben Kurtovic +# Released under the terms of the MIT License. See LICENSE for details. + +""" +This script generates 'src/assembler/instructions.inc.c' from +'src/assembler/instructions.yml'. It should be run automatically by make +when the latter is modified, but can also be run manually. +""" + +from __future__ import print_function + +from itertools import product +import re +import time + +SOURCE = "src/assembler/instructions.yml" +DEST = "src/assembler/instructions.inc.c" + +ENCODING = "utf8" +TAB = " " * 4 + +try: + import yaml +except ImportError: + print("Error: PyYAML is required (https://pypi.python.org/pypi/PyYAML)\n" + "If you don't want to rebuild {0}, do:\n`make -t {0}`".format(DEST)) + exit(1) + +re_date = re.compile(r"^(\s*@AUTOGEN_DATE\s*)(.*?)$", re.M) +re_inst = re.compile( + r"(/\* @AUTOGEN_INST_BLOCK_START \*/\n*)(.*?)" + r"(\n*/\* @AUTOGEN_INST_BLOCK_END \*/)", re.S) +re_lookup = re.compile( + r"(/\* @AUTOGEN_LOOKUP_BLOCK_START \*/\n*)(.*?)" + r"(\n*/\* @AUTOGEN_LOOKUP_BLOCK_END \*/)", re.S) + +class Instruction(object): + """ + Represent a single ASM instruction mnemonic. + """ + ARG_TYPES = { + "register": "AT_REGISTER", + "immediate": "AT_IMMEDIATE", + "indirect": "AT_INDIRECT", + "indexed": "AT_INDEXED", + "condition": "AT_CONDITION", + "port": "AT_PORT" + } + PSEUDO_TYPES = { + "indirect_hl_or_indexed": ["AT_INDIRECT", "AT_INDEXED"] + } + + def __init__(self, name, data): + self._name = name + self._data = data + self._has_optional_args = False + + def _get_arg_parse_mask(self, num): + """ + Return the appropriate mask to parse_args() for the num-th argument. + """ + types = set() + optional = False + for case in self._data["cases"]: + if num < len(case["type"]): + atype = case["type"][num] + if atype in self.ARG_TYPES: + types.add(self.ARG_TYPES[atype]) + else: + types.update(self.PSEUDO_TYPES[atype]) + else: + optional = True + + if not types: + return "AT_NONE" + if optional: + types.add("AT_OPTIONAL") + self._has_optional_args = True + return "|".join(sorted(types)) + + def _handle_return(self, ret, indent=1): + """ + Return code to handle an instruction return statement. + """ + data = ", ".join("0x%02X" % byte if isinstance(byte, int) else byte + for byte in ret) + return TAB * indent + "INST_RETURN({0}, {1})".format(len(ret), data) + + def _build_case_type_check(self, args): + """ + Return the test part of an if statement for an instruction case. + """ + conds = ["INST_TYPE({0}) == {1}".format(i, self.ARG_TYPES[cond]) + for i, cond in enumerate(args)] + check = " && ".join(conds) + + if self._has_optional_args: + return "INST_NARGS == {0} && ".format(len(args)) + check + return check + + def _build_register_check(self, num, cond): + """ + Return an expression to check for a particular register value. + """ + return "INST_REG({0}) == REG_{1}".format(num, cond.upper()) + + def _build_immediate_check(self, num, cond): + """ + Return an expression to check for a particular immediate value. + """ + if "." in cond: + itype, value = cond.split(".", 1) + try: + value = int(value) + except ValueError: + value = int(value, 16) + vtype = "sval" if itype.upper() in ["S8", "REL"] else "uval" + + test1 = "INST_IMM({0}).mask & IMM_{1}".format(num, itype.upper()) + if (itype.upper() == "U16"): + test1 += " && !INST_IMM({0}).is_label".format(num) + test2 = "INST_IMM({0}).{1} == {2}".format(num, vtype, value) + return "({0} && {1})".format(test1, test2) + + return "INST_IMM({0}).mask & IMM_{1}".format(num, cond.upper()) + + def _build_indirect_check(self, num, cond): + """ + Return an expression to check for a particular indirect value. + """ + if cond.startswith("reg."): + test1 = "INST_INDIRECT({0}).type == AT_REGISTER".format(num) + test2 = "INST_INDIRECT({0}).addr.reg == REG_{1}".format( + num, cond[len("reg."):].upper()) + return "({0} && {1})".format(test1, test2) + + if cond == "imm" or cond == "immediate": + return "INST_INDIRECT({0}).type == AT_IMMEDIATE".format(num) + + err = "Unknown condition for indirect argument: {0}" + return RuntimeError(err.format(cond)) + + def _build_indexed_check(self, num, cond): + """ + Return an expression to check for a particular indexed value. + """ + raise RuntimeError("The indexed arg type does not support conditions") + + def _build_condition_check(self, num, cond): + """ + Return an expression to check for a particular condition value. + """ + return "INST_COND({0}) == COND_{1}".format(num, cond.upper()) + + def _build_port_check(self, num, cond): + """ + Return an expression to check for a particular port value. + """ + if cond == "reg" or cond == "reg.c": + return "INST_PORT({0}).type == AT_REGISTER".format(num) + if cond == "imm" or cond == "immediate": + return "INST_PORT({0}).type == AT_IMMEDIATE".format(num) + + err = "Unknown condition for port argument: {0}" + return RuntimeError(err.format(cond)) + + _SUBCASE_LOOKUP_TABLE = { + "register": _build_register_check, + "immediate": _build_immediate_check, + "indirect": _build_indirect_check, + "indexed": _build_indexed_check, + "condition": _build_condition_check, + "port": _build_port_check + } + + def _build_subcase_check(self, types, conds): + """ + Return the test part of an if statement for an instruction subcase. + """ + conds = [self._SUBCASE_LOOKUP_TABLE[types[i]](self, i, cond) + for i, cond in enumerate(conds) if cond != "_"] + return " && ".join(conds) + + def _iter_permutations(self, types, conds): + """ + Iterate over all permutations of the given subcase conditions. + """ + def split(typ, cond): + if "|" in cond: + splits = [split(typ, c) for c in cond.split("|")] + merged = [choice for s in splits for choice in s] + if len(merged) != len(set(merged)): + msg = "Repeated conditions for {0}: {1}" + raise RuntimeError(msg.format(typ, cond)) + return merged + if typ == "register": + if cond == "i": + return ["ix", "iy"] + if cond == "ih": + return ["ixh", "iyh"] + if cond == "il": + return ["ixl", "iyl"] + return [cond] + + splits = [split(typ, cond) for typ, cond in zip(types, conds)] + num = max(len(cond) for cond in splits) + + if any(1 < len(cond) < num for cond in splits): + msg = "Invalid condition permutations: {0}" + raise RuntimeError(msg.format(conds)) + + choices = [cond * num if len(cond) == 1 else cond for cond in splits] + return zip(*choices) + + def _adapt_return(self, types, conds, ret): + """ + Return a modified byte list to accomodate for prefixes and immediates. + """ + ret = ret[:] + for i, byte in enumerate(ret): + if not isinstance(byte, int): + if byte == "u8": + try: + index = types.index("immediate") + imm = "INST_IMM({0})".format(index) + except ValueError: + index = types.index("port") + imm = "INST_PORT({0}).port.imm".format(index) + ret[i] = imm + ".uval" + + elif byte == "u16": + if i < len(ret) - 1: + raise RuntimeError("U16 return byte must be last") + try: + index = types.index("immediate") + imm = "INST_IMM({0})".format(index) + except ValueError: + indir = types.index("indirect") + if not conds[indir].startswith("imm"): + msg = "Passing non-immediate indirect as immediate" + raise RuntimeError(msg) + imm = "INST_INDIRECT({0}).addr.imm".format(indir) + ret[i] = "INST_IMM_U16_B1({0})".format(imm) + ret.append("INST_IMM_U16_B2({0})".format(imm)) + break + + elif byte == "rel": + index = types.index("immediate") + ret[i] = "INST_IMM({0}).sval - 2".format(index) + + else: + msg = "Unsupported return byte: {0}" + raise RuntimeError(msg.format(byte)) + + for i, cond in enumerate(conds): + if types[i] == "register" and cond[0] == "i": + prefix = "INST_I{0}_PREFIX".format(cond[1].upper()) + if ret[0] != prefix: + ret.insert(0, prefix) + elif types[i] == "indexed": + ret.insert(0, "INST_INDEX_PREFIX({0})".format(i)) + ret.insert(2, "INST_INDEX({0}).offset".format(i)) + + return ret + + def _handle_null_case(self, case): + """ + Return code to handle an instruction case that takes no arguments. + """ + return [ + TAB + "if (INST_NARGS == 0) {", + self._handle_return(case["return"], 2), + TAB + "}" + ] + + def _handle_pseudo_case(self, pseudo, case): + """ + Return code to handle an instruction pseudo-case. + + Pseudo-cases are cases that have pseudo-types as arguments. This means + they are expanded to cover multiple "real" argument types. + """ + index = case["type"].index(pseudo) + + if pseudo == "indirect_hl_or_indexed": + case["type"][index] = "indexed" + indexed = self._handle_case(case) + + case["type"][index] = "indirect" + indirect = self._handle_case(case) + base_cond = self._build_case_type_check(case["type"]) + hl_reg = TAB * 3 + self._build_indirect_check(index, "reg.hl") + indirect[0] = TAB + "if ({0} &&\n{1}) {{".format(base_cond, hl_reg) + + return indirect + indexed + + raise RuntimeError("Unknown pseudo-type: {0}".format(pseudo)) + + def _handle_case(self, case): + """ + Return code to handle an instruction case. + """ + ctype = case["type"] + if not ctype: + return self._handle_null_case(case) + + for pseudo in self.PSEUDO_TYPES: + if pseudo in ctype: + return self._handle_pseudo_case(pseudo, case) + + lines = [] + cond = self._build_case_type_check(ctype) + lines.append(TAB + "if ({0}) {{".format(cond)) + + subcases = [(perm, sub["return"]) for sub in case["cases"] + for perm in self._iter_permutations(ctype, sub["cond"])] + for cond, ret in subcases: + check = self._build_subcase_check(ctype, cond) + ret = self._adapt_return(ctype, cond, ret) + if check: + lines.append(TAB * 2 + "if ({0})".format(check)) + lines.append(self._handle_return(ret, 3)) + else: + lines.append(self._handle_return(ret, 2)) + break # Unconditional subcase + else: + lines.append(TAB * 2 + "INST_ERROR(ARG_VALUE)") + + lines.append(TAB + "}") + return lines + + def render(self): + """ + Convert data for an individual instruction into a C parse function. + """ + lines = [] + + if self._data["args"]: + lines.append("{tab}INST_TAKES_ARGS(\n{tab2}{0},\n{tab2}{1}," + "\n{tab2}{2}\n{tab})".format( + self._get_arg_parse_mask(0), self._get_arg_parse_mask(1), + self._get_arg_parse_mask(2), tab=TAB, tab2=TAB * 2)) + else: + lines.append(TAB + "INST_TAKES_NO_ARGS") + + if "return" in self._data: + lines.append(self._handle_return(self._data["return"])) + elif "cases" in self._data: + for case in self._data["cases"]: + lines.extend(self._handle_case(case)) + lines.append(TAB + "INST_ERROR(ARG_TYPE)") + else: + msg = "Missing return or case block for {0} instruction" + raise RuntimeError(msg.format(self._name)) + + contents = "\n".join(lines) + return "INST_FUNC({0})\n{{\n{1}\n}}".format(self._name, contents) + + +def build_inst_block(data): + """ + Return the instruction parser block, given instruction data. + """ + return "\n\n".join( + Instruction(k, v).render() for k, v in sorted(data.items())) + +def build_lookup_block(data): + """ + Return the instruction lookup block, given instruction data. + """ + macro = TAB + "HANDLE({0})" + return "\n".join(macro.format(inst) for inst in sorted(data.keys())) + +def process(template, data): + """ + Return C code generated from a source template and instruction data. + """ + inst_block = build_inst_block(data) + lookup_block = build_lookup_block(data) + date = time.asctime(time.gmtime()) + + result = re_date.sub(r"\1{0} UTC".format(date), template) + result = re_inst.sub(r"\1{0}\3".format(inst_block), result) + result = re_lookup.sub(r"\1{0}\3".format(lookup_block), result) + return result + +def main(): + """ + Main script entry point. + """ + with open(SOURCE, "r") as fp: + text = fp.read().decode(ENCODING) + with open(DEST, "r") as fp: + template = fp.read().decode(ENCODING) + + data = yaml.load(text) + result = process(template, data) + + with open(DEST, "w") as fp: + fp.write(result.encode(ENCODING)) + +if __name__ == "__main__": + main() diff --git a/src/assembler/errors.c b/src/assembler/errors.c index 4a30f10..5a6bcb5 100644 --- a/src/assembler/errors.c +++ b/src/assembler/errors.c @@ -53,11 +53,8 @@ static const char *error_descs[] = { [ED_PS_TOO_FEW_ARGS] = "too few arguments for opcode", [ED_PS_TOO_MANY_ARGS] = "too many arguments for opcode", [ED_PS_ARG_SYNTAX] = "invalid syntax in argument(s)", - [ED_PS_ARG0_TYPE] = "invalid type for first argument", - [ED_PS_ARG0_BAD_REG] = "unsupported register as first argument", - [ED_PS_ARG1_TYPE] = "invalid type for second argument", - [ED_PS_ARG1_BAD_REG] = "unsupported register as second argument", - [ED_PS_ARG1_RANGE] = "second argument out of range" + [ED_PS_ARG_TYPE] = "invalid argument type", + [ED_PS_ARG_VALUE] = "invalid value for argument" }; /* Internal structs */ diff --git a/src/assembler/errors.h b/src/assembler/errors.h index 6f5b8f3..cf7e1cf 100644 --- a/src/assembler/errors.h +++ b/src/assembler/errors.h @@ -52,11 +52,8 @@ typedef enum { ED_PS_TOO_FEW_ARGS, ED_PS_TOO_MANY_ARGS, ED_PS_ARG_SYNTAX, - ED_PS_ARG0_TYPE, - ED_PS_ARG0_BAD_REG, - ED_PS_ARG1_TYPE, - ED_PS_ARG1_BAD_REG, - ED_PS_ARG1_RANGE + ED_PS_ARG_TYPE, + ED_PS_ARG_VALUE } ASMErrorDesc; /* Structs */ diff --git a/src/assembler/inst_args.h b/src/assembler/inst_args.h index 29eaa77..83647d0 100644 --- a/src/assembler/inst_args.h +++ b/src/assembler/inst_args.h @@ -8,12 +8,14 @@ #define MAX_SYMBOL_SIZE 256 typedef enum { - AT_REGISTER, - AT_IMMEDIATE, - AT_INDIRECT, - AT_INDEXED, - AT_LABEL, - AT_CONDITION + AT_NONE = 0x00, + AT_OPTIONAL = 0x01, + AT_REGISTER = 0x02, + AT_IMMEDIATE = 0x04, + AT_INDIRECT = 0x08, + AT_INDEXED = 0x10, + AT_CONDITION = 0x20, + AT_PORT = 0x40 } ASMArgType; typedef enum { @@ -35,20 +37,17 @@ typedef enum { typedef struct { ASMArgImmType mask; + bool is_label; uint16_t uval; int16_t sval; + char label[MAX_SYMBOL_SIZE]; } ASMArgImmediate; typedef struct { - char text[MAX_SYMBOL_SIZE]; -} ASMArgLabel; - -typedef struct { ASMArgType type; union { ASMArgRegister reg; ASMArgImmediate imm; - ASMArgLabel label; } addr; } ASMArgIndirect; @@ -58,7 +57,7 @@ typedef struct { } ASMArgIndexed; typedef enum { - COND_NZ, COND_N, COND_NC, COND_C, COND_PO, COND_PE, COND_P, COND_M + COND_NZ, COND_Z, COND_NC, COND_C, COND_PO, COND_PE, COND_P, COND_M } ASMArgCondition; typedef struct { @@ -66,9 +65,17 @@ typedef struct { union { ASMArgRegister reg; ASMArgImmediate imm; + } port; +} ASMArgPort; + +typedef struct { + ASMArgType type; + union { + ASMArgRegister reg; + ASMArgImmediate imm; ASMArgIndirect indirect; ASMArgIndexed index; - ASMArgLabel label; ASMArgCondition cond; + ASMArgPort port; } data; } ASMInstArg; diff --git a/src/assembler/inst_support.c b/src/assembler/inst_support.c deleted file mode 100644 index 895f99d..0000000 --- a/src/assembler/inst_support.c +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright (C) 2014-2015 Ben Kurtovic - Released under the terms of the MIT License. See LICENSE for details. */ - -#include "inst_support.h" - -/* Macro used by parse_arg() */ - -#define TRY_PARSER(func, argtype, field) \ - if (argparse_##func(&arg->data.field, info)) { \ - arg->type = argtype; \ - return ED_NONE; \ - } - -/* - Fill an instruction's byte array with the given data. - - This internal function is only called for instructions longer than four - bytes (of which there is only one: the fake emulator debugging/testing - opcode with mnemonic "emu"), so it does not get used in normal situations. - - Return the value of the last byte inserted, for compatibility with the - INST_SETn_ family of macros. -*/ -uint8_t fill_bytes_variadic(uint8_t *bytes, size_t len, ...) -{ - va_list vargs; - va_start(vargs, len); - for (size_t i = 0; i < len; i++) - bytes[i] = va_arg(vargs, unsigned); - va_end(vargs); - return bytes[len - 1]; -} - -/* - Parse a single instruction argument into an ASMInstArg object. - - Return ED_NONE (0) on success or an error code on failure. -*/ -static ASMErrorDesc parse_arg( - ASMInstArg *arg, const char *str, size_t size, ASMDefineTable *deftable) -{ - ASMArgParseInfo info = {.arg = str, .size = size, .deftable = deftable}; - TRY_PARSER(register, AT_REGISTER, reg) - TRY_PARSER(immediate, AT_IMMEDIATE, imm) - TRY_PARSER(indirect, AT_INDIRECT, indirect) - TRY_PARSER(indexed, AT_INDEXED, index) - TRY_PARSER(condition, AT_CONDITION, cond) - TRY_PARSER(label, AT_LABEL, label) - return ED_PS_ARG_SYNTAX; -} - -/* - Parse an argument string into ASMInstArg objects. - - Return ED_NONE (0) on success or an error code on failure. -*/ -ASMErrorDesc parse_args( - ASMInstArg args[3], size_t *nargs, ASMArgParseInfo ap_info) -{ - ASMErrorDesc err; - ASMDefineTable *dt = ap_info.deftable; - const char *str = ap_info.arg; - size_t size = ap_info.size, start = 0, i = 0; - - 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, dt))) - return err; - (*nargs)++; - - i++; - if (i < size && str[i] == ' ') - i++; - start = i; - 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') || - c == ' ' || c == '+' || c == '-' || c == '(' || c == ')' || - c == '$' || c == '_' || c == '.') - i++; - else - return ED_PS_ARG_SYNTAX; - } - } - - if (i > start) { - if ((err = parse_arg(&args[*nargs], str + start, i - start, dt))) - return err; - (*nargs)++; - } - return ED_NONE; -} diff --git a/src/assembler/inst_support.h b/src/assembler/inst_support.h deleted file mode 100644 index ce282cd..0000000 --- a/src/assembler/inst_support.h +++ /dev/null @@ -1,155 +0,0 @@ -/* Copyright (C) 2014-2015 Ben Kurtovic - Released under the terms of the MIT License. See LICENSE for details. */ - -#pragma once - -#include -#include - -#include "errors.h" -#include "inst_args.h" -#include "parse_util.h" -#include "../util.h" - -/* Helper macros for get_inst_parser() */ - -#define JOIN_(a, b, c, d) ((uint32_t) ((a << 24) + (b << 16) + (c << 8) + d)) - -#define DISPATCH_(s, z) ( \ - (z) == 2 ? JOIN_(s[0], s[1], 0x00, 0x00) : \ - (z) == 3 ? JOIN_(s[0], s[1], s[2], 0x00) : \ - JOIN_(s[0], s[1], s[2], s[3])) \ - -#define MAKE_CMP_(s) DISPATCH_(s, sizeof(s) / sizeof(char) - 1) - -#define HANDLE(m) if (key == MAKE_CMP_(#m)) return parse_inst_##m; - -/* Internal helper macros */ - -#define INST_ALLOC_(len) \ - *length = len; \ - *bytes = cr_malloc(sizeof(uint8_t) * (len)); - -#define INST_SET_(b, val) ((*bytes)[b] = val) -#define INST_SET1_(b1) INST_SET_(0, b1) -#define INST_SET2_(b1, b2) INST_SET1_(b1), INST_SET_(1, b2) -#define INST_SET3_(b1, b2, b3) INST_SET2_(b1, b2), INST_SET_(2, b3) -#define INST_SET4_(b1, b2, b3, b4) INST_SET3_(b1, b2, b3), INST_SET_(3, b4) - -#define INST_DISPATCH_(a, b, c, d, target, ...) target - -#define INST_FILL_BYTES_(len, ...) \ - ((len > 4) ? fill_bytes_variadic(*bytes, len, __VA_ARGS__) : \ - INST_DISPATCH_(__VA_ARGS__, INST_SET4_, INST_SET3_, INST_SET2_, \ - INST_SET1_, __VA_ARGS__)(__VA_ARGS__)); - -#define INST_IX_PREFIX_ 0xDD -#define INST_IY_PREFIX_ 0xFD - -#define INST_PREFIX_(reg) \ - (((reg) == REG_IX || (reg) == REG_IXH || (reg) == REG_IXL) ? \ - INST_IX_PREFIX_ : INST_IY_PREFIX_) - -#define INST_RETURN_WITH_SYMBOL_(len, label, ...) { \ - *symbol = cr_strdup(label.text); \ - INST_ALLOC_(len) \ - INST_FILL_BYTES_(len - 2, __VA_ARGS__) \ - return ED_NONE; \ - } - -/* Essential/basic helper macros */ - -#define INST_FUNC(mnemonic) \ -static ASMErrorDesc parse_inst_##mnemonic( \ - uint8_t **bytes, size_t *length, char **symbol, ASMArgParseInfo ap_info) \ - -#define INST_ERROR(desc) return ED_PS_##desc; - -#define INST_TAKES_NO_ARGS \ - if (ap_info.arg) \ - INST_ERROR(TOO_MANY_ARGS) - -#define INST_TAKES_ARGS(lo, hi) \ - if (!ap_info.arg) \ - INST_ERROR(TOO_FEW_ARGS) \ - ASMInstArg args[3]; \ - size_t nargs = 0; \ - ASMErrorDesc err = parse_args(args, &nargs, ap_info); \ - if (err) \ - return err; \ - if (nargs < lo) \ - INST_ERROR(TOO_FEW_ARGS) \ - if (nargs > hi) \ - INST_ERROR(TOO_MANY_ARGS) - -#define INST_NARGS nargs -#define INST_TYPE(n) args[n].type -#define INST_REG(n) args[n].data.reg -#define INST_IMM(n) args[n].data.imm -#define INST_INDIRECT(n) args[n].data.indirect -#define INST_INDEX(n) args[n].data.index -#define INST_LABEL(n) args[n].data.label -#define INST_COND(n) args[n].data.cond - -#define INST_RETURN(len, ...) { \ - (void) symbol; \ - INST_ALLOC_(len) \ - INST_FILL_BYTES_(len, __VA_ARGS__) \ - return ED_NONE; \ - } - -/* Convenience macros */ - -#define INST_FORCE_TYPE(n, t) { \ - if (INST_TYPE(n) != t) \ - INST_ERROR(ARG##n##_TYPE) \ - } - -#define INST_CHECK_IMM(n, m) { \ - if (!(INST_IMM(n).mask & (m))) \ - INST_ERROR(ARG##n##_RANGE) \ - } - -#define INST_REG_ONLY(n, reg) { \ - if (INST_TYPE(n) != AT_REGISTER) \ - INST_ERROR(ARG##n##_TYPE) \ - if (INST_REG(n) != reg) \ - INST_ERROR(ARG##n##_BAD_REG) \ - } - -#define INST_INDIRECT_HL_ONLY(n) { \ - if (INST_INDIRECT(n).type != AT_REGISTER) \ - INST_ERROR(ARG##n##_TYPE) \ - if (INST_INDIRECT(n).addr.reg != REG_HL) \ - INST_ERROR(ARG##n##_BAD_REG) \ - } - -#define INST_INDEX_PREFIX(n) INST_PREFIX_(INST_INDEX(n).reg) - -#define INST_INDEX_BYTES(n, b) \ - INST_INDEX_PREFIX(n), b, INST_INDEX(n).offset - -#define INST_INDIRECT_IMM(n) \ - INST_INDIRECT(n).addr.imm.uval >> 8, \ - INST_INDIRECT(n).addr.imm.uval & 0xFF - -#define INST_RETURN_INDIRECT_LABEL(n, len, ...) \ - INST_RETURN_WITH_SYMBOL_(len, INST_INDIRECT(n).addr.label, __VA_ARGS__) - -#define INST_HANDLE_MAIN_8_BIT_REGS(base) \ - case REG_A: INST_RETURN(1, base + 7) \ - case REG_B: INST_RETURN(1, base) \ - case REG_C: INST_RETURN(1, base + 1) \ - case REG_D: INST_RETURN(1, base + 2) \ - case REG_E: INST_RETURN(1, base + 3) \ - case REG_H: INST_RETURN(1, base + 4) \ - case REG_L: INST_RETURN(1, base + 5) \ - case REG_IXH: INST_RETURN(2, INST_IX_PREFIX_, base + 4) \ - case REG_IXL: INST_RETURN(2, INST_IX_PREFIX_, base + 5) \ - case REG_IYH: INST_RETURN(2, INST_IY_PREFIX_, base + 4) \ - case REG_IYL: INST_RETURN(2, INST_IY_PREFIX_, base + 5) \ - -/* Internal functions */ - -uint8_t fill_bytes_variadic(uint8_t*, size_t, ...); -ASMErrorDesc parse_args(ASMInstArg args[3], size_t*, ASMArgParseInfo); diff --git a/src/assembler/instructions.c b/src/assembler/instructions.c index 652e210..04e0cea 100644 --- a/src/assembler/instructions.c +++ b/src/assembler/instructions.c @@ -1,705 +1,203 @@ /* Copyright (C) 2014-2015 Ben Kurtovic Released under the terms of the MIT License. See LICENSE for details. */ -#include "instructions.h" -#include "inst_support.h" - -/* Instruction parser functions */ - -INST_FUNC(adc) -{ - INST_TAKES_ARGS(2, 2) - INST_FORCE_TYPE(0, AT_REGISTER) - switch (INST_REG(0)) { - case REG_A: - switch (INST_TYPE(1)) { - case AT_REGISTER: - switch (INST_REG(1)) { - INST_HANDLE_MAIN_8_BIT_REGS(0x88) - default: INST_ERROR(ARG1_BAD_REG) - } - case AT_IMMEDIATE: - INST_CHECK_IMM(1, IMM_U8) - INST_RETURN(2, 0xCE, INST_IMM(1).uval) - case AT_INDIRECT: - INST_INDIRECT_HL_ONLY(1) - INST_RETURN(1, 0x8E) - case AT_INDEXED: - INST_RETURN(3, INST_INDEX_BYTES(1, 0x8E)) - default: - INST_ERROR(ARG1_TYPE) - } - case REG_HL: - INST_FORCE_TYPE(1, AT_REGISTER) - switch (INST_REG(1)) { - case REG_BC: INST_RETURN(2, 0xED, 0x4A) - case REG_DE: INST_RETURN(2, 0xED, 0x5A) - case REG_HL: INST_RETURN(2, 0xED, 0x6A) - case REG_SP: INST_RETURN(2, 0xED, 0x7A) - default: INST_ERROR(ARG1_BAD_REG) - } - default: - INST_ERROR(ARG0_TYPE) - } -} - -INST_FUNC(add) -{ - INST_TAKES_ARGS(2, 2) - INST_FORCE_TYPE(0, AT_REGISTER) - switch (INST_REG(0)) { - case REG_A: - switch (INST_TYPE(1)) { - case AT_REGISTER: - switch (INST_REG(1)) { - INST_HANDLE_MAIN_8_BIT_REGS(0x80) - default: INST_ERROR(ARG1_BAD_REG) - } - case AT_IMMEDIATE: - INST_CHECK_IMM(1, IMM_U8) - INST_RETURN(2, 0xC6, INST_IMM(1).uval) - case AT_INDIRECT: - INST_INDIRECT_HL_ONLY(1) - INST_RETURN(1, 0x86) - case AT_INDEXED: - INST_RETURN(3, INST_INDEX_BYTES(1, 0x86)) - default: - INST_ERROR(ARG1_TYPE) - } - case REG_HL: - INST_FORCE_TYPE(1, AT_REGISTER) - switch (INST_REG(1)) { - case REG_BC: INST_RETURN(1, 0x09) - case REG_DE: INST_RETURN(1, 0x19) - case REG_HL: INST_RETURN(1, 0x29) - case REG_SP: INST_RETURN(1, 0x39) - default: INST_ERROR(ARG1_BAD_REG) - } - case REG_IX: - case REG_IY: - INST_FORCE_TYPE(1, AT_REGISTER) - switch (INST_REG(1)) { - case REG_BC: INST_RETURN(2, INST_INDEX_PREFIX(1), 0x09) - case REG_DE: INST_RETURN(2, INST_INDEX_PREFIX(1), 0x19) - case REG_IX: - case REG_IY: - if (INST_REG(0) != INST_REG(1)) - INST_ERROR(ARG1_BAD_REG) - INST_RETURN(2, INST_INDEX_PREFIX(1), 0x29) - case REG_SP: INST_RETURN(2, INST_INDEX_PREFIX(1), 0x39) - default: INST_ERROR(ARG1_BAD_REG) - } - default: - INST_ERROR(ARG0_TYPE) - } -} - -INST_FUNC(and) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(bit) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(call) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(ccf) -{ - INST_TAKES_NO_ARGS - INST_RETURN(1, 0x3F) -} - -INST_FUNC(cp) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(cpd) -{ - INST_TAKES_NO_ARGS - INST_RETURN(2, 0xED, 0xA9) -} - -INST_FUNC(cpdr) -{ - INST_TAKES_NO_ARGS - INST_RETURN(2, 0xED, 0xB9) -} - -INST_FUNC(cpi) -{ - INST_TAKES_NO_ARGS - INST_RETURN(2, 0xED, 0xA1) -} - -INST_FUNC(cpir) -{ - INST_TAKES_NO_ARGS - INST_RETURN(2, 0xED, 0xB1) -} - -INST_FUNC(cpl) -{ - INST_TAKES_NO_ARGS - INST_RETURN(1, 0x2F) -} - -INST_FUNC(daa) -{ - INST_TAKES_NO_ARGS - INST_RETURN(1, 0x27) -} - -INST_FUNC(dec) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(di) -{ - INST_TAKES_NO_ARGS - INST_RETURN(1, 0xF3) -} +#include +#include -INST_FUNC(djnz) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} +#include "instructions.h" +#include "inst_args.h" +#include "../util.h" -INST_FUNC(ei) -{ - INST_TAKES_NO_ARGS - INST_RETURN(1, 0xFB) -} +/* Helper macros for get_inst_parser() and lookup_parser() */ -INST_FUNC(ex) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} +#define JOIN(a, b, c, d) ((uint32_t) ((a << 24) + (b << 16) + (c << 8) + d)) -INST_FUNC(exx) -{ - INST_TAKES_NO_ARGS - INST_RETURN(1, 0xD9) -} +#define DISPATCH_(s, z) ( \ + (z) == 2 ? JOIN(s[0], s[1], 0x00, 0x00) : \ + (z) == 3 ? JOIN(s[0], s[1], s[2], 0x00) : \ + JOIN(s[0], s[1], s[2], s[3])) \ -INST_FUNC(halt) -{ - INST_TAKES_NO_ARGS - INST_RETURN(1, 0x76) -} +#define MAKE_CMP_(s) DISPATCH_(s, sizeof(s) / sizeof(char) - 1) -INST_FUNC(im) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} +#define HANDLE(m) if (key == MAKE_CMP_(#m)) return parse_inst_##m; -INST_FUNC(in) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} +/* Helper macro for parse_arg() */ -INST_FUNC(inc) -{ - INST_TAKES_ARGS(1, 1) - switch (INST_TYPE(0)) { - case AT_REGISTER: - switch (INST_REG(0)) { - case REG_A: INST_RETURN(1, 0x3C) - case REG_B: INST_RETURN(1, 0x04) - case REG_C: INST_RETURN(1, 0x0C) - case REG_D: INST_RETURN(1, 0x14) - case REG_E: INST_RETURN(1, 0x1C) - case REG_H: INST_RETURN(1, 0x24) - case REG_L: INST_RETURN(1, 0x2C) - case REG_BC: INST_RETURN(1, 0x03) - case REG_DE: INST_RETURN(1, 0x13) - case REG_HL: INST_RETURN(1, 0x23) - case REG_SP: INST_RETURN(1, 0x33) - case REG_IX: INST_RETURN(2, 0xDD, 0x23) - case REG_IY: INST_RETURN(2, 0xFD, 0x23) - case REG_IXH: INST_RETURN(2, 0xDD, 0x2C) - case REG_IXL: INST_RETURN(2, 0xFD, 0x2C) - case REG_IYH: INST_RETURN(2, 0xDD, 0x2C) - case REG_IYL: INST_RETURN(2, 0xFD, 0x2C) - default: INST_ERROR(ARG0_BAD_REG) - } - case AT_INDIRECT: - INST_INDIRECT_HL_ONLY(0) - INST_RETURN(1, 0x34) - case AT_INDEXED: - INST_RETURN(3, INST_INDEX_BYTES(0, 0x34)) - default: - INST_ERROR(ARG0_TYPE) +#define TRY_PARSER(func, argtype, field) \ + if (mask & argtype && argparse_##func(&arg->data.field, info)) { \ + arg->type = argtype; \ + return ED_NONE; \ } -} - -INST_FUNC(ind) -{ - INST_TAKES_NO_ARGS - INST_RETURN(2, 0xED, 0xAA) -} - -INST_FUNC(indr) -{ - INST_TAKES_NO_ARGS - INST_RETURN(2, 0xED, 0xBA) -} -INST_FUNC(ini) -{ - INST_TAKES_NO_ARGS - INST_RETURN(2, 0xED, 0xA2) -} - -INST_FUNC(inir) -{ - INST_TAKES_NO_ARGS - INST_RETURN(2, 0xED, 0xB2) -} - -INST_FUNC(jp) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(jr) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(ld) -{ - uint8_t base; - INST_TAKES_ARGS(2, 2) - switch (INST_TYPE(0)) { - case AT_REGISTER: - switch (INST_REG(0)) { - case REG_A: - switch (INST_TYPE(1)) { - case AT_REGISTER: - switch (INST_REG(1)) { - INST_HANDLE_MAIN_8_BIT_REGS(0x78) - case REG_I: INST_RETURN(2, 0xED, 0x57) - case REG_R: INST_RETURN(2, 0xED, 0x5F) - default: INST_ERROR(ARG1_BAD_REG) - } - case AT_IMMEDIATE: - INST_CHECK_IMM(1, IMM_U8) - INST_RETURN(2, 0x3E, INST_IMM(1).uval) - case AT_INDIRECT: - switch (INST_INDIRECT(1).type) { - case AT_REGISTER: - switch (INST_INDIRECT(1).addr.reg) { - case REG_BC: INST_RETURN(1, 0x0A) - case REG_DE: INST_RETURN(1, 0x1A) - case REG_HL: INST_RETURN(1, 0x7E) - default: INST_ERROR(ARG0_BAD_REG) - } - case AT_IMMEDIATE: - INST_RETURN(3, 0x3A, INST_INDIRECT_IMM(1)) - case AT_LABEL: - INST_RETURN_INDIRECT_LABEL(1, 3, 0x3A) - default: - INST_ERROR(ARG1_TYPE) - } - case AT_INDEXED: - INST_RETURN(3, INST_INDEX_BYTES(1, 0x7E)) - default: - INST_ERROR(ARG1_TYPE) - } - case REG_B: - base = 0x00; - case REG_C: - base = 0x08; - case REG_D: - base = 0x10; - case REG_E: - base = 0x18; - switch (INST_TYPE(1)) { - case AT_REGISTER: - switch (INST_REG(1)) { - INST_HANDLE_MAIN_8_BIT_REGS(base + 0x40) - default: INST_ERROR(ARG1_BAD_REG) - } - case AT_IMMEDIATE: - INST_CHECK_IMM(1, IMM_U8) - INST_RETURN(2, base + 0x06, INST_IMM(1).uval) - case AT_INDIRECT: - INST_INDIRECT_HL_ONLY(1) - INST_RETURN(1, base + 0x46) - case AT_INDEXED: - INST_RETURN(3, INST_INDEX_BYTES(1, base + 0x46)) - default: - INST_ERROR(ARG1_TYPE) - } - case REG_H: // TODO (11 cases) - case REG_L: // TODO (11 cases) - case REG_I: - INST_REG_ONLY(1, REG_A) - INST_RETURN(2, 0xED, 0x47) - case REG_R: - INST_REG_ONLY(1, REG_A) - INST_RETURN(2, 0xED, 0x4F) - case REG_BC: // TODO ( 2 cases) - case REG_DE: // TODO ( 2 cases) - case REG_HL: // TODO ( 3 cases) - case REG_IX: // TODO ( 2 cases) - case REG_IY: // TODO ( 2 cases) - case REG_SP: // TODO ( 5 cases) - case REG_IXH: // TODO ( 8 cases) - case REG_IXL: // TODO ( 8 cases) - case REG_IYH: // TODO ( 8 cases) - case REG_IYL: // TODO ( 8 cases) - default: INST_ERROR(ARG0_BAD_REG) - } - case AT_INDIRECT: - switch (INST_INDIRECT(0).type) { - case AT_REGISTER: - switch (INST_INDIRECT(0).addr.reg) { - case REG_BC: // TODO (1 case ) - case REG_DE: // TODO (1 case ) - case REG_HL: // TODO (8 cases) - default: INST_ERROR(ARG0_BAD_REG) - } - case AT_IMMEDIATE: - // TODO (8 cases) - case AT_LABEL: - // TODO (same 8 cases) - default: - INST_ERROR(ARG0_TYPE) - } - case AT_INDEXED: - // TODO (16 cases) - default: - INST_ERROR(ARG0_TYPE) +/* Internal helper macros */ + +#define INST_ALLOC_(len) \ + *length = len; \ + *bytes = cr_malloc(sizeof(uint8_t) * (len)); + +#define INST_SET_(b, val) ((*bytes)[b] = val) +#define INST_SET1_(b1) INST_SET_(0, b1) +#define INST_SET2_(b1, b2) INST_SET1_(b1), INST_SET_(1, b2) +#define INST_SET3_(b1, b2, b3) INST_SET2_(b1, b2), INST_SET_(2, b3) +#define INST_SET4_(b1, b2, b3, b4) INST_SET3_(b1, b2, b3), INST_SET_(3, b4) + +#define INST_DISPATCH_(a, b, c, d, target, ...) target + +#define INST_FILL_BYTES_(len, ...) \ + ((len > 4) ? fill_bytes_variadic(*bytes, len, __VA_ARGS__) : \ + INST_DISPATCH_(__VA_ARGS__, INST_SET4_, INST_SET3_, INST_SET2_, \ + INST_SET1_, __VA_ARGS__)(__VA_ARGS__)); + +#define INST_PREFIX_(reg) \ + (((reg) == REG_IX || (reg) == REG_IXH || (reg) == REG_IXL) ? \ + INST_IX_PREFIX : INST_IY_PREFIX) + +/* Helper macros for instruction parsers */ + +#define INST_FUNC(mnemonic) \ +static ASMErrorDesc parse_inst_##mnemonic( \ + uint8_t **bytes, size_t *length, char **symbol, ASMArgParseInfo ap_info) \ + +#define INST_ERROR(desc) return ED_PS_##desc; + +#define INST_TAKES_NO_ARGS \ + if (ap_info.arg) \ + INST_ERROR(TOO_MANY_ARGS) + +#define INST_TAKES_ARGS(a0, a1, a2) \ + ASMInstArg args[3]; \ + size_t nargs; \ + ASMArgType masks[] = {a0, a1, a2}; \ + ASMErrorDesc err = parse_args(args, &nargs, ap_info, masks); \ + if (err) \ + return err; \ + +#define INST_NARGS nargs +#define INST_TYPE(n) args[n].type +#define INST_REG(n) args[n].data.reg +#define INST_IMM(n) args[n].data.imm +#define INST_INDIRECT(n) args[n].data.indirect +#define INST_INDEX(n) args[n].data.index +#define INST_COND(n) args[n].data.cond +#define INST_PORT(n) args[n].data.port + +#define INST_IX_PREFIX 0xDD +#define INST_IY_PREFIX 0xFD + +#define INST_RETURN(len, ...) { \ + (void) symbol; \ + INST_ALLOC_(len) \ + INST_FILL_BYTES_(len, __VA_ARGS__) \ + return ED_NONE; \ } -} - -INST_FUNC(ldd) -{ - INST_TAKES_NO_ARGS - INST_RETURN(2, 0xED, 0xA8) -} - -INST_FUNC(lddr) -{ - INST_TAKES_NO_ARGS - INST_RETURN(2, 0xED, 0xB8) -} - -INST_FUNC(ldi) -{ - INST_TAKES_NO_ARGS - INST_RETURN(2, 0xED, 0xA0) -} - -INST_FUNC(ldir) -{ - INST_TAKES_NO_ARGS - INST_RETURN(2, 0xED, 0xB0) -} -INST_FUNC(neg) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(nop) -{ - INST_TAKES_NO_ARGS - INST_RETURN(1, 0x00) -} - -INST_FUNC(or) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(otdr) -{ - INST_TAKES_NO_ARGS - INST_RETURN(2, 0xED, 0xBB) -} - -INST_FUNC(otir) -{ - INST_TAKES_NO_ARGS - INST_RETURN(2, 0xED, 0xB3) -} - -INST_FUNC(out) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(outd) -{ - INST_TAKES_NO_ARGS - INST_RETURN(2, 0xED, 0xAB) -} - -INST_FUNC(outi) -{ - INST_TAKES_NO_ARGS - INST_RETURN(2, 0xED, 0xA3) -} - -INST_FUNC(pop) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(push) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(res) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(ret) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(reti) -{ - INST_TAKES_NO_ARGS - INST_RETURN(2, 0xED, 0x4D) -} - -INST_FUNC(retn) -{ - INST_TAKES_NO_ARGS - INST_RETURN(2, 0xED, 0x45) -} - -INST_FUNC(rl) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(rla) -{ - INST_TAKES_NO_ARGS - INST_RETURN(1, 0x17) -} - -INST_FUNC(rlc) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} +#define INST_IMM_U16_B1(imm) \ + ((imm).is_label ? (*symbol = cr_strdup((imm).label), 0) : (imm).uval >> 8) +#define INST_IMM_U16_B2(imm) \ + ((imm).is_label ? 0 : (imm).uval & 0xFF) -INST_FUNC(rlca) -{ - INST_TAKES_NO_ARGS - INST_RETURN(1, 0x07) -} +#define INST_INDEX_PREFIX(n) INST_PREFIX_(INST_INDEX(n).reg) -INST_FUNC(rld) -{ - INST_TAKES_NO_ARGS - INST_RETURN(2, 0xED, 0x6F) -} +/* ----------------------------- END WORK BLOCK ---------------------------- */ -INST_FUNC(rr) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(rra) -{ - INST_TAKES_NO_ARGS - INST_RETURN(1, 0x1F) -} - -INST_FUNC(rrc) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(rrca) -{ - INST_TAKES_NO_ARGS - INST_RETURN(1, 0x0F) -} - -INST_FUNC(rrd) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(rst) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(sbc) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(scf) -{ - INST_TAKES_NO_ARGS - INST_RETURN(1, 0x37) -} +/* + Fill an instruction's byte array with the given data. -INST_FUNC(set) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} + This internal function is only called for instructions longer than four + bytes (of which there is only one: the fake emulator debugging/testing + opcode with mnemonic "emu"), so it does not get used in normal situations. -INST_FUNC(sl1) + Return the value of the last byte inserted, for compatibility with the + INST_SETn_ family of macros. +*/ +static uint8_t fill_bytes_variadic(uint8_t *bytes, size_t len, ...) { - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) + va_list vargs; + va_start(vargs, len); + for (size_t i = 0; i < len; i++) + bytes[i] = va_arg(vargs, unsigned); + va_end(vargs); + return bytes[len - 1]; } -INST_FUNC(sla) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} +/* + Parse a single instruction argument into an ASMInstArg object. -INST_FUNC(sll) + Return ED_NONE (0) on success or an error code on failure. +*/ +static ASMErrorDesc parse_arg( + ASMInstArg *arg, const char *str, size_t size, ASMDefineTable *deftable, + ASMArgType mask) { - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) + ASMArgParseInfo info = {.arg = str, .size = size, .deftable = deftable}; + TRY_PARSER(register, AT_REGISTER, reg) + TRY_PARSER(condition, AT_CONDITION, cond) + TRY_PARSER(indexed, AT_INDEXED, index) + TRY_PARSER(indirect, AT_INDIRECT, indirect) + TRY_PARSER(port, AT_PORT, port) + TRY_PARSER(immediate, AT_IMMEDIATE, imm) + return ED_PS_ARG_SYNTAX; } -INST_FUNC(sls) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} +/* + Parse an argument string into ASMInstArg objects. -INST_FUNC(sra) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} + Return ED_NONE (0) on success or an error code on failure. +*/ +static ASMErrorDesc parse_args( + ASMInstArg args[3], size_t *nargs, ASMArgParseInfo ap_info, + ASMArgType masks[3]) +{ + ASMErrorDesc err; + ASMDefineTable *dt = ap_info.deftable; + const char *str = ap_info.arg; + size_t size = ap_info.size, start = 0, i = 0, n = 0; + + while (i < size) { + char c = str[i]; + if (c == ',') { + if (i == start) + return ED_PS_ARG_SYNTAX; + if (masks[n] == AT_NONE) + return ED_PS_TOO_MANY_ARGS; + err = parse_arg(&args[n], str + start, i - start, dt, masks[n]); + if (err) + return err; + n++; + + i++; + if (i < size && str[i] == ' ') + i++; + start = i; + if (i == size) + return ED_PS_ARG_SYNTAX; + if (n >= 3) + return ED_PS_TOO_MANY_ARGS; + } else { + if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || + c == ' ' || c == '+' || c == '-' || c == '(' || c == ')' || + c == '$' || c == '_' || c == '.') + i++; + else + return ED_PS_ARG_SYNTAX; + } + } -INST_FUNC(srl) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} + if (i > start) { + if (masks[n] == AT_NONE) + return ED_PS_TOO_MANY_ARGS; + if ((err = parse_arg(&args[n], str + start, i - start, dt, masks[n]))) + return err; + n++; + } -INST_FUNC(sub) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) + if (n < 3 && masks[n] != AT_NONE && !(masks[n] & AT_OPTIONAL)) + return ED_PS_TOO_FEW_ARGS; + *nargs = n; + return ED_NONE; } -INST_FUNC(xor) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} +#include "instructions.inc.c" /* Return the relevant ASMInstParser function for a given mnemonic. @@ -710,78 +208,6 @@ ASMInstParser get_inst_parser(char mstr[MAX_MNEMONIC_SIZE]) { // Exploit the fact that we can store the entire mnemonic string as a // single 32-bit value to do fast lookups: - uint32_t key = (mstr[0] << 24) + (mstr[1] << 16) + (mstr[2] << 8) + mstr[3]; - - HANDLE(adc) - HANDLE(add) - HANDLE(and) - HANDLE(bit) - HANDLE(call) - HANDLE(ccf) - HANDLE(cp) - HANDLE(cpd) - HANDLE(cpdr) - HANDLE(cpi) - HANDLE(cpir) - HANDLE(cpl) - HANDLE(daa) - HANDLE(dec) - HANDLE(di) - HANDLE(djnz) - HANDLE(ei) - HANDLE(ex) - HANDLE(exx) - HANDLE(halt) - HANDLE(im) - HANDLE(in) - HANDLE(inc) - HANDLE(ind) - HANDLE(indr) - HANDLE(ini) - HANDLE(inir) - HANDLE(jp) - HANDLE(jr) - HANDLE(ld) - HANDLE(ldd) - HANDLE(lddr) - HANDLE(ldi) - HANDLE(ldir) - HANDLE(neg) - HANDLE(nop) - HANDLE(or) - HANDLE(otdr) - HANDLE(otir) - HANDLE(out) - HANDLE(outd) - HANDLE(outi) - HANDLE(pop) - HANDLE(push) - HANDLE(res) - HANDLE(ret) - HANDLE(reti) - HANDLE(retn) - HANDLE(rl) - HANDLE(rla) - HANDLE(rlc) - HANDLE(rlca) - HANDLE(rld) - HANDLE(rr) - HANDLE(rra) - HANDLE(rrc) - HANDLE(rrca) - HANDLE(rrd) - HANDLE(rst) - HANDLE(sbc) - HANDLE(scf) - HANDLE(set) - HANDLE(sl1) - HANDLE(sla) - HANDLE(sll) - HANDLE(sls) - HANDLE(sra) - HANDLE(srl) - HANDLE(sub) - HANDLE(xor) - - return NULL; + uint32_t key = JOIN(mstr[0], mstr[1], mstr[2], mstr[3]); + return lookup_parser(key); } diff --git a/src/assembler/instructions.inc.c b/src/assembler/instructions.inc.c new file mode 100644 index 0000000..9bbd8d8 --- /dev/null +++ b/src/assembler/instructions.inc.c @@ -0,0 +1,2784 @@ +/* Copyright (C) 2014-2015 Ben Kurtovic + Released under the terms of the MIT License. See LICENSE for details. */ + +/* + This file is AUTO-GENERATED from 'instructions.yml'. + + `make` should trigger a rebuild when it is modified; if not, use: + `python scripts/update_asm_instructions.py`. + + @AUTOGEN_DATE Wed May 20 07:34:18 2015 UTC +*/ + +/* @AUTOGEN_INST_BLOCK_START */ + +INST_FUNC(adc) +{ + INST_TAKES_ARGS( + AT_REGISTER, + AT_IMMEDIATE|AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_NONE + ) + if (INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_REGISTER) { + if (INST_REG(0) == REG_A && INST_REG(1) == REG_A) + INST_RETURN(1, 0x8F) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_B) + INST_RETURN(1, 0x88) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_C) + INST_RETURN(1, 0x89) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_D) + INST_RETURN(1, 0x8A) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_E) + INST_RETURN(1, 0x8B) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_H) + INST_RETURN(1, 0x8C) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_IXH) + INST_RETURN(2, INST_IX_PREFIX, 0x8C) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_IYH) + INST_RETURN(2, INST_IY_PREFIX, 0x8C) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_L) + INST_RETURN(1, 0x8D) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_IXL) + INST_RETURN(2, INST_IX_PREFIX, 0x8D) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_IYL) + INST_RETURN(2, INST_IY_PREFIX, 0x8D) + if (INST_REG(0) == REG_HL && INST_REG(1) == REG_BC) + INST_RETURN(2, 0xED, 0x4A) + if (INST_REG(0) == REG_HL && INST_REG(1) == REG_DE) + INST_RETURN(2, 0xED, 0x5A) + if (INST_REG(0) == REG_HL && INST_REG(1) == REG_HL) + INST_RETURN(2, 0xED, 0x6A) + if (INST_REG(0) == REG_HL && INST_REG(1) == REG_SP) + INST_RETURN(2, 0xED, 0x7A) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_IMMEDIATE) { + if (INST_REG(0) == REG_A && INST_IMM(1).mask & IMM_U8) + INST_RETURN(2, 0xCE, INST_IMM(1).uval) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_INDIRECT && + (INST_INDIRECT(1).type == AT_REGISTER && INST_INDIRECT(1).addr.reg == REG_HL)) { + if (INST_REG(0) == REG_A) + INST_RETURN(1, 0x8E) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_INDEXED) { + if (INST_REG(0) == REG_A) + INST_RETURN(3, INST_INDEX_PREFIX(1), 0x8E, INST_INDEX(1).offset) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(add) +{ + INST_TAKES_ARGS( + AT_REGISTER, + AT_IMMEDIATE|AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_NONE + ) + if (INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_REGISTER) { + if (INST_REG(0) == REG_A && INST_REG(1) == REG_A) + INST_RETURN(1, 0x87) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_B) + INST_RETURN(1, 0x80) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_C) + INST_RETURN(1, 0x81) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_D) + INST_RETURN(1, 0x82) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_E) + INST_RETURN(1, 0x83) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_H) + INST_RETURN(1, 0x84) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_IXH) + INST_RETURN(2, INST_IX_PREFIX, 0x84) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_IYH) + INST_RETURN(2, INST_IY_PREFIX, 0x84) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_L) + INST_RETURN(1, 0x85) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_IXL) + INST_RETURN(2, INST_IX_PREFIX, 0x85) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_IYL) + INST_RETURN(2, INST_IY_PREFIX, 0x85) + if (INST_REG(0) == REG_HL && INST_REG(1) == REG_BC) + INST_RETURN(1, 0x09) + if (INST_REG(0) == REG_IX && INST_REG(1) == REG_BC) + INST_RETURN(2, INST_IX_PREFIX, 0x09) + if (INST_REG(0) == REG_IY && INST_REG(1) == REG_BC) + INST_RETURN(2, INST_IY_PREFIX, 0x09) + if (INST_REG(0) == REG_HL && INST_REG(1) == REG_DE) + INST_RETURN(1, 0x19) + if (INST_REG(0) == REG_IX && INST_REG(1) == REG_DE) + INST_RETURN(2, INST_IX_PREFIX, 0x19) + if (INST_REG(0) == REG_IY && INST_REG(1) == REG_DE) + INST_RETURN(2, INST_IY_PREFIX, 0x19) + if (INST_REG(0) == REG_HL && INST_REG(1) == REG_HL) + INST_RETURN(1, 0x29) + if (INST_REG(0) == REG_IX && INST_REG(1) == REG_IX) + INST_RETURN(2, INST_IX_PREFIX, 0x29) + if (INST_REG(0) == REG_IY && INST_REG(1) == REG_IY) + INST_RETURN(2, INST_IY_PREFIX, 0x29) + if (INST_REG(0) == REG_HL && INST_REG(1) == REG_SP) + INST_RETURN(1, 0x39) + if (INST_REG(0) == REG_IX && INST_REG(1) == REG_SP) + INST_RETURN(2, INST_IX_PREFIX, 0x39) + if (INST_REG(0) == REG_IY && INST_REG(1) == REG_SP) + INST_RETURN(2, INST_IY_PREFIX, 0x39) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_IMMEDIATE) { + if (INST_REG(0) == REG_A && INST_IMM(1).mask & IMM_U8) + INST_RETURN(2, 0xC6, INST_IMM(1).uval) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_INDIRECT && + (INST_INDIRECT(1).type == AT_REGISTER && INST_INDIRECT(1).addr.reg == REG_HL)) { + if (INST_REG(0) == REG_A) + INST_RETURN(1, 0x86) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_INDEXED) { + if (INST_REG(0) == REG_A) + INST_RETURN(3, INST_INDEX_PREFIX(1), 0x86, INST_INDEX(1).offset) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(and) +{ + INST_TAKES_ARGS( + AT_IMMEDIATE|AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_NONE, + AT_NONE + ) + if (INST_TYPE(0) == AT_REGISTER) { + if (INST_REG(0) == REG_A) + INST_RETURN(1, 0xA7) + if (INST_REG(0) == REG_B) + INST_RETURN(1, 0xA0) + if (INST_REG(0) == REG_C) + INST_RETURN(1, 0xA1) + if (INST_REG(0) == REG_D) + INST_RETURN(1, 0xA2) + if (INST_REG(0) == REG_E) + INST_RETURN(1, 0xA3) + if (INST_REG(0) == REG_H) + INST_RETURN(1, 0xA4) + if (INST_REG(0) == REG_IXH) + INST_RETURN(2, INST_IX_PREFIX, 0xA4) + if (INST_REG(0) == REG_IYH) + INST_RETURN(2, INST_IY_PREFIX, 0xA4) + if (INST_REG(0) == REG_L) + INST_RETURN(1, 0xA5) + if (INST_REG(0) == REG_IXL) + INST_RETURN(2, INST_IX_PREFIX, 0xA5) + if (INST_REG(0) == REG_IYL) + INST_RETURN(2, INST_IY_PREFIX, 0xA5) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_IMMEDIATE) { + if (INST_IMM(0).mask & IMM_U8) + INST_RETURN(2, 0xE6, INST_IMM(0).uval) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_INDIRECT && + (INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL)) { + INST_RETURN(1, 0xA6) + } + if (INST_TYPE(0) == AT_INDEXED) { + INST_RETURN(3, INST_INDEX_PREFIX(0), 0xA6, INST_INDEX(0).offset) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(bit) +{ + INST_TAKES_ARGS( + AT_IMMEDIATE, + AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_NONE + ) + if (INST_TYPE(0) == AT_IMMEDIATE && INST_TYPE(1) == AT_REGISTER) { + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(1) == REG_A) + INST_RETURN(2, 0xCB, 0x47) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(1) == REG_B) + INST_RETURN(2, 0xCB, 0x40) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(1) == REG_C) + INST_RETURN(2, 0xCB, 0x41) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(1) == REG_D) + INST_RETURN(2, 0xCB, 0x42) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(1) == REG_E) + INST_RETURN(2, 0xCB, 0x43) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(1) == REG_H) + INST_RETURN(2, 0xCB, 0x44) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0x45) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(1) == REG_A) + INST_RETURN(2, 0xCB, 0x4F) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(1) == REG_B) + INST_RETURN(2, 0xCB, 0x48) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(1) == REG_C) + INST_RETURN(2, 0xCB, 0x49) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(1) == REG_D) + INST_RETURN(2, 0xCB, 0x4A) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(1) == REG_E) + INST_RETURN(2, 0xCB, 0x4B) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(1) == REG_H) + INST_RETURN(2, 0xCB, 0x4C) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0x4D) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(1) == REG_A) + INST_RETURN(2, 0xCB, 0x57) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(1) == REG_B) + INST_RETURN(2, 0xCB, 0x50) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(1) == REG_C) + INST_RETURN(2, 0xCB, 0x51) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(1) == REG_D) + INST_RETURN(2, 0xCB, 0x52) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(1) == REG_E) + INST_RETURN(2, 0xCB, 0x53) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(1) == REG_H) + INST_RETURN(2, 0xCB, 0x54) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0x55) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(1) == REG_A) + INST_RETURN(2, 0xCB, 0x5F) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(1) == REG_B) + INST_RETURN(2, 0xCB, 0x58) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(1) == REG_C) + INST_RETURN(2, 0xCB, 0x59) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(1) == REG_D) + INST_RETURN(2, 0xCB, 0x5A) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(1) == REG_E) + INST_RETURN(2, 0xCB, 0x5B) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(1) == REG_H) + INST_RETURN(2, 0xCB, 0x5C) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0x5D) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(1) == REG_A) + INST_RETURN(2, 0xCB, 0x67) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(1) == REG_B) + INST_RETURN(2, 0xCB, 0x60) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(1) == REG_C) + INST_RETURN(2, 0xCB, 0x61) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(1) == REG_D) + INST_RETURN(2, 0xCB, 0x62) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(1) == REG_E) + INST_RETURN(2, 0xCB, 0x63) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(1) == REG_H) + INST_RETURN(2, 0xCB, 0x64) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0x65) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(1) == REG_A) + INST_RETURN(2, 0xCB, 0x6F) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(1) == REG_B) + INST_RETURN(2, 0xCB, 0x68) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(1) == REG_C) + INST_RETURN(2, 0xCB, 0x69) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(1) == REG_D) + INST_RETURN(2, 0xCB, 0x6A) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(1) == REG_E) + INST_RETURN(2, 0xCB, 0x6B) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(1) == REG_H) + INST_RETURN(2, 0xCB, 0x6C) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0x6D) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(1) == REG_A) + INST_RETURN(2, 0xCB, 0x77) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(1) == REG_B) + INST_RETURN(2, 0xCB, 0x70) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(1) == REG_C) + INST_RETURN(2, 0xCB, 0x71) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(1) == REG_D) + INST_RETURN(2, 0xCB, 0x72) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(1) == REG_E) + INST_RETURN(2, 0xCB, 0x73) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(1) == REG_H) + INST_RETURN(2, 0xCB, 0x74) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0x75) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(1) == REG_A) + INST_RETURN(2, 0xCB, 0x7F) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(1) == REG_B) + INST_RETURN(2, 0xCB, 0x78) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(1) == REG_C) + INST_RETURN(2, 0xCB, 0x79) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(1) == REG_D) + INST_RETURN(2, 0xCB, 0x7A) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(1) == REG_E) + INST_RETURN(2, 0xCB, 0x7B) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(1) == REG_H) + INST_RETURN(2, 0xCB, 0x7C) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0x7D) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_IMMEDIATE && INST_TYPE(1) == AT_INDIRECT && + (INST_INDIRECT(1).type == AT_REGISTER && INST_INDIRECT(1).addr.reg == REG_HL)) { + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0)) + INST_RETURN(2, 0xCB, 0x46) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1)) + INST_RETURN(2, 0xCB, 0x4E) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2)) + INST_RETURN(2, 0xCB, 0x56) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3)) + INST_RETURN(2, 0xCB, 0x5E) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4)) + INST_RETURN(2, 0xCB, 0x66) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5)) + INST_RETURN(2, 0xCB, 0x6E) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6)) + INST_RETURN(2, 0xCB, 0x76) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7)) + INST_RETURN(2, 0xCB, 0x7E) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_IMMEDIATE && INST_TYPE(1) == AT_INDEXED) { + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0)) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x46) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1)) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x4E) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2)) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x56) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3)) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x5E) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4)) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x66) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5)) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x6E) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6)) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x76) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7)) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x7E) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(call) +{ + INST_TAKES_ARGS( + AT_CONDITION|AT_IMMEDIATE, + AT_IMMEDIATE|AT_OPTIONAL, + AT_NONE + ) + if (INST_NARGS == 1 && INST_TYPE(0) == AT_IMMEDIATE) { + if (INST_IMM(0).mask & IMM_U16) + INST_RETURN(3, 0xCD, INST_IMM_U16_B1(INST_IMM(0)), INST_IMM_U16_B2(INST_IMM(0))) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 2 && INST_TYPE(0) == AT_CONDITION && INST_TYPE(1) == AT_IMMEDIATE) { + if (INST_COND(0) == COND_NZ && INST_IMM(1).mask & IMM_U16) + INST_RETURN(3, 0xC4, INST_IMM_U16_B1(INST_IMM(1)), INST_IMM_U16_B2(INST_IMM(1))) + if (INST_COND(0) == COND_Z && INST_IMM(1).mask & IMM_U16) + INST_RETURN(3, 0xCC, INST_IMM_U16_B1(INST_IMM(1)), INST_IMM_U16_B2(INST_IMM(1))) + if (INST_COND(0) == COND_NC && INST_IMM(1).mask & IMM_U16) + INST_RETURN(3, 0xD4, INST_IMM_U16_B1(INST_IMM(1)), INST_IMM_U16_B2(INST_IMM(1))) + if (INST_COND(0) == COND_C && INST_IMM(1).mask & IMM_U16) + INST_RETURN(3, 0xDC, INST_IMM_U16_B1(INST_IMM(1)), INST_IMM_U16_B2(INST_IMM(1))) + if (INST_COND(0) == COND_PO && INST_IMM(1).mask & IMM_U16) + INST_RETURN(3, 0xE4, INST_IMM_U16_B1(INST_IMM(1)), INST_IMM_U16_B2(INST_IMM(1))) + if (INST_COND(0) == COND_PE && INST_IMM(1).mask & IMM_U16) + INST_RETURN(3, 0xEC, INST_IMM_U16_B1(INST_IMM(1)), INST_IMM_U16_B2(INST_IMM(1))) + if (INST_COND(0) == COND_P && INST_IMM(1).mask & IMM_U16) + INST_RETURN(3, 0xF4, INST_IMM_U16_B1(INST_IMM(1)), INST_IMM_U16_B2(INST_IMM(1))) + if (INST_COND(0) == COND_M && INST_IMM(1).mask & IMM_U16) + INST_RETURN(3, 0xFC, INST_IMM_U16_B1(INST_IMM(1)), INST_IMM_U16_B2(INST_IMM(1))) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(ccf) +{ + INST_TAKES_NO_ARGS + INST_RETURN(1, 0x3F) +} + +INST_FUNC(cp) +{ + INST_TAKES_ARGS( + AT_IMMEDIATE|AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_NONE, + AT_NONE + ) + if (INST_TYPE(0) == AT_REGISTER) { + if (INST_REG(0) == REG_A) + INST_RETURN(1, 0xBF) + if (INST_REG(0) == REG_B) + INST_RETURN(1, 0xB8) + if (INST_REG(0) == REG_C) + INST_RETURN(1, 0xB9) + if (INST_REG(0) == REG_D) + INST_RETURN(1, 0xBA) + if (INST_REG(0) == REG_E) + INST_RETURN(1, 0xBB) + if (INST_REG(0) == REG_H) + INST_RETURN(1, 0xBC) + if (INST_REG(0) == REG_IXH) + INST_RETURN(2, INST_IX_PREFIX, 0xBC) + if (INST_REG(0) == REG_IYH) + INST_RETURN(2, INST_IY_PREFIX, 0xBC) + if (INST_REG(0) == REG_L) + INST_RETURN(1, 0xBD) + if (INST_REG(0) == REG_IXL) + INST_RETURN(2, INST_IX_PREFIX, 0xBD) + if (INST_REG(0) == REG_IYL) + INST_RETURN(2, INST_IY_PREFIX, 0xBD) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_INDIRECT && + (INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL)) { + INST_RETURN(1, 0xBE) + } + if (INST_TYPE(0) == AT_INDEXED) { + INST_RETURN(3, INST_INDEX_PREFIX(0), 0xBE, INST_INDEX(0).offset) + } + if (INST_TYPE(0) == AT_IMMEDIATE) { + if (INST_IMM(0).mask & IMM_U8) + INST_RETURN(2, 0xFE, INST_IMM(0).uval) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(cpd) +{ + INST_TAKES_NO_ARGS + INST_RETURN(2, 0xED, 0xA9) +} + +INST_FUNC(cpdr) +{ + INST_TAKES_NO_ARGS + INST_RETURN(2, 0xED, 0xB9) +} + +INST_FUNC(cpi) +{ + INST_TAKES_NO_ARGS + INST_RETURN(2, 0xED, 0xA1) +} + +INST_FUNC(cpir) +{ + INST_TAKES_NO_ARGS + INST_RETURN(2, 0xED, 0xB1) +} + +INST_FUNC(cpl) +{ + INST_TAKES_NO_ARGS + INST_RETURN(1, 0x2F) +} + +INST_FUNC(daa) +{ + INST_TAKES_NO_ARGS + INST_RETURN(1, 0x27) +} + +INST_FUNC(dec) +{ + INST_TAKES_ARGS( + AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_NONE, + AT_NONE + ) + if (INST_TYPE(0) == AT_REGISTER) { + if (INST_REG(0) == REG_A) + INST_RETURN(1, 0x3D) + if (INST_REG(0) == REG_B) + INST_RETURN(1, 0x05) + if (INST_REG(0) == REG_C) + INST_RETURN(1, 0x0D) + if (INST_REG(0) == REG_D) + INST_RETURN(1, 0x15) + if (INST_REG(0) == REG_E) + INST_RETURN(1, 0x1D) + if (INST_REG(0) == REG_H) + INST_RETURN(1, 0x25) + if (INST_REG(0) == REG_IXH) + INST_RETURN(2, INST_IX_PREFIX, 0x25) + if (INST_REG(0) == REG_IYH) + INST_RETURN(2, INST_IY_PREFIX, 0x25) + if (INST_REG(0) == REG_L) + INST_RETURN(1, 0x2D) + if (INST_REG(0) == REG_IXL) + INST_RETURN(2, INST_IX_PREFIX, 0x2D) + if (INST_REG(0) == REG_IYL) + INST_RETURN(2, INST_IY_PREFIX, 0x2D) + if (INST_REG(0) == REG_BC) + INST_RETURN(1, 0x0B) + if (INST_REG(0) == REG_DE) + INST_RETURN(1, 0x1B) + if (INST_REG(0) == REG_HL) + INST_RETURN(1, 0x2B) + if (INST_REG(0) == REG_IX) + INST_RETURN(2, INST_IX_PREFIX, 0x2B) + if (INST_REG(0) == REG_IY) + INST_RETURN(2, INST_IY_PREFIX, 0x2B) + if (INST_REG(0) == REG_SP) + INST_RETURN(1, 0x3B) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_INDIRECT && + (INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL)) { + INST_RETURN(1, 0x35) + } + if (INST_TYPE(0) == AT_INDEXED) { + INST_RETURN(3, INST_INDEX_PREFIX(0), 0x35, INST_INDEX(0).offset) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(di) +{ + INST_TAKES_NO_ARGS + INST_RETURN(1, 0xF3) +} + +INST_FUNC(djnz) +{ + INST_TAKES_ARGS( + AT_IMMEDIATE, + AT_NONE, + AT_NONE + ) + if (INST_TYPE(0) == AT_IMMEDIATE) { + if (INST_IMM(0).mask & IMM_REL) + INST_RETURN(2, 0x10, INST_IMM(0).sval - 2) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(ei) +{ + INST_TAKES_NO_ARGS + INST_RETURN(1, 0xFB) +} + +INST_FUNC(ex) +{ + INST_TAKES_ARGS( + AT_INDIRECT|AT_REGISTER, + AT_REGISTER, + AT_NONE + ) + if (INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_REGISTER) { + if (INST_REG(0) == REG_AF && INST_REG(1) == REG_AF_) + INST_RETURN(1, 0x08) + if (INST_REG(0) == REG_DE && INST_REG(1) == REG_HL) + INST_RETURN(1, 0xEB) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_INDIRECT && INST_TYPE(1) == AT_REGISTER) { + if ((INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_SP) && INST_REG(1) == REG_HL) + INST_RETURN(1, 0xE3) + if ((INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_SP) && INST_REG(1) == REG_IX) + INST_RETURN(2, INST_IX_PREFIX, 0xE3) + if ((INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_SP) && INST_REG(1) == REG_IY) + INST_RETURN(2, INST_IY_PREFIX, 0xE3) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(exx) +{ + INST_TAKES_NO_ARGS + INST_RETURN(1, 0xD9) +} + +INST_FUNC(halt) +{ + INST_TAKES_NO_ARGS + INST_RETURN(1, 0x76) +} + +INST_FUNC(im) +{ + INST_TAKES_ARGS( + AT_IMMEDIATE, + AT_NONE, + AT_NONE + ) + if (INST_TYPE(0) == AT_IMMEDIATE) { + if ((INST_IMM(0).mask & IMM_IM && INST_IMM(0).uval == 0)) + INST_RETURN(2, 0xED, 0x46) + if ((INST_IMM(0).mask & IMM_IM && INST_IMM(0).uval == 1)) + INST_RETURN(2, 0xED, 0x56) + if ((INST_IMM(0).mask & IMM_IM && INST_IMM(0).uval == 2)) + INST_RETURN(2, 0xED, 0x5E) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(in) +{ + INST_TAKES_ARGS( + AT_PORT|AT_REGISTER, + AT_OPTIONAL|AT_PORT, + AT_NONE + ) + if (INST_NARGS == 2 && INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_PORT) { + if (INST_REG(0) == REG_A && INST_PORT(1).type == AT_IMMEDIATE) + INST_RETURN(2, 0xDB, INST_PORT(1).port.imm.uval) + if (INST_REG(0) == REG_A && INST_PORT(1).type == AT_REGISTER) + INST_RETURN(2, 0xED, 0x78) + if (INST_REG(0) == REG_B && INST_PORT(1).type == AT_REGISTER) + INST_RETURN(2, 0xED, 0x40) + if (INST_REG(0) == REG_C && INST_PORT(1).type == AT_REGISTER) + INST_RETURN(2, 0xED, 0x48) + if (INST_REG(0) == REG_D && INST_PORT(1).type == AT_REGISTER) + INST_RETURN(2, 0xED, 0x50) + if (INST_REG(0) == REG_E && INST_PORT(1).type == AT_REGISTER) + INST_RETURN(2, 0xED, 0x58) + if (INST_REG(0) == REG_H && INST_PORT(1).type == AT_REGISTER) + INST_RETURN(2, 0xED, 0x60) + if (INST_REG(0) == REG_L && INST_PORT(1).type == AT_REGISTER) + INST_RETURN(2, 0xED, 0x68) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_PORT) { + if (INST_PORT(0).type == AT_REGISTER) + INST_RETURN(2, 0xED, 0x70) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(inc) +{ + INST_TAKES_ARGS( + AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_NONE, + AT_NONE + ) + if (INST_TYPE(0) == AT_REGISTER) { + if (INST_REG(0) == REG_A) + INST_RETURN(1, 0x3C) + if (INST_REG(0) == REG_B) + INST_RETURN(1, 0x04) + if (INST_REG(0) == REG_C) + INST_RETURN(1, 0x0C) + if (INST_REG(0) == REG_D) + INST_RETURN(1, 0x14) + if (INST_REG(0) == REG_E) + INST_RETURN(1, 0x1C) + if (INST_REG(0) == REG_H) + INST_RETURN(1, 0x24) + if (INST_REG(0) == REG_IXH) + INST_RETURN(2, INST_IX_PREFIX, 0x24) + if (INST_REG(0) == REG_IYH) + INST_RETURN(2, INST_IY_PREFIX, 0x24) + if (INST_REG(0) == REG_L) + INST_RETURN(1, 0x2C) + if (INST_REG(0) == REG_IXL) + INST_RETURN(2, INST_IX_PREFIX, 0x2C) + if (INST_REG(0) == REG_IYL) + INST_RETURN(2, INST_IY_PREFIX, 0x2C) + if (INST_REG(0) == REG_BC) + INST_RETURN(1, 0x03) + if (INST_REG(0) == REG_DE) + INST_RETURN(1, 0x13) + if (INST_REG(0) == REG_HL) + INST_RETURN(1, 0x23) + if (INST_REG(0) == REG_IX) + INST_RETURN(2, INST_IX_PREFIX, 0x23) + if (INST_REG(0) == REG_IY) + INST_RETURN(2, INST_IY_PREFIX, 0x23) + if (INST_REG(0) == REG_SP) + INST_RETURN(1, 0x33) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_INDIRECT && + (INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL)) { + INST_RETURN(1, 0x34) + } + if (INST_TYPE(0) == AT_INDEXED) { + INST_RETURN(3, INST_INDEX_PREFIX(0), 0x34, INST_INDEX(0).offset) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(ind) +{ + INST_TAKES_NO_ARGS + INST_RETURN(2, 0xED, 0xAA) +} + +INST_FUNC(indr) +{ + INST_TAKES_NO_ARGS + INST_RETURN(2, 0xED, 0xBA) +} + +INST_FUNC(ini) +{ + INST_TAKES_NO_ARGS + INST_RETURN(2, 0xED, 0xA2) +} + +INST_FUNC(inir) +{ + INST_TAKES_NO_ARGS + INST_RETURN(2, 0xED, 0xB2) +} + +INST_FUNC(jp) +{ + INST_TAKES_ARGS( + AT_CONDITION|AT_IMMEDIATE|AT_INDEXED|AT_INDIRECT, + AT_IMMEDIATE|AT_OPTIONAL, + AT_NONE + ) + if (INST_NARGS == 1 && INST_TYPE(0) == AT_IMMEDIATE) { + if (INST_IMM(0).mask & IMM_U16) + INST_RETURN(3, 0xC3, INST_IMM_U16_B1(INST_IMM(0)), INST_IMM_U16_B2(INST_IMM(0))) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 2 && INST_TYPE(0) == AT_CONDITION && INST_TYPE(1) == AT_IMMEDIATE) { + if (INST_COND(0) == COND_NZ && INST_IMM(1).mask & IMM_U16) + INST_RETURN(3, 0xC2, INST_IMM_U16_B1(INST_IMM(1)), INST_IMM_U16_B2(INST_IMM(1))) + if (INST_COND(0) == COND_Z && INST_IMM(1).mask & IMM_U16) + INST_RETURN(3, 0xCA, INST_IMM_U16_B1(INST_IMM(1)), INST_IMM_U16_B2(INST_IMM(1))) + if (INST_COND(0) == COND_NC && INST_IMM(1).mask & IMM_U16) + INST_RETURN(3, 0xD2, INST_IMM_U16_B1(INST_IMM(1)), INST_IMM_U16_B2(INST_IMM(1))) + if (INST_COND(0) == COND_C && INST_IMM(1).mask & IMM_U16) + INST_RETURN(3, 0xDA, INST_IMM_U16_B1(INST_IMM(1)), INST_IMM_U16_B2(INST_IMM(1))) + if (INST_COND(0) == COND_PO && INST_IMM(1).mask & IMM_U16) + INST_RETURN(3, 0xE2, INST_IMM_U16_B1(INST_IMM(1)), INST_IMM_U16_B2(INST_IMM(1))) + if (INST_COND(0) == COND_PE && INST_IMM(1).mask & IMM_U16) + INST_RETURN(3, 0xEA, INST_IMM_U16_B1(INST_IMM(1)), INST_IMM_U16_B2(INST_IMM(1))) + if (INST_COND(0) == COND_P && INST_IMM(1).mask & IMM_U16) + INST_RETURN(3, 0xF2, INST_IMM_U16_B1(INST_IMM(1)), INST_IMM_U16_B2(INST_IMM(1))) + if (INST_COND(0) == COND_M && INST_IMM(1).mask & IMM_U16) + INST_RETURN(3, 0xFA, INST_IMM_U16_B1(INST_IMM(1)), INST_IMM_U16_B2(INST_IMM(1))) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDIRECT && + (INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL)) { + INST_RETURN(1, 0xE9) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDEXED) { + INST_RETURN(3, INST_INDEX_PREFIX(0), 0xE9, INST_INDEX(0).offset) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(jr) +{ + INST_TAKES_ARGS( + AT_CONDITION|AT_IMMEDIATE, + AT_IMMEDIATE|AT_OPTIONAL, + AT_NONE + ) + if (INST_NARGS == 1 && INST_TYPE(0) == AT_IMMEDIATE) { + if (INST_IMM(0).mask & IMM_REL) + INST_RETURN(2, 0x18, INST_IMM(0).sval - 2) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 2 && INST_TYPE(0) == AT_CONDITION && INST_TYPE(1) == AT_IMMEDIATE) { + if (INST_COND(0) == COND_NZ && INST_IMM(1).mask & IMM_REL) + INST_RETURN(2, 0x20, INST_IMM(1).sval - 2) + if (INST_COND(0) == COND_Z && INST_IMM(1).mask & IMM_REL) + INST_RETURN(2, 0x28, INST_IMM(1).sval - 2) + if (INST_COND(0) == COND_NC && INST_IMM(1).mask & IMM_REL) + INST_RETURN(2, 0x30, INST_IMM(1).sval - 2) + if (INST_COND(0) == COND_C && INST_IMM(1).mask & IMM_REL) + INST_RETURN(2, 0x38, INST_IMM(1).sval - 2) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(ld) +{ + INST_TAKES_ARGS( + AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_IMMEDIATE|AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_NONE + ) + if (INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_REGISTER) { + if (INST_REG(0) == REG_A && INST_REG(1) == REG_A) + INST_RETURN(1, 0x7F) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_B) + INST_RETURN(1, 0x78) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_C) + INST_RETURN(1, 0x79) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_D) + INST_RETURN(1, 0x7A) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_E) + INST_RETURN(1, 0x7B) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_H) + INST_RETURN(1, 0x7C) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_IXH) + INST_RETURN(2, INST_IX_PREFIX, 0x7C) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_IYH) + INST_RETURN(2, INST_IY_PREFIX, 0x7C) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_L) + INST_RETURN(1, 0x7D) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_IXL) + INST_RETURN(2, INST_IX_PREFIX, 0x7D) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_IYL) + INST_RETURN(2, INST_IY_PREFIX, 0x7D) + if (INST_REG(0) == REG_B && INST_REG(1) == REG_A) + INST_RETURN(1, 0x47) + if (INST_REG(0) == REG_B && INST_REG(1) == REG_B) + INST_RETURN(1, 0x40) + if (INST_REG(0) == REG_B && INST_REG(1) == REG_C) + INST_RETURN(1, 0x41) + if (INST_REG(0) == REG_B && INST_REG(1) == REG_D) + INST_RETURN(1, 0x42) + if (INST_REG(0) == REG_B && INST_REG(1) == REG_E) + INST_RETURN(1, 0x43) + if (INST_REG(0) == REG_B && INST_REG(1) == REG_H) + INST_RETURN(1, 0x44) + if (INST_REG(0) == REG_B && INST_REG(1) == REG_IXH) + INST_RETURN(2, INST_IX_PREFIX, 0x44) + if (INST_REG(0) == REG_B && INST_REG(1) == REG_IYH) + INST_RETURN(2, INST_IY_PREFIX, 0x44) + if (INST_REG(0) == REG_B && INST_REG(1) == REG_L) + INST_RETURN(1, 0x45) + if (INST_REG(0) == REG_B && INST_REG(1) == REG_IXL) + INST_RETURN(2, INST_IX_PREFIX, 0x45) + if (INST_REG(0) == REG_B && INST_REG(1) == REG_IYL) + INST_RETURN(2, INST_IY_PREFIX, 0x45) + if (INST_REG(0) == REG_C && INST_REG(1) == REG_A) + INST_RETURN(1, 0x4F) + if (INST_REG(0) == REG_C && INST_REG(1) == REG_B) + INST_RETURN(1, 0x48) + if (INST_REG(0) == REG_C && INST_REG(1) == REG_C) + INST_RETURN(1, 0x49) + if (INST_REG(0) == REG_C && INST_REG(1) == REG_D) + INST_RETURN(1, 0x4A) + if (INST_REG(0) == REG_C && INST_REG(1) == REG_E) + INST_RETURN(1, 0x4B) + if (INST_REG(0) == REG_C && INST_REG(1) == REG_H) + INST_RETURN(1, 0x4C) + if (INST_REG(0) == REG_C && INST_REG(1) == REG_IXH) + INST_RETURN(2, INST_IX_PREFIX, 0x4C) + if (INST_REG(0) == REG_C && INST_REG(1) == REG_IYH) + INST_RETURN(2, INST_IY_PREFIX, 0x4C) + if (INST_REG(0) == REG_C && INST_REG(1) == REG_L) + INST_RETURN(1, 0x4D) + if (INST_REG(0) == REG_C && INST_REG(1) == REG_IXL) + INST_RETURN(2, INST_IX_PREFIX, 0x4D) + if (INST_REG(0) == REG_C && INST_REG(1) == REG_IYL) + INST_RETURN(2, INST_IY_PREFIX, 0x4D) + if (INST_REG(0) == REG_D && INST_REG(1) == REG_A) + INST_RETURN(1, 0x57) + if (INST_REG(0) == REG_D && INST_REG(1) == REG_B) + INST_RETURN(1, 0x50) + if (INST_REG(0) == REG_D && INST_REG(1) == REG_C) + INST_RETURN(1, 0x51) + if (INST_REG(0) == REG_D && INST_REG(1) == REG_D) + INST_RETURN(1, 0x52) + if (INST_REG(0) == REG_D && INST_REG(1) == REG_E) + INST_RETURN(1, 0x53) + if (INST_REG(0) == REG_D && INST_REG(1) == REG_H) + INST_RETURN(1, 0x54) + if (INST_REG(0) == REG_D && INST_REG(1) == REG_IXH) + INST_RETURN(2, INST_IX_PREFIX, 0x54) + if (INST_REG(0) == REG_D && INST_REG(1) == REG_IYH) + INST_RETURN(2, INST_IY_PREFIX, 0x54) + if (INST_REG(0) == REG_D && INST_REG(1) == REG_L) + INST_RETURN(1, 0x55) + if (INST_REG(0) == REG_D && INST_REG(1) == REG_IXL) + INST_RETURN(2, INST_IX_PREFIX, 0x55) + if (INST_REG(0) == REG_D && INST_REG(1) == REG_IYL) + INST_RETURN(2, INST_IY_PREFIX, 0x55) + if (INST_REG(0) == REG_E && INST_REG(1) == REG_A) + INST_RETURN(1, 0x5F) + if (INST_REG(0) == REG_E && INST_REG(1) == REG_B) + INST_RETURN(1, 0x58) + if (INST_REG(0) == REG_E && INST_REG(1) == REG_C) + INST_RETURN(1, 0x59) + if (INST_REG(0) == REG_E && INST_REG(1) == REG_D) + INST_RETURN(1, 0x5A) + if (INST_REG(0) == REG_E && INST_REG(1) == REG_E) + INST_RETURN(1, 0x5B) + if (INST_REG(0) == REG_E && INST_REG(1) == REG_H) + INST_RETURN(1, 0x5C) + if (INST_REG(0) == REG_E && INST_REG(1) == REG_IXH) + INST_RETURN(2, INST_IX_PREFIX, 0x5C) + if (INST_REG(0) == REG_E && INST_REG(1) == REG_IYH) + INST_RETURN(2, INST_IY_PREFIX, 0x5C) + if (INST_REG(0) == REG_E && INST_REG(1) == REG_L) + INST_RETURN(1, 0x5D) + if (INST_REG(0) == REG_E && INST_REG(1) == REG_IXL) + INST_RETURN(2, INST_IX_PREFIX, 0x5D) + if (INST_REG(0) == REG_E && INST_REG(1) == REG_IYL) + INST_RETURN(2, INST_IY_PREFIX, 0x5D) + if (INST_REG(0) == REG_H && INST_REG(1) == REG_A) + INST_RETURN(1, 0x67) + if (INST_REG(0) == REG_IXH && INST_REG(1) == REG_A) + INST_RETURN(2, INST_IX_PREFIX, 0x67) + if (INST_REG(0) == REG_IYH && INST_REG(1) == REG_A) + INST_RETURN(2, INST_IY_PREFIX, 0x67) + if (INST_REG(0) == REG_H && INST_REG(1) == REG_B) + INST_RETURN(1, 0x60) + if (INST_REG(0) == REG_IXH && INST_REG(1) == REG_B) + INST_RETURN(2, INST_IX_PREFIX, 0x60) + if (INST_REG(0) == REG_IYH && INST_REG(1) == REG_B) + INST_RETURN(2, INST_IY_PREFIX, 0x60) + if (INST_REG(0) == REG_H && INST_REG(1) == REG_C) + INST_RETURN(1, 0x61) + if (INST_REG(0) == REG_IXH && INST_REG(1) == REG_C) + INST_RETURN(2, INST_IX_PREFIX, 0x61) + if (INST_REG(0) == REG_IYH && INST_REG(1) == REG_C) + INST_RETURN(2, INST_IY_PREFIX, 0x61) + if (INST_REG(0) == REG_H && INST_REG(1) == REG_D) + INST_RETURN(1, 0x62) + if (INST_REG(0) == REG_IXH && INST_REG(1) == REG_D) + INST_RETURN(2, INST_IX_PREFIX, 0x62) + if (INST_REG(0) == REG_IYH && INST_REG(1) == REG_D) + INST_RETURN(2, INST_IY_PREFIX, 0x62) + if (INST_REG(0) == REG_H && INST_REG(1) == REG_E) + INST_RETURN(1, 0x63) + if (INST_REG(0) == REG_IXH && INST_REG(1) == REG_E) + INST_RETURN(2, INST_IX_PREFIX, 0x63) + if (INST_REG(0) == REG_IYH && INST_REG(1) == REG_E) + INST_RETURN(2, INST_IY_PREFIX, 0x63) + if (INST_REG(0) == REG_H && INST_REG(1) == REG_H) + INST_RETURN(1, 0x64) + if (INST_REG(0) == REG_IXH && INST_REG(1) == REG_IXH) + INST_RETURN(2, INST_IX_PREFIX, 0x64) + if (INST_REG(0) == REG_IYH && INST_REG(1) == REG_IYH) + INST_RETURN(2, INST_IY_PREFIX, 0x64) + if (INST_REG(0) == REG_H && INST_REG(1) == REG_L) + INST_RETURN(1, 0x65) + if (INST_REG(0) == REG_IXH && INST_REG(1) == REG_IXL) + INST_RETURN(2, INST_IX_PREFIX, 0x65) + if (INST_REG(0) == REG_IYH && INST_REG(1) == REG_IYL) + INST_RETURN(2, INST_IY_PREFIX, 0x65) + if (INST_REG(0) == REG_L && INST_REG(1) == REG_A) + INST_RETURN(1, 0x6F) + if (INST_REG(0) == REG_IXL && INST_REG(1) == REG_A) + INST_RETURN(2, INST_IX_PREFIX, 0x6F) + if (INST_REG(0) == REG_IYL && INST_REG(1) == REG_A) + INST_RETURN(2, INST_IY_PREFIX, 0x6F) + if (INST_REG(0) == REG_L && INST_REG(1) == REG_B) + INST_RETURN(1, 0x68) + if (INST_REG(0) == REG_IXL && INST_REG(1) == REG_B) + INST_RETURN(2, INST_IX_PREFIX, 0x68) + if (INST_REG(0) == REG_IYL && INST_REG(1) == REG_B) + INST_RETURN(2, INST_IY_PREFIX, 0x68) + if (INST_REG(0) == REG_L && INST_REG(1) == REG_C) + INST_RETURN(1, 0x69) + if (INST_REG(0) == REG_IXL && INST_REG(1) == REG_C) + INST_RETURN(2, INST_IX_PREFIX, 0x69) + if (INST_REG(0) == REG_IYL && INST_REG(1) == REG_C) + INST_RETURN(2, INST_IY_PREFIX, 0x69) + if (INST_REG(0) == REG_L && INST_REG(1) == REG_D) + INST_RETURN(1, 0x6A) + if (INST_REG(0) == REG_IXL && INST_REG(1) == REG_D) + INST_RETURN(2, INST_IX_PREFIX, 0x6A) + if (INST_REG(0) == REG_IYL && INST_REG(1) == REG_D) + INST_RETURN(2, INST_IY_PREFIX, 0x6A) + if (INST_REG(0) == REG_L && INST_REG(1) == REG_E) + INST_RETURN(1, 0x6B) + if (INST_REG(0) == REG_IXL && INST_REG(1) == REG_E) + INST_RETURN(2, INST_IX_PREFIX, 0x6B) + if (INST_REG(0) == REG_IYL && INST_REG(1) == REG_E) + INST_RETURN(2, INST_IY_PREFIX, 0x6B) + if (INST_REG(0) == REG_L && INST_REG(1) == REG_H) + INST_RETURN(1, 0x6C) + if (INST_REG(0) == REG_IXL && INST_REG(1) == REG_IXH) + INST_RETURN(2, INST_IX_PREFIX, 0x6C) + if (INST_REG(0) == REG_IYL && INST_REG(1) == REG_IYH) + INST_RETURN(2, INST_IY_PREFIX, 0x6C) + if (INST_REG(0) == REG_L && INST_REG(1) == REG_L) + INST_RETURN(1, 0x6D) + if (INST_REG(0) == REG_IXL && INST_REG(1) == REG_IXL) + INST_RETURN(2, INST_IX_PREFIX, 0x6D) + if (INST_REG(0) == REG_IYL && INST_REG(1) == REG_IYL) + INST_RETURN(2, INST_IY_PREFIX, 0x6D) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_IX) + INST_RETURN(3, INST_IX_PREFIX, 0xED, 0x57) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_IY) + INST_RETURN(3, INST_IY_PREFIX, 0xED, 0x57) + if (INST_REG(0) == REG_IX && INST_REG(1) == REG_A) + INST_RETURN(3, INST_IX_PREFIX, 0xED, 0x47) + if (INST_REG(0) == REG_IY && INST_REG(1) == REG_A) + INST_RETURN(3, INST_IY_PREFIX, 0xED, 0x47) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_R) + INST_RETURN(2, 0xED, 0x5F) + if (INST_REG(0) == REG_R && INST_REG(1) == REG_A) + INST_RETURN(2, 0xED, 0x4F) + if (INST_REG(0) == REG_SP && INST_REG(1) == REG_HL) + INST_RETURN(1, 0xF9) + if (INST_REG(0) == REG_SP && INST_REG(1) == REG_IX) + INST_RETURN(2, INST_IX_PREFIX, 0xF9) + if (INST_REG(0) == REG_SP && INST_REG(1) == REG_IY) + INST_RETURN(2, INST_IY_PREFIX, 0xF9) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_IMMEDIATE) { + if (INST_REG(0) == REG_A && INST_IMM(1).mask & IMM_U8) + INST_RETURN(2, 0x3E, INST_IMM(1).uval) + if (INST_REG(0) == REG_B && INST_IMM(1).mask & IMM_U8) + INST_RETURN(2, 0x06, INST_IMM(1).uval) + if (INST_REG(0) == REG_C && INST_IMM(1).mask & IMM_U8) + INST_RETURN(2, 0x0E, INST_IMM(1).uval) + if (INST_REG(0) == REG_D && INST_IMM(1).mask & IMM_U8) + INST_RETURN(2, 0x16, INST_IMM(1).uval) + if (INST_REG(0) == REG_E && INST_IMM(1).mask & IMM_U8) + INST_RETURN(2, 0x1E, INST_IMM(1).uval) + if (INST_REG(0) == REG_H && INST_IMM(1).mask & IMM_U8) + INST_RETURN(2, 0x26, INST_IMM(1).uval) + if (INST_REG(0) == REG_IXH && INST_IMM(1).mask & IMM_U8) + INST_RETURN(3, INST_IX_PREFIX, 0x26, INST_IMM(1).uval) + if (INST_REG(0) == REG_IYH && INST_IMM(1).mask & IMM_U8) + INST_RETURN(3, INST_IY_PREFIX, 0x26, INST_IMM(1).uval) + if (INST_REG(0) == REG_L && INST_IMM(1).mask & IMM_U8) + INST_RETURN(2, 0x2E, INST_IMM(1).uval) + if (INST_REG(0) == REG_IXL && INST_IMM(1).mask & IMM_U8) + INST_RETURN(3, INST_IX_PREFIX, 0x2E, INST_IMM(1).uval) + if (INST_REG(0) == REG_IYL && INST_IMM(1).mask & IMM_U8) + INST_RETURN(3, INST_IY_PREFIX, 0x2E, INST_IMM(1).uval) + if (INST_REG(0) == REG_BC && INST_IMM(1).mask & IMM_U16) + INST_RETURN(3, 0x01, INST_IMM_U16_B1(INST_IMM(1)), INST_IMM_U16_B2(INST_IMM(1))) + if (INST_REG(0) == REG_DE && INST_IMM(1).mask & IMM_U16) + INST_RETURN(3, 0x11, INST_IMM_U16_B1(INST_IMM(1)), INST_IMM_U16_B2(INST_IMM(1))) + if (INST_REG(0) == REG_HL && INST_IMM(1).mask & IMM_U16) + INST_RETURN(3, 0x21, INST_IMM_U16_B1(INST_IMM(1)), INST_IMM_U16_B2(INST_IMM(1))) + if (INST_REG(0) == REG_IX && INST_IMM(1).mask & IMM_U16) + INST_RETURN(4, INST_IX_PREFIX, 0x21, INST_IMM_U16_B1(INST_IMM(1)), INST_IMM_U16_B2(INST_IMM(1))) + if (INST_REG(0) == REG_IY && INST_IMM(1).mask & IMM_U16) + INST_RETURN(4, INST_IY_PREFIX, 0x21, INST_IMM_U16_B1(INST_IMM(1)), INST_IMM_U16_B2(INST_IMM(1))) + if (INST_REG(0) == REG_SP && INST_IMM(1).mask & IMM_U16) + INST_RETURN(3, 0x31, INST_IMM_U16_B1(INST_IMM(1)), INST_IMM_U16_B2(INST_IMM(1))) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_INDIRECT && + (INST_INDIRECT(1).type == AT_REGISTER && INST_INDIRECT(1).addr.reg == REG_HL)) { + if (INST_REG(0) == REG_A) + INST_RETURN(1, 0x7E) + if (INST_REG(0) == REG_B) + INST_RETURN(1, 0x46) + if (INST_REG(0) == REG_C) + INST_RETURN(1, 0x4E) + if (INST_REG(0) == REG_D) + INST_RETURN(1, 0x56) + if (INST_REG(0) == REG_E) + INST_RETURN(1, 0x5E) + if (INST_REG(0) == REG_H) + INST_RETURN(1, 0x66) + if (INST_REG(0) == REG_L) + INST_RETURN(1, 0x6E) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_INDEXED) { + if (INST_REG(0) == REG_A) + INST_RETURN(3, INST_INDEX_PREFIX(1), 0x7E, INST_INDEX(1).offset) + if (INST_REG(0) == REG_B) + INST_RETURN(3, INST_INDEX_PREFIX(1), 0x46, INST_INDEX(1).offset) + if (INST_REG(0) == REG_C) + INST_RETURN(3, INST_INDEX_PREFIX(1), 0x4E, INST_INDEX(1).offset) + if (INST_REG(0) == REG_D) + INST_RETURN(3, INST_INDEX_PREFIX(1), 0x56, INST_INDEX(1).offset) + if (INST_REG(0) == REG_E) + INST_RETURN(3, INST_INDEX_PREFIX(1), 0x5E, INST_INDEX(1).offset) + if (INST_REG(0) == REG_H) + INST_RETURN(3, INST_INDEX_PREFIX(1), 0x66, INST_INDEX(1).offset) + if (INST_REG(0) == REG_L) + INST_RETURN(3, INST_INDEX_PREFIX(1), 0x6E, INST_INDEX(1).offset) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_INDIRECT) { + if (INST_REG(0) == REG_A && (INST_INDIRECT(1).type == AT_REGISTER && INST_INDIRECT(1).addr.reg == REG_BC)) + INST_RETURN(1, 0x0A) + if (INST_REG(0) == REG_A && (INST_INDIRECT(1).type == AT_REGISTER && INST_INDIRECT(1).addr.reg == REG_DE)) + INST_RETURN(1, 0x1A) + if (INST_REG(0) == REG_HL && INST_INDIRECT(1).type == AT_IMMEDIATE) + INST_RETURN(3, 0x2A, INST_IMM_U16_B1(INST_INDIRECT(1).addr.imm), INST_IMM_U16_B2(INST_INDIRECT(1).addr.imm)) + if (INST_REG(0) == REG_IX && INST_INDIRECT(1).type == AT_IMMEDIATE) + INST_RETURN(4, INST_IX_PREFIX, 0x2A, INST_IMM_U16_B1(INST_INDIRECT(1).addr.imm), INST_IMM_U16_B2(INST_INDIRECT(1).addr.imm)) + if (INST_REG(0) == REG_IY && INST_INDIRECT(1).type == AT_IMMEDIATE) + INST_RETURN(4, INST_IY_PREFIX, 0x2A, INST_IMM_U16_B1(INST_INDIRECT(1).addr.imm), INST_IMM_U16_B2(INST_INDIRECT(1).addr.imm)) + if (INST_REG(0) == REG_A && INST_INDIRECT(1).type == AT_IMMEDIATE) + INST_RETURN(3, 0x3A, INST_IMM_U16_B1(INST_INDIRECT(1).addr.imm), INST_IMM_U16_B2(INST_INDIRECT(1).addr.imm)) + if (INST_REG(0) == REG_BC && INST_INDIRECT(1).type == AT_IMMEDIATE) + INST_RETURN(4, 0xED, 0x4B, INST_IMM_U16_B1(INST_INDIRECT(1).addr.imm), INST_IMM_U16_B2(INST_INDIRECT(1).addr.imm)) + if (INST_REG(0) == REG_DE && INST_INDIRECT(1).type == AT_IMMEDIATE) + INST_RETURN(4, 0xED, 0x5B, INST_IMM_U16_B1(INST_INDIRECT(1).addr.imm), INST_IMM_U16_B2(INST_INDIRECT(1).addr.imm)) + if (INST_REG(0) == REG_SP && INST_INDIRECT(1).type == AT_IMMEDIATE) + INST_RETURN(4, 0xED, 0x7B, INST_IMM_U16_B1(INST_INDIRECT(1).addr.imm), INST_IMM_U16_B2(INST_INDIRECT(1).addr.imm)) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_INDIRECT && INST_TYPE(1) == AT_REGISTER && + (INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL)) { + if (INST_REG(1) == REG_A) + INST_RETURN(1, 0x77) + if (INST_REG(1) == REG_B) + INST_RETURN(1, 0x70) + if (INST_REG(1) == REG_C) + INST_RETURN(1, 0x71) + if (INST_REG(1) == REG_D) + INST_RETURN(1, 0x72) + if (INST_REG(1) == REG_E) + INST_RETURN(1, 0x73) + if (INST_REG(1) == REG_H) + INST_RETURN(1, 0x74) + if (INST_REG(1) == REG_L) + INST_RETURN(1, 0x75) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_INDEXED && INST_TYPE(1) == AT_REGISTER) { + if (INST_REG(1) == REG_A) + INST_RETURN(3, INST_INDEX_PREFIX(0), 0x77, INST_INDEX(0).offset) + if (INST_REG(1) == REG_B) + INST_RETURN(3, INST_INDEX_PREFIX(0), 0x70, INST_INDEX(0).offset) + if (INST_REG(1) == REG_C) + INST_RETURN(3, INST_INDEX_PREFIX(0), 0x71, INST_INDEX(0).offset) + if (INST_REG(1) == REG_D) + INST_RETURN(3, INST_INDEX_PREFIX(0), 0x72, INST_INDEX(0).offset) + if (INST_REG(1) == REG_E) + INST_RETURN(3, INST_INDEX_PREFIX(0), 0x73, INST_INDEX(0).offset) + if (INST_REG(1) == REG_H) + INST_RETURN(3, INST_INDEX_PREFIX(0), 0x74, INST_INDEX(0).offset) + if (INST_REG(1) == REG_L) + INST_RETURN(3, INST_INDEX_PREFIX(0), 0x75, INST_INDEX(0).offset) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_INDIRECT && INST_TYPE(1) == AT_IMMEDIATE && + (INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL)) { + if (INST_IMM(1).mask & IMM_U8) + INST_RETURN(2, 0x36, INST_IMM(1).uval) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_INDEXED && INST_TYPE(1) == AT_IMMEDIATE) { + if (INST_IMM(1).mask & IMM_U8) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0x36, INST_INDEX(0).offset, INST_IMM(1).uval) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_INDIRECT && INST_TYPE(1) == AT_REGISTER) { + if ((INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_BC) && INST_REG(1) == REG_A) + INST_RETURN(1, 0x02) + if ((INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_DE) && INST_REG(1) == REG_A) + INST_RETURN(1, 0x12) + if (INST_INDIRECT(0).type == AT_IMMEDIATE && INST_REG(1) == REG_HL) + INST_RETURN(3, 0x22, INST_IMM_U16_B1(INST_INDIRECT(0).addr.imm), INST_IMM_U16_B2(INST_INDIRECT(0).addr.imm)) + if (INST_INDIRECT(0).type == AT_IMMEDIATE && INST_REG(1) == REG_IX) + INST_RETURN(4, INST_IX_PREFIX, 0x22, INST_IMM_U16_B1(INST_INDIRECT(0).addr.imm), INST_IMM_U16_B2(INST_INDIRECT(0).addr.imm)) + if (INST_INDIRECT(0).type == AT_IMMEDIATE && INST_REG(1) == REG_IY) + INST_RETURN(4, INST_IY_PREFIX, 0x22, INST_IMM_U16_B1(INST_INDIRECT(0).addr.imm), INST_IMM_U16_B2(INST_INDIRECT(0).addr.imm)) + if (INST_INDIRECT(0).type == AT_IMMEDIATE && INST_REG(1) == REG_A) + INST_RETURN(3, 0x32, INST_IMM_U16_B1(INST_INDIRECT(0).addr.imm), INST_IMM_U16_B2(INST_INDIRECT(0).addr.imm)) + if (INST_INDIRECT(0).type == AT_IMMEDIATE && INST_REG(1) == REG_BC) + INST_RETURN(4, 0xED, 0x43, INST_IMM_U16_B1(INST_INDIRECT(0).addr.imm), INST_IMM_U16_B2(INST_INDIRECT(0).addr.imm)) + if (INST_INDIRECT(0).type == AT_IMMEDIATE && INST_REG(1) == REG_DE) + INST_RETURN(4, 0xED, 0x53, INST_IMM_U16_B1(INST_INDIRECT(0).addr.imm), INST_IMM_U16_B2(INST_INDIRECT(0).addr.imm)) + if (INST_INDIRECT(0).type == AT_IMMEDIATE && INST_REG(1) == REG_SP) + INST_RETURN(4, 0xED, 0x73, INST_IMM_U16_B1(INST_INDIRECT(0).addr.imm), INST_IMM_U16_B2(INST_INDIRECT(0).addr.imm)) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(ldd) +{ + INST_TAKES_NO_ARGS + INST_RETURN(2, 0xED, 0xA8) +} + +INST_FUNC(lddr) +{ + INST_TAKES_NO_ARGS + INST_RETURN(2, 0xED, 0xB8) +} + +INST_FUNC(ldi) +{ + INST_TAKES_NO_ARGS + INST_RETURN(2, 0xED, 0xA0) +} + +INST_FUNC(ldir) +{ + INST_TAKES_NO_ARGS + INST_RETURN(2, 0xED, 0xB0) +} + +INST_FUNC(neg) +{ + INST_TAKES_NO_ARGS + INST_RETURN(2, 0xED, 0x44) +} + +INST_FUNC(nop) +{ + INST_TAKES_NO_ARGS + INST_RETURN(1, 0x00) +} + +INST_FUNC(or) +{ + INST_TAKES_ARGS( + AT_IMMEDIATE|AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_NONE, + AT_NONE + ) + if (INST_TYPE(0) == AT_REGISTER) { + if (INST_REG(0) == REG_A) + INST_RETURN(1, 0xB7) + if (INST_REG(0) == REG_B) + INST_RETURN(1, 0xB0) + if (INST_REG(0) == REG_C) + INST_RETURN(1, 0xB1) + if (INST_REG(0) == REG_D) + INST_RETURN(1, 0xB2) + if (INST_REG(0) == REG_E) + INST_RETURN(1, 0xB3) + if (INST_REG(0) == REG_H) + INST_RETURN(1, 0xB4) + if (INST_REG(0) == REG_IXH) + INST_RETURN(2, INST_IX_PREFIX, 0xB4) + if (INST_REG(0) == REG_IYH) + INST_RETURN(2, INST_IY_PREFIX, 0xB4) + if (INST_REG(0) == REG_L) + INST_RETURN(1, 0xB5) + if (INST_REG(0) == REG_IXL) + INST_RETURN(2, INST_IX_PREFIX, 0xB5) + if (INST_REG(0) == REG_IYL) + INST_RETURN(2, INST_IY_PREFIX, 0xB5) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_IMMEDIATE) { + if (INST_IMM(0).mask & IMM_U8) + INST_RETURN(2, 0xF6, INST_IMM(0).uval) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_INDIRECT && + (INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL)) { + INST_RETURN(1, 0xB6) + } + if (INST_TYPE(0) == AT_INDEXED) { + INST_RETURN(3, INST_INDEX_PREFIX(0), 0xB6, INST_INDEX(0).offset) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(otdr) +{ + INST_TAKES_NO_ARGS + INST_RETURN(2, 0xED, 0xBB) +} + +INST_FUNC(otir) +{ + INST_TAKES_NO_ARGS + INST_RETURN(2, 0xED, 0xB3) +} + +INST_FUNC(out) +{ + INST_TAKES_ARGS( + AT_PORT, + AT_IMMEDIATE|AT_REGISTER, + AT_NONE + ) + if (INST_TYPE(0) == AT_PORT && INST_TYPE(1) == AT_REGISTER) { + if (INST_PORT(0).type == AT_IMMEDIATE && INST_REG(1) == REG_A) + INST_RETURN(2, 0xD3, INST_PORT(0).port.imm.uval) + if (INST_PORT(0).type == AT_REGISTER && INST_REG(1) == REG_A) + INST_RETURN(2, 0xED, 0x79) + if (INST_PORT(0).type == AT_REGISTER && INST_REG(1) == REG_B) + INST_RETURN(2, 0xED, 0x41) + if (INST_PORT(0).type == AT_REGISTER && INST_REG(1) == REG_C) + INST_RETURN(2, 0xED, 0x49) + if (INST_PORT(0).type == AT_REGISTER && INST_REG(1) == REG_D) + INST_RETURN(2, 0xED, 0x51) + if (INST_PORT(0).type == AT_REGISTER && INST_REG(1) == REG_E) + INST_RETURN(2, 0xED, 0x59) + if (INST_PORT(0).type == AT_REGISTER && INST_REG(1) == REG_H) + INST_RETURN(2, 0xED, 0x61) + if (INST_PORT(0).type == AT_REGISTER && INST_REG(1) == REG_L) + INST_RETURN(2, 0xED, 0x69) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_PORT && INST_TYPE(1) == AT_IMMEDIATE) { + if (INST_PORT(0).type == AT_REGISTER && (INST_IMM(1).mask & IMM_U8 && INST_IMM(1).uval == 0)) + INST_RETURN(2, 0xED, 0x71) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(outd) +{ + INST_TAKES_NO_ARGS + INST_RETURN(2, 0xED, 0xAB) +} + +INST_FUNC(outi) +{ + INST_TAKES_NO_ARGS + INST_RETURN(2, 0xED, 0xA3) +} + +INST_FUNC(pop) +{ + INST_TAKES_ARGS( + AT_REGISTER, + AT_NONE, + AT_NONE + ) + if (INST_TYPE(0) == AT_REGISTER) { + if (INST_REG(0) == REG_BC) + INST_RETURN(1, 0xC1) + if (INST_REG(0) == REG_DE) + INST_RETURN(1, 0xD1) + if (INST_REG(0) == REG_HL) + INST_RETURN(1, 0xE1) + if (INST_REG(0) == REG_IX) + INST_RETURN(2, INST_IX_PREFIX, 0xE1) + if (INST_REG(0) == REG_IY) + INST_RETURN(2, INST_IY_PREFIX, 0xE1) + if (INST_REG(0) == REG_AF) + INST_RETURN(1, 0xF1) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(push) +{ + INST_TAKES_ARGS( + AT_REGISTER, + AT_NONE, + AT_NONE + ) + if (INST_TYPE(0) == AT_REGISTER) { + if (INST_REG(0) == REG_BC) + INST_RETURN(1, 0xC5) + if (INST_REG(0) == REG_DE) + INST_RETURN(1, 0xD5) + if (INST_REG(0) == REG_HL) + INST_RETURN(1, 0xE5) + if (INST_REG(0) == REG_IX) + INST_RETURN(2, INST_IX_PREFIX, 0xE5) + if (INST_REG(0) == REG_IY) + INST_RETURN(2, INST_IY_PREFIX, 0xE5) + if (INST_REG(0) == REG_AF) + INST_RETURN(1, 0xF5) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(res) +{ + INST_TAKES_ARGS( + AT_IMMEDIATE, + AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_OPTIONAL|AT_REGISTER + ) + if (INST_NARGS == 2 && INST_TYPE(0) == AT_IMMEDIATE && INST_TYPE(1) == AT_REGISTER) { + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(1) == REG_A) + INST_RETURN(2, 0xCB, 0x87) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(1) == REG_B) + INST_RETURN(2, 0xCB, 0x80) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(1) == REG_C) + INST_RETURN(2, 0xCB, 0x81) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(1) == REG_D) + INST_RETURN(2, 0xCB, 0x82) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(1) == REG_E) + INST_RETURN(2, 0xCB, 0x83) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(1) == REG_H) + INST_RETURN(2, 0xCB, 0x84) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0x85) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(1) == REG_A) + INST_RETURN(2, 0xCB, 0x8F) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(1) == REG_B) + INST_RETURN(2, 0xCB, 0x88) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(1) == REG_C) + INST_RETURN(2, 0xCB, 0x89) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(1) == REG_D) + INST_RETURN(2, 0xCB, 0x8A) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(1) == REG_E) + INST_RETURN(2, 0xCB, 0x8B) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(1) == REG_H) + INST_RETURN(2, 0xCB, 0x8C) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0x8D) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(1) == REG_A) + INST_RETURN(2, 0xCB, 0x97) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(1) == REG_B) + INST_RETURN(2, 0xCB, 0x90) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(1) == REG_C) + INST_RETURN(2, 0xCB, 0x91) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(1) == REG_D) + INST_RETURN(2, 0xCB, 0x92) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(1) == REG_E) + INST_RETURN(2, 0xCB, 0x93) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(1) == REG_H) + INST_RETURN(2, 0xCB, 0x94) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0x95) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(1) == REG_A) + INST_RETURN(2, 0xCB, 0x9F) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(1) == REG_B) + INST_RETURN(2, 0xCB, 0x98) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(1) == REG_C) + INST_RETURN(2, 0xCB, 0x99) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(1) == REG_D) + INST_RETURN(2, 0xCB, 0x9A) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(1) == REG_E) + INST_RETURN(2, 0xCB, 0x9B) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(1) == REG_H) + INST_RETURN(2, 0xCB, 0x9C) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0x9D) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(1) == REG_A) + INST_RETURN(2, 0xCB, 0xA7) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(1) == REG_B) + INST_RETURN(2, 0xCB, 0xA0) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(1) == REG_C) + INST_RETURN(2, 0xCB, 0xA1) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(1) == REG_D) + INST_RETURN(2, 0xCB, 0xA2) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(1) == REG_E) + INST_RETURN(2, 0xCB, 0xA3) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(1) == REG_H) + INST_RETURN(2, 0xCB, 0xA4) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0xA5) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(1) == REG_A) + INST_RETURN(2, 0xCB, 0xAF) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(1) == REG_B) + INST_RETURN(2, 0xCB, 0xA8) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(1) == REG_C) + INST_RETURN(2, 0xCB, 0xA9) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(1) == REG_D) + INST_RETURN(2, 0xCB, 0xAA) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(1) == REG_E) + INST_RETURN(2, 0xCB, 0xAB) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(1) == REG_H) + INST_RETURN(2, 0xCB, 0xAC) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0xAD) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(1) == REG_A) + INST_RETURN(2, 0xCB, 0xB7) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(1) == REG_B) + INST_RETURN(2, 0xCB, 0xB0) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(1) == REG_C) + INST_RETURN(2, 0xCB, 0xB1) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(1) == REG_D) + INST_RETURN(2, 0xCB, 0xB2) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(1) == REG_E) + INST_RETURN(2, 0xCB, 0xB3) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(1) == REG_H) + INST_RETURN(2, 0xCB, 0xB4) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0xB5) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(1) == REG_A) + INST_RETURN(2, 0xCB, 0xBF) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(1) == REG_B) + INST_RETURN(2, 0xCB, 0xB8) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(1) == REG_C) + INST_RETURN(2, 0xCB, 0xB9) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(1) == REG_D) + INST_RETURN(2, 0xCB, 0xBA) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(1) == REG_E) + INST_RETURN(2, 0xCB, 0xBB) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(1) == REG_H) + INST_RETURN(2, 0xCB, 0xBC) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0xBD) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 2 && INST_TYPE(0) == AT_IMMEDIATE && INST_TYPE(1) == AT_INDIRECT && + (INST_INDIRECT(1).type == AT_REGISTER && INST_INDIRECT(1).addr.reg == REG_HL)) { + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0)) + INST_RETURN(2, 0xCB, 0x86) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1)) + INST_RETURN(2, 0xCB, 0x8E) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2)) + INST_RETURN(2, 0xCB, 0x96) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3)) + INST_RETURN(2, 0xCB, 0x9E) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4)) + INST_RETURN(2, 0xCB, 0xA6) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5)) + INST_RETURN(2, 0xCB, 0xAE) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6)) + INST_RETURN(2, 0xCB, 0xB6) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7)) + INST_RETURN(2, 0xCB, 0xBE) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 2 && INST_TYPE(0) == AT_IMMEDIATE && INST_TYPE(1) == AT_INDEXED) { + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0)) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x86) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1)) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x8E) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2)) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x96) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3)) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x9E) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4)) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xA6) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5)) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xAE) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6)) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xB6) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7)) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xBE) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 3 && INST_TYPE(0) == AT_IMMEDIATE && INST_TYPE(1) == AT_INDEXED && INST_TYPE(2) == AT_REGISTER) { + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(2) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x87) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(2) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x80) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(2) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x81) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(2) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x82) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(2) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x83) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(2) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x84) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(2) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x85) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(2) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x8F) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(2) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x88) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(2) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x89) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(2) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x8A) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(2) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x8B) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(2) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x8C) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(2) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x8D) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(2) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x97) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(2) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x90) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(2) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x91) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(2) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x92) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(2) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x93) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(2) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x94) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(2) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x95) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(2) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x9F) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(2) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x98) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(2) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x99) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(2) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x9A) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(2) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x9B) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(2) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x9C) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(2) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0x9D) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(2) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xA7) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(2) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xA0) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(2) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xA1) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(2) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xA2) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(2) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xA3) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(2) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xA4) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(2) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xA5) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(2) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xAF) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(2) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xA8) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(2) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xA9) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(2) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xAA) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(2) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xAB) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(2) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xAC) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(2) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xAD) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(2) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xB7) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(2) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xB0) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(2) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xB1) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(2) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xB2) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(2) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xB3) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(2) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xB4) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(2) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xB5) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(2) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xBF) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(2) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xB8) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(2) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xB9) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(2) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xBA) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(2) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xBB) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(2) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xBC) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(2) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xBD) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(ret) +{ + INST_TAKES_ARGS( + AT_CONDITION|AT_OPTIONAL, + AT_NONE, + AT_NONE + ) + if (INST_NARGS == 0) { + INST_RETURN(1, 0xC9) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_CONDITION) { + if (INST_COND(0) == COND_NZ) + INST_RETURN(1, 0xC0) + if (INST_COND(0) == COND_Z) + INST_RETURN(1, 0xC8) + if (INST_COND(0) == COND_NC) + INST_RETURN(1, 0xD0) + if (INST_COND(0) == COND_C) + INST_RETURN(1, 0xD8) + if (INST_COND(0) == COND_PO) + INST_RETURN(1, 0xE0) + if (INST_COND(0) == COND_PE) + INST_RETURN(1, 0xE8) + if (INST_COND(0) == COND_P) + INST_RETURN(1, 0xF0) + if (INST_COND(0) == COND_M) + INST_RETURN(1, 0xF8) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(reti) +{ + INST_TAKES_NO_ARGS + INST_RETURN(2, 0xED, 0x4D) +} + +INST_FUNC(retn) +{ + INST_TAKES_NO_ARGS + INST_RETURN(2, 0xED, 0x45) +} + +INST_FUNC(rl) +{ + INST_TAKES_ARGS( + AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_OPTIONAL|AT_REGISTER, + AT_NONE + ) + if (INST_NARGS == 1 && INST_TYPE(0) == AT_REGISTER) { + if (INST_REG(0) == REG_A) + INST_RETURN(2, 0xCB, 0x17) + if (INST_REG(0) == REG_B) + INST_RETURN(2, 0xCB, 0x10) + if (INST_REG(0) == REG_C) + INST_RETURN(2, 0xCB, 0x11) + if (INST_REG(0) == REG_D) + INST_RETURN(2, 0xCB, 0x12) + if (INST_REG(0) == REG_E) + INST_RETURN(2, 0xCB, 0x13) + if (INST_REG(0) == REG_H) + INST_RETURN(2, 0xCB, 0x14) + if (INST_REG(0) == REG_L) + INST_RETURN(2, 0xCB, 0x15) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDIRECT && + (INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL)) { + INST_RETURN(2, 0xCB, 0x16) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDEXED) { + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x16) + } + if (INST_NARGS == 2 && INST_TYPE(0) == AT_INDEXED && INST_TYPE(1) == AT_REGISTER) { + if (INST_REG(1) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x17) + if (INST_REG(1) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x10) + if (INST_REG(1) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x11) + if (INST_REG(1) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x12) + if (INST_REG(1) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x13) + if (INST_REG(1) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x14) + if (INST_REG(1) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x15) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(rla) +{ + INST_TAKES_NO_ARGS + INST_RETURN(1, 0x17) +} + +INST_FUNC(rlc) +{ + INST_TAKES_ARGS( + AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_OPTIONAL|AT_REGISTER, + AT_NONE + ) + if (INST_NARGS == 1 && INST_TYPE(0) == AT_REGISTER) { + if (INST_REG(0) == REG_A) + INST_RETURN(2, 0xCB, 0x07) + if (INST_REG(0) == REG_B) + INST_RETURN(2, 0xCB, 0x00) + if (INST_REG(0) == REG_C) + INST_RETURN(2, 0xCB, 0x01) + if (INST_REG(0) == REG_D) + INST_RETURN(2, 0xCB, 0x02) + if (INST_REG(0) == REG_E) + INST_RETURN(2, 0xCB, 0x03) + if (INST_REG(0) == REG_H) + INST_RETURN(2, 0xCB, 0x04) + if (INST_REG(0) == REG_L) + INST_RETURN(2, 0xCB, 0x05) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDIRECT && + (INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL)) { + INST_RETURN(2, 0xCB, 0x06) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDEXED) { + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x06) + } + if (INST_NARGS == 2 && INST_TYPE(0) == AT_INDEXED && INST_TYPE(1) == AT_REGISTER) { + if (INST_REG(1) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x07) + if (INST_REG(1) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x00) + if (INST_REG(1) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x01) + if (INST_REG(1) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x02) + if (INST_REG(1) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x03) + if (INST_REG(1) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x04) + if (INST_REG(1) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x05) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(rlca) +{ + INST_TAKES_NO_ARGS + INST_RETURN(1, 0x07) +} + +INST_FUNC(rld) +{ + INST_TAKES_NO_ARGS + INST_RETURN(2, 0xED, 0x6F) +} + +INST_FUNC(rr) +{ + INST_TAKES_ARGS( + AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_OPTIONAL|AT_REGISTER, + AT_NONE + ) + if (INST_NARGS == 1 && INST_TYPE(0) == AT_REGISTER) { + if (INST_REG(0) == REG_A) + INST_RETURN(2, 0xCB, 0x1F) + if (INST_REG(0) == REG_B) + INST_RETURN(2, 0xCB, 0x18) + if (INST_REG(0) == REG_C) + INST_RETURN(2, 0xCB, 0x19) + if (INST_REG(0) == REG_D) + INST_RETURN(2, 0xCB, 0x1A) + if (INST_REG(0) == REG_E) + INST_RETURN(2, 0xCB, 0x1B) + if (INST_REG(0) == REG_H) + INST_RETURN(2, 0xCB, 0x1C) + if (INST_REG(0) == REG_L) + INST_RETURN(2, 0xCB, 0x1D) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDIRECT && + (INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL)) { + INST_RETURN(2, 0xCB, 0x1E) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDEXED) { + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x1E) + } + if (INST_NARGS == 2 && INST_TYPE(0) == AT_INDEXED && INST_TYPE(1) == AT_REGISTER) { + if (INST_REG(1) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x1F) + if (INST_REG(1) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x18) + if (INST_REG(1) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x19) + if (INST_REG(1) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x1A) + if (INST_REG(1) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x1B) + if (INST_REG(1) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x1C) + if (INST_REG(1) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x1D) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(rra) +{ + INST_TAKES_NO_ARGS + INST_RETURN(1, 0x1F) +} + +INST_FUNC(rrc) +{ + INST_TAKES_ARGS( + AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_OPTIONAL|AT_REGISTER, + AT_NONE + ) + if (INST_NARGS == 1 && INST_TYPE(0) == AT_REGISTER) { + if (INST_REG(0) == REG_A) + INST_RETURN(2, 0xCB, 0x0F) + if (INST_REG(0) == REG_B) + INST_RETURN(2, 0xCB, 0x08) + if (INST_REG(0) == REG_C) + INST_RETURN(2, 0xCB, 0x09) + if (INST_REG(0) == REG_D) + INST_RETURN(2, 0xCB, 0x0A) + if (INST_REG(0) == REG_E) + INST_RETURN(2, 0xCB, 0x0B) + if (INST_REG(0) == REG_H) + INST_RETURN(2, 0xCB, 0x0C) + if (INST_REG(0) == REG_L) + INST_RETURN(2, 0xCB, 0x0D) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDIRECT && + (INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL)) { + INST_RETURN(2, 0xCB, 0x0E) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDEXED) { + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x0E) + } + if (INST_NARGS == 2 && INST_TYPE(0) == AT_INDEXED && INST_TYPE(1) == AT_REGISTER) { + if (INST_REG(1) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x0F) + if (INST_REG(1) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x08) + if (INST_REG(1) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x09) + if (INST_REG(1) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x0A) + if (INST_REG(1) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x0B) + if (INST_REG(1) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x0C) + if (INST_REG(1) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x0D) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(rrca) +{ + INST_TAKES_NO_ARGS + INST_RETURN(1, 0x0F) +} + +INST_FUNC(rrd) +{ + INST_TAKES_NO_ARGS + INST_RETURN(2, 0xED, 0x67) +} + +INST_FUNC(rst) +{ + INST_TAKES_ARGS( + AT_IMMEDIATE, + AT_NONE, + AT_NONE + ) + if (INST_TYPE(0) == AT_IMMEDIATE) { + if ((INST_IMM(0).mask & IMM_RST && INST_IMM(0).uval == 0)) + INST_RETURN(1, 0xC7) + if ((INST_IMM(0).mask & IMM_RST && INST_IMM(0).uval == 8)) + INST_RETURN(1, 0xCF) + if ((INST_IMM(0).mask & IMM_RST && INST_IMM(0).uval == 16)) + INST_RETURN(1, 0xD7) + if ((INST_IMM(0).mask & IMM_RST && INST_IMM(0).uval == 24)) + INST_RETURN(1, 0xDF) + if ((INST_IMM(0).mask & IMM_RST && INST_IMM(0).uval == 32)) + INST_RETURN(1, 0xE7) + if ((INST_IMM(0).mask & IMM_RST && INST_IMM(0).uval == 40)) + INST_RETURN(1, 0xEF) + if ((INST_IMM(0).mask & IMM_RST && INST_IMM(0).uval == 48)) + INST_RETURN(1, 0xF7) + if ((INST_IMM(0).mask & IMM_RST && INST_IMM(0).uval == 56)) + INST_RETURN(1, 0xFF) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(sbc) +{ + INST_TAKES_ARGS( + AT_REGISTER, + AT_IMMEDIATE|AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_NONE + ) + if (INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_REGISTER) { + if (INST_REG(0) == REG_A && INST_REG(1) == REG_A) + INST_RETURN(1, 0x9F) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_B) + INST_RETURN(1, 0x98) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_C) + INST_RETURN(1, 0x99) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_D) + INST_RETURN(1, 0x9A) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_E) + INST_RETURN(1, 0x9B) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_H) + INST_RETURN(1, 0x9C) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_IXH) + INST_RETURN(2, INST_IX_PREFIX, 0x9C) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_IYH) + INST_RETURN(2, INST_IY_PREFIX, 0x9C) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_L) + INST_RETURN(1, 0x9D) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_IXL) + INST_RETURN(2, INST_IX_PREFIX, 0x9D) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_IYL) + INST_RETURN(2, INST_IY_PREFIX, 0x9D) + if (INST_REG(0) == REG_HL && INST_REG(1) == REG_BC) + INST_RETURN(2, 0xED, 0x42) + if (INST_REG(0) == REG_HL && INST_REG(1) == REG_DE) + INST_RETURN(2, 0xED, 0x52) + if (INST_REG(0) == REG_HL && INST_REG(1) == REG_HL) + INST_RETURN(2, 0xED, 0x62) + if (INST_REG(0) == REG_HL && INST_REG(1) == REG_SP) + INST_RETURN(2, 0xED, 0x72) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_IMMEDIATE) { + if (INST_REG(0) == REG_A && INST_IMM(1).mask & IMM_U8) + INST_RETURN(2, 0xDE, INST_IMM(1).uval) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_INDIRECT && + (INST_INDIRECT(1).type == AT_REGISTER && INST_INDIRECT(1).addr.reg == REG_HL)) { + if (INST_REG(0) == REG_A) + INST_RETURN(1, 0x9E) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_INDEXED) { + if (INST_REG(0) == REG_A) + INST_RETURN(3, INST_INDEX_PREFIX(1), 0x9E, INST_INDEX(1).offset) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(scf) +{ + INST_TAKES_NO_ARGS + INST_RETURN(1, 0x37) +} + +INST_FUNC(set) +{ + INST_TAKES_ARGS( + AT_IMMEDIATE, + AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_OPTIONAL|AT_REGISTER + ) + if (INST_NARGS == 2 && INST_TYPE(0) == AT_IMMEDIATE && INST_TYPE(1) == AT_REGISTER) { + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(1) == REG_A) + INST_RETURN(2, 0xCB, 0xC7) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(1) == REG_B) + INST_RETURN(2, 0xCB, 0xC0) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(1) == REG_C) + INST_RETURN(2, 0xCB, 0xC1) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(1) == REG_D) + INST_RETURN(2, 0xCB, 0xC2) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(1) == REG_E) + INST_RETURN(2, 0xCB, 0xC3) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(1) == REG_H) + INST_RETURN(2, 0xCB, 0xC4) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0xC5) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(1) == REG_A) + INST_RETURN(2, 0xCB, 0xCF) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(1) == REG_B) + INST_RETURN(2, 0xCB, 0xC8) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(1) == REG_C) + INST_RETURN(2, 0xCB, 0xC9) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(1) == REG_D) + INST_RETURN(2, 0xCB, 0xCA) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(1) == REG_E) + INST_RETURN(2, 0xCB, 0xCB) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(1) == REG_H) + INST_RETURN(2, 0xCB, 0xCC) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0xCD) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(1) == REG_A) + INST_RETURN(2, 0xCB, 0xD7) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(1) == REG_B) + INST_RETURN(2, 0xCB, 0xD0) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(1) == REG_C) + INST_RETURN(2, 0xCB, 0xD1) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(1) == REG_D) + INST_RETURN(2, 0xCB, 0xD2) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(1) == REG_E) + INST_RETURN(2, 0xCB, 0xD3) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(1) == REG_H) + INST_RETURN(2, 0xCB, 0xD4) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0xD5) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(1) == REG_A) + INST_RETURN(2, 0xCB, 0xDF) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(1) == REG_B) + INST_RETURN(2, 0xCB, 0xD8) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(1) == REG_C) + INST_RETURN(2, 0xCB, 0xD9) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(1) == REG_D) + INST_RETURN(2, 0xCB, 0xDA) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(1) == REG_E) + INST_RETURN(2, 0xCB, 0xDB) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(1) == REG_H) + INST_RETURN(2, 0xCB, 0xDC) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0xDD) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(1) == REG_A) + INST_RETURN(2, 0xCB, 0xE7) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(1) == REG_B) + INST_RETURN(2, 0xCB, 0xE0) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(1) == REG_C) + INST_RETURN(2, 0xCB, 0xE1) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(1) == REG_D) + INST_RETURN(2, 0xCB, 0xE2) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(1) == REG_E) + INST_RETURN(2, 0xCB, 0xE3) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(1) == REG_H) + INST_RETURN(2, 0xCB, 0xE4) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0xE5) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(1) == REG_A) + INST_RETURN(2, 0xCB, 0xEF) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(1) == REG_B) + INST_RETURN(2, 0xCB, 0xE8) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(1) == REG_C) + INST_RETURN(2, 0xCB, 0xE9) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(1) == REG_D) + INST_RETURN(2, 0xCB, 0xEA) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(1) == REG_E) + INST_RETURN(2, 0xCB, 0xEB) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(1) == REG_H) + INST_RETURN(2, 0xCB, 0xEC) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0xED) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(1) == REG_A) + INST_RETURN(2, 0xCB, 0xF7) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(1) == REG_B) + INST_RETURN(2, 0xCB, 0xF0) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(1) == REG_C) + INST_RETURN(2, 0xCB, 0xF1) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(1) == REG_D) + INST_RETURN(2, 0xCB, 0xF2) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(1) == REG_E) + INST_RETURN(2, 0xCB, 0xF3) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(1) == REG_H) + INST_RETURN(2, 0xCB, 0xF4) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0xF5) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(1) == REG_A) + INST_RETURN(2, 0xCB, 0xFF) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(1) == REG_B) + INST_RETURN(2, 0xCB, 0xF8) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(1) == REG_C) + INST_RETURN(2, 0xCB, 0xF9) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(1) == REG_D) + INST_RETURN(2, 0xCB, 0xFA) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(1) == REG_E) + INST_RETURN(2, 0xCB, 0xFB) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(1) == REG_H) + INST_RETURN(2, 0xCB, 0xFC) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0xFD) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 2 && INST_TYPE(0) == AT_IMMEDIATE && INST_TYPE(1) == AT_INDIRECT && + (INST_INDIRECT(1).type == AT_REGISTER && INST_INDIRECT(1).addr.reg == REG_HL)) { + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0)) + INST_RETURN(2, 0xCB, 0xC6) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1)) + INST_RETURN(2, 0xCB, 0xCE) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2)) + INST_RETURN(2, 0xCB, 0xD6) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3)) + INST_RETURN(2, 0xCB, 0xDE) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4)) + INST_RETURN(2, 0xCB, 0xE6) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5)) + INST_RETURN(2, 0xCB, 0xEE) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6)) + INST_RETURN(2, 0xCB, 0xF6) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7)) + INST_RETURN(2, 0xCB, 0xFE) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 2 && INST_TYPE(0) == AT_IMMEDIATE && INST_TYPE(1) == AT_INDEXED) { + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0)) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xC6) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1)) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xCE) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2)) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xD6) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3)) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xDE) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4)) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xE6) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5)) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xEE) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6)) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xF6) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7)) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xFE) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 3 && INST_TYPE(0) == AT_IMMEDIATE && INST_TYPE(1) == AT_INDEXED && INST_TYPE(2) == AT_REGISTER) { + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(2) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xC7) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(2) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xC0) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(2) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xC1) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(2) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xC2) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(2) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xC3) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(2) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xC4) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 0) && INST_REG(2) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xC5) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(2) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xCF) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(2) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xC8) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(2) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xC9) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(2) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xCA) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(2) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xCB) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(2) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xCC) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 1) && INST_REG(2) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xCD) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(2) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xD7) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(2) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xD0) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(2) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xD1) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(2) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xD2) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(2) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xD3) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(2) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xD4) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 2) && INST_REG(2) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xD5) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(2) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xDF) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(2) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xD8) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(2) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xD9) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(2) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xDA) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(2) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xDB) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(2) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xDC) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 3) && INST_REG(2) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xDD) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(2) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xE7) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(2) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xE0) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(2) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xE1) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(2) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xE2) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(2) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xE3) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(2) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xE4) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 4) && INST_REG(2) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xE5) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(2) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xEF) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(2) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xE8) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(2) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xE9) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(2) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xEA) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(2) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xEB) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(2) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xEC) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 5) && INST_REG(2) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xED) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(2) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xF7) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(2) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xF0) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(2) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xF1) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(2) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xF2) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(2) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xF3) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(2) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xF4) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 6) && INST_REG(2) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xF5) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(2) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xFF) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(2) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xF8) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(2) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xF9) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(2) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xFA) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(2) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xFB) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(2) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xFC) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7) && INST_REG(2) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(1), 0xCB, INST_INDEX(1).offset, 0xFD) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(sl1) +{ + INST_TAKES_ARGS( + AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_OPTIONAL|AT_REGISTER, + AT_NONE + ) + if (INST_NARGS == 1 && INST_TYPE(0) == AT_REGISTER) { + if (INST_REG(0) == REG_A) + INST_RETURN(2, 0xCB, 0x37) + if (INST_REG(0) == REG_B) + INST_RETURN(2, 0xCB, 0x30) + if (INST_REG(0) == REG_C) + INST_RETURN(2, 0xCB, 0x31) + if (INST_REG(0) == REG_D) + INST_RETURN(2, 0xCB, 0x32) + if (INST_REG(0) == REG_E) + INST_RETURN(2, 0xCB, 0x33) + if (INST_REG(0) == REG_H) + INST_RETURN(2, 0xCB, 0x34) + if (INST_REG(0) == REG_L) + INST_RETURN(2, 0xCB, 0x35) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDIRECT && + (INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL)) { + INST_RETURN(2, 0xCB, 0x36) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDEXED) { + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x36) + } + if (INST_NARGS == 2 && INST_TYPE(0) == AT_INDEXED && INST_TYPE(1) == AT_REGISTER) { + if (INST_REG(1) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x37) + if (INST_REG(1) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x30) + if (INST_REG(1) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x31) + if (INST_REG(1) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x32) + if (INST_REG(1) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x33) + if (INST_REG(1) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x34) + if (INST_REG(1) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x35) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(sla) +{ + INST_TAKES_ARGS( + AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_OPTIONAL|AT_REGISTER, + AT_NONE + ) + if (INST_NARGS == 1 && INST_TYPE(0) == AT_REGISTER) { + if (INST_REG(0) == REG_A) + INST_RETURN(2, 0xCB, 0x27) + if (INST_REG(0) == REG_B) + INST_RETURN(2, 0xCB, 0x20) + if (INST_REG(0) == REG_C) + INST_RETURN(2, 0xCB, 0x21) + if (INST_REG(0) == REG_D) + INST_RETURN(2, 0xCB, 0x22) + if (INST_REG(0) == REG_E) + INST_RETURN(2, 0xCB, 0x23) + if (INST_REG(0) == REG_H) + INST_RETURN(2, 0xCB, 0x24) + if (INST_REG(0) == REG_L) + INST_RETURN(2, 0xCB, 0x25) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDIRECT && + (INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL)) { + INST_RETURN(2, 0xCB, 0x26) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDEXED) { + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x26) + } + if (INST_NARGS == 2 && INST_TYPE(0) == AT_INDEXED && INST_TYPE(1) == AT_REGISTER) { + if (INST_REG(1) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x27) + if (INST_REG(1) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x20) + if (INST_REG(1) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x21) + if (INST_REG(1) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x22) + if (INST_REG(1) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x23) + if (INST_REG(1) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x24) + if (INST_REG(1) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x25) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(sll) +{ + INST_TAKES_ARGS( + AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_OPTIONAL|AT_REGISTER, + AT_NONE + ) + if (INST_NARGS == 1 && INST_TYPE(0) == AT_REGISTER) { + if (INST_REG(0) == REG_A) + INST_RETURN(2, 0xCB, 0x37) + if (INST_REG(0) == REG_B) + INST_RETURN(2, 0xCB, 0x30) + if (INST_REG(0) == REG_C) + INST_RETURN(2, 0xCB, 0x31) + if (INST_REG(0) == REG_D) + INST_RETURN(2, 0xCB, 0x32) + if (INST_REG(0) == REG_E) + INST_RETURN(2, 0xCB, 0x33) + if (INST_REG(0) == REG_H) + INST_RETURN(2, 0xCB, 0x34) + if (INST_REG(0) == REG_L) + INST_RETURN(2, 0xCB, 0x35) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDIRECT) { + INST_RETURN(2, 0xCB, 0x36) + } + if (INST_NARGS == 2 && INST_TYPE(0) == AT_INDEXED && INST_TYPE(1) == AT_REGISTER) { + if (INST_REG(1) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x37) + if (INST_REG(1) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x30) + if (INST_REG(1) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x31) + if (INST_REG(1) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x32) + if (INST_REG(1) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x33) + if (INST_REG(1) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x34) + if (INST_REG(1) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x35) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(sls) +{ + INST_TAKES_ARGS( + AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_OPTIONAL|AT_REGISTER, + AT_NONE + ) + if (INST_NARGS == 1 && INST_TYPE(0) == AT_REGISTER) { + if (INST_REG(0) == REG_A) + INST_RETURN(2, 0xCB, 0x37) + if (INST_REG(0) == REG_B) + INST_RETURN(2, 0xCB, 0x30) + if (INST_REG(0) == REG_C) + INST_RETURN(2, 0xCB, 0x31) + if (INST_REG(0) == REG_D) + INST_RETURN(2, 0xCB, 0x32) + if (INST_REG(0) == REG_E) + INST_RETURN(2, 0xCB, 0x33) + if (INST_REG(0) == REG_H) + INST_RETURN(2, 0xCB, 0x34) + if (INST_REG(0) == REG_L) + INST_RETURN(2, 0xCB, 0x35) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDIRECT) { + INST_RETURN(2, 0xCB, 0x36) + } + if (INST_NARGS == 2 && INST_TYPE(0) == AT_INDEXED && INST_TYPE(1) == AT_REGISTER) { + if (INST_REG(1) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x37) + if (INST_REG(1) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x30) + if (INST_REG(1) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x31) + if (INST_REG(1) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x32) + if (INST_REG(1) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x33) + if (INST_REG(1) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x34) + if (INST_REG(1) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x35) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(sra) +{ + INST_TAKES_ARGS( + AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_OPTIONAL|AT_REGISTER, + AT_NONE + ) + if (INST_NARGS == 1 && INST_TYPE(0) == AT_REGISTER) { + if (INST_REG(0) == REG_A) + INST_RETURN(2, 0xCB, 0x2F) + if (INST_REG(0) == REG_B) + INST_RETURN(2, 0xCB, 0x28) + if (INST_REG(0) == REG_C) + INST_RETURN(2, 0xCB, 0x29) + if (INST_REG(0) == REG_D) + INST_RETURN(2, 0xCB, 0x2A) + if (INST_REG(0) == REG_E) + INST_RETURN(2, 0xCB, 0x2B) + if (INST_REG(0) == REG_H) + INST_RETURN(2, 0xCB, 0x2C) + if (INST_REG(0) == REG_L) + INST_RETURN(2, 0xCB, 0x2D) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDIRECT && + (INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL)) { + INST_RETURN(2, 0xCB, 0x2E) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDEXED) { + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x2E) + } + if (INST_NARGS == 2 && INST_TYPE(0) == AT_INDEXED && INST_TYPE(1) == AT_REGISTER) { + if (INST_REG(1) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x2F) + if (INST_REG(1) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x28) + if (INST_REG(1) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x29) + if (INST_REG(1) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x2A) + if (INST_REG(1) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x2B) + if (INST_REG(1) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x2C) + if (INST_REG(1) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x2D) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(srl) +{ + INST_TAKES_ARGS( + AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_OPTIONAL|AT_REGISTER, + AT_NONE + ) + if (INST_NARGS == 1 && INST_TYPE(0) == AT_REGISTER) { + if (INST_REG(0) == REG_A) + INST_RETURN(2, 0xCB, 0x3F) + if (INST_REG(0) == REG_B) + INST_RETURN(2, 0xCB, 0x38) + if (INST_REG(0) == REG_C) + INST_RETURN(2, 0xCB, 0x39) + if (INST_REG(0) == REG_D) + INST_RETURN(2, 0xCB, 0x3A) + if (INST_REG(0) == REG_E) + INST_RETURN(2, 0xCB, 0x3B) + if (INST_REG(0) == REG_H) + INST_RETURN(2, 0xCB, 0x3C) + if (INST_REG(0) == REG_L) + INST_RETURN(2, 0xCB, 0x3D) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDIRECT && + (INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL)) { + INST_RETURN(2, 0xCB, 0x3E) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDEXED) { + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x3E) + } + if (INST_NARGS == 2 && INST_TYPE(0) == AT_INDEXED && INST_TYPE(1) == AT_REGISTER) { + if (INST_REG(1) == REG_A) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x3F) + if (INST_REG(1) == REG_B) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x38) + if (INST_REG(1) == REG_C) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x39) + if (INST_REG(1) == REG_D) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x3A) + if (INST_REG(1) == REG_E) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x3B) + if (INST_REG(1) == REG_H) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x3C) + if (INST_REG(1) == REG_L) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0xCB, INST_INDEX(0).offset, 0x3D) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(sub) +{ + INST_TAKES_ARGS( + AT_IMMEDIATE|AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_NONE, + AT_NONE + ) + if (INST_TYPE(0) == AT_REGISTER) { + if (INST_REG(0) == REG_A) + INST_RETURN(1, 0x97) + if (INST_REG(0) == REG_B) + INST_RETURN(1, 0x90) + if (INST_REG(0) == REG_C) + INST_RETURN(1, 0x91) + if (INST_REG(0) == REG_D) + INST_RETURN(1, 0x92) + if (INST_REG(0) == REG_E) + INST_RETURN(1, 0x93) + if (INST_REG(0) == REG_H) + INST_RETURN(1, 0x94) + if (INST_REG(0) == REG_IXH) + INST_RETURN(2, INST_IX_PREFIX, 0x94) + if (INST_REG(0) == REG_IYH) + INST_RETURN(2, INST_IY_PREFIX, 0x94) + if (INST_REG(0) == REG_L) + INST_RETURN(1, 0x95) + if (INST_REG(0) == REG_IXL) + INST_RETURN(2, INST_IX_PREFIX, 0x95) + if (INST_REG(0) == REG_IYL) + INST_RETURN(2, INST_IY_PREFIX, 0x95) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_IMMEDIATE) { + if (INST_IMM(0).mask & IMM_U8) + INST_RETURN(2, 0xD6, INST_IMM(0).uval) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_INDIRECT && + (INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL)) { + INST_RETURN(1, 0x96) + } + if (INST_TYPE(0) == AT_INDEXED) { + INST_RETURN(3, INST_INDEX_PREFIX(0), 0x96, INST_INDEX(0).offset) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(xor) +{ + INST_TAKES_ARGS( + AT_IMMEDIATE|AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_NONE, + AT_NONE + ) + if (INST_TYPE(0) == AT_REGISTER) { + if (INST_REG(0) == REG_A) + INST_RETURN(1, 0xAF) + if (INST_REG(0) == REG_B) + INST_RETURN(1, 0xA8) + if (INST_REG(0) == REG_C) + INST_RETURN(1, 0xA9) + if (INST_REG(0) == REG_D) + INST_RETURN(1, 0xAA) + if (INST_REG(0) == REG_E) + INST_RETURN(1, 0xAB) + if (INST_REG(0) == REG_H) + INST_RETURN(1, 0xAC) + if (INST_REG(0) == REG_IXH) + INST_RETURN(2, INST_IX_PREFIX, 0xAC) + if (INST_REG(0) == REG_IYH) + INST_RETURN(2, INST_IY_PREFIX, 0xAC) + if (INST_REG(0) == REG_L) + INST_RETURN(1, 0xAD) + if (INST_REG(0) == REG_IXL) + INST_RETURN(2, INST_IX_PREFIX, 0xAD) + if (INST_REG(0) == REG_IYL) + INST_RETURN(2, INST_IY_PREFIX, 0xAD) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_IMMEDIATE) { + if (INST_IMM(0).mask & IMM_U8) + INST_RETURN(2, 0xEE, INST_IMM(0).uval) + INST_ERROR(ARG_VALUE) + } + if (INST_TYPE(0) == AT_INDIRECT && + (INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL)) { + INST_RETURN(1, 0xAE) + } + if (INST_TYPE(0) == AT_INDEXED) { + INST_RETURN(3, INST_INDEX_PREFIX(0), 0xAE, INST_INDEX(0).offset) + } + INST_ERROR(ARG_TYPE) +} + +/* @AUTOGEN_INST_BLOCK_END */ + +/* + Return the relevant ASMInstParser function for the given encoded mnemonic. +*/ +static ASMInstParser lookup_parser(uint32_t key) +{ +/* @AUTOGEN_LOOKUP_BLOCK_START */ + HANDLE(adc) + HANDLE(add) + HANDLE(and) + HANDLE(bit) + HANDLE(call) + HANDLE(ccf) + HANDLE(cp) + HANDLE(cpd) + HANDLE(cpdr) + HANDLE(cpi) + HANDLE(cpir) + HANDLE(cpl) + HANDLE(daa) + HANDLE(dec) + HANDLE(di) + HANDLE(djnz) + HANDLE(ei) + HANDLE(ex) + HANDLE(exx) + HANDLE(halt) + HANDLE(im) + HANDLE(in) + HANDLE(inc) + HANDLE(ind) + HANDLE(indr) + HANDLE(ini) + HANDLE(inir) + HANDLE(jp) + HANDLE(jr) + HANDLE(ld) + HANDLE(ldd) + HANDLE(lddr) + HANDLE(ldi) + HANDLE(ldir) + HANDLE(neg) + HANDLE(nop) + HANDLE(or) + HANDLE(otdr) + HANDLE(otir) + HANDLE(out) + HANDLE(outd) + HANDLE(outi) + HANDLE(pop) + HANDLE(push) + HANDLE(res) + HANDLE(ret) + HANDLE(reti) + HANDLE(retn) + HANDLE(rl) + HANDLE(rla) + HANDLE(rlc) + HANDLE(rlca) + HANDLE(rld) + HANDLE(rr) + HANDLE(rra) + HANDLE(rrc) + HANDLE(rrca) + HANDLE(rrd) + HANDLE(rst) + HANDLE(sbc) + HANDLE(scf) + HANDLE(set) + HANDLE(sl1) + HANDLE(sla) + HANDLE(sll) + HANDLE(sls) + HANDLE(sra) + HANDLE(srl) + HANDLE(sub) + HANDLE(xor) +/* @AUTOGEN_LOOKUP_BLOCK_END */ + return NULL; +} diff --git a/src/assembler/instructions.yml b/src/assembler/instructions.yml new file mode 100644 index 0000000..3acea68 --- /dev/null +++ b/src/assembler/instructions.yml @@ -0,0 +1,1859 @@ +# Copyright (C) 2014-2015 Ben Kurtovic +# Released under the terms of the MIT License. See LICENSE for details. + +# *** ASM Instruction Description File *** + +# This file is used to generate 'instructions.inc.c'. + +# `make` should trigger a rebuild when this file is modified; if not, use: +# `python scripts/update_asm_instructions.py`. + +--- + +adc: + args: yes + cases: + - type: [register, register] + cases: + - cond: [a, a] + return: [0x8F] + - cond: [a, b] + return: [0x88] + - cond: [a, c] + return: [0x89] + - cond: [a, d] + return: [0x8A] + - cond: [a, e] + return: [0x8B] + - cond: [a, h|ih] + return: [0x8C] + - cond: [a, l|il] + return: [0x8D] + - cond: [hl, bc] + return: [0xED, 0x4A] + - cond: [hl, de] + return: [0xED, 0x5A] + - cond: [hl, hl] + return: [0xED, 0x6A] + - cond: [hl, sp] + return: [0xED, 0x7A] + - type: [register, immediate] + cases: + - cond: [a, u8] + return: [0xCE, u8] + - type: [register, indirect_hl_or_indexed] + cases: + - cond: [a, _] + return: [0x8E] + +add: + args: yes + cases: + - type: [register, register] + cases: + - cond: [a, a] + return: [0x87] + - cond: [a, b] + return: [0x80] + - cond: [a, c] + return: [0x81] + - cond: [a, d] + return: [0x82] + - cond: [a, e] + return: [0x83] + - cond: [a, h|ih] + return: [0x84] + - cond: [a, l|il] + return: [0x85] + - cond: [hl|i, bc] + return: [0x09] + - cond: [hl|i, de] + return: [0x19] + - cond: [hl|i, hl|i] + return: [0x29] + - cond: [hl|i, sp] + return: [0x39] + - type: [register, immediate] + cases: + - cond: [a, u8] + return: [0xC6, u8] + - type: [register, indirect_hl_or_indexed] + cases: + - cond: [a, _] + return: [0x86] + +and: + args: yes + cases: + - type: [register] + cases: + - cond: [a] + return: [0xA7] + - cond: [b] + return: [0xA0] + - cond: [c] + return: [0xA1] + - cond: [d] + return: [0xA2] + - cond: [e] + return: [0xA3] + - cond: [h|ih] + return: [0xA4] + - cond: [l|il] + return: [0xA5] + - type: [immediate] + cases: + - cond: [u8] + return: [0xE6, u8] + - type: [indirect_hl_or_indexed] + cases: + - cond: [_] + return: [0xA6] + +bit: + args: yes + cases: + - type: [immediate, register] + cases: + - cond: [bit.0, a] + return: [0xCB, 0x47] + - cond: [bit.0, b] + return: [0xCB, 0x40] + - cond: [bit.0, c] + return: [0xCB, 0x41] + - cond: [bit.0, d] + return: [0xCB, 0x42] + - cond: [bit.0, e] + return: [0xCB, 0x43] + - cond: [bit.0, h] + return: [0xCB, 0x44] + - cond: [bit.0, l] + return: [0xCB, 0x45] + - cond: [bit.1, a] + return: [0xCB, 0x4F] + - cond: [bit.1, b] + return: [0xCB, 0x48] + - cond: [bit.1, c] + return: [0xCB, 0x49] + - cond: [bit.1, d] + return: [0xCB, 0x4A] + - cond: [bit.1, e] + return: [0xCB, 0x4B] + - cond: [bit.1, h] + return: [0xCB, 0x4C] + - cond: [bit.1, l] + return: [0xCB, 0x4D] + - cond: [bit.2, a] + return: [0xCB, 0x57] + - cond: [bit.2, b] + return: [0xCB, 0x50] + - cond: [bit.2, c] + return: [0xCB, 0x51] + - cond: [bit.2, d] + return: [0xCB, 0x52] + - cond: [bit.2, e] + return: [0xCB, 0x53] + - cond: [bit.2, h] + return: [0xCB, 0x54] + - cond: [bit.2, l] + return: [0xCB, 0x55] + - cond: [bit.3, a] + return: [0xCB, 0x5F] + - cond: [bit.3, b] + return: [0xCB, 0x58] + - cond: [bit.3, c] + return: [0xCB, 0x59] + - cond: [bit.3, d] + return: [0xCB, 0x5A] + - cond: [bit.3, e] + return: [0xCB, 0x5B] + - cond: [bit.3, h] + return: [0xCB, 0x5C] + - cond: [bit.3, l] + return: [0xCB, 0x5D] + - cond: [bit.4, a] + return: [0xCB, 0x67] + - cond: [bit.4, b] + return: [0xCB, 0x60] + - cond: [bit.4, c] + return: [0xCB, 0x61] + - cond: [bit.4, d] + return: [0xCB, 0x62] + - cond: [bit.4, e] + return: [0xCB, 0x63] + - cond: [bit.4, h] + return: [0xCB, 0x64] + - cond: [bit.4, l] + return: [0xCB, 0x65] + - cond: [bit.5, a] + return: [0xCB, 0x6F] + - cond: [bit.5, b] + return: [0xCB, 0x68] + - cond: [bit.5, c] + return: [0xCB, 0x69] + - cond: [bit.5, d] + return: [0xCB, 0x6A] + - cond: [bit.5, e] + return: [0xCB, 0x6B] + - cond: [bit.5, h] + return: [0xCB, 0x6C] + - cond: [bit.5, l] + return: [0xCB, 0x6D] + - cond: [bit.6, a] + return: [0xCB, 0x77] + - cond: [bit.6, b] + return: [0xCB, 0x70] + - cond: [bit.6, c] + return: [0xCB, 0x71] + - cond: [bit.6, d] + return: [0xCB, 0x72] + - cond: [bit.6, e] + return: [0xCB, 0x73] + - cond: [bit.6, h] + return: [0xCB, 0x74] + - cond: [bit.6, l] + return: [0xCB, 0x75] + - cond: [bit.7, a] + return: [0xCB, 0x7F] + - cond: [bit.7, b] + return: [0xCB, 0x78] + - cond: [bit.7, c] + return: [0xCB, 0x79] + - cond: [bit.7, d] + return: [0xCB, 0x7A] + - cond: [bit.7, e] + return: [0xCB, 0x7B] + - cond: [bit.7, h] + return: [0xCB, 0x7C] + - cond: [bit.7, l] + return: [0xCB, 0x7D] + - type: [immediate, indirect_hl_or_indexed] + cases: + - cond: [bit.0, _] + return: [0xCB, 0x46] + - cond: [bit.1, _] + return: [0xCB, 0x4E] + - cond: [bit.2, _] + return: [0xCB, 0x56] + - cond: [bit.3, _] + return: [0xCB, 0x5E] + - cond: [bit.4, _] + return: [0xCB, 0x66] + - cond: [bit.5, _] + return: [0xCB, 0x6E] + - cond: [bit.6, _] + return: [0xCB, 0x76] + - cond: [bit.7, _] + return: [0xCB, 0x7E] + +call: + args: yes + cases: + - type: [immediate] + cases: + - cond: [u16] + return: [0xCD, u16] + - type: [condition, immediate] + cases: + - cond: [nz, u16] + return: [0xC4, u16] + - cond: [z, u16] + return: [0xCC, u16] + - cond: [nc, u16] + return: [0xD4, u16] + - cond: [c, u16] + return: [0xDC, u16] + - cond: [po, u16] + return: [0xE4, u16] + - cond: [pe, u16] + return: [0xEC, u16] + - cond: [p, u16] + return: [0xF4, u16] + - cond: [m, u16] + return: [0xFC, u16] + +ccf: + args: no + return: [0x3F] + +cp: + args: yes + cases: + - type: [register] + cases: + - cond: [a] + return: [0xBF] + - cond: [b] + return: [0xB8] + - cond: [c] + return: [0xB9] + - cond: [d] + return: [0xBA] + - cond: [e] + return: [0xBB] + - cond: [h|ih] + return: [0xBC] + - cond: [l|il] + return: [0xBD] + - type: [indirect_hl_or_indexed] + cases: + - cond: [_] + return: [0xBE] + - type: [immediate] + cases: + - cond: [u8] + return: [0xFE, u8] + +cpd: + args: no + return: [0xED, 0xA9] + +cpdr: + args: no + return: [0xED, 0xB9] + +cpi: + args: no + return: [0xED, 0xA1] + +cpir: + args: no + return: [0xED, 0xB1] + +cpl: + args: no + return: [0x2F] + +daa: + args: no + return: [0x27] + +dec: + args: yes + cases: + - type: [register] + cases: + - cond: [a] + return: [0x3D] + - cond: [b] + return: [0x05] + - cond: [c] + return: [0x0D] + - cond: [d] + return: [0x15] + - cond: [e] + return: [0x1D] + - cond: [h|ih] + return: [0x25] + - cond: [l|il] + return: [0x2D] + - cond: [bc] + return: [0x0B] + - cond: [de] + return: [0x1B] + - cond: [hl|i] + return: [0x2B] + - cond: [sp] + return: [0x3B] + - type: [indirect_hl_or_indexed] + cases: + - cond: [_] + return: [0x35] + +di: + args: no + return: [0xF3] + +djnz: + args: yes + cases: + - type: [immediate] + cases: + - cond: [rel] + return: [0x10, rel] + +ei: + args: no + return: [0xFB] + +ex: + args: yes + cases: + - type: [register, register] + cases: + - cond: [af, af_] + return: [0x08] + - cond: [de, hl] + return: [0xEB] + - type: [indirect, register] + cases: + - cond: [reg.sp, hl|i] + return: [0xE3] + +exx: + args: no + return: [0xD9] + +halt: + args: no + return: [0x76] + +im: + args: yes + cases: + - type: [immediate] + cases: + - cond: [im.0] + return: [0xED, 0x46] + - cond: [im.1] + return: [0xED, 0x56] + - cond: [im.2] + return: [0xED, 0x5E] + +in: + args: yes + cases: + - type: [register, port] + cases: + - cond: [a, imm] + return: [0xDB, u8] + - cond: [a, reg.c] + return: [0xED, 0x78] + - cond: [b, reg.c] + return: [0xED, 0x40] + - cond: [c, reg.c] + return: [0xED, 0x48] + - cond: [d, reg.c] + return: [0xED, 0x50] + - cond: [e, reg.c] + return: [0xED, 0x58] + - cond: [h, reg.c] + return: [0xED, 0x60] + - cond: [l, reg.c] + return: [0xED, 0x68] + - type: [port] + cases: + - cond: [reg.c] + return: [0xED, 0x70] + +inc: + args: yes + cases: + - type: [register] + cases: + - cond: [a] + return: [0x3C] + - cond: [b] + return: [0x04] + - cond: [c] + return: [0x0C] + - cond: [d] + return: [0x14] + - cond: [e] + return: [0x1C] + - cond: [h|ih] + return: [0x24] + - cond: [l|il] + return: [0x2C] + - cond: [bc] + return: [0x03] + - cond: [de] + return: [0x13] + - cond: [hl|i] + return: [0x23] + - cond: [sp] + return: [0x33] + - type: [indirect_hl_or_indexed] + cases: + - cond: [_] + return: [0x34] + +ind: + args: no + return: [0xED, 0xAA] + +indr: + args: no + return: [0xED, 0xBA] + +ini: + args: no + return: [0xED, 0xA2] + +inir: + args: no + return: [0xED, 0xB2] + +jp: + args: yes + cases: + - type: [immediate] + cases: + - cond: [u16] + return: [0xC3, u16] + - type: [condition, immediate] + cases: + - cond: [nz, u16] + return: [0xC2, u16] + - cond: [z, u16] + return: [0xCA, u16] + - cond: [nc, u16] + return: [0xD2, u16] + - cond: [c, u16] + return: [0xDA, u16] + - cond: [po, u16] + return: [0xE2, u16] + - cond: [pe, u16] + return: [0xEA, u16] + - cond: [p, u16] + return: [0xF2, u16] + - cond: [m, u16] + return: [0xFA, u16] + - type: [indirect_hl_or_indexed] + cases: + - cond: [_] + return: [0xE9] + +jr: + args: yes + cases: + - type: [immediate] + cases: + - cond: [rel] + return: [0x18, rel] + - type: [condition, immediate] + cases: + - cond: [nz, rel] + return: [0x20, rel] + - cond: [z, rel] + return: [0x28, rel] + - cond: [nc, rel] + return: [0x30, rel] + - cond: [c, rel] + return: [0x38, rel] + +ld: + args: yes + cases: + - type: [register, register] + cases: + - cond: [a, a] + return: [0x7F] + - cond: [a, b] + return: [0x78] + - cond: [a, c] + return: [0x79] + - cond: [a, d] + return: [0x7A] + - cond: [a, e] + return: [0x7B] + - cond: [a, h|ih] + return: [0x7C] + - cond: [a, l|il] + return: [0x7D] + - cond: [b, a] + return: [0x47] + - cond: [b, b] + return: [0x40] + - cond: [b, c] + return: [0x41] + - cond: [b, d] + return: [0x42] + - cond: [b, e] + return: [0x43] + - cond: [b, h|ih] + return: [0x44] + - cond: [b, l|il] + return: [0x45] + - cond: [c, a] + return: [0x4F] + - cond: [c, b] + return: [0x48] + - cond: [c, c] + return: [0x49] + - cond: [c, d] + return: [0x4A] + - cond: [c, e] + return: [0x4B] + - cond: [c, h|ih] + return: [0x4C] + - cond: [c, l|il] + return: [0x4D] + - cond: [d, a] + return: [0x57] + - cond: [d, b] + return: [0x50] + - cond: [d, c] + return: [0x51] + - cond: [d, d] + return: [0x52] + - cond: [d, e] + return: [0x53] + - cond: [d, h|ih] + return: [0x54] + - cond: [d, l|il] + return: [0x55] + - cond: [e, a] + return: [0x5F] + - cond: [e, b] + return: [0x58] + - cond: [e, c] + return: [0x59] + - cond: [e, d] + return: [0x5A] + - cond: [e, e] + return: [0x5B] + - cond: [e, h|ih] + return: [0x5C] + - cond: [e, l|il] + return: [0x5D] + - cond: [h|ih, a] + return: [0x67] + - cond: [h|ih, b] + return: [0x60] + - cond: [h|ih, c] + return: [0x61] + - cond: [h|ih, d] + return: [0x62] + - cond: [h|ih, e] + return: [0x63] + - cond: [h|ih, h|ih] + return: [0x64] + - cond: [h|ih, l|il] + return: [0x65] + - cond: [l|il, a] + return: [0x6F] + - cond: [l|il, b] + return: [0x68] + - cond: [l|il, c] + return: [0x69] + - cond: [l|il, d] + return: [0x6A] + - cond: [l|il, e] + return: [0x6B] + - cond: [l|il, h|ih] + return: [0x6C] + - cond: [l|il, l|il] + return: [0x6D] + - cond: [a, i] + return: [0xED, 0x57] + - cond: [i, a] + return: [0xED, 0x47] + - cond: [a, r] + return: [0xED, 0x5F] + - cond: [r, a] + return: [0xED, 0x4F] + - cond: [sp, hl|i] + return: [0xF9] + - type: [register, immediate] + cases: + - cond: [a, u8] + return: [0x3E, u8] + - cond: [b, u8] + return: [0x06, u8] + - cond: [c, u8] + return: [0x0E, u8] + - cond: [d, u8] + return: [0x16, u8] + - cond: [e, u8] + return: [0x1E, u8] + - cond: [h|ih, u8] + return: [0x26, u8] + - cond: [l|il, u8] + return: [0x2E, u8] + - cond: [bc, u16] + return: [0x01, u16] + - cond: [de, u16] + return: [0x11, u16] + - cond: [hl|i, u16] + return: [0x21, u16] + - cond: [sp, u16] + return: [0x31, u16] + - type: [register, indirect_hl_or_indexed] + cases: + - cond: [a, _] + return: [0x7E] + - cond: [b, _] + return: [0x46] + - cond: [c, _] + return: [0x4E] + - cond: [d, _] + return: [0x56] + - cond: [e, _] + return: [0x5E] + - cond: [h, _] + return: [0x66] + - cond: [l, _] + return: [0x6E] + - type: [register, indirect] + cases: + - cond: [a, reg.bc] + return: [0x0A] + - cond: [a, reg.de] + return: [0x1A] + - cond: [hl|i, imm] + return: [0x2A, u16] + - cond: [a, imm] + return: [0x3A, u16] + - cond: [bc, imm] + return: [0xED, 0x4B, u16] + - cond: [de, imm] + return: [0xED, 0x5B, u16] + - cond: [sp, imm] + return: [0xED, 0x7B, u16] + - type: [indirect_hl_or_indexed, register] + cases: + - cond: [_, a] + return: [0x77] + - cond: [_, b] + return: [0x70] + - cond: [_, c] + return: [0x71] + - cond: [_, d] + return: [0x72] + - cond: [_, e] + return: [0x73] + - cond: [_, h] + return: [0x74] + - cond: [_, l] + return: [0x75] + - type: [indirect_hl_or_indexed, immediate] + cases: + - cond: [_, u8] + return: [0x36, u8] + - type: [indirect, register] + cases: + - cond: [reg.bc, a] + return: [0x02] + - cond: [reg.de, a] + return: [0x12] + - cond: [imm, hl|i] + return: [0x22, u16] + - cond: [imm, a] + return: [0x32, u16] + - cond: [imm, bc] + return: [0xED, 0x43, u16] + - cond: [imm, de] + return: [0xED, 0x53, u16] + - cond: [imm, sp] + return: [0xED, 0x73, u16] + +ldd: + args: no + return: [0xED, 0xA8] + +lddr: + args: no + return: [0xED, 0xB8] + +ldi: + args: no + return: [0xED, 0xA0] + +ldir: + args: no + return: [0xED, 0xB0] + +neg: + args: no + return: [0xED, 0x44] + +nop: + args: no + return: [0x00] + +or: + args: yes + cases: + - type: [register] + cases: + - cond: [a] + return: [0xB7] + - cond: [b] + return: [0xB0] + - cond: [c] + return: [0xB1] + - cond: [d] + return: [0xB2] + - cond: [e] + return: [0xB3] + - cond: [h|ih] + return: [0xB4] + - cond: [l|il] + return: [0xB5] + - type: [immediate] + cases: + - cond: [u8] + return: [0xF6, u8] + - type: [indirect_hl_or_indexed] + cases: + - cond: [_] + return: [0xB6] + +otdr: + args: no + return: [0xED, 0xBB] + +otir: + args: no + return: [0xED, 0xB3] + +out: + args: yes + cases: + - type: [port, register] + cases: + - cond: [imm, a] + return: [0xD3, u8] + - cond: [reg.c, a] + return: [0xED, 0x79] + - cond: [reg.c, b] + return: [0xED, 0x41] + - cond: [reg.c, c] + return: [0xED, 0x49] + - cond: [reg.c, d] + return: [0xED, 0x51] + - cond: [reg.c, e] + return: [0xED, 0x59] + - cond: [reg.c, h] + return: [0xED, 0x61] + - cond: [reg.c, l] + return: [0xED, 0x69] + - type: [port, immediate] + cases: + - cond: [reg.c, u8.0] + return: [0xED, 0x71] + +outd: + args: no + return: [0xED, 0xAB] + +outi: + args: no + return: [0xED, 0xA3] + +pop: + args: yes + cases: + - type: [register] + cases: + - cond: [bc] + return: [0xC1] + - cond: [de] + return: [0xD1] + - cond: [hl|i] + return: [0xE1] + - cond: [af] + return: [0xF1] + +push: + args: yes + cases: + - type: [register] + cases: + - cond: [bc] + return: [0xC5] + - cond: [de] + return: [0xD5] + - cond: [hl|i] + return: [0xE5] + - cond: [af] + return: [0xF5] + +res: + args: yes + cases: + - type: [immediate, register] + cases: + - cond: [bit.0, a] + return: [0xCB, 0x87] + - cond: [bit.0, b] + return: [0xCB, 0x80] + - cond: [bit.0, c] + return: [0xCB, 0x81] + - cond: [bit.0, d] + return: [0xCB, 0x82] + - cond: [bit.0, e] + return: [0xCB, 0x83] + - cond: [bit.0, h] + return: [0xCB, 0x84] + - cond: [bit.0, l] + return: [0xCB, 0x85] + - cond: [bit.1, a] + return: [0xCB, 0x8F] + - cond: [bit.1, b] + return: [0xCB, 0x88] + - cond: [bit.1, c] + return: [0xCB, 0x89] + - cond: [bit.1, d] + return: [0xCB, 0x8A] + - cond: [bit.1, e] + return: [0xCB, 0x8B] + - cond: [bit.1, h] + return: [0xCB, 0x8C] + - cond: [bit.1, l] + return: [0xCB, 0x8D] + - cond: [bit.2, a] + return: [0xCB, 0x97] + - cond: [bit.2, b] + return: [0xCB, 0x90] + - cond: [bit.2, c] + return: [0xCB, 0x91] + - cond: [bit.2, d] + return: [0xCB, 0x92] + - cond: [bit.2, e] + return: [0xCB, 0x93] + - cond: [bit.2, h] + return: [0xCB, 0x94] + - cond: [bit.2, l] + return: [0xCB, 0x95] + - cond: [bit.3, a] + return: [0xCB, 0x9F] + - cond: [bit.3, b] + return: [0xCB, 0x98] + - cond: [bit.3, c] + return: [0xCB, 0x99] + - cond: [bit.3, d] + return: [0xCB, 0x9A] + - cond: [bit.3, e] + return: [0xCB, 0x9B] + - cond: [bit.3, h] + return: [0xCB, 0x9C] + - cond: [bit.3, l] + return: [0xCB, 0x9D] + - cond: [bit.4, a] + return: [0xCB, 0xA7] + - cond: [bit.4, b] + return: [0xCB, 0xA0] + - cond: [bit.4, c] + return: [0xCB, 0xA1] + - cond: [bit.4, d] + return: [0xCB, 0xA2] + - cond: [bit.4, e] + return: [0xCB, 0xA3] + - cond: [bit.4, h] + return: [0xCB, 0xA4] + - cond: [bit.4, l] + return: [0xCB, 0xA5] + - cond: [bit.5, a] + return: [0xCB, 0xAF] + - cond: [bit.5, b] + return: [0xCB, 0xA8] + - cond: [bit.5, c] + return: [0xCB, 0xA9] + - cond: [bit.5, d] + return: [0xCB, 0xAA] + - cond: [bit.5, e] + return: [0xCB, 0xAB] + - cond: [bit.5, h] + return: [0xCB, 0xAC] + - cond: [bit.5, l] + return: [0xCB, 0xAD] + - cond: [bit.6, a] + return: [0xCB, 0xB7] + - cond: [bit.6, b] + return: [0xCB, 0xB0] + - cond: [bit.6, c] + return: [0xCB, 0xB1] + - cond: [bit.6, d] + return: [0xCB, 0xB2] + - cond: [bit.6, e] + return: [0xCB, 0xB3] + - cond: [bit.6, h] + return: [0xCB, 0xB4] + - cond: [bit.6, l] + return: [0xCB, 0xB5] + - cond: [bit.7, a] + return: [0xCB, 0xBF] + - cond: [bit.7, b] + return: [0xCB, 0xB8] + - cond: [bit.7, c] + return: [0xCB, 0xB9] + - cond: [bit.7, d] + return: [0xCB, 0xBA] + - cond: [bit.7, e] + return: [0xCB, 0xBB] + - cond: [bit.7, h] + return: [0xCB, 0xBC] + - cond: [bit.7, l] + return: [0xCB, 0xBD] + - type: [immediate, indirect_hl_or_indexed] + cases: + - cond: [bit.0, _] + return: [0xCB, 0x86] + - cond: [bit.1, _] + return: [0xCB, 0x8E] + - cond: [bit.2, _] + return: [0xCB, 0x96] + - cond: [bit.3, _] + return: [0xCB, 0x9E] + - cond: [bit.4, _] + return: [0xCB, 0xA6] + - cond: [bit.5, _] + return: [0xCB, 0xAE] + - cond: [bit.6, _] + return: [0xCB, 0xB6] + - cond: [bit.7, _] + return: [0xCB, 0xBE] + - type: [immediate, indexed, register] + cases: + - cond: [bit.0, _, a] + return: [0xCB, 0x87] + - cond: [bit.0, _, b] + return: [0xCB, 0x80] + - cond: [bit.0, _, c] + return: [0xCB, 0x81] + - cond: [bit.0, _, d] + return: [0xCB, 0x82] + - cond: [bit.0, _, e] + return: [0xCB, 0x83] + - cond: [bit.0, _, h] + return: [0xCB, 0x84] + - cond: [bit.0, _, l] + return: [0xCB, 0x85] + - cond: [bit.1, _, a] + return: [0xCB, 0x8F] + - cond: [bit.1, _, b] + return: [0xCB, 0x88] + - cond: [bit.1, _, c] + return: [0xCB, 0x89] + - cond: [bit.1, _, d] + return: [0xCB, 0x8A] + - cond: [bit.1, _, e] + return: [0xCB, 0x8B] + - cond: [bit.1, _, h] + return: [0xCB, 0x8C] + - cond: [bit.1, _, l] + return: [0xCB, 0x8D] + - cond: [bit.2, _, a] + return: [0xCB, 0x97] + - cond: [bit.2, _, b] + return: [0xCB, 0x90] + - cond: [bit.2, _, c] + return: [0xCB, 0x91] + - cond: [bit.2, _, d] + return: [0xCB, 0x92] + - cond: [bit.2, _, e] + return: [0xCB, 0x93] + - cond: [bit.2, _, h] + return: [0xCB, 0x94] + - cond: [bit.2, _, l] + return: [0xCB, 0x95] + - cond: [bit.3, _, a] + return: [0xCB, 0x9F] + - cond: [bit.3, _, b] + return: [0xCB, 0x98] + - cond: [bit.3, _, c] + return: [0xCB, 0x99] + - cond: [bit.3, _, d] + return: [0xCB, 0x9A] + - cond: [bit.3, _, e] + return: [0xCB, 0x9B] + - cond: [bit.3, _, h] + return: [0xCB, 0x9C] + - cond: [bit.3, _, l] + return: [0xCB, 0x9D] + - cond: [bit.4, _, a] + return: [0xCB, 0xA7] + - cond: [bit.4, _, b] + return: [0xCB, 0xA0] + - cond: [bit.4, _, c] + return: [0xCB, 0xA1] + - cond: [bit.4, _, d] + return: [0xCB, 0xA2] + - cond: [bit.4, _, e] + return: [0xCB, 0xA3] + - cond: [bit.4, _, h] + return: [0xCB, 0xA4] + - cond: [bit.4, _, l] + return: [0xCB, 0xA5] + - cond: [bit.5, _, a] + return: [0xCB, 0xAF] + - cond: [bit.5, _, b] + return: [0xCB, 0xA8] + - cond: [bit.5, _, c] + return: [0xCB, 0xA9] + - cond: [bit.5, _, d] + return: [0xCB, 0xAA] + - cond: [bit.5, _, e] + return: [0xCB, 0xAB] + - cond: [bit.5, _, h] + return: [0xCB, 0xAC] + - cond: [bit.5, _, l] + return: [0xCB, 0xAD] + - cond: [bit.6, _, a] + return: [0xCB, 0xB7] + - cond: [bit.6, _, b] + return: [0xCB, 0xB0] + - cond: [bit.6, _, c] + return: [0xCB, 0xB1] + - cond: [bit.6, _, d] + return: [0xCB, 0xB2] + - cond: [bit.6, _, e] + return: [0xCB, 0xB3] + - cond: [bit.6, _, h] + return: [0xCB, 0xB4] + - cond: [bit.6, _, l] + return: [0xCB, 0xB5] + - cond: [bit.7, _, a] + return: [0xCB, 0xBF] + - cond: [bit.7, _, b] + return: [0xCB, 0xB8] + - cond: [bit.7, _, c] + return: [0xCB, 0xB9] + - cond: [bit.7, _, d] + return: [0xCB, 0xBA] + - cond: [bit.7, _, e] + return: [0xCB, 0xBB] + - cond: [bit.7, _, h] + return: [0xCB, 0xBC] + - cond: [bit.7, _, l] + return: [0xCB, 0xBD] + +ret: + args: yes + cases: + - type: [] + return: [0xC9] + - type: [condition] + cases: + - cond: [nz] + return: [0xC0] + - cond: [z] + return: [0xC8] + - cond: [nc] + return: [0xD0] + - cond: [c] + return: [0xD8] + - cond: [po] + return: [0xE0] + - cond: [pe] + return: [0xE8] + - cond: [p] + return: [0xF0] + - cond: [m] + return: [0xF8] + +reti: + args: no + return: [0xED, 0x4D] + +retn: + args: no + return: [0xED, 0x45] + +rl: + args: yes + cases: + - type: [register] + cases: + - cond: [a] + return: [0xCB, 0x17] + - cond: [b] + return: [0xCB, 0x10] + - cond: [c] + return: [0xCB, 0x11] + - cond: [d] + return: [0xCB, 0x12] + - cond: [e] + return: [0xCB, 0x13] + - cond: [h] + return: [0xCB, 0x14] + - cond: [l] + return: [0xCB, 0x15] + - type: [indirect_hl_or_indexed] + cases: + - cond: [_] + return: [0xCB, 0x16] + - type: [indexed, register] + cases: + - cond: [_, a] + return: [0xCB, 0x17] + - cond: [_, b] + return: [0xCB, 0x10] + - cond: [_, c] + return: [0xCB, 0x11] + - cond: [_, d] + return: [0xCB, 0x12] + - cond: [_, e] + return: [0xCB, 0x13] + - cond: [_, h] + return: [0xCB, 0x14] + - cond: [_, l] + return: [0xCB, 0x15] + +rla: + args: no + return: [0x17] + +rlc: + args: yes + cases: + - type: [register] + cases: + - cond: [a] + return: [0xCB, 0x07] + - cond: [b] + return: [0xCB, 0x00] + - cond: [c] + return: [0xCB, 0x01] + - cond: [d] + return: [0xCB, 0x02] + - cond: [e] + return: [0xCB, 0x03] + - cond: [h] + return: [0xCB, 0x04] + - cond: [l] + return: [0xCB, 0x05] + - type: [indirect_hl_or_indexed] + cases: + - cond: [_] + return: [0xCB, 0x06] + - type: [indexed, register] + cases: + - cond: [_, a] + return: [0xCB, 0x07] + - cond: [_, b] + return: [0xCB, 0x00] + - cond: [_, c] + return: [0xCB, 0x01] + - cond: [_, d] + return: [0xCB, 0x02] + - cond: [_, e] + return: [0xCB, 0x03] + - cond: [_, h] + return: [0xCB, 0x04] + - cond: [_, l] + return: [0xCB, 0x05] + +rlca: + args: no + return: [0x07] + +rld: + args: no + return: [0xED, 0x6F] + +rr: + args: yes + cases: + - type: [register] + cases: + - cond: [a] + return: [0xCB, 0x1F] + - cond: [b] + return: [0xCB, 0x18] + - cond: [c] + return: [0xCB, 0x19] + - cond: [d] + return: [0xCB, 0x1A] + - cond: [e] + return: [0xCB, 0x1B] + - cond: [h] + return: [0xCB, 0x1C] + - cond: [l] + return: [0xCB, 0x1D] + - type: [indirect_hl_or_indexed] + cases: + - cond: [_] + return: [0xCB, 0x1E] + - type: [indexed, register] + cases: + - cond: [_, a] + return: [0xCB, 0x1F] + - cond: [_, b] + return: [0xCB, 0x18] + - cond: [_, c] + return: [0xCB, 0x19] + - cond: [_, d] + return: [0xCB, 0x1A] + - cond: [_, e] + return: [0xCB, 0x1B] + - cond: [_, h] + return: [0xCB, 0x1C] + - cond: [_, l] + return: [0xCB, 0x1D] + +rra: + args: no + return: [0x1F] + +rrc: + args: yes + cases: + - type: [register] + cases: + - cond: [a] + return: [0xCB, 0x0F] + - cond: [b] + return: [0xCB, 0x08] + - cond: [c] + return: [0xCB, 0x09] + - cond: [d] + return: [0xCB, 0x0A] + - cond: [e] + return: [0xCB, 0x0B] + - cond: [h] + return: [0xCB, 0x0C] + - cond: [l] + return: [0xCB, 0x0D] + - type: [indirect_hl_or_indexed] + cases: + - cond: [_] + return: [0xCB, 0x0E] + - type: [indexed, register] + cases: + - cond: [_, a] + return: [0xCB, 0x0F] + - cond: [_, b] + return: [0xCB, 0x08] + - cond: [_, c] + return: [0xCB, 0x09] + - cond: [_, d] + return: [0xCB, 0x0A] + - cond: [_, e] + return: [0xCB, 0x0B] + - cond: [_, h] + return: [0xCB, 0x0C] + - cond: [_, l] + return: [0xCB, 0x0D] + +rrca: + args: no + return: [0x0F] + +rrd: + args: no + return: [0xED, 0x67] + +rst: + args: yes + cases: + - type: [immediate] + cases: + - cond: [rst.0x00] + return: [0xC7] + - cond: [rst.0x08] + return: [0xCF] + - cond: [rst.0x10] + return: [0xD7] + - cond: [rst.0x18] + return: [0xDF] + - cond: [rst.0x20] + return: [0xE7] + - cond: [rst.0x28] + return: [0xEF] + - cond: [rst.0x30] + return: [0xF7] + - cond: [rst.0x38] + return: [0xFF] + +sbc: + args: yes + cases: + - type: [register, register] + cases: + - cond: [a, a] + return: [0x9F] + - cond: [a, b] + return: [0x98] + - cond: [a, c] + return: [0x99] + - cond: [a, d] + return: [0x9A] + - cond: [a, e] + return: [0x9B] + - cond: [a, h|ih] + return: [0x9C] + - cond: [a, l|il] + return: [0x9D] + - cond: [hl, bc] + return: [0xED, 0x42] + - cond: [hl, de] + return: [0xED, 0x52] + - cond: [hl, hl] + return: [0xED, 0x62] + - cond: [hl, sp] + return: [0xED, 0x72] + - type: [register, immediate] + cases: + - cond: [a, u8] + return: [0xDE, u8] + - type: [register, indirect_hl_or_indexed] + cases: + - cond: [a, _] + return: [0x9E] + +scf: + args: no + return: [0x37] + +set: + args: yes + cases: + - type: [immediate, register] + cases: + - cond: [bit.0, a] + return: [0xCB, 0xC7] + - cond: [bit.0, b] + return: [0xCB, 0xC0] + - cond: [bit.0, c] + return: [0xCB, 0xC1] + - cond: [bit.0, d] + return: [0xCB, 0xC2] + - cond: [bit.0, e] + return: [0xCB, 0xC3] + - cond: [bit.0, h] + return: [0xCB, 0xC4] + - cond: [bit.0, l] + return: [0xCB, 0xC5] + - cond: [bit.1, a] + return: [0xCB, 0xCF] + - cond: [bit.1, b] + return: [0xCB, 0xC8] + - cond: [bit.1, c] + return: [0xCB, 0xC9] + - cond: [bit.1, d] + return: [0xCB, 0xCA] + - cond: [bit.1, e] + return: [0xCB, 0xCB] + - cond: [bit.1, h] + return: [0xCB, 0xCC] + - cond: [bit.1, l] + return: [0xCB, 0xCD] + - cond: [bit.2, a] + return: [0xCB, 0xD7] + - cond: [bit.2, b] + return: [0xCB, 0xD0] + - cond: [bit.2, c] + return: [0xCB, 0xD1] + - cond: [bit.2, d] + return: [0xCB, 0xD2] + - cond: [bit.2, e] + return: [0xCB, 0xD3] + - cond: [bit.2, h] + return: [0xCB, 0xD4] + - cond: [bit.2, l] + return: [0xCB, 0xD5] + - cond: [bit.3, a] + return: [0xCB, 0xDF] + - cond: [bit.3, b] + return: [0xCB, 0xD8] + - cond: [bit.3, c] + return: [0xCB, 0xD9] + - cond: [bit.3, d] + return: [0xCB, 0xDA] + - cond: [bit.3, e] + return: [0xCB, 0xDB] + - cond: [bit.3, h] + return: [0xCB, 0xDC] + - cond: [bit.3, l] + return: [0xCB, 0xDD] + - cond: [bit.4, a] + return: [0xCB, 0xE7] + - cond: [bit.4, b] + return: [0xCB, 0xE0] + - cond: [bit.4, c] + return: [0xCB, 0xE1] + - cond: [bit.4, d] + return: [0xCB, 0xE2] + - cond: [bit.4, e] + return: [0xCB, 0xE3] + - cond: [bit.4, h] + return: [0xCB, 0xE4] + - cond: [bit.4, l] + return: [0xCB, 0xE5] + - cond: [bit.5, a] + return: [0xCB, 0xEF] + - cond: [bit.5, b] + return: [0xCB, 0xE8] + - cond: [bit.5, c] + return: [0xCB, 0xE9] + - cond: [bit.5, d] + return: [0xCB, 0xEA] + - cond: [bit.5, e] + return: [0xCB, 0xEB] + - cond: [bit.5, h] + return: [0xCB, 0xEC] + - cond: [bit.5, l] + return: [0xCB, 0xED] + - cond: [bit.6, a] + return: [0xCB, 0xF7] + - cond: [bit.6, b] + return: [0xCB, 0xF0] + - cond: [bit.6, c] + return: [0xCB, 0xF1] + - cond: [bit.6, d] + return: [0xCB, 0xF2] + - cond: [bit.6, e] + return: [0xCB, 0xF3] + - cond: [bit.6, h] + return: [0xCB, 0xF4] + - cond: [bit.6, l] + return: [0xCB, 0xF5] + - cond: [bit.7, a] + return: [0xCB, 0xFF] + - cond: [bit.7, b] + return: [0xCB, 0xF8] + - cond: [bit.7, c] + return: [0xCB, 0xF9] + - cond: [bit.7, d] + return: [0xCB, 0xFA] + - cond: [bit.7, e] + return: [0xCB, 0xFB] + - cond: [bit.7, h] + return: [0xCB, 0xFC] + - cond: [bit.7, l] + return: [0xCB, 0xFD] + - type: [immediate, indirect_hl_or_indexed] + cases: + - cond: [bit.0, _] + return: [0xCB, 0xC6] + - cond: [bit.1, _] + return: [0xCB, 0xCE] + - cond: [bit.2, _] + return: [0xCB, 0xD6] + - cond: [bit.3, _] + return: [0xCB, 0xDE] + - cond: [bit.4, _] + return: [0xCB, 0xE6] + - cond: [bit.5, _] + return: [0xCB, 0xEE] + - cond: [bit.6, _] + return: [0xCB, 0xF6] + - cond: [bit.7, _] + return: [0xCB, 0xFE] + - type: [immediate, indexed, register] + cases: + - cond: [bit.0, _, a] + return: [0xCB, 0xC7] + - cond: [bit.0, _, b] + return: [0xCB, 0xC0] + - cond: [bit.0, _, c] + return: [0xCB, 0xC1] + - cond: [bit.0, _, d] + return: [0xCB, 0xC2] + - cond: [bit.0, _, e] + return: [0xCB, 0xC3] + - cond: [bit.0, _, h] + return: [0xCB, 0xC4] + - cond: [bit.0, _, l] + return: [0xCB, 0xC5] + - cond: [bit.1, _, a] + return: [0xCB, 0xCF] + - cond: [bit.1, _, b] + return: [0xCB, 0xC8] + - cond: [bit.1, _, c] + return: [0xCB, 0xC9] + - cond: [bit.1, _, d] + return: [0xCB, 0xCA] + - cond: [bit.1, _, e] + return: [0xCB, 0xCB] + - cond: [bit.1, _, h] + return: [0xCB, 0xCC] + - cond: [bit.1, _, l] + return: [0xCB, 0xCD] + - cond: [bit.2, _, a] + return: [0xCB, 0xD7] + - cond: [bit.2, _, b] + return: [0xCB, 0xD0] + - cond: [bit.2, _, c] + return: [0xCB, 0xD1] + - cond: [bit.2, _, d] + return: [0xCB, 0xD2] + - cond: [bit.2, _, e] + return: [0xCB, 0xD3] + - cond: [bit.2, _, h] + return: [0xCB, 0xD4] + - cond: [bit.2, _, l] + return: [0xCB, 0xD5] + - cond: [bit.3, _, a] + return: [0xCB, 0xDF] + - cond: [bit.3, _, b] + return: [0xCB, 0xD8] + - cond: [bit.3, _, c] + return: [0xCB, 0xD9] + - cond: [bit.3, _, d] + return: [0xCB, 0xDA] + - cond: [bit.3, _, e] + return: [0xCB, 0xDB] + - cond: [bit.3, _, h] + return: [0xCB, 0xDC] + - cond: [bit.3, _, l] + return: [0xCB, 0xDD] + - cond: [bit.4, _, a] + return: [0xCB, 0xE7] + - cond: [bit.4, _, b] + return: [0xCB, 0xE0] + - cond: [bit.4, _, c] + return: [0xCB, 0xE1] + - cond: [bit.4, _, d] + return: [0xCB, 0xE2] + - cond: [bit.4, _, e] + return: [0xCB, 0xE3] + - cond: [bit.4, _, h] + return: [0xCB, 0xE4] + - cond: [bit.4, _, l] + return: [0xCB, 0xE5] + - cond: [bit.5, _, a] + return: [0xCB, 0xEF] + - cond: [bit.5, _, b] + return: [0xCB, 0xE8] + - cond: [bit.5, _, c] + return: [0xCB, 0xE9] + - cond: [bit.5, _, d] + return: [0xCB, 0xEA] + - cond: [bit.5, _, e] + return: [0xCB, 0xEB] + - cond: [bit.5, _, h] + return: [0xCB, 0xEC] + - cond: [bit.5, _, l] + return: [0xCB, 0xED] + - cond: [bit.6, _, a] + return: [0xCB, 0xF7] + - cond: [bit.6, _, b] + return: [0xCB, 0xF0] + - cond: [bit.6, _, c] + return: [0xCB, 0xF1] + - cond: [bit.6, _, d] + return: [0xCB, 0xF2] + - cond: [bit.6, _, e] + return: [0xCB, 0xF3] + - cond: [bit.6, _, h] + return: [0xCB, 0xF4] + - cond: [bit.6, _, l] + return: [0xCB, 0xF5] + - cond: [bit.7, _, a] + return: [0xCB, 0xFF] + - cond: [bit.7, _, b] + return: [0xCB, 0xF8] + - cond: [bit.7, _, c] + return: [0xCB, 0xF9] + - cond: [bit.7, _, d] + return: [0xCB, 0xFA] + - cond: [bit.7, _, e] + return: [0xCB, 0xFB] + - cond: [bit.7, _, h] + return: [0xCB, 0xFC] + - cond: [bit.7, _, l] + return: [0xCB, 0xFD] + +sl1: &sl1 + args: yes + cases: + - type: [register] + cases: + - cond: [a] + return: [0xCB, 0x37] + - cond: [b] + return: [0xCB, 0x30] + - cond: [c] + return: [0xCB, 0x31] + - cond: [d] + return: [0xCB, 0x32] + - cond: [e] + return: [0xCB, 0x33] + - cond: [h] + return: [0xCB, 0x34] + - cond: [l] + return: [0xCB, 0x35] + - type: [indirect_hl_or_indexed] + cases: + - cond: [_] + return: [0xCB, 0x36] + - type: [indexed, register] + cases: + - cond: [_, a] + return: [0xCB, 0x37] + - cond: [_, b] + return: [0xCB, 0x30] + - cond: [_, c] + return: [0xCB, 0x31] + - cond: [_, d] + return: [0xCB, 0x32] + - cond: [_, e] + return: [0xCB, 0x33] + - cond: [_, h] + return: [0xCB, 0x34] + - cond: [_, l] + return: [0xCB, 0x35] + +sla: + args: yes + cases: + - type: [register] + cases: + - cond: [a] + return: [0xCB, 0x27] + - cond: [b] + return: [0xCB, 0x20] + - cond: [c] + return: [0xCB, 0x21] + - cond: [d] + return: [0xCB, 0x22] + - cond: [e] + return: [0xCB, 0x23] + - cond: [h] + return: [0xCB, 0x24] + - cond: [l] + return: [0xCB, 0x25] + - type: [indirect_hl_or_indexed] + cases: + - cond: [_] + return: [0xCB, 0x26] + - type: [indexed, register] + cases: + - cond: [_, a] + return: [0xCB, 0x27] + - cond: [_, b] + return: [0xCB, 0x20] + - cond: [_, c] + return: [0xCB, 0x21] + - cond: [_, d] + return: [0xCB, 0x22] + - cond: [_, e] + return: [0xCB, 0x23] + - cond: [_, h] + return: [0xCB, 0x24] + - cond: [_, l] + return: [0xCB, 0x25] + +sll: *sl1 + +sls: *sl1 + +sra: + args: yes + cases: + - type: [register] + cases: + - cond: [a] + return: [0xCB, 0x2F] + - cond: [b] + return: [0xCB, 0x28] + - cond: [c] + return: [0xCB, 0x29] + - cond: [d] + return: [0xCB, 0x2A] + - cond: [e] + return: [0xCB, 0x2B] + - cond: [h] + return: [0xCB, 0x2C] + - cond: [l] + return: [0xCB, 0x2D] + - type: [indirect_hl_or_indexed] + cases: + - cond: [_] + return: [0xCB, 0x2E] + - type: [indexed, register] + cases: + - cond: [_, a] + return: [0xCB, 0x2F] + - cond: [_, b] + return: [0xCB, 0x28] + - cond: [_, c] + return: [0xCB, 0x29] + - cond: [_, d] + return: [0xCB, 0x2A] + - cond: [_, e] + return: [0xCB, 0x2B] + - cond: [_, h] + return: [0xCB, 0x2C] + - cond: [_, l] + return: [0xCB, 0x2D] + +srl: + args: yes + cases: + - type: [register] + cases: + - cond: [a] + return: [0xCB, 0x3F] + - cond: [b] + return: [0xCB, 0x38] + - cond: [c] + return: [0xCB, 0x39] + - cond: [d] + return: [0xCB, 0x3A] + - cond: [e] + return: [0xCB, 0x3B] + - cond: [h] + return: [0xCB, 0x3C] + - cond: [l] + return: [0xCB, 0x3D] + - type: [indirect_hl_or_indexed] + cases: + - cond: [_] + return: [0xCB, 0x3E] + - type: [indexed, register] + cases: + - cond: [_, a] + return: [0xCB, 0x3F] + - cond: [_, b] + return: [0xCB, 0x38] + - cond: [_, c] + return: [0xCB, 0x39] + - cond: [_, d] + return: [0xCB, 0x3A] + - cond: [_, e] + return: [0xCB, 0x3B] + - cond: [_, h] + return: [0xCB, 0x3C] + - cond: [_, l] + return: [0xCB, 0x3D] + +sub: + args: yes + cases: + - type: [register] + cases: + - cond: [a] + return: [0x97] + - cond: [b] + return: [0x90] + - cond: [c] + return: [0x91] + - cond: [d] + return: [0x92] + - cond: [e] + return: [0x93] + - cond: [h|ih] + return: [0x94] + - cond: [l|il] + return: [0x95] + - type: [immediate] + cases: + - cond: [u8] + return: [0xD6, u8] + - type: [indirect_hl_or_indexed] + cases: + - cond: [_] + return: [0x96] + +xor: + args: yes + cases: + - type: [register] + cases: + - cond: [a] + return: [0xAF] + - cond: [b] + return: [0xA8] + - cond: [c] + return: [0xA9] + - cond: [d] + return: [0xAA] + - cond: [e] + return: [0xAB] + - cond: [h|ih] + return: [0xAC] + - cond: [l|il] + return: [0xAD] + - type: [immediate] + cases: + - cond: [u8] + return: [0xEE, u8] + - type: [indirect_hl_or_indexed] + cases: + - cond: [_] + return: [0xAE] diff --git a/src/assembler/parse_util.c b/src/assembler/parse_util.c index 2aa448a..e5c4c02 100644 --- a/src/assembler/parse_util.c +++ b/src/assembler/parse_util.c @@ -57,29 +57,31 @@ static bool adjust_for_indirection(ASMArgParseInfo *ap_info) /* Calculate the mask field for an ASMArgImmediate based on its uval/sval. */ -static void calculate_immediate_mask(ASMArgImmediate *imm) +static ASMArgImmType calculate_immediate_mask(uint32_t uval, bool negative) { - imm->mask = 0; - if (imm->sval < 0) { - if (imm->sval >= INT8_MIN) - imm->mask |= IMM_S8; - if (imm->sval >= INT8_MIN + 2) - imm->mask |= IMM_REL; + ASMArgImmType mask = 0; + if (negative && uval != 0) { + int32_t sval = -uval; + if (sval >= INT8_MIN) + mask |= IMM_S8; + if (sval >= INT8_MIN + 2) + mask |= IMM_REL; } else { - imm->mask = IMM_U16; - if (imm->uval <= UINT8_MAX) - imm->mask |= IMM_U8; - if (imm->uval <= INT8_MAX) - imm->mask |= IMM_S8; - if (imm->uval <= INT8_MAX + 2) - imm->mask |= IMM_REL; - if (imm->uval <= 7) - imm->mask |= IMM_BIT; - if (!(imm->uval & ~0x38)) - imm->mask |= IMM_RST; - if (imm->uval <= 2) - imm->mask |= IMM_IM; + mask = IMM_U16; + if (uval <= UINT8_MAX) + mask |= IMM_U8; + if (uval <= INT8_MAX) + mask |= IMM_S8; + if (uval <= INT8_MAX + 2) + mask |= IMM_REL; + if (uval <= 7) + mask |= IMM_BIT; + if (!(uval & ~0x38)) + mask |= IMM_RST; + if (uval <= 2) + mask |= IMM_IM; } + return mask; } /* @@ -300,7 +302,7 @@ bool argparse_condition(ASMArgCondition *result, ASMArgParseInfo ai) switch (ai.size) { case 1: switch (buf[0]) { - case 'n': return (*result = COND_N), true; + case 'z': return (*result = COND_Z), true; case 'c': return (*result = COND_C), true; case 'p': return (*result = COND_P), true; case 'm': return (*result = COND_M), true; @@ -319,6 +321,26 @@ bool argparse_condition(ASMArgCondition *result, ASMArgParseInfo ai) } /* + Read in a label immediate argument and store it in *result. +*/ +static bool argparse_imm_label(ASMArgImmediate *result, ASMArgParseInfo ai) +{ + if (ai.size >= MAX_SYMBOL_SIZE) + return false; + + for (const char *i = ai.arg; i < ai.arg + ai.size; i++) { + if (!is_valid_symbol_char(*i, i == ai.arg)) + return false; + } + + result->mask = IMM_U16; + result->is_label = true; + strncpy(result->label, ai.arg, ai.size); + result->label[ai.size] = '\0'; + return true; +} + +/* Read in an immediate argument and store it in *result. */ bool argparse_immediate(ASMArgImmediate *result, ASMArgParseInfo ai) @@ -326,10 +348,11 @@ bool argparse_immediate(ASMArgImmediate *result, ASMArgParseInfo ai) if (ai.size <= 0) return false; - bool negative = false; + bool negative = false, modifiers = false; ssize_t i = 0; while (ai.arg[i] == '-' || ai.arg[i] == '+' || ai.arg[i] == ' ') { + modifiers = true; if (ai.arg[i] == '-') negative = !negative; if (++i >= ai.size) @@ -341,9 +364,10 @@ bool argparse_immediate(ASMArgImmediate *result, ASMArgParseInfo ai) const ASMDefine *define = asm_deftable_find(ai.deftable, ai.arg, ai.size); if (define) { if (negative) { + result->is_label = false; result->uval = define->value.uval; result->sval = -define->value.sval; - calculate_immediate_mask(result); + result->mask = calculate_immediate_mask(result->uval, true); } else { *result = define->value; } @@ -351,16 +375,23 @@ bool argparse_immediate(ASMArgImmediate *result, ASMArgParseInfo ai) } uint32_t uval; - if (!parse_uint32_t(&uval, ai.arg, ai.size) || uval > UINT16_MAX) + if (!parse_uint32_t(&uval, ai.arg, ai.size)) { + if (!modifiers && argparse_imm_label(result, ai)) + return true; + return false; + } + + if (uval > UINT16_MAX) return false; int32_t sval = negative ? -uval : uval; if (sval < INT16_MIN) return false; + result->is_label = false; result->uval = uval; result->sval = sval; - calculate_immediate_mask(result); + result->mask = calculate_immediate_mask(uval, negative); return true; } @@ -374,9 +405,9 @@ bool argparse_indirect(ASMArgIndirect *result, ASMArgParseInfo ai) ASMArgRegister reg; ASMArgImmediate imm; - ASMArgLabel label; if (argparse_register(®, ai)) { - if (reg == REG_BC || reg == REG_DE || reg == REG_HL) { + if (reg == REG_BC || reg == REG_DE || reg == REG_HL || + reg == REG_IX || reg == REG_IY) { result->type = AT_REGISTER; result->addr.reg = reg; return true; @@ -387,10 +418,6 @@ bool argparse_indirect(ASMArgIndirect *result, ASMArgParseInfo ai) result->addr.imm = imm; return true; } - } else if (argparse_label(&label, ai)) { - result->type = AT_LABEL; - result->addr.label = label; - return true; } return false; } @@ -433,24 +460,29 @@ bool argparse_indexed(ASMArgIndexed *result, ASMArgParseInfo ai) } /* - Read in a label argument and store it in *result. + Read in a port argument and store it in *result. */ -bool argparse_label(ASMArgLabel *result, ASMArgParseInfo ai) +bool argparse_port(ASMArgPort *result, ASMArgParseInfo ai) { - if (ai.size <= 0 || ai.size >= MAX_SYMBOL_SIZE) + if (ai.size < 3 || !adjust_for_indirection(&ai)) return false; - for (const char *i = ai.arg; i < ai.arg + ai.size; i++) { - if (!is_valid_symbol_char(*i, i == ai.arg)) - return false; + ASMArgRegister reg; + ASMArgImmediate imm; + if (argparse_register(®, ai)) { + if (reg == REG_C) { + result->type = AT_REGISTER; + result->port.reg = reg; + return true; + } + } else if (argparse_immediate(&imm, ai)) { + if (imm.mask & IMM_U8) { + result->type = AT_IMMEDIATE; + result->port.imm = imm; + return true; + } } - - if (asm_deftable_find(ai.deftable, ai.arg, ai.size)) - return false; - - strncpy(result->text, ai.arg, ai.size); - result->text[ai.size] = '\0'; - return true; + return false; } /* diff --git a/src/assembler/parse_util.h b/src/assembler/parse_util.h index ab2003c..8d5c199 100644 --- a/src/assembler/parse_util.h +++ b/src/assembler/parse_util.h @@ -33,7 +33,7 @@ bool argparse_condition(ASMArgCondition*, ASMArgParseInfo); bool argparse_immediate(ASMArgImmediate*, ASMArgParseInfo); bool argparse_indirect(ASMArgIndirect*, ASMArgParseInfo); bool argparse_indexed(ASMArgIndexed*, ASMArgParseInfo); -bool argparse_label(ASMArgLabel*, ASMArgParseInfo); +bool argparse_port(ASMArgPort*, ASMArgParseInfo); /* Preprocessor directive parsers */ bool dparse_bool(bool*, const ASMLine*, const char*); diff --git a/src/assembler/tokenizer.c b/src/assembler/tokenizer.c index beb9808..c55b51e 100644 --- a/src/assembler/tokenizer.c +++ b/src/assembler/tokenizer.c @@ -155,7 +155,7 @@ static ErrorInfo* handle_define_directive( ASMArgImmediate imm; ASMArgParseInfo info = { .arg = line->data + i, .size = line->length - i, .deftable = deftab}; - if (!argparse_immediate(&imm, info)) + if (!argparse_immediate(&imm, info) || imm.is_label) return error_info_create(line, ET_PREPROC, ED_PP_BAD_ARG); ASMDefine *define = cr_malloc(sizeof(ASMDefine));