From ade92aea515dfce3fe29daed33da05ce010263e5 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Fri, 15 May 2015 17:25:29 -0400 Subject: [PATCH 01/25] Starting work on new ASM instructions system. --- makefile | 3 + scripts/update_asm_instructions.py | 89 ++++ src/assembler/errors.c | 7 +- src/assembler/errors.h | 7 +- src/assembler/inst_args.h | 31 +- src/assembler/inst_support.c | 98 ---- src/assembler/inst_support.h | 155 ------- src/assembler/instructions.c | 895 +++++++------------------------------ src/assembler/instructions.inc.c | 733 ++++++++++++++++++++++++++++++ src/assembler/instructions.yml | 323 +++++++++++++ src/assembler/parse_util.c | 76 +++- src/assembler/parse_util.h | 2 +- src/assembler/tokenizer.c | 2 +- 13 files changed, 1384 insertions(+), 1037 deletions(-) create mode 100755 scripts/update_asm_instructions.py delete mode 100644 src/assembler/inst_support.c delete mode 100644 src/assembler/inst_support.h create mode 100644 src/assembler/instructions.inc.c create mode 100644 src/assembler/instructions.yml diff --git a/makefile b/makefile index 57346bc..35bf657 100644 --- a/makefile +++ b/makefile @@ -47,6 +47,9 @@ $(BUILD)/$(MODE)/%.o: %.c -include $(DEPS) +$(SOURCES)/assembler/instructions.inc.c: $(SOURCES)/assembler/instructions.yml + python scripts/update_asm_instructions.py + 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..d2c5afa --- /dev/null +++ b/scripts/update_asm_instructions.py @@ -0,0 +1,89 @@ +#!/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 + +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) + +def build_inst(name, data): + """ + Convert data for an individual instruction into a C parse function. + """ + # TODO + return "INST_FUNC({0})\n{{\n}}".format(name) + +def build_inst_block(data): + """ + Return the instruction parser block, given instruction data. + """ + return "\n\n".join(build_inst(k, v) 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)) + print(result) # TODO: remove me! + +if __name__ == "__main__": + main() diff --git a/src/assembler/errors.c b/src/assembler/errors.c index 4a30f10..bc2094c 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] = "ED_PS_ARG_TYPE", // TODO + [ED_PS_ARG_VALUE] = "ED_PS_ARG_VALUE" // TODO }; /* 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..910f11c 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; @@ -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..4b6740e 100644 --- a/src/assembler/instructions.c +++ b/src/assembler/instructions.c @@ -1,705 +1,198 @@ /* 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) -} +#include +#include -INST_FUNC(call) -{ - // 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(ccf) -{ - INST_TAKES_NO_ARGS - INST_RETURN(1, 0x3F) -} +/* Helper macros for get_inst_parser() and lookup_parser() */ -INST_FUNC(cp) -{ - // 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(cpd) -{ - INST_TAKES_NO_ARGS - INST_RETURN(2, 0xED, 0xA9) -} +#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(cpdr) -{ - INST_TAKES_NO_ARGS - INST_RETURN(2, 0xED, 0xB9) -} +#define MAKE_CMP_(s) DISPATCH_(s, sizeof(s) / sizeof(char) - 1) -INST_FUNC(cpi) -{ - INST_TAKES_NO_ARGS - INST_RETURN(2, 0xED, 0xA1) -} +#define HANDLE(m) if (key == MAKE_CMP_(#m)) return parse_inst_##m; -INST_FUNC(cpir) -{ - INST_TAKES_NO_ARGS - INST_RETURN(2, 0xED, 0xB1) -} +/* Helper macro for parse_arg() */ -INST_FUNC(cpl) -{ - INST_TAKES_NO_ARGS - INST_RETURN(1, 0x2F) -} +#define TRY_PARSER(func, argtype, field) \ + if (argparse_##func(&arg->data.field, info)) { \ + arg->type = argtype; \ + return ED_NONE; \ + } -INST_FUNC(daa) -{ - INST_TAKES_NO_ARGS - INST_RETURN(1, 0x27) -} +/* Internal helper macros */ -INST_FUNC(dec) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} +#define INST_ALLOC_(len) \ + *length = len; \ + *bytes = cr_malloc(sizeof(uint8_t) * (len)); -INST_FUNC(di) -{ - INST_TAKES_NO_ARGS - INST_RETURN(1, 0xF3) -} +#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) -INST_FUNC(djnz) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} +#define INST_DISPATCH_(a, b, c, d, target, ...) target -INST_FUNC(ei) -{ - INST_TAKES_NO_ARGS - INST_RETURN(1, 0xFB) -} +#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__)); -INST_FUNC(ex) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} +#define INST_IX_PREFIX 0xDD +#define INST_IY_PREFIX 0xFD -INST_FUNC(exx) -{ - INST_TAKES_NO_ARGS - INST_RETURN(1, 0xD9) -} +#define INST_PREFIX_(reg) \ + (((reg) == REG_IX || (reg) == REG_IXH || (reg) == REG_IXL) ? \ + INST_IX_PREFIX : INST_IY_PREFIX) -INST_FUNC(halt) -{ - INST_TAKES_NO_ARGS - INST_RETURN(1, 0x76) -} - -INST_FUNC(im) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(in) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -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 INST_RETURN_WITH_SYMBOL_(len, label, ...) { \ // TODO + *symbol = cr_strdup(label.text); \ + INST_ALLOC_(len) \ + INST_FILL_BYTES_(len - 2, __VA_ARGS__) \ + 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) +/* 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) \ + if (!ap_info.arg) \ + INST_ERROR(TOO_FEW_ARGS) \ + ASMInstArg args[3]; \ + size_t nargs = 0; \ + ASMArgType masks = {a0, a1, a2}; \ + ASMErrorDesc err = parse_args(args, &nargs, ap_info, masks); \ + if (err) \ + return err; \ + +#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_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) -} +#define INST_INDEX_PREFIX(n) INST_PREFIX_(INST_INDEX(n).reg) -INST_FUNC(rlc) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} +#define INST_INDIRECT_IMM(n) \ // TODO + INST_INDIRECT(n).addr.imm.uval >> 8, \ + INST_INDIRECT(n).addr.imm.uval & 0xFF -INST_FUNC(rlca) -{ - INST_TAKES_NO_ARGS - INST_RETURN(1, 0x07) -} +/* ----------------------------- END WORK BLOCK ---------------------------- */ -INST_FUNC(rld) -{ - INST_TAKES_NO_ARGS - INST_RETURN(2, 0xED, 0x6F) -} - -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) -} - -INST_FUNC(set) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} +/* + Fill an instruction's byte array with the given data. -INST_FUNC(sl1) -{ - // 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(sla) + 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(sll) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} +/* + Parse a single instruction argument into an ASMInstArg object. -INST_FUNC(sls) + 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) { - // 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(indirect, AT_INDIRECT, indirect) + TRY_PARSER(indexed, AT_INDEXED, index) + TRY_PARSER(immediate, AT_IMMEDIATE, imm) + return ED_PS_ARG_SYNTAX; } -INST_FUNC(sra) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} +/* + Parse an argument string into ASMInstArg objects. -INST_FUNC(srl) -{ - // 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]) // TODO +{ + 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; + } + } -INST_FUNC(sub) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) + if (i > start) { + if ((err = parse_arg(&args[*nargs], str + start, i - start, dt))) + return err; + (*nargs)++; + } + 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 +203,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..34d8b69 --- /dev/null +++ b/src/assembler/instructions.inc.c @@ -0,0 +1,733 @@ +/* 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 Sun May 10 21:02:28 2015 +*/ + +/* @AUTOGEN_INST_BLOCK_START */ + +INST_FUNC(adc) +{ + INST_TAKES_ARGS( + AT_REGISTER, + AT_REGISTER|AT_IMMEDIATE|AT_INDEXED|AT_INDIRECT, + 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_H) + INST_RETURN(1, 0x8C) + if (INST_REG(0) == REG_A && INST_REG(1) == REG_IXH) + INST_RETURN(2, INST_IX_PREFIX, 0x8C) + // + 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_INDEXED) { + if (INST_REG(0) == REG_A) + INST_RETURN(3, INST_INDEX_PREFIX(1), 0x8E, INST_INDEX(1).offset) + 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) + } + INST_ERROR(ARG_TYPE) +} + +INST_FUNC(add) +{ + INST_TAKES_NO_ARGS + INST_ERROR(ARG_SYNTAX) + INST_RETURN(1, 0xFF) + + // INST_TAKES_ARGS(2, 2) + // INST_FORCE_TYPE(0, AT_REGISTER) + // switch (INST_REG(0)) { + // case REG_A: + // switch (INST_TYPE(1)) { + // INST_CASE_REGS(1, INST_CASE_ALL_8_BIT_REGS(0x80)) + // INST_CASE_IMM_U8(1, 2, 0xC6) + // INST_CASE_INDIRECT_HL_IX_IY(1, 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) // TODO: wrong prefix + // 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) +} + +INST_FUNC(djnz) +{ + // TODO + INST_TAKES_NO_ARGS + INST_ERROR(ARG_SYNTAX) + INST_RETURN(1, 0xFF) +} + +INST_FUNC(ei) +{ + INST_TAKES_NO_ARGS + INST_RETURN(1, 0xFB) +} + +INST_FUNC(ex) +{ + // TODO + INST_TAKES_NO_ARGS + INST_ERROR(ARG_SYNTAX) + INST_RETURN(1, 0xFF) +} + +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) +{ + // TODO + INST_TAKES_NO_ARGS + INST_ERROR(ARG_SYNTAX) + INST_RETURN(1, 0xFF) +} + +INST_FUNC(in) +{ + // TODO + INST_TAKES_NO_ARGS + INST_ERROR(ARG_SYNTAX) + INST_RETURN(1, 0xFF) +} + +INST_FUNC(inc) +{ + INST_TAKES_NO_ARGS + INST_ERROR(ARG_SYNTAX) + INST_RETURN(1, 0xFF) + + // 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) + // } + // INST_CASE_INDIRECT_HL_IX_IY(0, 1, 0x34) + // default: + // INST_ERROR(ARG0_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) +{ + // 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) +{ + INST_TAKES_NO_ARGS + INST_ERROR(ARG_SYNTAX) + INST_RETURN(1, 0xFF) + + // 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_CASE_ALL_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) + // } + // INST_CASE_IMM_U8(1, 2, 0x3E) + // 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: + // switch (INST_TYPE(1)) { + // INST_CASE_REGS(1, INST_CASE_ALL_8_BIT_REGS(0x40)) + // INST_CASE_IMM_U8(1, 2, 0x06) + // INST_CASE_INDIRECT_HL_IX_IY(1, 1, 0x46) + // default: INST_ERROR(ARG1_TYPE) + // } + // case REG_C: + // switch (INST_TYPE(1)) { + // INST_CASE_REGS(1, INST_CASE_ALL_8_BIT_REGS(0x48)) + // INST_CASE_IMM_U8(1, 2, 0x0E) + // INST_CASE_INDIRECT_HL_IX_IY(1, 1, 0x4E) + // default: INST_ERROR(ARG1_TYPE) + // } + // case REG_D: + // switch (INST_TYPE(1)) { + // INST_CASE_REGS(1, INST_CASE_ALL_8_BIT_REGS(0x50)) + // INST_CASE_IMM_U8(1, 2, 0x16) + // INST_CASE_INDIRECT_HL_IX_IY(1, 1, 0x56) + // default: INST_ERROR(ARG1_TYPE) + // } + // case REG_E: + // switch (INST_TYPE(1)) { + // INST_CASE_REGS(1, INST_CASE_ALL_8_BIT_REGS(0x58)) + // INST_CASE_IMM_U8(1, 2, 0x1E) + // INST_CASE_INDIRECT_HL_IX_IY(1, 1, 0x5E) + // default: INST_ERROR(ARG1_TYPE) + // } + // case REG_H: + // switch (INST_TYPE(1)) { + // INST_CASE_REGS(1, INST_CASE_MAIN_8_BIT_REGS(0x60)) + // INST_CASE_IMM_U8(1, 2, 0x26) + // INST_CASE_INDIRECT_HL_IX_IY(1, 1, 0x66) + // default: INST_ERROR(ARG1_TYPE) + // } + // case REG_L: + // switch (INST_TYPE(1)) { + // INST_CASE_REGS(1, INST_CASE_MAIN_8_BIT_REGS(0x68)) + // INST_CASE_IMM_U8(1, 2, 0x2E) + // INST_CASE_INDIRECT_HL_IX_IY(1, 1, 0x6E) + // default: INST_ERROR(ARG1_TYPE) + // } + // 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) + // } +} + +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) +{ + // 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) +} + +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) +{ + // 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) +} + +INST_FUNC(set) +{ + // TODO + INST_TAKES_NO_ARGS + INST_ERROR(ARG_SYNTAX) + INST_RETURN(1, 0xFF) +} + +INST_FUNC(sl1) +{ + // TODO + INST_TAKES_NO_ARGS + INST_ERROR(ARG_SYNTAX) + INST_RETURN(1, 0xFF) +} + +INST_FUNC(sla) +{ + // TODO + INST_TAKES_NO_ARGS + INST_ERROR(ARG_SYNTAX) + INST_RETURN(1, 0xFF) +} + +INST_FUNC(sll) +{ + // TODO + INST_TAKES_NO_ARGS + INST_ERROR(ARG_SYNTAX) + INST_RETURN(1, 0xFF) +} + +INST_FUNC(sls) +{ + // TODO + INST_TAKES_NO_ARGS + INST_ERROR(ARG_SYNTAX) + INST_RETURN(1, 0xFF) +} + +INST_FUNC(sra) +{ + // TODO + INST_TAKES_NO_ARGS + INST_ERROR(ARG_SYNTAX) + INST_RETURN(1, 0xFF) +} + +INST_FUNC(srl) +{ + // TODO + INST_TAKES_NO_ARGS + INST_ERROR(ARG_SYNTAX) + INST_RETURN(1, 0xFF) +} + +INST_FUNC(sub) +{ + // TODO + INST_TAKES_NO_ARGS + INST_ERROR(ARG_SYNTAX) + INST_RETURN(1, 0xFF) +} + +INST_FUNC(xor) +{ + // TODO + INST_TAKES_NO_ARGS + INST_ERROR(ARG_SYNTAX) + INST_RETURN(1, 0xFF) +} + +/* @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) +/* @AUTOGEN_LOOKUP_BLOCK_END */ + return NULL; +} diff --git a/src/assembler/instructions.yml b/src/assembler/instructions.yml new file mode 100644 index 0000000..0dd31d0 --- /dev/null +++ b/src/assembler/instructions.yml @@ -0,0 +1,323 @@ +# 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, indexed] + cases: + - cond: [a, _] + return: [0x8E] + +add: + args: no + return: error + +and: + args: no + return: error + +bit: + args: no + return: error + +call: + args: no + return: error + +ccf: + args: no + return: error + +cp: + args: no + return: error + +cpd: + args: no + return: error + +cpdr: + args: no + return: error + +cpi: + args: no + return: error + +cpir: + args: no + return: error + +cpl: + args: no + return: error + +daa: + args: no + return: error + +dec: + args: no + return: error + +di: + args: no + return: error + +djnz: + args: no + return: error + +ei: + args: no + return: error + +ex: + args: no + return: error + +exx: + args: no + return: error + +halt: + args: no + return: error + +im: + args: no + return: error + +in: + args: no + return: error + +inc: + args: no + return: error + +ind: + args: no + return: error + +indr: + args: no + return: error + +ini: + args: no + return: [0xED, 0xA2] + +inir: + args: no + return: error + +jp: + args: no + return: error + +jr: + args: no + return: error + +ld: + args: no + return: error + +ldd: + args: no + return: error + +lddr: + args: no + return: error + +ldi: + args: no + return: error + +ldir: + args: no + return: error + +neg: + args: no + return: error + +nop: + args: no + return: error + +or: + args: no + return: error + +otdr: + args: no + return: error + +otir: + args: no + return: error + +out: + args: no + return: error + +outd: + args: no + return: error + +outi: + args: no + return: error + +pop: + args: no + return: error + +push: + args: no + return: error + +res: + args: no + return: error + +ret: + args: no + return: error + +reti: + args: no + return: error + +retn: + args: no + return: error + +rl: + args: no + return: error + +rla: + args: no + return: error + +rlc: + args: no + return: error + +rlca: + args: no + return: error + +rld: + args: no + return: error + +rr: + args: no + return: error + +rra: + args: no + return: error + +rrc: + args: no + return: error + +rrca: + args: no + return: error + +rrd: + args: no + return: error + +rst: + args: no + return: error + +sbc: + args: no + return: error + +scf: + args: no + return: error + +set: + args: no + return: error + +sl1: + args: no + return: error + +sla: + args: no + return: error + +sll: + args: no + return: error + +sls: + args: no + return: error + +sra: + args: no + return: error + +srl: + args: no + return: error + +sub: + args: no + return: error + +xor: + args: no + return: error diff --git a/src/assembler/parse_util.c b/src/assembler/parse_util.c index 2aa448a..9d5ff5a 100644 --- a/src/assembler/parse_util.c +++ b/src/assembler/parse_util.c @@ -319,6 +319,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 +346,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 +362,10 @@ bool argparse_immediate(ASMArgImmediate *result, ASMArgParseInfo ai) const ASMDefine *define = asm_deftable_find(ai.deftable, ai.arg, ai.size); if (define) { if (negative) { + calculate_immediate_mask(result); + result->is_label = false; result->uval = define->value.uval; result->sval = -define->value.sval; - calculate_immediate_mask(result); } else { *result = define->value; } @@ -351,16 +373,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; + calculate_immediate_mask(result); + result->is_label = false; result->uval = uval; result->sval = sval; - calculate_immediate_mask(result); return true; } @@ -374,9 +403,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 +416,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 +458,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*, ASMArgParseInfo) { - 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->addr.reg = reg; + return true; + } + } else if (argparse_immediate(&imm, ai)) { + if (imm.mask & IMM_U8) { + result->type = AT_IMMEDIATE; + result->addr.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..896f822 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)); From 0548e5d18cc43a3d259ca9e58dec10fa0745cc6b Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Sat, 16 May 2015 16:57:38 -0400 Subject: [PATCH 02/25] More work on update_asm_instructions.py --- scripts/update_asm_instructions.py | 84 +++++++++++++++++++++++++++++++++++--- 1 file changed, 79 insertions(+), 5 deletions(-) diff --git a/scripts/update_asm_instructions.py b/scripts/update_asm_instructions.py index d2c5afa..6625b89 100755 --- a/scripts/update_asm_instructions.py +++ b/scripts/update_asm_instructions.py @@ -36,18 +36,92 @@ re_lookup = re.compile( r"(/\* @AUTOGEN_LOOKUP_BLOCK_START \*/\n*)(.*?)" r"(\n*/\* @AUTOGEN_LOOKUP_BLOCK_END \*/)", re.S) -def build_inst(name, data): +class Instruction(object): """ - Convert data for an individual instruction into a C parse function. + Represent a single ASM instruction mnemonic. """ - # TODO - return "INST_FUNC({0})\n{{\n}}".format(name) + ARG_TYPES = { + "register": "AT_REGISTER", + "immediate": "AT_IMMEDIATE", + "indirect": "AT_INDIRECT", + "indexed": "AT_INDEXED|AT_INDIRECT", + "condition": "AT_CONDITION", + "port": "AT_PORT" + } + + def __init__(self, name, data): + self._name = name + self._data = data + + 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"]): + types.add(self.ARG_TYPES[case["type"][num]]) + else: + optional = True + + if not types: + return "AT_NONE" + if optional: + types.add("AT_OPTIONAL") + return "|".join(types) + + def _handle_return(self, arg, indent=1): + """ + Return code to handle an instruction return statement. + """ + tabs = TAB * indent + if arg == "error": + return tabs + "INST_ERROR(ARG_SYNTAX)" + else: + data = ", ".join("0x%02X" % byte for byte in arg) + return tabs + "INST_RETURN({0}, {1})".format(len(arg), data) + + def _handle_case(self, case): + """ + TODO + """ + return [TAB + "// " + str(case)] + + 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(build_inst(k, v) for k, v in sorted(data.items())) + return "\n\n".join( + Instruction(k, v).render() for k, v in sorted(data.items())) def build_lookup_block(data): """ From 5f71035468f1f7d20e2a28c4751a5327ab8b6462 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Sat, 16 May 2015 19:17:25 -0400 Subject: [PATCH 03/25] More work on asm instructions. --- makefile | 6 +- scripts/update_asm_instructions.py | 130 +++++++++++- src/assembler/instructions.c | 1 + src/assembler/instructions.yml | 408 ++++++++++++++++++------------------- 4 files changed, 328 insertions(+), 217 deletions(-) diff --git a/makefile b/makefile index 35bf657..b6763ab 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) @@ -47,8 +48,9 @@ $(BUILD)/$(MODE)/%.o: %.c -include $(DEPS) -$(SOURCES)/assembler/instructions.inc.c: $(SOURCES)/assembler/instructions.yml - python scripts/update_asm_instructions.py +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 diff --git a/scripts/update_asm_instructions.py b/scripts/update_asm_instructions.py index 6625b89..762c8bc 100755 --- a/scripts/update_asm_instructions.py +++ b/scripts/update_asm_instructions.py @@ -12,6 +12,7 @@ when the latter is modified, but can also be run manually. from __future__ import print_function +from itertools import product import re import time @@ -44,10 +45,13 @@ class Instruction(object): "register": "AT_REGISTER", "immediate": "AT_IMMEDIATE", "indirect": "AT_INDIRECT", - "indexed": "AT_INDEXED|AT_INDIRECT", + "indexed": "AT_INDEXED", "condition": "AT_CONDITION", "port": "AT_PORT" } + ARG_EXTRA = { + "indexed": ["AT_INDIRECT"] + } def __init__(self, name, data): self._name = name @@ -61,7 +65,10 @@ class Instruction(object): optional = False for case in self._data["cases"]: if num < len(case["type"]): - types.add(self.ARG_TYPES[case["type"][num]]) + atype = case["type"][num] + types.add(self.ARG_TYPES[atype]) + if atype in self.ARG_EXTRA: + types.update(self.ARG_EXTRA[atype]) else: optional = True @@ -71,22 +78,123 @@ class Instruction(object): types.add("AT_OPTIONAL") return "|".join(types) - def _handle_return(self, arg, indent=1): + def _handle_return(self, ret, indent=1): """ Return code to handle an instruction return statement. """ - tabs = TAB * indent - if arg == "error": - return tabs + "INST_ERROR(ARG_SYNTAX)" - else: - data = ", ".join("0x%02X" % byte for byte in arg) - return tabs + "INST_RETURN({0}, {1})".format(len(arg), data) + 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)] + return "INST_NARGS == {0} && {1}".format(len(args), " && ".join(conds)) + + 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. + """ + 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. + """ + # TODO + return cond + + def _build_indexed_check(self, num, cond): + """ + Return an expression to check for a particular indexed value. + """ + # TODO + return cond + + 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. + """ + # TODO + return 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. + """ + return " && ".join(self._SUBCASE_LOOKUP_TABLE[types[i]](self, i, cond) + for i, cond in enumerate(conds) if cond != "_") + + def _iter_permutations(self, types, conds): + """ + Iterate over all permutations of the given subcase conditions. + """ + def split(typ, cond): + if "|" in cond: + sets = [split(typ, c) for c in cond.split("|")] + return {choice for s in sets for choice in s} + if typ == "register" and cond == "ih": + return {"ixh", "iyh"} + if typ == "register" and cond == "il": + return {"ixl", "iyl"} + return {cond} + + return product(*(split(types[i], cond) + for i, cond in enumerate(conds))) + + def _adapt_return(self, types, conds, ret): + """ + Return a modified byte list to accomodate for prefixes and immediates. + """ + for i, cond in enumerate(conds): + if types[i] == "register" and cond.startswith("ix"): + ret = ["INST_IX_PREFIX"] + ret + elif types[i] == "register" and cond.startswith("iy"): + ret = ["INST_IY_PREFIX"] + ret + return ret def _handle_case(self, case): """ - TODO + Return code to handle an instruction case. """ - return [TAB + "// " + str(case)] + lines = [] + cond = self._build_case_type_check(case["type"]) + lines.append(TAB + "if ({0}) {{".format(cond)) + + for subcase in case["cases"]: + for perm in self._iter_permutations(case["type"], subcase["cond"]): + cond = self._build_subcase_check(case["type"], perm) + ret = self._adapt_return(case["type"], perm, subcase["return"]) + lines.append(TAB * 2 + "if ({0})".format(cond)) + lines.append(self._handle_return(ret, 3)) + + lines.append(TAB * 2 + "INST_ERROR(ARG_VALUE)") + lines.append(TAB + "}") + return lines def render(self): """ diff --git a/src/assembler/instructions.c b/src/assembler/instructions.c index 4b6740e..121ecce 100644 --- a/src/assembler/instructions.c +++ b/src/assembler/instructions.c @@ -84,6 +84,7 @@ static ASMErrorDesc parse_inst_##mnemonic( \ 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 diff --git a/src/assembler/instructions.yml b/src/assembler/instructions.yml index 0dd31d0..d596130 100644 --- a/src/assembler/instructions.yml +++ b/src/assembler/instructions.yml @@ -46,278 +46,278 @@ adc: - cond: [a, _] return: [0x8E] -add: - args: no - return: error +# add: +# args: no +# return: error -and: - args: no - return: error +# and: +# args: no +# return: error -bit: - args: no - return: error +# bit: +# args: no +# return: error -call: - args: no - return: error +# call: +# args: no +# return: error -ccf: - args: no - return: error +# ccf: +# args: no +# return: error -cp: - args: no - return: error +# cp: +# args: no +# return: error -cpd: - args: no - return: error +# cpd: +# args: no +# return: error -cpdr: - args: no - return: error +# cpdr: +# args: no +# return: error -cpi: - args: no - return: error +# cpi: +# args: no +# return: error -cpir: - args: no - return: error +# cpir: +# args: no +# return: error -cpl: - args: no - return: error +# cpl: +# args: no +# return: error -daa: - args: no - return: error +# daa: +# args: no +# return: error -dec: - args: no - return: error +# dec: +# args: no +# return: error -di: - args: no - return: error +# di: +# args: no +# return: error -djnz: - args: no - return: error +# djnz: +# args: no +# return: error -ei: - args: no - return: error +# ei: +# args: no +# return: error -ex: - args: no - return: error +# ex: +# args: no +# return: error -exx: - args: no - return: error +# exx: +# args: no +# return: error -halt: - args: no - return: error +# halt: +# args: no +# return: error -im: - args: no - return: error +# im: +# args: no +# return: error -in: - args: no - return: error +# in: +# args: no +# return: error -inc: - args: no - return: error +# inc: +# args: no +# return: error -ind: - args: no - return: error +# ind: +# args: no +# return: error -indr: - args: no - return: error +# indr: +# args: no +# return: error ini: args: no return: [0xED, 0xA2] -inir: - args: no - return: error +# inir: +# args: no +# return: error -jp: - args: no - return: error +# jp: +# args: no +# return: error -jr: - args: no - return: error +# jr: +# args: no +# return: error -ld: - args: no - return: error +# ld: +# args: no +# return: error -ldd: - args: no - return: error +# ldd: +# args: no +# return: error -lddr: - args: no - return: error +# lddr: +# args: no +# return: error -ldi: - args: no - return: error +# ldi: +# args: no +# return: error -ldir: - args: no - return: error +# ldir: +# args: no +# return: error -neg: - args: no - return: error +# neg: +# args: no +# return: error -nop: - args: no - return: error +# nop: +# args: no +# return: error -or: - args: no - return: error +# or: +# args: no +# return: error -otdr: - args: no - return: error +# otdr: +# args: no +# return: error -otir: - args: no - return: error +# otir: +# args: no +# return: error -out: - args: no - return: error +# out: +# args: no +# return: error -outd: - args: no - return: error +# outd: +# args: no +# return: error -outi: - args: no - return: error +# outi: +# args: no +# return: error -pop: - args: no - return: error +# pop: +# args: no +# return: error -push: - args: no - return: error +# push: +# args: no +# return: error -res: - args: no - return: error +# res: +# args: no +# return: error -ret: - args: no - return: error +# ret: +# args: no +# return: error -reti: - args: no - return: error +# reti: +# args: no +# return: error -retn: - args: no - return: error +# retn: +# args: no +# return: error -rl: - args: no - return: error +# rl: +# args: no +# return: error -rla: - args: no - return: error +# rla: +# args: no +# return: error -rlc: - args: no - return: error +# rlc: +# args: no +# return: error -rlca: - args: no - return: error +# rlca: +# args: no +# return: error -rld: - args: no - return: error +# rld: +# args: no +# return: error -rr: - args: no - return: error +# rr: +# args: no +# return: error -rra: - args: no - return: error +# rra: +# args: no +# return: error -rrc: - args: no - return: error +# rrc: +# args: no +# return: error -rrca: - args: no - return: error +# rrca: +# args: no +# return: error -rrd: - args: no - return: error +# rrd: +# args: no +# return: error -rst: - args: no - return: error +# rst: +# args: no +# return: error -sbc: - args: no - return: error +# sbc: +# args: no +# return: error -scf: - args: no - return: error +# scf: +# args: no +# return: error -set: - args: no - return: error +# set: +# args: no +# return: error -sl1: - args: no - return: error +# sl1: +# args: no +# return: error -sla: - args: no - return: error +# sla: +# args: no +# return: error -sll: - args: no - return: error +# sll: +# args: no +# return: error -sls: - args: no - return: error +# sls: +# args: no +# return: error -sra: - args: no - return: error +# sra: +# args: no +# return: error -srl: - args: no - return: error +# srl: +# args: no +# return: error -sub: - args: no - return: error +# sub: +# args: no +# return: error -xor: - args: no - return: error +# xor: +# args: no +# return: error From e987653c3b2e353664510c77ef996fe4528dac1b Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Sat, 16 May 2015 23:07:43 -0400 Subject: [PATCH 04/25] Add more features to update_asm_instructions.py. --- scripts/update_asm_instructions.py | 76 ++++++++++++++++++++++++++++++++------ src/assembler/instructions.c | 6 +-- src/assembler/instructions.yml | 2 +- 3 files changed, 69 insertions(+), 15 deletions(-) diff --git a/scripts/update_asm_instructions.py b/scripts/update_asm_instructions.py index 762c8bc..cd190a4 100755 --- a/scripts/update_asm_instructions.py +++ b/scripts/update_asm_instructions.py @@ -49,8 +49,8 @@ class Instruction(object): "condition": "AT_CONDITION", "port": "AT_PORT" } - ARG_EXTRA = { - "indexed": ["AT_INDIRECT"] + PSEUDO_TYPES = { + "indirect_hl_or_indexed": ["AT_INDIRECT", "AT_INDEXED"] } def __init__(self, name, data): @@ -66,9 +66,10 @@ class Instruction(object): for case in self._data["cases"]: if num < len(case["type"]): atype = case["type"][num] - types.add(self.ARG_TYPES[atype]) - if atype in self.ARG_EXTRA: - types.update(self.ARG_EXTRA[atype]) + if atype in self.ARG_TYPES: + types.add(self.ARG_TYPES[atype]) + else: + types.update(self.PSEUDO_TYPES[atype]) else: optional = True @@ -104,21 +105,29 @@ class Instruction(object): """ Return an expression to check for a particular immediate value. """ + # TODO: also allow direct value comparisons here 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) + # TODO - return cond + + 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. """ - # TODO - return cond + raise RuntimeError("The indexed arg type does not support conditions") def _build_condition_check(self, num, cond): """ @@ -131,7 +140,9 @@ class Instruction(object): Return an expression to check for a particular port value. """ # TODO - return cond + + err = "Unknown condition for port argument: {0}" + return RuntimeError(err.format(cond)) _SUBCASE_LOOKUP_TABLE = { "register": _build_register_check, @@ -170,17 +181,60 @@ class Instruction(object): """ 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": + imm = types.index("immediate") + ret[i] = "INST_IMM({0}).uval".format(imm) + else: + msg = "Unsupported return byte: {0}" + raise RuntimeError(msg.format(byte)) + for i, cond in enumerate(conds): if types[i] == "register" and cond.startswith("ix"): - ret = ["INST_IX_PREFIX"] + ret + ret.insert(0, "INST_IX_PREFIX") elif types[i] == "register" and cond.startswith("iy"): - ret = ["INST_IY_PREFIX"] + ret + ret.insert(0, "INST_IY_PREFIX") + elif types[i] == "indexed": + ret.insert(0, "INST_INDEX_PREFIX({0})".format(i)) + ret.append("INST_INDEX({0}).offset".format(i)) + return ret + 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" + for subcase in case["cases"]: + if subcase["cond"][index] != "_": + raise RuntimeError( + "indirect_hl_or_indexed pseudo-type requires a " + "wildcard (_) in all corresponding conditionals") + subcase["cond"][index] = "reg.hl" + + return self._handle_case(case) + indexed + + raise RuntimeError("Unknown pseudo-type: {0}".format(pseudo)) + def _handle_case(self, case): """ Return code to handle an instruction case. """ + for pseudo in self.PSEUDO_TYPES: + if pseudo in case["type"]: + return self._handle_pseudo_case(pseudo, case) + lines = [] cond = self._build_case_type_check(case["type"]) lines.append(TAB + "if ({0}) {{".format(cond)) diff --git a/src/assembler/instructions.c b/src/assembler/instructions.c index 121ecce..bfb9a7d 100644 --- a/src/assembler/instructions.c +++ b/src/assembler/instructions.c @@ -48,9 +48,6 @@ 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) @@ -100,6 +97,9 @@ static ASMErrorDesc parse_inst_##mnemonic( \ return ED_NONE; \ } +#define INST_IX_PREFIX 0xDD +#define INST_IY_PREFIX 0xFD + #define INST_INDEX_PREFIX(n) INST_PREFIX_(INST_INDEX(n).reg) #define INST_INDIRECT_IMM(n) \ // TODO diff --git a/src/assembler/instructions.yml b/src/assembler/instructions.yml index d596130..9d97303 100644 --- a/src/assembler/instructions.yml +++ b/src/assembler/instructions.yml @@ -41,7 +41,7 @@ adc: cases: - cond: [a, u8] return: [0xCE, u8] - - type: [register, indexed] + - type: [register, indirect_hl_or_indexed] cases: - cond: [a, _] return: [0x8E] From b8b90724162a5709db35c4afd4ef1d3235ac1f47 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Sat, 16 May 2015 23:28:20 -0400 Subject: [PATCH 05/25] Implement no-arg instructions and 'add'. --- scripts/update_asm_instructions.py | 14 ++- src/assembler/instructions.yml | 230 +++++++++++++++++++++---------------- 2 files changed, 140 insertions(+), 104 deletions(-) diff --git a/scripts/update_asm_instructions.py b/scripts/update_asm_instructions.py index cd190a4..4be7be2 100755 --- a/scripts/update_asm_instructions.py +++ b/scripts/update_asm_instructions.py @@ -118,7 +118,8 @@ class Instruction(object): num, cond[len("reg."):].upper()) return "({0} && {1})".format(test1, test2) - # TODO + 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)) @@ -168,10 +169,13 @@ class Instruction(object): if "|" in cond: sets = [split(typ, c) for c in cond.split("|")] return {choice for s in sets for choice in s} - if typ == "register" and cond == "ih": - return {"ixh", "iyh"} - if typ == "register" and cond == "il": - return {"ixl", "iyl"} + if typ == "register": + if cond == "i": + return {"ix", "iy"} + if cond == "ih": + return {"ixh", "iyh"} + if cond == "il": + return {"ixl", "iyl"} return {cond} return product(*(split(types[i], cond) diff --git a/src/assembler/instructions.yml b/src/assembler/instructions.yml index 9d97303..47f1ed2 100644 --- a/src/assembler/instructions.yml +++ b/src/assembler/instructions.yml @@ -46,9 +46,41 @@ adc: - cond: [a, _] return: [0x8E] -# add: -# args: no -# return: error +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] + 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: no @@ -62,65 +94,65 @@ adc: # args: no # return: error -# ccf: -# args: no -# return: error +ccf: + args: no + return: [0x3F] # cp: # args: no # return: error -# cpd: -# args: no -# return: error +cpd: + args: no + return: [0xED, 0xA9] -# cpdr: -# args: no -# return: error +cpdr: + args: no + return: [0xED, 0xB9] -# cpi: -# args: no -# return: error +cpi: + args: no + return: [0xED, 0xA1] -# cpir: -# args: no -# return: error +cpir: + args: no + return: [0xED, 0xB1] -# cpl: -# args: no -# return: error +cpl: + args: no + return: [0x2F] -# daa: -# args: no -# return: error +daa: + args: no + return: [0x27] # dec: # args: no # return: error -# di: -# args: no -# return: error +di: + args: no + return: [0xF3] # djnz: # args: no # return: error -# ei: -# args: no -# return: error +ei: + args: no + return: [0xFB] # ex: # args: no # return: error -# exx: -# args: no -# return: error +exx: + args: no + return: [0xD9] -# halt: -# args: no -# return: error +halt: + args: no + return: [0x76] # im: # args: no @@ -134,21 +166,21 @@ adc: # args: no # return: error -# ind: -# args: no -# return: error +ind: + args: no + return: [0xED, 0xAA] -# indr: -# args: no -# return: error +indr: + args: no + return: [0xED, 0xBA] ini: args: no return: [0xED, 0xA2] -# inir: -# args: no -# return: error +inir: + args: no + return: [0xED, 0xB2] # jp: # args: no @@ -162,53 +194,53 @@ ini: # args: no # return: error -# ldd: -# args: no -# return: error +ldd: + args: no + return: [0xED, 0xA8] -# lddr: -# args: no -# return: error +lddr: + args: no + return: [0xED, 0xB8] -# ldi: -# args: no -# return: error +ldi: + args: no + return: [0xED, 0xA0] -# ldir: -# args: no -# return: error +ldir: + args: no + return: [0xED, 0xB0] -# neg: -# args: no -# return: error +neg: + args: no + return: [0xED, 0x44] -# nop: -# args: no -# return: error +nop: + args: no + return: [0x00] # or: # args: no # return: error -# otdr: -# args: no -# return: error +otdr: + args: no + return: [0xED, 0xBB] -# otir: -# args: no -# return: error +otir: + args: no + return: [0xED, 0xB3] # out: # args: no # return: error -# outd: -# args: no -# return: error +outd: + args: no + return: [0xED, 0xAB] -# outi: -# args: no -# return: error +outi: + args: no + return: [0xED, 0xA3] # pop: # args: no @@ -226,49 +258,49 @@ ini: # args: no # return: error -# reti: -# args: no -# return: error +reti: + args: no + return: [0xED, 0x4D] -# retn: -# args: no -# return: error +retn: + args: no + return: [0xED, 0x45] # rl: # args: no # return: error -# rla: -# args: no -# return: error +rla: + args: no + return: [0x17] # rlc: # args: no # return: error -# rlca: -# args: no -# return: error +rlca: + args: no + return: [0x07] -# rld: -# args: no -# return: error +rld: + args: no + return: [0xED, 0x6F] # rr: # args: no # return: error -# rra: -# args: no -# return: error +rra: + args: no + return: [0x1F] # rrc: # args: no # return: error -# rrca: -# args: no -# return: error +rrca: + args: no + return: [0x0F] # rrd: # args: no @@ -282,9 +314,9 @@ ini: # args: no # return: error -# scf: -# args: no -# return: error +scf: + args: no + return: [0x37] # set: # args: no From 352296d6e26293cdda31c00b8da2899421d6ba28 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Sat, 16 May 2015 23:38:50 -0400 Subject: [PATCH 06/25] Implement inc; make update script save updates; bugfix. --- scripts/update_asm_instructions.py | 12 +- src/assembler/instructions.inc.c | 661 +++++++++++-------------------------- src/assembler/instructions.yml | 34 +- 3 files changed, 225 insertions(+), 482 deletions(-) diff --git a/scripts/update_asm_instructions.py b/scripts/update_asm_instructions.py index 4be7be2..ce716e0 100755 --- a/scripts/update_asm_instructions.py +++ b/scripts/update_asm_instructions.py @@ -158,8 +158,9 @@ class Instruction(object): """ Return the test part of an if statement for an instruction subcase. """ - return " && ".join(self._SUBCASE_LOOKUP_TABLE[types[i]](self, i, cond) - for i, cond in enumerate(conds) if cond != "_") + conds = [self._SUBCASE_LOOKUP_TABLE[types[i]](self, i, cond) + for i, cond in enumerate(conds) if cond != "_"] + return " && ".join(conds) if conds else "1" def _iter_permutations(self, types, conds): """ @@ -261,7 +262,7 @@ class Instruction(object): lines = [] if self._data["args"]: - lines.append("{tab}INST_TAKES_ARGS(\n{tab2}{0}, \n{tab2}{1}, " + 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)) @@ -321,9 +322,8 @@ def main(): data = yaml.load(text) result = process(template, data) - # with open(DEST, "w") as fp: - # fp.write(result.encode(ENCODING)) - print(result) # TODO: remove me! + with open(DEST, "w") as fp: + fp.write(result.encode(ENCODING)) if __name__ == "__main__": main() diff --git a/src/assembler/instructions.inc.c b/src/assembler/instructions.inc.c index 34d8b69..e308af7 100644 --- a/src/assembler/instructions.inc.c +++ b/src/assembler/instructions.inc.c @@ -7,7 +7,7 @@ `make` should trigger a rebuild when it is modified; if not, use: `python scripts/update_asm_instructions.py`. - @AUTOGEN_DATE Sun May 10 21:02:28 2015 + @AUTOGEN_DATE Sun May 17 03:37:44 2015 UTC */ /* @AUTOGEN_INST_BLOCK_START */ @@ -16,37 +16,55 @@ INST_FUNC(adc) { INST_TAKES_ARGS( AT_REGISTER, - AT_REGISTER|AT_IMMEDIATE|AT_INDEXED|AT_INDIRECT, + AT_IMMEDIATE|AT_INDIRECT|AT_INDEXED|AT_REGISTER, AT_NONE ) - if (INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_REGISTER) { + if (INST_NARGS == 2 && 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_IYL) + INST_RETURN(2, INST_IY_PREFIX, 0x8D) + 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_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_NARGS == 2 && 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_INDEXED) { - if (INST_REG(0) == REG_A) - INST_RETURN(3, INST_INDEX_PREFIX(1), 0x8E, INST_INDEX(1).offset) + if (INST_NARGS == 2 && 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_HL)) + INST_RETURN(1, 0x8E) 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_NARGS == 2 && INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_INDEXED) { if (INST_REG(0) == REG_A) - INST_RETURN(1, 0x8E) + INST_RETURN(3, INST_INDEX_PREFIX(1), 0x8E, INST_INDEX(1).offset) INST_ERROR(ARG_VALUE) } INST_ERROR(ARG_TYPE) @@ -54,70 +72,76 @@ INST_FUNC(adc) INST_FUNC(add) { - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) - - // INST_TAKES_ARGS(2, 2) - // INST_FORCE_TYPE(0, AT_REGISTER) - // switch (INST_REG(0)) { - // case REG_A: - // switch (INST_TYPE(1)) { - // INST_CASE_REGS(1, INST_CASE_ALL_8_BIT_REGS(0x80)) - // INST_CASE_IMM_U8(1, 2, 0xC6) - // INST_CASE_INDIRECT_HL_IX_IY(1, 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) // TODO: wrong prefix - // 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_TAKES_ARGS( + AT_REGISTER, + AT_IMMEDIATE|AT_INDIRECT|AT_INDEXED|AT_REGISTER, + AT_NONE + ) + if (INST_NARGS == 2 && 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_IYL) + INST_RETURN(2, INST_IY_PREFIX, 0x85) + 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_IY && INST_REG(1) == REG_BC) + INST_RETURN(2, INST_IY_PREFIX, 0x09) + if (INST_REG(0) == REG_IX && INST_REG(1) == REG_BC) + INST_RETURN(2, INST_IX_PREFIX, 0x09) + if (INST_REG(0) == REG_HL && INST_REG(1) == REG_BC) + INST_RETURN(1, 0x09) + if (INST_REG(0) == REG_IY && INST_REG(1) == REG_DE) + INST_RETURN(2, INST_IY_PREFIX, 0x19) + if (INST_REG(0) == REG_IX && INST_REG(1) == REG_DE) + INST_RETURN(2, INST_IX_PREFIX, 0x19) + if (INST_REG(0) == REG_HL && INST_REG(1) == REG_DE) + INST_RETURN(1, 0x19) + if (INST_REG(0) == REG_IY && INST_REG(1) == REG_HL) + INST_RETURN(2, INST_IY_PREFIX, 0x29) + if (INST_REG(0) == REG_IX && INST_REG(1) == REG_HL) + INST_RETURN(2, INST_IX_PREFIX, 0x29) + if (INST_REG(0) == REG_HL && INST_REG(1) == REG_HL) + INST_RETURN(1, 0x29) + if (INST_REG(0) == REG_IY && INST_REG(1) == REG_SP) + INST_RETURN(2, INST_IY_PREFIX, 0x39) + if (INST_REG(0) == REG_IX && INST_REG(1) == REG_SP) + INST_RETURN(2, INST_IX_PREFIX, 0x39) + if (INST_REG(0) == REG_HL && INST_REG(1) == REG_SP) + INST_RETURN(1, 0x39) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 2 && 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_NARGS == 2 && 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_HL)) + INST_RETURN(1, 0x86) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 2 && 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(ccf) @@ -126,14 +150,6 @@ INST_FUNC(ccf) 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 @@ -170,42 +186,18 @@ INST_FUNC(daa) 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) } -INST_FUNC(djnz) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - INST_FUNC(ei) { INST_TAKES_NO_ARGS INST_RETURN(1, 0xFB) } -INST_FUNC(ex) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - INST_FUNC(exx) { INST_TAKES_NO_ARGS @@ -218,55 +210,61 @@ INST_FUNC(halt) INST_RETURN(1, 0x76) } -INST_FUNC(im) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(in) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - INST_FUNC(inc) { - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) - - // 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) - // } - // INST_CASE_INDIRECT_HL_IX_IY(0, 1, 0x34) - // default: - // INST_ERROR(ARG0_TYPE) - // } + INST_TAKES_ARGS( + AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_NONE, + AT_NONE + ) + if (INST_NARGS == 1 && 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_IYL) + INST_RETURN(2, INST_IY_PREFIX, 0x2C) + 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_BC) + INST_RETURN(1, 0x03) + if (INST_REG(0) == REG_DE) + INST_RETURN(1, 0x13) + if (INST_REG(0) == REG_IY) + INST_RETURN(2, INST_IY_PREFIX, 0x23) + if (INST_REG(0) == REG_IX) + INST_RETURN(2, INST_IX_PREFIX, 0x23) + if (INST_REG(0) == REG_HL) + INST_RETURN(1, 0x23) + if (INST_REG(0) == REG_SP) + INST_RETURN(1, 0x33) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDIRECT) { + if ((INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL)) + INST_RETURN(1, 0x34) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDEXED) { + if (1) + INST_RETURN(3, INST_INDEX_PREFIX(0), 0x34, INST_INDEX(0).offset) + INST_ERROR(ARG_VALUE) + } + INST_ERROR(ARG_TYPE) } INST_FUNC(ind) @@ -293,146 +291,6 @@ INST_FUNC(inir) 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) -{ - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) - - // 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_CASE_ALL_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) - // } - // INST_CASE_IMM_U8(1, 2, 0x3E) - // 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: - // switch (INST_TYPE(1)) { - // INST_CASE_REGS(1, INST_CASE_ALL_8_BIT_REGS(0x40)) - // INST_CASE_IMM_U8(1, 2, 0x06) - // INST_CASE_INDIRECT_HL_IX_IY(1, 1, 0x46) - // default: INST_ERROR(ARG1_TYPE) - // } - // case REG_C: - // switch (INST_TYPE(1)) { - // INST_CASE_REGS(1, INST_CASE_ALL_8_BIT_REGS(0x48)) - // INST_CASE_IMM_U8(1, 2, 0x0E) - // INST_CASE_INDIRECT_HL_IX_IY(1, 1, 0x4E) - // default: INST_ERROR(ARG1_TYPE) - // } - // case REG_D: - // switch (INST_TYPE(1)) { - // INST_CASE_REGS(1, INST_CASE_ALL_8_BIT_REGS(0x50)) - // INST_CASE_IMM_U8(1, 2, 0x16) - // INST_CASE_INDIRECT_HL_IX_IY(1, 1, 0x56) - // default: INST_ERROR(ARG1_TYPE) - // } - // case REG_E: - // switch (INST_TYPE(1)) { - // INST_CASE_REGS(1, INST_CASE_ALL_8_BIT_REGS(0x58)) - // INST_CASE_IMM_U8(1, 2, 0x1E) - // INST_CASE_INDIRECT_HL_IX_IY(1, 1, 0x5E) - // default: INST_ERROR(ARG1_TYPE) - // } - // case REG_H: - // switch (INST_TYPE(1)) { - // INST_CASE_REGS(1, INST_CASE_MAIN_8_BIT_REGS(0x60)) - // INST_CASE_IMM_U8(1, 2, 0x26) - // INST_CASE_INDIRECT_HL_IX_IY(1, 1, 0x66) - // default: INST_ERROR(ARG1_TYPE) - // } - // case REG_L: - // switch (INST_TYPE(1)) { - // INST_CASE_REGS(1, INST_CASE_MAIN_8_BIT_REGS(0x68)) - // INST_CASE_IMM_U8(1, 2, 0x2E) - // INST_CASE_INDIRECT_HL_IX_IY(1, 1, 0x6E) - // default: INST_ERROR(ARG1_TYPE) - // } - // 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) - // } -} - INST_FUNC(ldd) { INST_TAKES_NO_ARGS @@ -469,14 +327,6 @@ INST_FUNC(nop) 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 @@ -489,14 +339,6 @@ INST_FUNC(otir) 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 @@ -509,38 +351,6 @@ INST_FUNC(outi) 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 @@ -553,28 +363,12 @@ INST_FUNC(retn) 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) -} - INST_FUNC(rlca) { INST_TAKES_NO_ARGS @@ -587,136 +381,24 @@ INST_FUNC(rld) INST_RETURN(2, 0xED, 0x6F) } -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) } -INST_FUNC(set) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(sl1) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(sla) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(sll) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(sls) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(sra) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(srl) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(sub) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - -INST_FUNC(xor) -{ - // TODO - INST_TAKES_NO_ARGS - INST_ERROR(ARG_SYNTAX) - INST_RETURN(1, 0xFF) -} - /* @AUTOGEN_INST_BLOCK_END */ /* @@ -727,7 +409,40 @@ static ASMInstParser lookup_parser(uint32_t key) /* @AUTOGEN_LOOKUP_BLOCK_START */ HANDLE(adc) HANDLE(add) - HANDLE(and) + HANDLE(ccf) + HANDLE(cpd) + HANDLE(cpdr) + HANDLE(cpi) + HANDLE(cpir) + HANDLE(cpl) + HANDLE(daa) + HANDLE(di) + HANDLE(ei) + HANDLE(exx) + HANDLE(halt) + HANDLE(inc) + HANDLE(ind) + HANDLE(indr) + HANDLE(ini) + HANDLE(inir) + HANDLE(ldd) + HANDLE(lddr) + HANDLE(ldi) + HANDLE(ldir) + HANDLE(neg) + HANDLE(nop) + HANDLE(otdr) + HANDLE(otir) + HANDLE(outd) + HANDLE(outi) + HANDLE(reti) + HANDLE(retn) + HANDLE(rla) + HANDLE(rlca) + HANDLE(rld) + HANDLE(rra) + HANDLE(rrca) + HANDLE(scf) /* @AUTOGEN_LOOKUP_BLOCK_END */ return NULL; } diff --git a/src/assembler/instructions.yml b/src/assembler/instructions.yml index 47f1ed2..00359ac 100644 --- a/src/assembler/instructions.yml +++ b/src/assembler/instructions.yml @@ -162,9 +162,37 @@ halt: # args: no # return: error -# inc: -# args: no -# return: error +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 From 76f2783b64dce2538d1c9c9da46730735b6466fc Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Sun, 17 May 2015 00:21:22 -0400 Subject: [PATCH 07/25] Implement new masking system for ASM instructions; bugfixes. --- src/assembler/instructions.c | 48 ++++++++++++++++++++++++++------------------ src/assembler/parse_util.c | 6 +++--- src/assembler/tokenizer.c | 2 +- 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/assembler/instructions.c b/src/assembler/instructions.c index bfb9a7d..708ca68 100644 --- a/src/assembler/instructions.c +++ b/src/assembler/instructions.c @@ -24,7 +24,7 @@ /* Helper macro for parse_arg() */ #define TRY_PARSER(func, argtype, field) \ - if (argparse_##func(&arg->data.field, info)) { \ + if (mask & argtype && argparse_##func(&arg->data.field, info)) { \ arg->type = argtype; \ return ED_NONE; \ } @@ -52,13 +52,6 @@ (((reg) == REG_IX || (reg) == REG_IXH || (reg) == REG_IXL) ? \ INST_IX_PREFIX : INST_IY_PREFIX) -#define INST_RETURN_WITH_SYMBOL_(len, label, ...) { \ // TODO - *symbol = cr_strdup(label.text); \ - INST_ALLOC_(len) \ - INST_FILL_BYTES_(len - 2, __VA_ARGS__) \ - return ED_NONE; \ - } - /* Helper macros for instruction parsers */ #define INST_FUNC(mnemonic) \ @@ -75,8 +68,8 @@ static ASMErrorDesc parse_inst_##mnemonic( \ if (!ap_info.arg) \ INST_ERROR(TOO_FEW_ARGS) \ ASMInstArg args[3]; \ - size_t nargs = 0; \ - ASMArgType masks = {a0, a1, a2}; \ + size_t nargs; \ + ASMArgType masks[] = {a0, a1, a2}; \ ASMErrorDesc err = parse_args(args, &nargs, ap_info, masks); \ if (err) \ return err; \ @@ -102,7 +95,10 @@ static ASMErrorDesc parse_inst_##mnemonic( \ #define INST_INDEX_PREFIX(n) INST_PREFIX_(INST_INDEX(n).reg) -#define INST_INDIRECT_IMM(n) \ // TODO +// TODO: must check for imm actually using symbol... +// - hint: *symbol = cr_strdup(label.text); +// - hint: INST_FILL_BYTES_(len - 2, __VA_ARGS__) +#define INST_INDIRECT_IMM(n) \ INST_INDIRECT(n).addr.imm.uval >> 8, \ INST_INDIRECT(n).addr.imm.uval & 0xFF @@ -134,13 +130,15 @@ static uint8_t fill_bytes_variadic(uint8_t *bytes, size_t len, ...) 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) + ASMInstArg *arg, const char *str, size_t size, ASMDefineTable *deftable, + ASMArgType mask) { ASMArgParseInfo info = {.arg = str, .size = size, .deftable = deftable}; TRY_PARSER(register, AT_REGISTER, reg) TRY_PARSER(condition, AT_CONDITION, cond) - TRY_PARSER(indirect, AT_INDIRECT, indirect) 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; } @@ -151,21 +149,25 @@ static ASMErrorDesc parse_arg( 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]) // TODO + 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; + 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 ((err = parse_arg(&args[*nargs], str + start, i - start, dt))) + 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; - (*nargs)++; + n++; i++; if (i < size && str[i] == ' ') @@ -173,7 +175,7 @@ static ASMErrorDesc parse_args( start = i; if (i == size) return ED_PS_ARG_SYNTAX; - if (*nargs >= 3) + if (n >= 3) return ED_PS_TOO_MANY_ARGS; } else { if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || @@ -186,10 +188,16 @@ static ASMErrorDesc parse_args( } if (i > start) { - if ((err = parse_arg(&args[*nargs], str + start, i - start, dt))) + 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; - (*nargs)++; + n++; } + + if (n < 3 && masks[n] != AT_NONE && !(masks[n] & AT_OPTIONAL)) + return ED_PS_TOO_FEW_ARGS; + *nargs = n; return ED_NONE; } diff --git a/src/assembler/parse_util.c b/src/assembler/parse_util.c index 9d5ff5a..12b6bdb 100644 --- a/src/assembler/parse_util.c +++ b/src/assembler/parse_util.c @@ -460,7 +460,7 @@ bool argparse_indexed(ASMArgIndexed *result, ASMArgParseInfo ai) /* Read in a port argument and store it in *result. */ -bool argparse_port(ASMArgPort*, ASMArgParseInfo) +bool argparse_port(ASMArgPort *result, ASMArgParseInfo ai) { if (ai.size < 3 || !adjust_for_indirection(&ai)) return false; @@ -470,13 +470,13 @@ bool argparse_port(ASMArgPort*, ASMArgParseInfo) if (argparse_register(®, ai)) { if (reg == REG_C) { result->type = AT_REGISTER; - result->addr.reg = reg; + result->port.reg = reg; return true; } } else if (argparse_immediate(&imm, ai)) { if (imm.mask & IMM_U8) { result->type = AT_IMMEDIATE; - result->addr.imm = imm; + result->port.imm = imm; return true; } } diff --git a/src/assembler/tokenizer.c b/src/assembler/tokenizer.c index 896f822..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) || imm->is_label) + 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)); From 981c4d47830f698f3c92f4dc58194f07c5a98ab7 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Sun, 17 May 2015 04:00:57 -0400 Subject: [PATCH 08/25] Disable ASan; bugfix for immediate masks. --- makefile | 2 +- src/assembler/parse_util.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/makefile b/makefile index b6763ab..fdf785b 100644 --- a/makefile +++ b/makefile @@ -24,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 diff --git a/src/assembler/parse_util.c b/src/assembler/parse_util.c index 12b6bdb..fd4e776 100644 --- a/src/assembler/parse_util.c +++ b/src/assembler/parse_util.c @@ -362,10 +362,10 @@ bool argparse_immediate(ASMArgImmediate *result, ASMArgParseInfo ai) const ASMDefine *define = asm_deftable_find(ai.deftable, ai.arg, ai.size); if (define) { if (negative) { - calculate_immediate_mask(result); result->is_label = false; result->uval = define->value.uval; result->sval = -define->value.sval; + calculate_immediate_mask(result); } else { *result = define->value; } @@ -386,10 +386,10 @@ bool argparse_immediate(ASMArgImmediate *result, ASMArgParseInfo ai) if (sval < INT16_MIN) return false; - calculate_immediate_mask(result); result->is_label = false; result->uval = uval; result->sval = sval; + calculate_immediate_mask(result); return true; } From de3cbf741c6171abefcb68e559ccdd4d7cdd17bb Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Mon, 18 May 2015 00:54:36 -0400 Subject: [PATCH 09/25] Fix argparse_immediate() masks for large numbers. --- src/assembler/parse_util.c | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/src/assembler/parse_util.c b/src/assembler/parse_util.c index fd4e776..bed1b6b 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; } /* @@ -365,7 +367,7 @@ bool argparse_immediate(ASMArgImmediate *result, ASMArgParseInfo ai) 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; } @@ -389,7 +391,7 @@ bool argparse_immediate(ASMArgImmediate *result, ASMArgParseInfo ai) result->is_label = false; result->uval = uval; result->sval = sval; - calculate_immediate_mask(result); + result->mask = calculate_immediate_mask(uval, negative); return true; } From 9642dfb6b06fb23607da887d701fc12e4f838303 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Mon, 18 May 2015 00:55:34 -0400 Subject: [PATCH 10/25] Implement LD instruction; most remaining ASM instruction functionality. --- scripts/update_asm_instructions.py | 73 ++++-- src/assembler/errors.c | 4 +- src/assembler/instructions.c | 16 +- src/assembler/instructions.inc.c | 441 ++++++++++++++++++++++++++++++++++--- src/assembler/instructions.yml | 276 +++++++++++++++++++---- 5 files changed, 720 insertions(+), 90 deletions(-) diff --git a/scripts/update_asm_instructions.py b/scripts/update_asm_instructions.py index ce716e0..9c1f9df 100755 --- a/scripts/update_asm_instructions.py +++ b/scripts/update_asm_instructions.py @@ -77,7 +77,7 @@ class Instruction(object): return "AT_NONE" if optional: types.add("AT_OPTIONAL") - return "|".join(types) + return "|".join(sorted(types)) def _handle_return(self, ret, indent=1): """ @@ -105,7 +105,19 @@ class Instruction(object): """ Return an expression to check for a particular immediate value. """ - # TODO: also allow direct value comparisons here + 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()) + test2 = "!INST_IMM({0}).is_label".format(num) + test3 = "INST_IMM({0}).{1} == {2}".format(num, vtype, value) + return "({0} && {1} && {2})".format(test1, test2, test3) + return "INST_IMM({0}).mask & IMM_{1}".format(num, cond.upper()) def _build_indirect_check(self, num, cond): @@ -140,7 +152,14 @@ class Instruction(object): """ Return an expression to check for a particular port value. """ - # TODO + if cond.startswith("reg."): + test1 = "INST_PORT({0}).type == AT_REGISTER".format(num) + test2 = "INST_PORT({0}).port.reg == REG_{1}".format( + num, cond[len("reg."):].upper()) + return "({0} && {1})".format(test1, test2) + + 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)) @@ -168,19 +187,30 @@ class Instruction(object): """ def split(typ, cond): if "|" in cond: - sets = [split(typ, c) for c in cond.split("|")] - return {choice for s in sets for choice in s} + 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"} + return ["ix", "iy"] if cond == "ih": - return {"ixh", "iyh"} + return ["ixh", "iyh"] if cond == "il": - return {"ixl", "iyl"} - return {cond} + return ["ixl", "iyl"] + return [cond] + + splits = [split(typ, cond) for typ, cond in zip(types, conds)] + num = max(len(cond) for cond in splits) - return product(*(split(types[i], cond) - for i, cond in enumerate(conds))) + 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): """ @@ -190,8 +220,25 @@ class Instruction(object): for i, byte in enumerate(ret): if not isinstance(byte, int): if byte == "u8": - imm = types.index("immediate") - ret[i] = "INST_IMM({0}).uval".format(imm) + index = types.index("immediate") + ret[i] = "INST_IMM({0}).uval".format(index) + + 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 + else: msg = "Unsupported return byte: {0}" raise RuntimeError(msg.format(byte)) diff --git a/src/assembler/errors.c b/src/assembler/errors.c index bc2094c..5a6bcb5 100644 --- a/src/assembler/errors.c +++ b/src/assembler/errors.c @@ -53,8 +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_ARG_TYPE] = "ED_PS_ARG_TYPE", // TODO - [ED_PS_ARG_VALUE] = "ED_PS_ARG_VALUE" // TODO + [ED_PS_ARG_TYPE] = "invalid argument type", + [ED_PS_ARG_VALUE] = "invalid value for argument" }; /* Internal structs */ diff --git a/src/assembler/instructions.c b/src/assembler/instructions.c index 708ca68..ac2558f 100644 --- a/src/assembler/instructions.c +++ b/src/assembler/instructions.c @@ -83,6 +83,9 @@ static ASMErrorDesc parse_inst_##mnemonic( \ #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) \ @@ -90,18 +93,13 @@ static ASMErrorDesc parse_inst_##mnemonic( \ return ED_NONE; \ } -#define INST_IX_PREFIX 0xDD -#define INST_IY_PREFIX 0xFD +#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) #define INST_INDEX_PREFIX(n) INST_PREFIX_(INST_INDEX(n).reg) -// TODO: must check for imm actually using symbol... -// - hint: *symbol = cr_strdup(label.text); -// - hint: INST_FILL_BYTES_(len - 2, __VA_ARGS__) -#define INST_INDIRECT_IMM(n) \ - INST_INDIRECT(n).addr.imm.uval >> 8, \ - INST_INDIRECT(n).addr.imm.uval & 0xFF - /* ----------------------------- END WORK BLOCK ---------------------------- */ /* diff --git a/src/assembler/instructions.inc.c b/src/assembler/instructions.inc.c index e308af7..41bda1a 100644 --- a/src/assembler/instructions.inc.c +++ b/src/assembler/instructions.inc.c @@ -7,7 +7,7 @@ `make` should trigger a rebuild when it is modified; if not, use: `python scripts/update_asm_instructions.py`. - @AUTOGEN_DATE Sun May 17 03:37:44 2015 UTC + @AUTOGEN_DATE Mon May 18 04:41:13 2015 UTC */ /* @AUTOGEN_INST_BLOCK_START */ @@ -16,7 +16,7 @@ INST_FUNC(adc) { INST_TAKES_ARGS( AT_REGISTER, - AT_IMMEDIATE|AT_INDIRECT|AT_INDEXED|AT_REGISTER, + AT_IMMEDIATE|AT_INDEXED|AT_INDIRECT|AT_REGISTER, AT_NONE ) if (INST_NARGS == 2 && INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_REGISTER) { @@ -36,12 +36,12 @@ INST_FUNC(adc) 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_IYL) - INST_RETURN(2, INST_IY_PREFIX, 0x8D) 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) @@ -74,7 +74,7 @@ INST_FUNC(add) { INST_TAKES_ARGS( AT_REGISTER, - AT_IMMEDIATE|AT_INDIRECT|AT_INDEXED|AT_REGISTER, + AT_IMMEDIATE|AT_INDEXED|AT_INDIRECT|AT_REGISTER, AT_NONE ) if (INST_NARGS == 2 && INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_REGISTER) { @@ -94,36 +94,36 @@ INST_FUNC(add) 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_IYL) - INST_RETURN(2, INST_IY_PREFIX, 0x85) 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_IY && INST_REG(1) == REG_BC) - INST_RETURN(2, INST_IY_PREFIX, 0x09) - if (INST_REG(0) == REG_IX && INST_REG(1) == REG_BC) - INST_RETURN(2, INST_IX_PREFIX, 0x09) + 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_IY && INST_REG(1) == REG_DE) - INST_RETURN(2, INST_IY_PREFIX, 0x19) - if (INST_REG(0) == REG_IX && INST_REG(1) == REG_DE) - INST_RETURN(2, INST_IX_PREFIX, 0x19) + 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_IY && INST_REG(1) == REG_HL) - INST_RETURN(2, INST_IY_PREFIX, 0x29) - if (INST_REG(0) == REG_IX && INST_REG(1) == REG_HL) - INST_RETURN(2, INST_IX_PREFIX, 0x29) + 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_IY && INST_REG(1) == REG_SP) - INST_RETURN(2, INST_IY_PREFIX, 0x39) - if (INST_REG(0) == REG_IX && INST_REG(1) == REG_SP) - INST_RETURN(2, INST_IX_PREFIX, 0x39) + if (INST_REG(0) == REG_IX && INST_REG(1) == REG_IX) + INST_RETURN(3, INST_IX_PREFIX, INST_IX_PREFIX, 0x29) + if (INST_REG(0) == REG_IY && INST_REG(1) == REG_IY) + INST_RETURN(3, INST_IY_PREFIX, 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_NARGS == 2 && INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_IMMEDIATE) { @@ -234,22 +234,22 @@ INST_FUNC(inc) 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_IYL) - INST_RETURN(2, INST_IY_PREFIX, 0x2C) 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_IY) - INST_RETURN(2, INST_IY_PREFIX, 0x23) - if (INST_REG(0) == REG_IX) - INST_RETURN(2, INST_IX_PREFIX, 0x23) 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) @@ -291,6 +291,388 @@ INST_FUNC(inir) INST_RETURN(2, 0xED, 0xB2) } +INST_FUNC(ld) +{ + INST_TAKES_ARGS( + AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_IMMEDIATE|AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_NONE + ) + if (INST_NARGS == 2 && 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(3, INST_IX_PREFIX, INST_IX_PREFIX, 0x64) + if (INST_REG(0) == REG_IYH && INST_REG(1) == REG_IYH) + INST_RETURN(3, INST_IY_PREFIX, 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(3, INST_IX_PREFIX, INST_IX_PREFIX, 0x65) + if (INST_REG(0) == REG_IYH && INST_REG(1) == REG_IYL) + INST_RETURN(3, INST_IY_PREFIX, 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(3, INST_IX_PREFIX, INST_IX_PREFIX, 0x6C) + if (INST_REG(0) == REG_IYL && INST_REG(1) == REG_IYH) + INST_RETURN(3, INST_IY_PREFIX, 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(3, INST_IX_PREFIX, INST_IX_PREFIX, 0x6D) + if (INST_REG(0) == REG_IYL && INST_REG(1) == REG_IYL) + INST_RETURN(3, INST_IY_PREFIX, 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_NARGS == 2 && 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_NARGS == 2 && 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_HL)) + INST_RETURN(1, 0x7E) + if (INST_REG(0) == REG_B && (INST_INDIRECT(1).type == AT_REGISTER && INST_INDIRECT(1).addr.reg == REG_HL)) + INST_RETURN(1, 0x46) + if (INST_REG(0) == REG_C && (INST_INDIRECT(1).type == AT_REGISTER && INST_INDIRECT(1).addr.reg == REG_HL)) + INST_RETURN(1, 0x4E) + if (INST_REG(0) == REG_D && (INST_INDIRECT(1).type == AT_REGISTER && INST_INDIRECT(1).addr.reg == REG_HL)) + INST_RETURN(1, 0x56) + if (INST_REG(0) == REG_E && (INST_INDIRECT(1).type == AT_REGISTER && INST_INDIRECT(1).addr.reg == REG_HL)) + INST_RETURN(1, 0x5E) + if (INST_REG(0) == REG_H && (INST_INDIRECT(1).type == AT_REGISTER && INST_INDIRECT(1).addr.reg == REG_HL)) + INST_RETURN(1, 0x66) + if (INST_REG(0) == REG_L && (INST_INDIRECT(1).type == AT_REGISTER && INST_INDIRECT(1).addr.reg == REG_HL)) + INST_RETURN(1, 0x6E) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 2 && 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_NARGS == 2 && 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_NARGS == 2 && INST_TYPE(0) == AT_INDIRECT && INST_TYPE(1) == AT_REGISTER) { + if ((INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL) && INST_REG(1) == REG_A) + INST_RETURN(1, 0x77) + if ((INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL) && INST_REG(1) == REG_B) + INST_RETURN(1, 0x70) + if ((INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL) && INST_REG(1) == REG_C) + INST_RETURN(1, 0x71) + if ((INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL) && INST_REG(1) == REG_D) + INST_RETURN(1, 0x72) + if ((INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL) && INST_REG(1) == REG_E) + INST_RETURN(1, 0x73) + if ((INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL) && INST_REG(1) == REG_H) + INST_RETURN(1, 0x74) + if ((INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL) && INST_REG(1) == REG_L) + INST_RETURN(1, 0x75) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 2 && 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_NARGS == 2 && INST_TYPE(0) == AT_INDIRECT && INST_TYPE(1) == AT_IMMEDIATE) { + if ((INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL) && INST_IMM(1).mask & IMM_U8) + INST_RETURN(2, 0x36, INST_IMM(1).uval) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 2 && 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_IMM(1).uval, INST_INDEX(0).offset) + INST_ERROR(ARG_VALUE) + } + if (INST_NARGS == 2 && 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 @@ -425,6 +807,7 @@ static ASMInstParser lookup_parser(uint32_t key) HANDLE(indr) HANDLE(ini) HANDLE(inir) + HANDLE(ld) HANDLE(ldd) HANDLE(lddr) HANDLE(ldi) diff --git a/src/assembler/instructions.yml b/src/assembler/instructions.yml index 00359ac..dc4e5e0 100644 --- a/src/assembler/instructions.yml +++ b/src/assembler/instructions.yml @@ -69,7 +69,7 @@ add: return: [0x09] - cond: [hl|i, de] return: [0x19] - - cond: [hl|i, hl] + - cond: [hl|i, hl|i] return: [0x29] - cond: [hl|i, sp] return: [0x39] @@ -83,15 +83,15 @@ add: return: [0x86] # and: -# args: no +# args: yes # return: error # bit: -# args: no +# args: yes # return: error # call: -# args: no +# args: yes # return: error ccf: @@ -99,7 +99,7 @@ ccf: return: [0x3F] # cp: -# args: no +# args: yes # return: error cpd: @@ -127,7 +127,7 @@ daa: return: [0x27] # dec: -# args: no +# args: yes # return: error di: @@ -135,7 +135,7 @@ di: return: [0xF3] # djnz: -# args: no +# args: yes # return: error ei: @@ -143,7 +143,7 @@ ei: return: [0xFB] # ex: -# args: no +# args: yes # return: error exx: @@ -155,11 +155,11 @@ halt: return: [0x76] # im: -# args: no +# args: yes # return: error # in: -# args: no +# args: yes # return: error inc: @@ -211,16 +211,218 @@ inir: return: [0xED, 0xB2] # jp: -# args: no +# args: yes # return: error # jr: -# args: no +# args: yes # return: error -# ld: -# args: no -# return: error +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] # TODO, support both this and regular indirect + 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 @@ -247,7 +449,7 @@ nop: return: [0x00] # or: -# args: no +# args: yes # return: error otdr: @@ -259,7 +461,7 @@ otir: return: [0xED, 0xB3] # out: -# args: no +# args: yes # return: error outd: @@ -271,19 +473,19 @@ outi: return: [0xED, 0xA3] # pop: -# args: no +# args: yes # return: error # push: -# args: no +# args: yes # return: error # res: -# args: no +# args: yes # return: error # ret: -# args: no +# args: yes # return: error reti: @@ -295,7 +497,7 @@ retn: return: [0xED, 0x45] # rl: -# args: no +# args: yes # return: error rla: @@ -303,7 +505,7 @@ rla: return: [0x17] # rlc: -# args: no +# args: yes # return: error rlca: @@ -315,7 +517,7 @@ rld: return: [0xED, 0x6F] # rr: -# args: no +# args: yes # return: error rra: @@ -323,7 +525,7 @@ rra: return: [0x1F] # rrc: -# args: no +# args: yes # return: error rrca: @@ -331,15 +533,15 @@ rrca: return: [0x0F] # rrd: -# args: no +# args: yes # return: error # rst: -# args: no +# args: yes # return: error # sbc: -# args: no +# args: yes # return: error scf: @@ -347,37 +549,37 @@ scf: return: [0x37] # set: -# args: no +# args: yes # return: error # sl1: -# args: no +# args: yes # return: error # sla: -# args: no +# args: yes # return: error # sll: -# args: no +# args: yes # return: error # sls: -# args: no +# args: yes # return: error # sra: -# args: no +# args: yes # return: error # srl: -# args: no +# args: yes # return: error # sub: -# args: no +# args: yes # return: error # xor: -# args: no +# args: yes # return: error From eba6350f4e6d19c5fbe7063b6006c4a42ee3eb9f Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Mon, 18 May 2015 01:16:27 -0400 Subject: [PATCH 11/25] Fix duplicate prefixes. --- scripts/update_asm_instructions.py | 8 ++++---- src/assembler/instructions.inc.c | 22 +++++++++++----------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/scripts/update_asm_instructions.py b/scripts/update_asm_instructions.py index 9c1f9df..537ceda 100755 --- a/scripts/update_asm_instructions.py +++ b/scripts/update_asm_instructions.py @@ -244,10 +244,10 @@ class Instruction(object): raise RuntimeError(msg.format(byte)) for i, cond in enumerate(conds): - if types[i] == "register" and cond.startswith("ix"): - ret.insert(0, "INST_IX_PREFIX") - elif types[i] == "register" and cond.startswith("iy"): - ret.insert(0, "INST_IY_PREFIX") + 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.append("INST_INDEX({0}).offset".format(i)) diff --git a/src/assembler/instructions.inc.c b/src/assembler/instructions.inc.c index 41bda1a..350716b 100644 --- a/src/assembler/instructions.inc.c +++ b/src/assembler/instructions.inc.c @@ -7,7 +7,7 @@ `make` should trigger a rebuild when it is modified; if not, use: `python scripts/update_asm_instructions.py`. - @AUTOGEN_DATE Mon May 18 04:41:13 2015 UTC + @AUTOGEN_DATE Mon May 18 05:16:08 2015 UTC */ /* @AUTOGEN_INST_BLOCK_START */ @@ -115,9 +115,9 @@ INST_FUNC(add) 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(3, INST_IX_PREFIX, INST_IX_PREFIX, 0x29) + INST_RETURN(2, INST_IX_PREFIX, 0x29) if (INST_REG(0) == REG_IY && INST_REG(1) == REG_IY) - INST_RETURN(3, INST_IY_PREFIX, INST_IY_PREFIX, 0x29) + 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) @@ -442,15 +442,15 @@ INST_FUNC(ld) 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(3, INST_IX_PREFIX, INST_IX_PREFIX, 0x64) + INST_RETURN(2, INST_IX_PREFIX, 0x64) if (INST_REG(0) == REG_IYH && INST_REG(1) == REG_IYH) - INST_RETURN(3, INST_IY_PREFIX, INST_IY_PREFIX, 0x64) + 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(3, INST_IX_PREFIX, INST_IX_PREFIX, 0x65) + INST_RETURN(2, INST_IX_PREFIX, 0x65) if (INST_REG(0) == REG_IYH && INST_REG(1) == REG_IYL) - INST_RETURN(3, INST_IY_PREFIX, INST_IY_PREFIX, 0x65) + 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) @@ -484,15 +484,15 @@ INST_FUNC(ld) 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(3, INST_IX_PREFIX, INST_IX_PREFIX, 0x6C) + INST_RETURN(2, INST_IX_PREFIX, 0x6C) if (INST_REG(0) == REG_IYL && INST_REG(1) == REG_IYH) - INST_RETURN(3, INST_IY_PREFIX, INST_IY_PREFIX, 0x6C) + 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(3, INST_IX_PREFIX, INST_IX_PREFIX, 0x6D) + INST_RETURN(2, INST_IX_PREFIX, 0x6D) if (INST_REG(0) == REG_IYL && INST_REG(1) == REG_IYL) - INST_RETURN(3, INST_IY_PREFIX, INST_IY_PREFIX, 0x6D) + 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) From 17f08dff4b1d9bdc8babda5d5a0e6742fc63c3f0 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Mon, 18 May 2015 01:39:25 -0400 Subject: [PATCH 12/25] Fix behavior when combining indirect_hl_or_indexed and indirect. --- scripts/update_asm_instructions.py | 14 ++++---- src/assembler/instructions.inc.c | 56 +++++++++++++++++-------------- src/assembler/instructions.yml | 68 +++++++++++++++++++------------------- 3 files changed, 71 insertions(+), 67 deletions(-) diff --git a/scripts/update_asm_instructions.py b/scripts/update_asm_instructions.py index 537ceda..2897d5f 100755 --- a/scripts/update_asm_instructions.py +++ b/scripts/update_asm_instructions.py @@ -268,14 +268,12 @@ class Instruction(object): indexed = self._handle_case(case) case["type"][index] = "indirect" - for subcase in case["cases"]: - if subcase["cond"][index] != "_": - raise RuntimeError( - "indirect_hl_or_indexed pseudo-type requires a " - "wildcard (_) in all corresponding conditionals") - subcase["cond"][index] = "reg.hl" - - return self._handle_case(case) + indexed + 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)) diff --git a/src/assembler/instructions.inc.c b/src/assembler/instructions.inc.c index 350716b..d33f4b5 100644 --- a/src/assembler/instructions.inc.c +++ b/src/assembler/instructions.inc.c @@ -7,7 +7,7 @@ `make` should trigger a rebuild when it is modified; if not, use: `python scripts/update_asm_instructions.py`. - @AUTOGEN_DATE Mon May 18 05:16:08 2015 UTC + @AUTOGEN_DATE Mon May 18 05:31:58 2015 UTC */ /* @AUTOGEN_INST_BLOCK_START */ @@ -57,8 +57,9 @@ INST_FUNC(adc) INST_RETURN(2, 0xCE, INST_IMM(1).uval) INST_ERROR(ARG_VALUE) } - if (INST_NARGS == 2 && 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_HL)) + if (INST_NARGS == 2 && 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) } @@ -131,8 +132,9 @@ INST_FUNC(add) INST_RETURN(2, 0xC6, INST_IMM(1).uval) INST_ERROR(ARG_VALUE) } - if (INST_NARGS == 2 && 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_HL)) + if (INST_NARGS == 2 && 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) } @@ -254,8 +256,9 @@ INST_FUNC(inc) INST_RETURN(1, 0x33) INST_ERROR(ARG_VALUE) } - if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDIRECT) { - if ((INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL)) + if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDIRECT && + (INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL)) { + if (1) INST_RETURN(1, 0x34) INST_ERROR(ARG_VALUE) } @@ -550,20 +553,21 @@ INST_FUNC(ld) INST_RETURN(3, 0x31, INST_IMM_U16_B1(INST_IMM(1)), INST_IMM_U16_B2(INST_IMM(1))) INST_ERROR(ARG_VALUE) } - if (INST_NARGS == 2 && 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_HL)) + if (INST_NARGS == 2 && 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_INDIRECT(1).type == AT_REGISTER && INST_INDIRECT(1).addr.reg == REG_HL)) + if (INST_REG(0) == REG_B) INST_RETURN(1, 0x46) - if (INST_REG(0) == REG_C && (INST_INDIRECT(1).type == AT_REGISTER && INST_INDIRECT(1).addr.reg == REG_HL)) + if (INST_REG(0) == REG_C) INST_RETURN(1, 0x4E) - if (INST_REG(0) == REG_D && (INST_INDIRECT(1).type == AT_REGISTER && INST_INDIRECT(1).addr.reg == REG_HL)) + if (INST_REG(0) == REG_D) INST_RETURN(1, 0x56) - if (INST_REG(0) == REG_E && (INST_INDIRECT(1).type == AT_REGISTER && INST_INDIRECT(1).addr.reg == REG_HL)) + if (INST_REG(0) == REG_E) INST_RETURN(1, 0x5E) - if (INST_REG(0) == REG_H && (INST_INDIRECT(1).type == AT_REGISTER && INST_INDIRECT(1).addr.reg == REG_HL)) + if (INST_REG(0) == REG_H) INST_RETURN(1, 0x66) - if (INST_REG(0) == REG_L && (INST_INDIRECT(1).type == AT_REGISTER && INST_INDIRECT(1).addr.reg == REG_HL)) + if (INST_REG(0) == REG_L) INST_RETURN(1, 0x6E) INST_ERROR(ARG_VALUE) } @@ -605,20 +609,21 @@ INST_FUNC(ld) 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_NARGS == 2 && INST_TYPE(0) == AT_INDIRECT && INST_TYPE(1) == AT_REGISTER) { - if ((INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL) && INST_REG(1) == REG_A) + if (INST_NARGS == 2 && 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_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL) && INST_REG(1) == REG_B) + if (INST_REG(1) == REG_B) INST_RETURN(1, 0x70) - if ((INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL) && INST_REG(1) == REG_C) + if (INST_REG(1) == REG_C) INST_RETURN(1, 0x71) - if ((INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL) && INST_REG(1) == REG_D) + if (INST_REG(1) == REG_D) INST_RETURN(1, 0x72) - if ((INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL) && INST_REG(1) == REG_E) + if (INST_REG(1) == REG_E) INST_RETURN(1, 0x73) - if ((INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL) && INST_REG(1) == REG_H) + if (INST_REG(1) == REG_H) INST_RETURN(1, 0x74) - if ((INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL) && INST_REG(1) == REG_L) + if (INST_REG(1) == REG_L) INST_RETURN(1, 0x75) INST_ERROR(ARG_VALUE) } @@ -639,8 +644,9 @@ INST_FUNC(ld) INST_RETURN(3, INST_INDEX_PREFIX(0), 0x75, INST_INDEX(0).offset) INST_ERROR(ARG_VALUE) } - if (INST_NARGS == 2 && INST_TYPE(0) == AT_INDIRECT && INST_TYPE(1) == AT_IMMEDIATE) { - if ((INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL) && INST_IMM(1).mask & IMM_U8) + if (INST_NARGS == 2 && 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) } diff --git a/src/assembler/instructions.yml b/src/assembler/instructions.yml index dc4e5e0..104a64a 100644 --- a/src/assembler/instructions.yml +++ b/src/assembler/instructions.yml @@ -84,15 +84,15 @@ add: # and: # args: yes -# return: error +# return: TODO # bit: # args: yes -# return: error +# return: TODO # call: # args: yes -# return: error +# return: TODO ccf: args: no @@ -100,7 +100,7 @@ ccf: # cp: # args: yes -# return: error +# return: TODO cpd: args: no @@ -128,7 +128,7 @@ daa: # dec: # args: yes -# return: error +# return: TODO di: args: no @@ -136,7 +136,7 @@ di: # djnz: # args: yes -# return: error +# return: TODO ei: args: no @@ -144,7 +144,7 @@ ei: # ex: # args: yes -# return: error +# return: TODO exx: args: no @@ -156,11 +156,11 @@ halt: # im: # args: yes -# return: error +# return: TODO # in: # args: yes -# return: error +# return: TODO inc: args: yes @@ -212,11 +212,11 @@ inir: # jp: # args: yes -# return: error +# return: TODO # jr: # args: yes -# return: error +# return: TODO ld: args: yes @@ -387,7 +387,7 @@ ld: return: [0xED, 0x5B, u16] - cond: [sp, imm] return: [0xED, 0x7B, u16] - - type: [indirect_hl_or_indexed, register] # TODO, support both this and regular indirect + - type: [indirect_hl_or_indexed, register] cases: - cond: [_, a] return: [0x77] @@ -450,7 +450,7 @@ nop: # or: # args: yes -# return: error +# return: TODO otdr: args: no @@ -462,7 +462,7 @@ otir: # out: # args: yes -# return: error +# return: TODO outd: args: no @@ -474,19 +474,19 @@ outi: # pop: # args: yes -# return: error +# return: TODO # push: # args: yes -# return: error +# return: TODO # res: # args: yes -# return: error +# return: TODO # ret: # args: yes -# return: error +# return: TODO reti: args: no @@ -498,7 +498,7 @@ retn: # rl: # args: yes -# return: error +# return: TODO rla: args: no @@ -506,7 +506,7 @@ rla: # rlc: # args: yes -# return: error +# return: TODO rlca: args: no @@ -518,7 +518,7 @@ rld: # rr: # args: yes -# return: error +# return: TODO rra: args: no @@ -526,7 +526,7 @@ rra: # rrc: # args: yes -# return: error +# return: TODO rrca: args: no @@ -534,15 +534,15 @@ rrca: # rrd: # args: yes -# return: error +# return: TODO # rst: # args: yes -# return: error +# return: TODO # sbc: # args: yes -# return: error +# return: TODO scf: args: no @@ -550,36 +550,36 @@ scf: # set: # args: yes -# return: error +# return: TODO # sl1: # args: yes -# return: error +# return: TODO # sla: # args: yes -# return: error +# return: TODO # sll: # args: yes -# return: error +# return: TODO # sls: # args: yes -# return: error +# return: TODO # sra: # args: yes -# return: error +# return: TODO # srl: # args: yes -# return: error +# return: TODO # sub: # args: yes -# return: error +# return: TODO # xor: # args: yes -# return: error +# return: TODO From 5c6f1c288b68066609c4d73a8b484b450d09d095 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Mon, 18 May 2015 04:12:54 -0400 Subject: [PATCH 13/25] Implement AND; cleanup for unconditional subcases. --- scripts/update_asm_instructions.py | 25 ++++++++++------ src/assembler/instructions.inc.c | 58 +++++++++++++++++++++++++++++++++----- src/assembler/instructions.yml | 30 ++++++++++++++++++-- 3 files changed, 94 insertions(+), 19 deletions(-) diff --git a/scripts/update_asm_instructions.py b/scripts/update_asm_instructions.py index 2897d5f..161514f 100755 --- a/scripts/update_asm_instructions.py +++ b/scripts/update_asm_instructions.py @@ -179,7 +179,7 @@ class Instruction(object): """ conds = [self._SUBCASE_LOOKUP_TABLE[types[i]](self, i, cond) for i, cond in enumerate(conds) if cond != "_"] - return " && ".join(conds) if conds else "1" + return " && ".join(conds) def _iter_permutations(self, types, conds): """ @@ -281,22 +281,29 @@ class Instruction(object): """ Return code to handle an instruction case. """ + ctype = case["type"] for pseudo in self.PSEUDO_TYPES: - if pseudo in case["type"]: + if pseudo in ctype: return self._handle_pseudo_case(pseudo, case) lines = [] - cond = self._build_case_type_check(case["type"]) + cond = self._build_case_type_check(ctype) lines.append(TAB + "if ({0}) {{".format(cond)) - for subcase in case["cases"]: - for perm in self._iter_permutations(case["type"], subcase["cond"]): - cond = self._build_subcase_check(case["type"], perm) - ret = self._adapt_return(case["type"], perm, subcase["return"]) - lines.append(TAB * 2 + "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 * 2 + "INST_ERROR(ARG_VALUE)") lines.append(TAB + "}") return lines diff --git a/src/assembler/instructions.inc.c b/src/assembler/instructions.inc.c index d33f4b5..564a469 100644 --- a/src/assembler/instructions.inc.c +++ b/src/assembler/instructions.inc.c @@ -7,7 +7,7 @@ `make` should trigger a rebuild when it is modified; if not, use: `python scripts/update_asm_instructions.py`. - @AUTOGEN_DATE Mon May 18 05:31:58 2015 UTC + @AUTOGEN_DATE Mon May 18 08:11:32 2015 UTC */ /* @AUTOGEN_INST_BLOCK_START */ @@ -146,6 +146,53 @@ INST_FUNC(add) INST_ERROR(ARG_TYPE) } +INST_FUNC(and) +{ + INST_TAKES_ARGS( + AT_IMMEDIATE|AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_NONE, + AT_NONE + ) + if (INST_NARGS == 1 && 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_NARGS == 1 && 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_NARGS == 1 && INST_TYPE(0) == AT_INDIRECT && + (INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL)) { + INST_RETURN(1, 0xA6) + } + if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDEXED) { + INST_RETURN(3, INST_INDEX_PREFIX(0), 0xA6, INST_INDEX(0).offset) + } + INST_ERROR(ARG_TYPE) +} + INST_FUNC(ccf) { INST_TAKES_NO_ARGS @@ -258,14 +305,10 @@ INST_FUNC(inc) } if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDIRECT && (INST_INDIRECT(0).type == AT_REGISTER && INST_INDIRECT(0).addr.reg == REG_HL)) { - if (1) - INST_RETURN(1, 0x34) - INST_ERROR(ARG_VALUE) + INST_RETURN(1, 0x34) } if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDEXED) { - if (1) - INST_RETURN(3, INST_INDEX_PREFIX(0), 0x34, INST_INDEX(0).offset) - INST_ERROR(ARG_VALUE) + INST_RETURN(3, INST_INDEX_PREFIX(0), 0x34, INST_INDEX(0).offset) } INST_ERROR(ARG_TYPE) } @@ -797,6 +840,7 @@ static ASMInstParser lookup_parser(uint32_t key) /* @AUTOGEN_LOOKUP_BLOCK_START */ HANDLE(adc) HANDLE(add) + HANDLE(and) HANDLE(ccf) HANDLE(cpd) HANDLE(cpdr) diff --git a/src/assembler/instructions.yml b/src/assembler/instructions.yml index 104a64a..3f247b8 100644 --- a/src/assembler/instructions.yml +++ b/src/assembler/instructions.yml @@ -82,9 +82,33 @@ add: - cond: [a, _] return: [0x86] -# and: -# args: yes -# return: TODO +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 From d1a0b97198c23f60c6c0ed6086f03d8c2d5df801 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Mon, 18 May 2015 04:28:03 -0400 Subject: [PATCH 14/25] Fix indexed mode offset byte position. --- scripts/update_asm_instructions.py | 2 +- src/assembler/instructions.inc.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/update_asm_instructions.py b/scripts/update_asm_instructions.py index 161514f..b4c65ca 100755 --- a/scripts/update_asm_instructions.py +++ b/scripts/update_asm_instructions.py @@ -250,7 +250,7 @@ class Instruction(object): ret.insert(0, prefix) elif types[i] == "indexed": ret.insert(0, "INST_INDEX_PREFIX({0})".format(i)) - ret.append("INST_INDEX({0}).offset".format(i)) + ret.insert(2, "INST_INDEX({0}).offset".format(i)) return ret diff --git a/src/assembler/instructions.inc.c b/src/assembler/instructions.inc.c index 564a469..bda0df7 100644 --- a/src/assembler/instructions.inc.c +++ b/src/assembler/instructions.inc.c @@ -7,7 +7,7 @@ `make` should trigger a rebuild when it is modified; if not, use: `python scripts/update_asm_instructions.py`. - @AUTOGEN_DATE Mon May 18 08:11:32 2015 UTC + @AUTOGEN_DATE Mon May 18 08:27:39 2015 UTC */ /* @AUTOGEN_INST_BLOCK_START */ @@ -695,7 +695,7 @@ INST_FUNC(ld) } if (INST_NARGS == 2 && 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_IMM(1).uval, INST_INDEX(0).offset) + INST_RETURN(4, INST_INDEX_PREFIX(0), 0x36, INST_INDEX(0).offset, INST_IMM(1).uval) INST_ERROR(ARG_VALUE) } if (INST_NARGS == 2 && INST_TYPE(0) == AT_INDIRECT && INST_TYPE(1) == AT_REGISTER) { From 631bd33b647766f6502c89fb6406a8e89bc9fe9b Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Mon, 18 May 2015 04:41:06 -0400 Subject: [PATCH 15/25] Implement BIT instruction. --- src/assembler/instructions.inc.c | 167 ++++++++++++++++++++++++++++++++++++++- src/assembler/instructions.yml | 138 +++++++++++++++++++++++++++++++- 2 files changed, 301 insertions(+), 4 deletions(-) diff --git a/src/assembler/instructions.inc.c b/src/assembler/instructions.inc.c index bda0df7..92f5a21 100644 --- a/src/assembler/instructions.inc.c +++ b/src/assembler/instructions.inc.c @@ -7,7 +7,7 @@ `make` should trigger a rebuild when it is modified; if not, use: `python scripts/update_asm_instructions.py`. - @AUTOGEN_DATE Mon May 18 08:27:39 2015 UTC + @AUTOGEN_DATE Mon May 18 08:39:52 2015 UTC */ /* @AUTOGEN_INST_BLOCK_START */ @@ -193,6 +193,170 @@ INST_FUNC(and) INST_ERROR(ARG_TYPE) } +INST_FUNC(bit) +{ + INST_TAKES_ARGS( + AT_IMMEDIATE, + AT_INDEXED|AT_INDIRECT|AT_REGISTER, + AT_NONE + ) + if (INST_NARGS == 2 && INST_TYPE(0) == AT_IMMEDIATE && INST_TYPE(1) == AT_REGISTER) { + if ((INST_IMM(0).mask & IMM_BIT && !INST_IMM(0).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && INST_IMM(0).uval == 7) && INST_REG(1) == REG_L) + INST_RETURN(2, 0xCB, 0x7D) + 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).is_label && INST_IMM(0).uval == 0)) + INST_RETURN(2, 0xCB, 0x46) + if ((INST_IMM(0).mask & IMM_BIT && !INST_IMM(0).is_label && INST_IMM(0).uval == 1)) + INST_RETURN(2, 0xCB, 0x4E) + if ((INST_IMM(0).mask & IMM_BIT && !INST_IMM(0).is_label && INST_IMM(0).uval == 2)) + INST_RETURN(2, 0xCB, 0x56) + if ((INST_IMM(0).mask & IMM_BIT && !INST_IMM(0).is_label && INST_IMM(0).uval == 3)) + INST_RETURN(2, 0xCB, 0x5E) + if ((INST_IMM(0).mask & IMM_BIT && !INST_IMM(0).is_label && INST_IMM(0).uval == 4)) + INST_RETURN(2, 0xCB, 0x66) + if ((INST_IMM(0).mask & IMM_BIT && !INST_IMM(0).is_label && INST_IMM(0).uval == 5)) + INST_RETURN(2, 0xCB, 0x6E) + if ((INST_IMM(0).mask & IMM_BIT && !INST_IMM(0).is_label && INST_IMM(0).uval == 6)) + INST_RETURN(2, 0xCB, 0x76) + if ((INST_IMM(0).mask & IMM_BIT && !INST_IMM(0).is_label && INST_IMM(0).uval == 7)) + INST_RETURN(2, 0xCB, 0x7E) + 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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).is_label && 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(ccf) { INST_TAKES_NO_ARGS @@ -841,6 +1005,7 @@ static ASMInstParser lookup_parser(uint32_t key) HANDLE(adc) HANDLE(add) HANDLE(and) + HANDLE(bit) HANDLE(ccf) HANDLE(cpd) HANDLE(cpdr) diff --git a/src/assembler/instructions.yml b/src/assembler/instructions.yml index 3f247b8..a993e2c 100644 --- a/src/assembler/instructions.yml +++ b/src/assembler/instructions.yml @@ -110,9 +110,141 @@ and: - cond: [_] return: [0xA6] -# bit: -# args: yes -# return: TODO +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 From 308af448d86714835a38ceab2d08a63c5de3063f Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Mon, 18 May 2015 04:45:19 -0400 Subject: [PATCH 16/25] Don't check immediate's is_label if it's not a U16. --- scripts/update_asm_instructions.py | 7 +- src/assembler/instructions.inc.c | 146 ++++++++++++++++++------------------- 2 files changed, 77 insertions(+), 76 deletions(-) diff --git a/scripts/update_asm_instructions.py b/scripts/update_asm_instructions.py index b4c65ca..95ba6c7 100755 --- a/scripts/update_asm_instructions.py +++ b/scripts/update_asm_instructions.py @@ -114,9 +114,10 @@ class Instruction(object): vtype = "sval" if itype.upper() in ["S8", "REL"] else "uval" test1 = "INST_IMM({0}).mask & IMM_{1}".format(num, itype.upper()) - test2 = "!INST_IMM({0}).is_label".format(num) - test3 = "INST_IMM({0}).{1} == {2}".format(num, vtype, value) - return "({0} && {1} && {2})".format(test1, test2, test3) + 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()) diff --git a/src/assembler/instructions.inc.c b/src/assembler/instructions.inc.c index 92f5a21..90bbcd6 100644 --- a/src/assembler/instructions.inc.c +++ b/src/assembler/instructions.inc.c @@ -7,7 +7,7 @@ `make` should trigger a rebuild when it is modified; if not, use: `python scripts/update_asm_instructions.py`. - @AUTOGEN_DATE Mon May 18 08:39:52 2015 UTC + @AUTOGEN_DATE Mon May 18 08:43:46 2015 UTC */ /* @AUTOGEN_INST_BLOCK_START */ @@ -201,156 +201,156 @@ INST_FUNC(bit) AT_NONE ) if (INST_NARGS == 2 && INST_TYPE(0) == AT_IMMEDIATE && INST_TYPE(1) == AT_REGISTER) { - if ((INST_IMM(0).mask & IMM_BIT && !INST_IMM(0).is_label && INST_IMM(0).uval == 0) && INST_REG(1) == REG_A) + 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).is_label && INST_IMM(0).uval == 0) && INST_REG(1) == REG_B) + 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).is_label && INST_IMM(0).uval == 0) && INST_REG(1) == REG_C) + 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).is_label && INST_IMM(0).uval == 0) && INST_REG(1) == REG_D) + 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).is_label && INST_IMM(0).uval == 0) && INST_REG(1) == REG_E) + 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).is_label && INST_IMM(0).uval == 0) && INST_REG(1) == REG_H) + 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).is_label && INST_IMM(0).uval == 0) && INST_REG(1) == REG_L) + 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).is_label && INST_IMM(0).uval == 1) && INST_REG(1) == REG_A) + 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).is_label && INST_IMM(0).uval == 1) && INST_REG(1) == REG_B) + 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).is_label && INST_IMM(0).uval == 1) && INST_REG(1) == REG_C) + 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).is_label && INST_IMM(0).uval == 1) && INST_REG(1) == REG_D) + 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).is_label && INST_IMM(0).uval == 1) && INST_REG(1) == REG_E) + 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).is_label && INST_IMM(0).uval == 1) && INST_REG(1) == REG_H) + 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).is_label && INST_IMM(0).uval == 1) && INST_REG(1) == REG_L) + 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).is_label && INST_IMM(0).uval == 2) && INST_REG(1) == REG_A) + 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).is_label && INST_IMM(0).uval == 2) && INST_REG(1) == REG_B) + 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).is_label && INST_IMM(0).uval == 2) && INST_REG(1) == REG_C) + 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).is_label && INST_IMM(0).uval == 2) && INST_REG(1) == REG_D) + 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).is_label && INST_IMM(0).uval == 2) && INST_REG(1) == REG_E) + 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).is_label && INST_IMM(0).uval == 2) && INST_REG(1) == REG_H) + 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).is_label && INST_IMM(0).uval == 2) && INST_REG(1) == REG_L) + 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).is_label && INST_IMM(0).uval == 3) && INST_REG(1) == REG_A) + 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).is_label && INST_IMM(0).uval == 3) && INST_REG(1) == REG_B) + 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).is_label && INST_IMM(0).uval == 3) && INST_REG(1) == REG_C) + 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).is_label && INST_IMM(0).uval == 3) && INST_REG(1) == REG_D) + 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).is_label && INST_IMM(0).uval == 3) && INST_REG(1) == REG_E) + 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).is_label && INST_IMM(0).uval == 3) && INST_REG(1) == REG_H) + 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).is_label && INST_IMM(0).uval == 3) && INST_REG(1) == REG_L) + 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).is_label && INST_IMM(0).uval == 4) && INST_REG(1) == REG_A) + 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).is_label && INST_IMM(0).uval == 4) && INST_REG(1) == REG_B) + 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).is_label && INST_IMM(0).uval == 4) && INST_REG(1) == REG_C) + 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).is_label && INST_IMM(0).uval == 4) && INST_REG(1) == REG_D) + 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).is_label && INST_IMM(0).uval == 4) && INST_REG(1) == REG_E) + 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).is_label && INST_IMM(0).uval == 4) && INST_REG(1) == REG_H) + 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).is_label && INST_IMM(0).uval == 4) && INST_REG(1) == REG_L) + 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).is_label && INST_IMM(0).uval == 5) && INST_REG(1) == REG_A) + 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).is_label && INST_IMM(0).uval == 5) && INST_REG(1) == REG_B) + 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).is_label && INST_IMM(0).uval == 5) && INST_REG(1) == REG_C) + 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).is_label && INST_IMM(0).uval == 5) && INST_REG(1) == REG_D) + 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).is_label && INST_IMM(0).uval == 5) && INST_REG(1) == REG_E) + 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).is_label && INST_IMM(0).uval == 5) && INST_REG(1) == REG_H) + 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).is_label && INST_IMM(0).uval == 5) && INST_REG(1) == REG_L) + 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).is_label && INST_IMM(0).uval == 6) && INST_REG(1) == REG_A) + 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).is_label && INST_IMM(0).uval == 6) && INST_REG(1) == REG_B) + 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).is_label && INST_IMM(0).uval == 6) && INST_REG(1) == REG_C) + 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).is_label && INST_IMM(0).uval == 6) && INST_REG(1) == REG_D) + 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).is_label && INST_IMM(0).uval == 6) && INST_REG(1) == REG_E) + 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).is_label && INST_IMM(0).uval == 6) && INST_REG(1) == REG_H) + 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).is_label && INST_IMM(0).uval == 6) && INST_REG(1) == REG_L) + 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).is_label && INST_IMM(0).uval == 7) && INST_REG(1) == REG_A) + 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).is_label && INST_IMM(0).uval == 7) && INST_REG(1) == REG_B) + 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).is_label && INST_IMM(0).uval == 7) && INST_REG(1) == REG_C) + 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).is_label && INST_IMM(0).uval == 7) && INST_REG(1) == REG_D) + 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).is_label && INST_IMM(0).uval == 7) && INST_REG(1) == REG_E) + 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).is_label && INST_IMM(0).uval == 7) && INST_REG(1) == REG_H) + 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).is_label && INST_IMM(0).uval == 7) && INST_REG(1) == REG_L) + 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_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).is_label && INST_IMM(0).uval == 0)) + 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).is_label && INST_IMM(0).uval == 1)) + 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).is_label && INST_IMM(0).uval == 2)) + 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).is_label && INST_IMM(0).uval == 3)) + 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).is_label && INST_IMM(0).uval == 4)) + 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).is_label && INST_IMM(0).uval == 5)) + 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).is_label && INST_IMM(0).uval == 6)) + 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).is_label && INST_IMM(0).uval == 7)) + if ((INST_IMM(0).mask & IMM_BIT && INST_IMM(0).uval == 7)) INST_RETURN(2, 0xCB, 0x7E) 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).is_label && INST_IMM(0).uval == 0)) + 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).is_label && INST_IMM(0).uval == 1)) + 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).is_label && INST_IMM(0).uval == 2)) + 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).is_label && INST_IMM(0).uval == 3)) + 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).is_label && INST_IMM(0).uval == 4)) + 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).is_label && INST_IMM(0).uval == 5)) + 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).is_label && INST_IMM(0).uval == 6)) + 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).is_label && INST_IMM(0).uval == 7)) + 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) } From 4bc8339ba115d5a28865be51c75511085fb315a0 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Mon, 18 May 2015 04:56:01 -0400 Subject: [PATCH 17/25] Implement CALL; bugfix for condition 'Z'. --- src/assembler/inst_args.h | 2 +- src/assembler/instructions.inc.c | 37 ++++++++++++++++++++++++++++++++++++- src/assembler/instructions.yml | 28 +++++++++++++++++++++++++--- src/assembler/parse_util.c | 2 +- 4 files changed, 63 insertions(+), 6 deletions(-) diff --git a/src/assembler/inst_args.h b/src/assembler/inst_args.h index 910f11c..83647d0 100644 --- a/src/assembler/inst_args.h +++ b/src/assembler/inst_args.h @@ -57,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 { diff --git a/src/assembler/instructions.inc.c b/src/assembler/instructions.inc.c index 90bbcd6..32afd0f 100644 --- a/src/assembler/instructions.inc.c +++ b/src/assembler/instructions.inc.c @@ -7,7 +7,7 @@ `make` should trigger a rebuild when it is modified; if not, use: `python scripts/update_asm_instructions.py`. - @AUTOGEN_DATE Mon May 18 08:43:46 2015 UTC + @AUTOGEN_DATE Mon May 18 08:55:31 2015 UTC */ /* @AUTOGEN_INST_BLOCK_START */ @@ -357,6 +357,40 @@ INST_FUNC(bit) 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 @@ -1006,6 +1040,7 @@ static ASMInstParser lookup_parser(uint32_t key) HANDLE(add) HANDLE(and) HANDLE(bit) + HANDLE(call) HANDLE(ccf) HANDLE(cpd) HANDLE(cpdr) diff --git a/src/assembler/instructions.yml b/src/assembler/instructions.yml index a993e2c..91fbf18 100644 --- a/src/assembler/instructions.yml +++ b/src/assembler/instructions.yml @@ -246,9 +246,31 @@ bit: - cond: [bit.7, _] return: [0xCB, 0x7E] -# call: -# args: yes -# return: TODO +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 diff --git a/src/assembler/parse_util.c b/src/assembler/parse_util.c index bed1b6b..e5c4c02 100644 --- a/src/assembler/parse_util.c +++ b/src/assembler/parse_util.c @@ -302,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; From 980383feee58ec3998c7dcd2712c752d11b51b68 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Mon, 18 May 2015 05:05:12 -0400 Subject: [PATCH 18/25] Don't check INST_NARGS unless inst has optional arguments. --- scripts/update_asm_instructions.py | 8 +++++- src/assembler/instructions.inc.c | 58 +++++++++++++++++++------------------- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/scripts/update_asm_instructions.py b/scripts/update_asm_instructions.py index 95ba6c7..354c718 100755 --- a/scripts/update_asm_instructions.py +++ b/scripts/update_asm_instructions.py @@ -56,6 +56,7 @@ class Instruction(object): def __init__(self, name, data): self._name = name self._data = data + self._has_optional_args = False def _get_arg_parse_mask(self, num): """ @@ -77,6 +78,7 @@ class Instruction(object): 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): @@ -93,7 +95,11 @@ class Instruction(object): """ conds = ["INST_TYPE({0}) == {1}".format(i, self.ARG_TYPES[cond]) for i, cond in enumerate(args)] - return "INST_NARGS == {0} && {1}".format(len(args), " && ".join(conds)) + 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): """ diff --git a/src/assembler/instructions.inc.c b/src/assembler/instructions.inc.c index 32afd0f..15a6891 100644 --- a/src/assembler/instructions.inc.c +++ b/src/assembler/instructions.inc.c @@ -7,7 +7,7 @@ `make` should trigger a rebuild when it is modified; if not, use: `python scripts/update_asm_instructions.py`. - @AUTOGEN_DATE Mon May 18 08:55:31 2015 UTC + @AUTOGEN_DATE Mon May 18 09:04:07 2015 UTC */ /* @AUTOGEN_INST_BLOCK_START */ @@ -19,7 +19,7 @@ INST_FUNC(adc) AT_IMMEDIATE|AT_INDEXED|AT_INDIRECT|AT_REGISTER, AT_NONE ) - if (INST_NARGS == 2 && INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_REGISTER) { + 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) @@ -52,18 +52,18 @@ INST_FUNC(adc) INST_RETURN(2, 0xED, 0x7A) INST_ERROR(ARG_VALUE) } - if (INST_NARGS == 2 && INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_IMMEDIATE) { + 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_NARGS == 2 && INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_INDIRECT && + 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_NARGS == 2 && INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_INDEXED) { + 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) @@ -78,7 +78,7 @@ INST_FUNC(add) AT_IMMEDIATE|AT_INDEXED|AT_INDIRECT|AT_REGISTER, AT_NONE ) - if (INST_NARGS == 2 && INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_REGISTER) { + 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) @@ -127,18 +127,18 @@ INST_FUNC(add) INST_RETURN(2, INST_IY_PREFIX, 0x39) INST_ERROR(ARG_VALUE) } - if (INST_NARGS == 2 && INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_IMMEDIATE) { + 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_NARGS == 2 && INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_INDIRECT && + 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_NARGS == 2 && INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_INDEXED) { + 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) @@ -153,7 +153,7 @@ INST_FUNC(and) AT_NONE, AT_NONE ) - if (INST_NARGS == 1 && INST_TYPE(0) == AT_REGISTER) { + if (INST_TYPE(0) == AT_REGISTER) { if (INST_REG(0) == REG_A) INST_RETURN(1, 0xA7) if (INST_REG(0) == REG_B) @@ -178,16 +178,16 @@ INST_FUNC(and) INST_RETURN(2, INST_IY_PREFIX, 0xA5) INST_ERROR(ARG_VALUE) } - if (INST_NARGS == 1 && INST_TYPE(0) == AT_IMMEDIATE) { + 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_NARGS == 1 && INST_TYPE(0) == AT_INDIRECT && + 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_NARGS == 1 && INST_TYPE(0) == AT_INDEXED) { + if (INST_TYPE(0) == AT_INDEXED) { INST_RETURN(3, INST_INDEX_PREFIX(0), 0xA6, INST_INDEX(0).offset) } INST_ERROR(ARG_TYPE) @@ -200,7 +200,7 @@ INST_FUNC(bit) AT_INDEXED|AT_INDIRECT|AT_REGISTER, AT_NONE ) - if (INST_NARGS == 2 && INST_TYPE(0) == AT_IMMEDIATE && INST_TYPE(1) == AT_REGISTER) { + 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) @@ -315,7 +315,7 @@ INST_FUNC(bit) INST_RETURN(2, 0xCB, 0x7D) INST_ERROR(ARG_VALUE) } - if (INST_NARGS == 2 && INST_TYPE(0) == AT_IMMEDIATE && INST_TYPE(1) == AT_INDIRECT && + 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) @@ -335,7 +335,7 @@ INST_FUNC(bit) INST_RETURN(2, 0xCB, 0x7E) INST_ERROR(ARG_VALUE) } - if (INST_NARGS == 2 && INST_TYPE(0) == AT_IMMEDIATE && INST_TYPE(1) == AT_INDEXED) { + 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)) @@ -464,7 +464,7 @@ INST_FUNC(inc) AT_NONE, AT_NONE ) - if (INST_NARGS == 1 && INST_TYPE(0) == AT_REGISTER) { + if (INST_TYPE(0) == AT_REGISTER) { if (INST_REG(0) == REG_A) INST_RETURN(1, 0x3C) if (INST_REG(0) == REG_B) @@ -501,11 +501,11 @@ INST_FUNC(inc) INST_RETURN(1, 0x33) INST_ERROR(ARG_VALUE) } - if (INST_NARGS == 1 && INST_TYPE(0) == AT_INDIRECT && + 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_NARGS == 1 && INST_TYPE(0) == AT_INDEXED) { + if (INST_TYPE(0) == AT_INDEXED) { INST_RETURN(3, INST_INDEX_PREFIX(0), 0x34, INST_INDEX(0).offset) } INST_ERROR(ARG_TYPE) @@ -542,7 +542,7 @@ INST_FUNC(ld) AT_IMMEDIATE|AT_INDEXED|AT_INDIRECT|AT_REGISTER, AT_NONE ) - if (INST_NARGS == 2 && INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_REGISTER) { + 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) @@ -757,7 +757,7 @@ INST_FUNC(ld) INST_RETURN(2, INST_IY_PREFIX, 0xF9) INST_ERROR(ARG_VALUE) } - if (INST_NARGS == 2 && INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_IMMEDIATE) { + 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) @@ -794,7 +794,7 @@ INST_FUNC(ld) INST_RETURN(3, 0x31, INST_IMM_U16_B1(INST_IMM(1)), INST_IMM_U16_B2(INST_IMM(1))) INST_ERROR(ARG_VALUE) } - if (INST_NARGS == 2 && INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_INDIRECT && + 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) @@ -812,7 +812,7 @@ INST_FUNC(ld) INST_RETURN(1, 0x6E) INST_ERROR(ARG_VALUE) } - if (INST_NARGS == 2 && INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_INDEXED) { + 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) @@ -829,7 +829,7 @@ INST_FUNC(ld) INST_RETURN(3, INST_INDEX_PREFIX(1), 0x6E, INST_INDEX(1).offset) INST_ERROR(ARG_VALUE) } - if (INST_NARGS == 2 && INST_TYPE(0) == AT_REGISTER && INST_TYPE(1) == AT_INDIRECT) { + 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)) @@ -850,7 +850,7 @@ INST_FUNC(ld) 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_NARGS == 2 && INST_TYPE(0) == AT_INDIRECT && INST_TYPE(1) == AT_REGISTER && + 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) @@ -868,7 +868,7 @@ INST_FUNC(ld) INST_RETURN(1, 0x75) INST_ERROR(ARG_VALUE) } - if (INST_NARGS == 2 && INST_TYPE(0) == AT_INDEXED && INST_TYPE(1) == AT_REGISTER) { + 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) @@ -885,18 +885,18 @@ INST_FUNC(ld) INST_RETURN(3, INST_INDEX_PREFIX(0), 0x75, INST_INDEX(0).offset) INST_ERROR(ARG_VALUE) } - if (INST_NARGS == 2 && INST_TYPE(0) == AT_INDIRECT && INST_TYPE(1) == AT_IMMEDIATE && + 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_NARGS == 2 && INST_TYPE(0) == AT_INDEXED && INST_TYPE(1) == AT_IMMEDIATE) { + 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_NARGS == 2 && INST_TYPE(0) == AT_INDIRECT && INST_TYPE(1) == AT_REGISTER) { + 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) From 5e9b890285f19d5059cb97eeaf56e262c6aa479b Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Tue, 19 May 2015 02:51:56 -0400 Subject: [PATCH 19/25] Support relative addressing in update script; implement CP/DEC/DJNZ. --- scripts/update_asm_instructions.py | 4 ++ src/assembler/instructions.inc.c | 121 ++++++++++++++++++++++++++++++++++++- src/assembler/instructions.yml | 74 ++++++++++++++++++++--- 3 files changed, 189 insertions(+), 10 deletions(-) diff --git a/scripts/update_asm_instructions.py b/scripts/update_asm_instructions.py index 354c718..cce99ff 100755 --- a/scripts/update_asm_instructions.py +++ b/scripts/update_asm_instructions.py @@ -246,6 +246,10 @@ class Instruction(object): 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)) diff --git a/src/assembler/instructions.inc.c b/src/assembler/instructions.inc.c index 15a6891..c7aef17 100644 --- a/src/assembler/instructions.inc.c +++ b/src/assembler/instructions.inc.c @@ -7,7 +7,7 @@ `make` should trigger a rebuild when it is modified; if not, use: `python scripts/update_asm_instructions.py`. - @AUTOGEN_DATE Mon May 18 09:04:07 2015 UTC + @AUTOGEN_DATE Tue May 19 06:49:06 2015 UTC */ /* @AUTOGEN_INST_BLOCK_START */ @@ -397,6 +397,53 @@ INST_FUNC(ccf) 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 @@ -433,12 +480,81 @@ INST_FUNC(daa) 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 @@ -1042,13 +1158,16 @@ static ASMInstParser lookup_parser(uint32_t key) 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(exx) HANDLE(halt) diff --git a/src/assembler/instructions.yml b/src/assembler/instructions.yml index 91fbf18..dfd1c5b 100644 --- a/src/assembler/instructions.yml +++ b/src/assembler/instructions.yml @@ -276,9 +276,33 @@ ccf: args: no return: [0x3F] -# cp: -# args: yes -# return: TODO +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 @@ -304,17 +328,49 @@ daa: args: no return: [0x27] -# dec: -# args: yes -# return: TODO +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 -# return: TODO +djnz: + args: yes + cases: + - type: [immediate] + cases: + - cond: [rel] + return: [0x10, rel] ei: args: no From b5459549b0962e6268cdf4a5d817601c7b9ce15b Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Tue, 19 May 2015 03:11:34 -0400 Subject: [PATCH 20/25] Support ports in update script; implement EX/IM/IN. --- scripts/update_asm_instructions.py | 17 ++++---- src/assembler/instructions.inc.c | 84 +++++++++++++++++++++++++++++++++++++- src/assembler/instructions.yml | 60 ++++++++++++++++++++++----- 3 files changed, 142 insertions(+), 19 deletions(-) diff --git a/scripts/update_asm_instructions.py b/scripts/update_asm_instructions.py index cce99ff..bbb06d5 100755 --- a/scripts/update_asm_instructions.py +++ b/scripts/update_asm_instructions.py @@ -159,12 +159,8 @@ class Instruction(object): """ Return an expression to check for a particular port value. """ - if cond.startswith("reg."): - test1 = "INST_PORT({0}).type == AT_REGISTER".format(num) - test2 = "INST_PORT({0}).port.reg == REG_{1}".format( - num, cond[len("reg."):].upper()) - return "({0} && {1})".format(test1, test2) - + 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) @@ -227,8 +223,13 @@ class Instruction(object): for i, byte in enumerate(ret): if not isinstance(byte, int): if byte == "u8": - index = types.index("immediate") - ret[i] = "INST_IMM({0}).uval".format(index) + 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: diff --git a/src/assembler/instructions.inc.c b/src/assembler/instructions.inc.c index c7aef17..4bcf4d3 100644 --- a/src/assembler/instructions.inc.c +++ b/src/assembler/instructions.inc.c @@ -7,7 +7,7 @@ `make` should trigger a rebuild when it is modified; if not, use: `python scripts/update_asm_instructions.py`. - @AUTOGEN_DATE Tue May 19 06:49:06 2015 UTC + @AUTOGEN_DATE Tue May 19 07:10:15 2015 UTC */ /* @AUTOGEN_INST_BLOCK_START */ @@ -561,6 +561,32 @@ INST_FUNC(ei) 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 @@ -573,6 +599,59 @@ INST_FUNC(halt) 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( @@ -1169,8 +1248,11 @@ static ASMInstParser lookup_parser(uint32_t key) HANDLE(di) HANDLE(djnz) HANDLE(ei) + HANDLE(ex) HANDLE(exx) HANDLE(halt) + HANDLE(im) + HANDLE(in) HANDLE(inc) HANDLE(ind) HANDLE(indr) diff --git a/src/assembler/instructions.yml b/src/assembler/instructions.yml index dfd1c5b..5c28308 100644 --- a/src/assembler/instructions.yml +++ b/src/assembler/instructions.yml @@ -376,9 +376,19 @@ ei: args: no return: [0xFB] -# ex: -# args: yes -# return: TODO +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 @@ -388,13 +398,43 @@ halt: args: no return: [0x76] -# im: -# args: yes -# return: TODO - -# in: -# args: yes -# return: TODO +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 From 5fab99ee17af07de661d35c1901c6d78a5e8bd4c Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Wed, 20 May 2015 02:25:08 -0400 Subject: [PATCH 21/25] Implement JP, JR, OR, OUT. --- src/assembler/instructions.inc.c | 154 ++++++++++++++++++++++++++++++++++++++- src/assembler/instructions.yml | 110 +++++++++++++++++++++++++--- 2 files changed, 251 insertions(+), 13 deletions(-) diff --git a/src/assembler/instructions.inc.c b/src/assembler/instructions.inc.c index 4bcf4d3..e1088ba 100644 --- a/src/assembler/instructions.inc.c +++ b/src/assembler/instructions.inc.c @@ -7,7 +7,7 @@ `make` should trigger a rebuild when it is modified; if not, use: `python scripts/update_asm_instructions.py`. - @AUTOGEN_DATE Tue May 19 07:10:15 2015 UTC + @AUTOGEN_DATE Wed May 20 06:24:37 2015 UTC */ /* @AUTOGEN_INST_BLOCK_START */ @@ -730,6 +730,73 @@ INST_FUNC(inir) 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( @@ -1151,6 +1218,53 @@ INST_FUNC(nop) 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 @@ -1163,6 +1277,40 @@ INST_FUNC(otir) 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 @@ -1258,6 +1406,8 @@ static ASMInstParser lookup_parser(uint32_t key) HANDLE(indr) HANDLE(ini) HANDLE(inir) + HANDLE(jp) + HANDLE(jr) HANDLE(ld) HANDLE(ldd) HANDLE(lddr) @@ -1265,8 +1415,10 @@ static ASMInstParser lookup_parser(uint32_t key) HANDLE(ldir) HANDLE(neg) HANDLE(nop) + HANDLE(or) HANDLE(otdr) HANDLE(otir) + HANDLE(out) HANDLE(outd) HANDLE(outi) HANDLE(reti) diff --git a/src/assembler/instructions.yml b/src/assembler/instructions.yml index 5c28308..488a71a 100644 --- a/src/assembler/instructions.yml +++ b/src/assembler/instructions.yml @@ -484,13 +484,53 @@ inir: args: no return: [0xED, 0xB2] -# jp: -# args: yes -# return: TODO +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 -# return: TODO +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 @@ -722,9 +762,33 @@ nop: args: no return: [0x00] -# or: -# args: yes -# return: TODO +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 @@ -734,9 +798,31 @@ otir: args: no return: [0xED, 0xB3] -# out: -# args: yes -# return: TODO +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 From f341148eb7b35507f80ab5f735072f9316fa6b21 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Wed, 20 May 2015 02:40:40 -0400 Subject: [PATCH 22/25] Implement POP, PUSH, RES, and SET. --- src/assembler/instructions.inc.c | 614 ++++++++++++++++++++++++++++++++++++++- src/assembler/instructions.yml | 536 +++++++++++++++++++++++++++++++++- 2 files changed, 1137 insertions(+), 13 deletions(-) diff --git a/src/assembler/instructions.inc.c b/src/assembler/instructions.inc.c index e1088ba..c368a00 100644 --- a/src/assembler/instructions.inc.c +++ b/src/assembler/instructions.inc.c @@ -7,7 +7,7 @@ `make` should trigger a rebuild when it is modified; if not, use: `python scripts/update_asm_instructions.py`. - @AUTOGEN_DATE Wed May 20 06:24:37 2015 UTC + @AUTOGEN_DATE Wed May 20 06:40:09 2015 UTC */ /* @AUTOGEN_INST_BLOCK_START */ @@ -1323,6 +1323,335 @@ INST_FUNC(outi) 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(reti) { INST_TAKES_NO_ARGS @@ -1371,6 +1700,285 @@ INST_FUNC(scf) 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) +} + /* @AUTOGEN_INST_BLOCK_END */ /* @@ -1421,6 +2029,9 @@ static ASMInstParser lookup_parser(uint32_t key) HANDLE(out) HANDLE(outd) HANDLE(outi) + HANDLE(pop) + HANDLE(push) + HANDLE(res) HANDLE(reti) HANDLE(retn) HANDLE(rla) @@ -1429,6 +2040,7 @@ static ASMInstParser lookup_parser(uint32_t key) HANDLE(rra) HANDLE(rrca) HANDLE(scf) + HANDLE(set) /* @AUTOGEN_LOOKUP_BLOCK_END */ return NULL; } diff --git a/src/assembler/instructions.yml b/src/assembler/instructions.yml index 488a71a..6815608 100644 --- a/src/assembler/instructions.yml +++ b/src/assembler/instructions.yml @@ -832,17 +832,283 @@ outi: args: no return: [0xED, 0xA3] -# pop: -# args: yes -# return: TODO +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 -# return: TODO +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 -# return: TODO +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 @@ -908,9 +1174,255 @@ scf: args: no return: [0x37] -# set: -# args: yes -# return: TODO +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: # args: yes From 071cad0563283ee49933c928c1197acfb88bf24a Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Wed, 20 May 2015 02:54:40 -0400 Subject: [PATCH 23/25] Support instructions with args and no args; implement RET. --- scripts/update_asm_instructions.py | 13 +++++++++++++ src/assembler/instructions.c | 2 -- src/assembler/instructions.inc.c | 35 ++++++++++++++++++++++++++++++++++- src/assembler/instructions.yml | 26 +++++++++++++++++++++++--- 4 files changed, 70 insertions(+), 6 deletions(-) diff --git a/scripts/update_asm_instructions.py b/scripts/update_asm_instructions.py index bbb06d5..94f9608 100755 --- a/scripts/update_asm_instructions.py +++ b/scripts/update_asm_instructions.py @@ -266,6 +266,16 @@ class Instruction(object): 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. @@ -294,6 +304,9 @@ class Instruction(object): 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) diff --git a/src/assembler/instructions.c b/src/assembler/instructions.c index ac2558f..04e0cea 100644 --- a/src/assembler/instructions.c +++ b/src/assembler/instructions.c @@ -65,8 +65,6 @@ static ASMErrorDesc parse_inst_##mnemonic( \ INST_ERROR(TOO_MANY_ARGS) #define INST_TAKES_ARGS(a0, a1, a2) \ - if (!ap_info.arg) \ - INST_ERROR(TOO_FEW_ARGS) \ ASMInstArg args[3]; \ size_t nargs; \ ASMArgType masks[] = {a0, a1, a2}; \ diff --git a/src/assembler/instructions.inc.c b/src/assembler/instructions.inc.c index c368a00..3e3ce2a 100644 --- a/src/assembler/instructions.inc.c +++ b/src/assembler/instructions.inc.c @@ -7,7 +7,7 @@ `make` should trigger a rebuild when it is modified; if not, use: `python scripts/update_asm_instructions.py`. - @AUTOGEN_DATE Wed May 20 06:40:09 2015 UTC + @AUTOGEN_DATE Wed May 20 06:53:00 2015 UTC */ /* @AUTOGEN_INST_BLOCK_START */ @@ -1652,6 +1652,38 @@ INST_FUNC(res) 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 @@ -2032,6 +2064,7 @@ static ASMInstParser lookup_parser(uint32_t key) HANDLE(pop) HANDLE(push) HANDLE(res) + HANDLE(ret) HANDLE(reti) HANDLE(retn) HANDLE(rla) diff --git a/src/assembler/instructions.yml b/src/assembler/instructions.yml index 6815608..ad68719 100644 --- a/src/assembler/instructions.yml +++ b/src/assembler/instructions.yml @@ -1110,9 +1110,29 @@ res: - cond: [bit.7, _, l] return: [0xCB, 0xBD] -# ret: -# args: yes -# return: TODO +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 From a8de15de2dccf91168b1a909b621c0272eaeafb9 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Wed, 20 May 2015 03:17:40 -0400 Subject: [PATCH 24/25] Implement RL, RLC, RR, RRC, SLA, SRA, SRL, and SL1/SLL/SLS. --- src/assembler/instructions.inc.c | 514 ++++++++++++++++++++++++++++++++++++++- src/assembler/instructions.yml | 344 +++++++++++++++++++++++--- 2 files changed, 827 insertions(+), 31 deletions(-) diff --git a/src/assembler/instructions.inc.c b/src/assembler/instructions.inc.c index 3e3ce2a..fcf8216 100644 --- a/src/assembler/instructions.inc.c +++ b/src/assembler/instructions.inc.c @@ -7,7 +7,7 @@ `make` should trigger a rebuild when it is modified; if not, use: `python scripts/update_asm_instructions.py`. - @AUTOGEN_DATE Wed May 20 06:53:00 2015 UTC + @AUTOGEN_DATE Wed May 20 07:15:29 2015 UTC */ /* @AUTOGEN_INST_BLOCK_START */ @@ -1696,12 +1696,114 @@ INST_FUNC(retn) 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 @@ -1714,12 +1816,114 @@ INST_FUNC(rld) 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 @@ -2011,6 +2215,304 @@ INST_FUNC(set) 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) +} + /* @AUTOGEN_INST_BLOCK_END */ /* @@ -2067,13 +2569,23 @@ static ASMInstParser lookup_parser(uint32_t key) 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(scf) HANDLE(set) + HANDLE(sl1) + HANDLE(sla) + HANDLE(sll) + HANDLE(sls) + HANDLE(sra) + HANDLE(srl) /* @AUTOGEN_LOOKUP_BLOCK_END */ return NULL; } diff --git a/src/assembler/instructions.yml b/src/assembler/instructions.yml index ad68719..bf4fd85 100644 --- a/src/assembler/instructions.yml +++ b/src/assembler/instructions.yml @@ -1142,17 +1142,89 @@ retn: args: no return: [0xED, 0x45] -# rl: -# args: yes -# return: TODO +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 -# return: TODO +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 @@ -1162,17 +1234,89 @@ rld: args: no return: [0xED, 0x6F] -# rr: -# args: yes -# return: TODO +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 -# return: TODO +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 @@ -1444,29 +1588,169 @@ set: - cond: [bit.7, _, l] return: [0xCB, 0xFD] -# sl1: -# args: yes -# return: TODO +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 -# return: TODO +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: -# args: yes -# return: TODO +sll: *sl1 -# sls: -# args: yes -# return: TODO +sls: *sl1 -# sra: -# args: yes -# return: TODO +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 -# return: TODO +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 From 764211a379ad551d13bd6b8c8c468d72c7ffb12c Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Wed, 20 May 2015 03:34:50 -0400 Subject: [PATCH 25/25] Implement RRD, RST, SBC, SUB, and XOR. --- src/assembler/instructions.inc.c | 195 ++++++++++++++++++++++++++++++++++++++- src/assembler/instructions.yml | 130 ++++++++++++++++++++++---- 2 files changed, 308 insertions(+), 17 deletions(-) diff --git a/src/assembler/instructions.inc.c b/src/assembler/instructions.inc.c index fcf8216..9bbd8d8 100644 --- a/src/assembler/instructions.inc.c +++ b/src/assembler/instructions.inc.c @@ -7,7 +7,7 @@ `make` should trigger a rebuild when it is modified; if not, use: `python scripts/update_asm_instructions.py`. - @AUTOGEN_DATE Wed May 20 07:15:29 2015 UTC + @AUTOGEN_DATE Wed May 20 07:34:18 2015 UTC */ /* @AUTOGEN_INST_BLOCK_START */ @@ -1930,6 +1930,100 @@ INST_FUNC(rrca) 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 @@ -2513,6 +2607,100 @@ INST_FUNC(srl) 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 */ /* @@ -2578,6 +2766,9 @@ static ASMInstParser lookup_parser(uint32_t key) HANDLE(rra) HANDLE(rrc) HANDLE(rrca) + HANDLE(rrd) + HANDLE(rst) + HANDLE(sbc) HANDLE(scf) HANDLE(set) HANDLE(sl1) @@ -2586,6 +2777,8 @@ static ASMInstParser lookup_parser(uint32_t key) 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 index bf4fd85..3acea68 100644 --- a/src/assembler/instructions.yml +++ b/src/assembler/instructions.yml @@ -1322,17 +1322,67 @@ rrca: args: no return: [0x0F] -# rrd: -# args: yes -# return: TODO - -# rst: -# args: yes -# return: TODO +rrd: + args: no + return: [0xED, 0x67] -# sbc: -# args: yes -# return: TODO +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 @@ -1752,10 +1802,58 @@ srl: - cond: [_, l] return: [0xCB, 0x3D] -# sub: -# args: yes -# return: TODO +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 -# return: TODO +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]