/*
 * Copyright 2025 Tadashi G. Takaoka
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "asm_z380.h"
#include "test_asm_helper.h"

using namespace libasm;
using namespace libasm::z380;
using namespace libasm::test;

AsmZ380 asz380;
Assembler &assembler(asz380);

bool isZ180() {
    return strcasecmp_P("Z180", assembler.config().cpu_P()) == 0;
}

bool isZ380() {
    return strcasecmp_P("Z380", assembler.config().cpu_P()) == 0;
}

#define DDIR_W 0xDD, 0xC0    // DDIR W
#define DDIR_IBW 0xDD, 0xC1  // DDIR IB,W
#define DDIR_IWW 0xDD, 0xC2  // DDIR IW,W
#define DDIR_IB 0xDD, 0xC3   // DDIR IB
#define DDIR_LW 0xFD, 0xC0   // DDIR LW
#define DDIR_IBL 0xFD, 0xC1  // DDIR IB,LW
#define DDIR_IWL 0xFD, 0xC2  // DDIR IW,LW
#define DDIR_IW 0xFD, 0xC3   // DDIR IW

void set_up() {
    assembler.reset();
}

void tear_down() {
    symtab.reset();
}

// clang-format off
void test_cpu() {
    EQUALS("cpu z80", true, assembler.setCpu("z80"));
    EQUALS_P("get cpu", "Z80", assembler.config().cpu_P());

    EQUALS("cpu z180", true, assembler.setCpu("z180"));
    EQUALS_P("get cpu", "Z180", assembler.config().cpu_P());

    EQUALS("cpu z380", true, assembler.setCpu("z380"));
    EQUALS_P("get cpu", "Z380", assembler.config().cpu_P());
}

void test_load_registers() {
    TEST("LD A,A", 0x7F);
    TEST("LD A,B", 0x78);
    TEST("LD A,C", 0x79);
    TEST("LD A,D", 0x7A);
    TEST("LD A,E", 0x7B);
    TEST("LD A,H", 0x7C);
    TEST("LD A,L", 0x7D);

    TEST("LD B,A", 0x47);
    TEST("LD B,B", 0x40);
    TEST("LD B,C", 0x41);
    TEST("LD B,D", 0x42);
    TEST("LD B,E", 0x43);
    TEST("LD B,H", 0x44);
    TEST("LD B,L", 0x45);

    TEST("LD C,A", 0x4F);
    TEST("LD C,B", 0x48);
    TEST("LD C,C", 0x49);
    TEST("LD C,D", 0x4A);
    TEST("LD C,E", 0x4B);
    TEST("LD C,H", 0x4C);
    TEST("LD C,L", 0x4D);

    TEST("LD D,A", 0x57);
    TEST("LD D,B", 0x50);
    TEST("LD D,C", 0x51);
    TEST("LD D,D", 0x52);
    TEST("LD D,E", 0x53);
    TEST("LD D,H", 0x54);
    TEST("LD D,L", 0x55);

    TEST("LD E,A", 0x5F);
    TEST("LD E,B", 0x58);
    TEST("LD E,C", 0x59);
    TEST("LD E,D", 0x5A);
    TEST("LD E,E", 0x5B);
    TEST("LD E,H", 0x5C);
    TEST("LD E,L", 0x5D);

    TEST("LD H,A", 0x67);
    TEST("LD H,B", 0x60);
    TEST("LD H,C", 0x61);
    TEST("LD H,D", 0x62);
    TEST("LD H,E", 0x63);
    TEST("LD H,H", 0x64);
    TEST("LD H,L", 0x65);

    TEST("LD L,A", 0x6F);
    TEST("LD L,B", 0x68);
    TEST("LD L,C", 0x69);
    TEST("LD L,D", 0x6A);
    TEST("LD L,E", 0x6B);
    TEST("LD L,H", 0x6C);
    TEST("LD L,L", 0x6D);


    if (isZ380()) {
        TEST("LD A, IXU", 0xDD, 0x7C);
        TEST("LD A, IXL", 0xDD, 0x7D);
        TEST("LD A, IYU", 0xFD, 0x7C);
        TEST("LD A, IYL", 0xFD, 0x7D);

        TEST("LD B, IXU", 0xDD, 0x44);
        TEST("LD B, IXL", 0xDD, 0x45);
        TEST("LD B, IYU", 0xFD, 0x44);
        TEST("LD B, IYL", 0xFD, 0x45);

        TEST("LD C, IXU", 0xDD, 0x4C);
        TEST("LD C, IXL", 0xDD, 0x4D);
        TEST("LD C, IYU", 0xFD, 0x4C);
        TEST("LD C, IYL", 0xFD, 0x4D);

        TEST("LD D, IXU", 0xDD, 0x54);
        TEST("LD D, IXL", 0xDD, 0x55);
        TEST("LD D, IYU", 0xFD, 0x54);
        TEST("LD D, IYL", 0xFD, 0x55);

        TEST("LD E, IXU", 0xDD, 0x5C);
        TEST("LD E, IXL", 0xDD, 0x5D);
        TEST("LD E, IYU", 0xFD, 0x5C);
        TEST("LD E, IYL", 0xFD, 0x5D);

        ERRT("LD H, IXU", REGISTER_NOT_ALLOWED, "H, IXU", 0xDD, 0x64);
        ERRT("LD H, IXL", REGISTER_NOT_ALLOWED, "H, IXL", 0xDD, 0x65);
        ERRT("LD H, IYU", REGISTER_NOT_ALLOWED, "H, IYU", 0xFD, 0x64);
        ERRT("LD H, IYL", REGISTER_NOT_ALLOWED, "H, IYL", 0xFD, 0x65);

        ERRT("LD L, IXU", REGISTER_NOT_ALLOWED, "L, IXU", 0xDD, 0x6C);
        ERRT("LD L, IXL", REGISTER_NOT_ALLOWED, "L, IXL", 0xDD, 0x6D);
        ERRT("LD L, IYU", REGISTER_NOT_ALLOWED, "L, IYU", 0xFD, 0x6C);
        ERRT("LD L, IYL", REGISTER_NOT_ALLOWED, "L, IYL", 0xFD, 0x6D);

        TEST("LD IXU, A", 0xDD, 0x67);
        TEST("LD IXU, B", 0xDD, 0x60);
        TEST("LD IXU, C", 0xDD, 0x61);
        TEST("LD IXU, D", 0xDD, 0x62);
        TEST("LD IXU, E", 0xDD, 0x63);
        ERRT("LD IXU, H", REGISTER_NOT_ALLOWED, "H", 0xDD, 0x64);
        ERRT("LD IXU, L", REGISTER_NOT_ALLOWED, "L", 0xDD, 0x65);
        TEST("LD IXU, IXU", 0xDD, 0x64);
        TEST("LD IXU, IXL", 0xDD, 0x65);

        TEST("LD IXL, A", 0xDD, 0x6F);
        TEST("LD IXL, B", 0xDD, 0x68);
        TEST("LD IXL, C", 0xDD, 0x69);
        TEST("LD IXL, D", 0xDD, 0x6A);
        TEST("LD IXL, E", 0xDD, 0x6B);
        ERRT("LD IXL, H", REGISTER_NOT_ALLOWED, "H", 0xDD, 0x6C);
        ERRT("LD IXL, L", REGISTER_NOT_ALLOWED, "L", 0xDD, 0x6D);
        TEST("LD IXL, IXL", 0xDD, 0x6D);
        TEST("LD IXL, IXU", 0xDD, 0x6C);

        TEST("LD IYU, A", 0xFD, 0x67);
        TEST("LD IYU, B", 0xFD, 0x60);
        TEST("LD IYU, C", 0xFD, 0x61);
        TEST("LD IYU, D", 0xFD, 0x62);
        TEST("LD IYU, E", 0xFD, 0x63);
        ERRT("LD IYU, H", REGISTER_NOT_ALLOWED, "H", 0xFD, 0x64);
        ERRT("LD IYU, L", REGISTER_NOT_ALLOWED, "L", 0xFD, 0x65);
        TEST("LD IYU, IYU", 0xFD, 0x64);
        TEST("LD IYU, IYL", 0xFD, 0x65);

        TEST("LD IYL, A", 0xFD, 0x6F);
        TEST("LD IYL, B", 0xFD, 0x68);
        TEST("LD IYL, C", 0xFD, 0x69);
        TEST("LD IYL, D", 0xFD, 0x6A);
        TEST("LD IYL, E", 0xFD, 0x6B);
        ERRT("LD IYL, H", REGISTER_NOT_ALLOWED, "H", 0xFD, 0x6C);
        ERRT("LD IYL, L", REGISTER_NOT_ALLOWED, "L", 0xFD, 0x6D);
        TEST("LD IYL, IYL", 0xFD, 0x6D);
        TEST("LD IYL, IYU", 0xFD, 0x6C);
    }

    TEST("LD R,A", 0xED, 0x4F);
    TEST("LD A,R", 0xED, 0x5F);
    TEST("LD I,A", 0xED, 0x47);
    TEST("LD A,I", 0xED, 0x57);
    if (isZ380()) {
        TEST("LDW I, HL", 0xDD, 0x47);
        TEST("LD  I, HL", 0xDD, 0x47);
        TEST("LDW HL, I", 0xDD, 0x57);
        TEST("LD  HL, I", 0xDD, 0x57);
        ATEST(0x1000, "DDIR W",  DDIR_W);
        CTEST(0x1002, 0x1002, "LD  I, HL", 0xDD, 0x47);
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0x1002, 0x1002, "LD  HL, I", 0xDD, 0x57);
        ATEST(0x1000, "DDIR IW", DDIR_IW);
        CERRT(0x1002, 0x1002, "LD  HL, I",
              PREFIX_HAS_NO_EFFECT, "LD  HL, I", 0xDD, 0x57);
        ATEST(0x1000, "DDIR IB,W", DDIR_IBW);
        CERRT(0x1002, 0x1000, "LD  HL, I",
              SUBOPTIMAL_INSTRUCTION, "LD  HL, I", DDIR_W, 0xDD, 0x57);
    }

    TEST("LD SP,HL", 0xF9);
    TEST("LD SP,IX", 0xDD, 0xF9);
    TEST("LD SP,IY", 0xFD, 0xF9);

    if (isZ380()) {
        TEST("LDW BC, DE", 0xDD, 0x02);
        TEST("LDW DE, DE", 0xDD, 0x12);
        TEST("LDW HL, DE", 0xDD, 0x32);
        TEST("LD  BC, DE", 0xDD, 0x02);
        TEST("LD  DE, DE", 0xDD, 0x12);
        TEST("LD  HL, DE", 0xDD, 0x32);
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0x1002, 0x1002, "LD  HL, DE", 0xDD, 0x32);

        TEST("LDW BC, BC", 0xED, 0x02);
        TEST("LDW DE, BC", 0xED, 0x12);
        TEST("LDW HL, BC", 0xED, 0x32);
        TEST("LD  BC, BC", 0xED, 0x02);
        TEST("LD  DE, BC", 0xED, 0x12);
        TEST("LD  HL, BC", 0xED, 0x32);
        ATEST(0x1000, "DDIR W", DDIR_W);
        CTEST(0x1002, 0x1002, "LDW DE, BC", 0xED, 0x12);

        TEST("LDW BC, HL", 0xFD, 0x02);
        TEST("LDW DE, HL", 0xFD, 0x12);
        TEST("LDW HL, HL", 0xFD, 0x32);
        TEST("LD  BC, HL", 0xFD, 0x02);
        TEST("LD  DE, HL", 0xFD, 0x12);
        TEST("LD  HL, HL", 0xFD, 0x32);
        ATEST(0x1000, "DDIR IB", DDIR_IB);
        CERRT(0x1002, 0x1002, "LDW HL, HL",
              PREFIX_HAS_NO_EFFECT, "LDW HL, HL", 0xFD, 0x32);

        TEST("LDW BC, IX", 0xDD, 0x0B);
        TEST("LDW DE, IX", 0xDD, 0x1B);
        TEST("LDW HL, IX", 0xDD, 0x3B);
        TEST("LDW IY, IX", 0xFD, 0x27);
        TEST("LD  BC, IX", 0xDD, 0x0B);
        TEST("LD  DE, IX", 0xDD, 0x1B);
        TEST("LD  HL, IX", 0xDD, 0x3B);
        TEST("LD  IY, IX", 0xFD, 0x27);
        ATEST(0x1000, "DDIR IW", DDIR_IW);
        CERRT(0x1002, 0x1002, "LD  IY, IX",
              PREFIX_HAS_NO_EFFECT, "LD  IY, IX", 0xFD, 0x27);

        TEST("LDW BC, IY", 0xFD, 0x0B);
        TEST("LDW DE, IY", 0xFD, 0x1B);
        TEST("LDW HL, IY", 0xFD, 0x3B);
        TEST("LDW IX, IY", 0xDD, 0x27);
        TEST("LD  BC, IY", 0xFD, 0x0B);
        TEST("LD  DE, IY", 0xFD, 0x1B);
        TEST("LD  HL, IY", 0xFD, 0x3B);
        TEST("LD  IX, IY", 0xDD, 0x27);
        ATEST(0x10000, "DDIR IW,LW", DDIR_IWL);
        CERRT(0x10002, 0x10000, "LD  BC, IY",
              SUBOPTIMAL_INSTRUCTION, "LD  BC, IY", DDIR_LW, 0xFD, 0x0B);

        ATEST(0x01000, "DDIR IB,W", DDIR_IBW);
        CERRT(0x01002, 0x01000, "LD  SP, IX",
              SUBOPTIMAL_INSTRUCTION, "LD  SP, IX", DDIR_W, 0xDD, 0xF9);
    }
}

void test_load_immediate() {
    TEST("LD B,0F6H", 0x06, 0xF6);
    TEST("LD C,9FH",  0x0E, 0x9F);
    TEST("LD D,3AH",  0x16, 0x3A);
    TEST("LD E,80H",  0x1E, 0x80);
    TEST("LD H,0F6H", 0x26, 0xF6);
    TEST("LD L,0F6H", 0x2E, 0xF6);
    if (isZ380()) {
        TEST("LD IXU, 0F6H", 0xDD, 0x26, 0xF6);
        TEST("LD IXL, 9FH",  0xDD, 0x2E, 0x9F);
        TEST("LD IYU, 3AH",  0xFD, 0x26, 0x3A);
        TEST("LD IYL, 80H",  0xFD, 0x2E, 0x80);
    }

    TEST("LD A,0FEH", 0x3E, 0xFE);
    TEST("LD A,-1",   0x3E, 0xFF);
    TEST("LD A,255",  0x3E, 0xFF);
    ERRT("LD A,256",  OVERFLOW_RANGE, "256",  0x3E, 0x00);
    TEST("LD A,-128", 0x3E, 0x80);
    ERRT("LD A,-129", OVERFLOW_RANGE, "-129", 0x3E, 0x7F);
    if (isZ380()) {
        TEST("LD (IX-128), 56H", 0xDD, 0x36, 0x80, 0x56);
        TEST("LD (IY+127), 56H", 0xFD, 0x36, 0x7F, 0x56);
        TEST("LD (IY+7FFFH), 56H",   DDIR_IB, 0xFD, 0x36, 0xFF, 0x7F, 0x56);
        TEST("LD (IY+7FFFFFH), 56H", DDIR_IW, 0xFD, 0x36, 0xFF, 0xFF, 0x7F, 0x56);
    }

    TEST("LD BC,0BEEFH", 0x01, 0xEF, 0xBE);
    TEST("LD DE,1234H",  0x11, 0x34, 0x12);
    TEST("LD HL,0BEEFH", 0x21, 0xEF, 0xBE);
    TEST("LD SP,6789H",  0x31, 0x89, 0x67);
    TEST("LD IX,0ABCDH", 0xDD, 0x21, 0xCD, 0xAB);
    TEST("LD IY,0ABCDH", 0xFD, 0x21, 0xCD, 0xAB);
    if (isZ380()) {
        TEST("lwordmode on");
        TEST("LD IX, 0ABCDEFH",   DDIR_IB, 0xDD, 0x21, 0xEF, 0xCD, 0xAB);
        TEST("LD SP, 6789H",               0x31, 0x89, 0x67);
        TEST("LD DE, 123456H",    DDIR_IB, 0x11, 0x56, 0x34, 0x12);
        TEST("LD HL, 0BEEFCAFEH", DDIR_IW, 0x21, 0xFE, 0xCA, 0xEF, 0xBE);
        TEST("LD IY, 0ABCDEF01H", DDIR_IW, 0xFD, 0x21, 0x01, 0xEF, 0xCD, 0xAB);
        TEST("lwordmode off");
        TEST("LD IX, 0ABCDH",               0xDD, 0x21, 0xCD, 0xAB);
        ERRT("LD SP, 345678H",    OVERFLOW_RANGE,    "345678H", 0x31, 0x78, 0x56);
        ERRT("LD DE, 123456H",    OVERFLOW_RANGE,    "123456H", 0x11, 0x56, 0x34);
        ERRT("LD HL, 0BEEFCAFEH", OVERFLOW_RANGE, "0BEEFCAFEH", 0x21, 0xFE, 0xCA);
        ERRT("LD IY, 0ABCDEF01H", OVERFLOW_RANGE, "0ABCDEF01H", 0xFD, 0x21, 0x01, 0xEF);
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0x1002, 0x1002, "LD IX, 0ABCDH",               0xDD, 0x21, 0xCD, 0xAB);
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0X1002, 0X1000, "LD SP, 346789H",    DDIR_IBL, 0x31, 0x89, 0x67, 0x34);
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0X1002, 0X1000, "LD DE, 123456H",    DDIR_IBL, 0x11, 0x56, 0x34, 0x12);
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0X1002, 0X1000, "LD HL, 0BEEFCAFEH", DDIR_IWL, 0x21, 0xFE, 0xCA, 0xEF, 0xBE);
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0X1002, 0X1000, "LD IY, 0ABCDEF01H", DDIR_IWL, 0xFD, 0x21, 0x01, 0xEF, 0xCD, 0xAB);

        TEST("LDW (BC), 1234H", 0xED, 0x06, 0x34, 0x12);
        TEST("LDW (DE), 1234H", 0xED, 0x16, 0x34, 0x12);
        TEST("LDW (HL), 1234H", 0xED, 0x36, 0x34, 0x12);
        TEST("LDW (BC), 12345678H", DDIR_IW, 0xED, 0x06, 0x78, 0x56, 0x34, 0x12);
        TEST("LDW (DE), 123456H",   DDIR_IB, 0xED, 0x16, 0x56, 0x34, 0x12);
        TEST("LDW (HL), 12345678H", DDIR_IW, 0xED, 0x36, 0x78, 0x56, 0x34, 0x12);

        TEST("lwordmode on");
        TEST("PUSH 1234H",              0xFD, 0xF5, 0x34, 0x12);
        TEST("PUSH 123456H",   DDIR_IB, 0xFD, 0xF5, 0x56, 0x34, 0x12);
        TEST("PUSH 12345678H", DDIR_IW, 0xFD, 0xF5, 0x78, 0x56, 0x34, 0x12);
        TEST("lwordmode off");
        TEST("PUSH 1234H",                                  0xFD, 0xF5, 0x34, 0x12);
        ERRT("PUSH 123456H",   OVERFLOW_RANGE,   "123456H", 0xFD, 0xF5, 0x56, 0x34);
        ERRT("PUSH 12345678H", OVERFLOW_RANGE, "12345678H", 0xFD, 0xF5, 0x78, 0x56);
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0x1002, 0x1002, "PUSH 1234H",     0xFD, 0xF5, 0x34, 0x12);
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0x1002, 0x1000, "PUSH 123456H",   DDIR_IBL, 0xFD, 0xF5, 0x56, 0x34, 0x12);
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0x1002, 0x1000, "PUSH 12345678H", DDIR_IWL, 0xFD, 0xF5, 0x78, 0x56, 0x34, 0x12);
    }

    symtab.intern(-1,  "minus_1");
    symtab.intern(255, "max?255");

    TEST("LD B, minus_1", 0x06, 0xFF);
    TEST("LD C, max?255", 0x0E, 0xFF);
}

void test_load() {
    TEST("LD A,(HL)", 0x7E);
    TEST("ld b,(hl)", 0x46);
    TEST("LD C,(HL)", 0x4E);
    TEST("LD D,(HL)", 0x56);
    TEST("LD E,(HL)", 0x5E);
    TEST("LD H,(HL)", 0x66);
    TEST("LD L,(HL)", 0x6E);

    TEST("LD A,(BC)", 0x0A);
    TEST("LD A,(DE)", 0x1A);
    TEST("LD A,(1234H)", 0x3A, 0x34, 0x12);
    if (isZ380()) {
        TEST("LD A, (123456H)",   DDIR_IB, 0x3A, 0x56, 0x34, 0x12);
        TEST("LD A, (12345678H)", DDIR_IW, 0x3A, 0x78, 0x56, 0x34, 0x12);
    }

    TEST("LD A,(IX+2)", 0xDD, 0x7E, 0x02);
    TEST("LD B,(IX+2)", 0xDD, 0x46, 0x02);
    TEST("LD C,(IX+2)", 0xDD, 0x4E, 0x02);
    TEST("LD D,(IX+2)", 0xDD, 0x56, 0x02);
    TEST("LD E,(IX+2)", 0xDD, 0x5E, 0x02);
    TEST("LD H,(IX+2)", 0xDD, 0x66, 0x02);
    TEST("LD L,(IX+2)", 0xDD, 0x6E, 0x02);
    TEST("LD A,(IY-2)", 0xFD, 0x7E, 0xFE);
    TEST("LD B,(IY-2)", 0xFD, 0x46, 0xFE);
    TEST("LD C,(IY-2)", 0xFD, 0x4E, 0xFE);
    TEST("LD D,(IY-2)", 0xFD, 0x56, 0xFE);
    TEST("LD E,(IY-2)", 0xFD, 0x5E, 0xFE);
    TEST("LD H,(IY-2)", 0xFD, 0x66, 0xFE);
    TEST("LD L,(IY-2)", 0xFD, 0x6E, 0xFE);
    ERRT("LD (HL),(IX+2)", OPERAND_NOT_ALLOWED, "(HL),(IX+2)");
    if (isZ380()) {
        TEST("LD C, (IY-129)",   DDIR_IB, 0xFD, 0x4E, 0x7F, 0xFF);
        TEST("LD L, (IY-32769)", DDIR_IW, 0xFD, 0x6E, 0xFF, 0x7F, 0xFF);
    }

    TEST("LD BC,(05678H)", 0xED, 0x4B, 0x78, 0x56);
    TEST("LD DE,(05678H)", 0xED, 0x5B, 0x78, 0x56);
    TEST("LD HL,(5678H)",  0x2A, 0x78, 0x56);
    TEST("LD SP,(05678H)", 0xED, 0x7B, 0x78, 0x56);
    TEST("LD IX,(5678H)",  0xDD, 0x2A, 0x78, 0x56);
    TEST("LD IY,(5678H)",  0xFD, 0x2A, 0x78, 0x56);
    if (isZ380()) {
        TEST("LD  BC, (BC)", 0xDD, 0x0C);
        TEST("LDW BC, (DE)", 0xDD, 0x0D);
        TEST("LDW BC, (HL)", 0xDD, 0x0F);
        ATEST(0x1000, "DDIR W", DDIR_W);
        CTEST(0x1002, 0x1002, "LDW BC, (DE)", 0xDD, 0x0D);

        TEST("LDW DE, (BC)", 0xDD, 0x1C);
        TEST("LD  DE, (DE)", 0xDD, 0x1D);
        TEST("LDW DE, (HL)", 0xDD, 0x1F);
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0x1002, 0x1002, "LDW DE, (HL)", 0xDD, 0x1F);

        TEST("LDW HL, (BC)", 0xDD, 0x3C);
        TEST("LDW HL, (DE)", 0xDD, 0x3D);
        TEST("LD  HL, (HL)", 0xDD, 0x3F);
        ATEST(0x1000, "DDIR IB", DDIR_IB);
        CERRT(0x1002, 0x1002, "LD  HL, (HL)",
              PREFIX_HAS_NO_EFFECT, "LD  HL, (HL)", 0xDD, 0x3F);

        TEST("LD  IX, (BC)", 0xDD, 0x03);
        TEST("LDW IX, (DE)", 0xDD, 0x13);
        TEST("LDW IX, (HL)", 0xDD, 0x33);
        ATEST(0x1234, "DDIR IW,LW", DDIR_IWL);
        CERRT(0x1236, 0x1234, "LDW IX, (DE)",
              SUBOPTIMAL_INSTRUCTION, "LDW IX, (DE)", DDIR_LW, 0xDD, 0x13);

        TEST("LDW IY, (BC)", 0xFD, 0x03);
        TEST("LD  IY, (DE)", 0xFD, 0x13);
        TEST("LDW IY, (HL)", 0xFD, 0x33);
        ATEST(0x1000, "DDIR IB,W", DDIR_IBW);
        CERRT(0x1002, 0x1000, "LD  IY, (DE)",
              SUBOPTIMAL_INSTRUCTION, "LD  IY, (DE)", DDIR_W, 0xFD, 0x13);

        TEST("LDW HL, (5678H)",              0x2A, 0x78, 0x56);
        TEST("LD  HL, (345678H)",   DDIR_IB, 0x2A, 0x78, 0x56, 0x34);
        TEST("LDW HL, (12345678H)", DDIR_IW, 0x2A, 0x78, 0x56, 0x34, 0x12);
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0x1002, 0x1000, "LD  HL, (345678H)",
              DDIR_IBL, 0x2A, 0x78, 0x56, 0x34);
        ATEST(0x1000, "DDIR W", DDIR_W);
        CTEST(0x1002, 0x1000, "LDW HL, (12345678H)",
              DDIR_IWW, 0x2A, 0x78, 0x56, 0x34, 0x12);

        TEST("LDW BC, (IX+127)", 0xDD, 0xCB, 0x7F, 0x03);
        TEST("LDW DE, (IX+127)", 0xDD, 0xCB, 0x7F, 0x13);
        TEST("LDW IY, (IX+127)", 0xDD, 0xCB, 0x7F, 0x23);
        TEST("LDW HL, (IX+127)", 0xDD, 0xCB, 0x7F, 0x33);
        TEST("LD  BC, (IX+127)", 0xDD, 0xCB, 0x7F, 0x03);
        TEST("LD  DE, (IX+127)", 0xDD, 0xCB, 0x7F, 0x13);
        TEST("LD  IY, (IX+127)", 0xDD, 0xCB, 0x7F, 0x23);
        TEST("LD  HL, (IX+127)", 0xDD, 0xCB, 0x7F, 0x33);
        TEST("LD  HL, (IX+256)",   DDIR_IB, 0xDD, 0xCB, 0x00, 0x01, 0x33);
        TEST("LD  HL, (IX+65536)", DDIR_IW, 0xDD, 0xCB, 0x00, 0x00, 0x01, 0x33);

        TEST("LDW BC, (IY-128)", 0xFD, 0xCB, 0x80, 0x03);
        TEST("LDW DE, (IY-128)", 0xFD, 0xCB, 0x80, 0x13);
        TEST("LDW IX, (IY-128)", 0xFD, 0xCB, 0x80, 0x23);
        TEST("LDW HL, (IY-128)", 0xFD, 0xCB, 0x80, 0x33);
        TEST("LD  BC, (IY-128)", 0xFD, 0xCB, 0x80, 0x03);
        TEST("LD  DE, (IY-128)", 0xFD, 0xCB, 0x80, 0x13);
        TEST("LD  IX, (IY-128)", 0xFD, 0xCB, 0x80, 0x23);
        TEST("LD  HL, (IY-128)", 0xFD, 0xCB, 0x80, 0x33);
        TEST("LD  IX, (IY-256)",   DDIR_IB, 0xFD, 0xCB, 0x00, 0xFF, 0x23);
        TEST("LD  HL, (IY-65536)", DDIR_IW, 0xFD, 0xCB, 0x00, 0x00, 0xFF, 0x33);

        TEST("LDW BC, (SP+127)", 0xDD, 0xCB, 0x7F, 0x01);
        TEST("LDW DE, (SP+127)", 0xDD, 0xCB, 0x7F, 0x11);
        TEST("LDW HL, (SP-128)", 0xDD, 0xCB, 0x80, 0x31);
        TEST("LDW IX, (SP+127)", 0xDD, 0xCB, 0x7F, 0x21);
        TEST("LDW IY, (SP-128)", 0xFD, 0xCB, 0x80, 0x21);
        TEST("LD  BC, (SP+127)", 0xDD, 0xCB, 0x7F, 0x01);
        TEST("LD  DE, (SP+127)", 0xDD, 0xCB, 0x7F, 0x11);
        TEST("LD  HL, (SP-128)", 0xDD, 0xCB, 0x80, 0x31);
        TEST("LD  IX, (SP+127)", 0xDD, 0xCB, 0x7F, 0x21);
        TEST("LD  IY, (SP-128)", 0xFD, 0xCB, 0x80, 0x21);
        TEST("LD  IX, (SP+256)",   DDIR_IB, 0xDD, 0xCB, 0x00, 0x01, 0x21);
        TEST("LD  IY, (SP-65536)", DDIR_IW, 0xFD, 0xCB, 0x00, 0x00, 0xFF, 0x21);
    }
}

void test_store() {
    TEST("LD (HL),A", 0x77);
    TEST("LD (HL),B", 0x70);
    TEST("LD (HL),C", 0x71);
    TEST("LD (HL),D", 0x72);
    TEST("LD (HL),E", 0x73);
    TEST("LD (HL),H", 0x74);
    TEST("LD (HL),L", 0x75);

    TEST("LD (BC),A", 0x02);
    TEST("LD (DE),A", 0x12);
    TEST("LD (9ABCH),A", 0x32, 0xBC, 0x9A);
    if (isZ380()) {
        TEST("LD (9ABCDEH), A",   DDIR_IB, 0x32, 0xDE, 0xBC, 0x9A);
        TEST("LD (9ABCDEF0H), A", DDIR_IW, 0x32, 0xF0, 0xDE, 0xBC, 0x9A);
    }

    TEST("LD (IX+2),A", 0xDD, 0x77, 0x02);
    TEST("LD (IX+2),B", 0xDD, 0x70, 0x02);
    TEST("LD (IX+2),C", 0xDD, 0x71, 0x02);
    TEST("LD (IX+2),D", 0xDD, 0x72, 0x02);
    TEST("LD (IX+0),E", 0xDD, 0x73, 0x00);
    TEST("LD (IX+2),H", 0xDD, 0x74, 0x02);
    TEST("LD (IX+2),L", 0xDD, 0x75, 0x02);
    TEST("LD (IY-2),A", 0xFD, 0x77, 0xFE);
    TEST("LD (IY-2),B", 0xFD, 0x70, 0xFE);
    TEST("LD (IY-2),C", 0xFD, 0x71, 0xFE);
    TEST("LD (IY-2),D", 0xFD, 0x72, 0xFE);
    TEST("LD (IY-2),E", 0xFD, 0x73, 0xFE);
    TEST("LD (IY-2),H", 0xFD, 0x74, 0xFE);
    TEST("LD (IY-2),L", 0xFD, 0x75, 0xFE);
    ERRT("LD (IX+2),(HL)", OPERAND_NOT_ALLOWED, "(IX+2),(HL)");

    if (isZ380()) {
        TEST("LD (IX+7FFFH), D",   DDIR_IB, 0xDD, 0x72, 0xFF, 0x7F);
        TEST("LD (IY-800000H), A", DDIR_IW, 0xFD, 0x77, 0x00, 0x00, 0x80);
    }

    TEST("LD (HL),0F6H",   0x36, 0xF6);
    TEST("LD (IX+2),0F6H", 0xDD, 0x36, 0x02, 0xF6);
    TEST("LD (IY-2),0F6H", 0xFD, 0x36, 0xFE, 0xF6);
    if (isZ380()) {
        TEST("LD (IX+128),0F6H", DDIR_IB, 0xDD, 0x36, 0x80, 0x00, 0xF6);
        TEST("LD (IY-129),0F6H", DDIR_IB, 0xFD, 0x36, 0x7F, 0xFF, 0xF6);
    } else {
        ERRT("LD (IX+128),0F6H", OVERFLOW_RANGE, "(IX+128),0F6H", 0xDD, 0x36, 0x80, 0xF6);
        ERRT("LD (IY-129),0F6H", OVERFLOW_RANGE, "(IY-129),0F6H", 0xFD, 0x36, 0x7F, 0xF6);
    }

    TEST("LD (0ABCDH),BC", 0xED, 0x43, 0xCD, 0xAB);
    TEST("LD (0ABCDH),DE", 0xED, 0x53, 0xCD, 0xAB);
    TEST("LD (0ABCDH),HL", 0x22, 0xCD, 0xAB);
    TEST("LD (0ABCDH),SP", 0xED, 0x73, 0xCD, 0xAB);
    TEST("LD (0ABCDH),IX", 0xDD, 0x22, 0xCD, 0xAB);
    TEST("LD (0ABCDH),IY", 0xFD, 0x22, 0xCD, 0xAB);
    if (isZ380()) {
        TEST("LDW (5678H), HL", 0x22, 0x78, 0x56);

        TEST("LDW (BC), BC", 0xFD, 0x0C);
        TEST("LDW (BC), DE", 0xFD, 0x1C);
        TEST("LDW (BC), HL", 0xFD, 0x3C);
        TEST("LDW (BC), IX", 0xDD, 0x01);
        TEST("LDW (BC), IY", 0xFD, 0x01);
        TEST("LD  (BC), BC", 0xFD, 0x0C);
        TEST("LD  (BC), DE", 0xFD, 0x1C);
        TEST("LD  (BC), HL", 0xFD, 0x3C);
        TEST("LD  (BC), IX", 0xDD, 0x01);
        TEST("LD  (BC), IY", 0xFD, 0x01);
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0x1002, 0x1002, "LD  (BC), IY", 0xFD, 0x01);

        TEST("LDW (DE), BC", 0xFD, 0x0D);
        TEST("LDW (DE), DE", 0xFD, 0x1D);
        TEST("LDW (DE), HL", 0xFD, 0x3D);
        TEST("LDW (DE), IX", 0xDD, 0x11);
        TEST("LDW (DE), IY", 0xFD, 0x11);
        TEST("LD  (DE), BC", 0xFD, 0x0D);
        TEST("LD  (DE), DE", 0xFD, 0x1D);
        TEST("LD  (DE), HL", 0xFD, 0x3D);
        TEST("LD  (DE), IX", 0xDD, 0x11);
        TEST("LD  (DE), IY", 0xFD, 0x11);
        ATEST(0x1000, "DDIR W", DDIR_W);
        CTEST(0x1002, 0x1002, "LD  (DE), HL", 0xFD, 0x3D);

        TEST("LDW (HL), BC", 0xFD, 0x0F);
        TEST("LDW (HL), DE", 0xFD, 0x1F);
        TEST("LDW (HL), HL", 0xFD, 0x3F);
        TEST("LDW (HL), IX", 0xDD, 0x31);
        TEST("LDW (HL), IY", 0xFD, 0x31);
        TEST("LD  (HL), BC", 0xFD, 0x0F);
        TEST("LD  (HL), DE", 0xFD, 0x1F);
        TEST("LD  (HL), HL", 0xFD, 0x3F);
        TEST("LD  (HL), IX", 0xDD, 0x31);
        TEST("LD  (HL), IY", 0xFD, 0x31);
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0x1002, 0x1002, "LDW (HL), IX", 0xDD, 0x31);

        TEST("LDW (IX-128), BC", 0xDD, 0xCB, 0x80, 0x0B);
        TEST("LDW (IX-128), DE", 0xDD, 0xCB, 0x80, 0x1B);
        TEST("LDW (IX-128), HL", 0xDD, 0xCB, 0x80, 0x3B);
        TEST("LDW (IX-128), IY", 0xDD, 0xCB, 0x80, 0x2B);
        TEST("LD  (IX-128), BC", 0xDD, 0xCB, 0x80, 0x0B);
        TEST("LD  (IX-128), DE", 0xDD, 0xCB, 0x80, 0x1B);
        TEST("LD  (IX-128), HL", 0xDD, 0xCB, 0x80, 0x3B);
        TEST("LD  (IX-128), IY", 0xDD, 0xCB, 0x80, 0x2B);
        TEST("LDW (IX-8000H), DE",   DDIR_IB, 0xDD, 0xCB, 0x00, 0x80, 0x1B);
        TEST("LDW (IX-800000H), HL", DDIR_IW, 0xDD, 0xCB, 0x00, 0x00, 0x80, 0x3B);

        TEST("LDW (IY+127), BC", 0xFD, 0xCB, 0x7F, 0x0B);
        TEST("LDW (IY+127), DE", 0xFD, 0xCB, 0x7F, 0x1B);
        TEST("LDW (IY+127), HL", 0xFD, 0xCB, 0x7F, 0x3B);
        TEST("LDW (IY+127), IX", 0xFD, 0xCB, 0x7F, 0x2B);
        TEST("LD  (IY+127), BC", 0xFD, 0xCB, 0x7F, 0x0B);
        TEST("LD  (IY+127), DE", 0xFD, 0xCB, 0x7F, 0x1B);
        TEST("LD  (IY+127), HL", 0xFD, 0xCB, 0x7F, 0x3B);
        TEST("LD  (IY+127), IX", 0xFD, 0xCB, 0x7F, 0x2B);
        TEST("LD  (IY+7FFFH), DE",   DDIR_IB, 0xFD, 0xCB, 0xFF, 0x7F, 0x1B);
        TEST("LD  (IY+7FFFFFH), HL", DDIR_IW, 0xFD, 0xCB, 0xFF, 0xFF, 0x7F, 0x3B);

        TEST("LDW (SP+127), BC", 0xDD, 0xCB, 0x7F, 0x09);
        TEST("LDW (SP+127), DE", 0xDD, 0xCB, 0x7F, 0x19);
        TEST("LDW (SP+127), HL", 0xDD, 0xCB, 0x7F, 0x39);
        TEST("LDW (SP+127), IX", 0xDD, 0xCB, 0x7F, 0x29);
        TEST("LDW (SP-128), IY", 0xFD, 0xCB, 0x80, 0x29);
        TEST("LD  (SP+127), BC", 0xDD, 0xCB, 0x7F, 0x09);
        TEST("LD  (SP+127), DE", 0xDD, 0xCB, 0x7F, 0x19);
        TEST("LD  (SP+127), HL", 0xDD, 0xCB, 0x7F, 0x39);
        TEST("LD  (SP+127), IX", 0xDD, 0xCB, 0x7F, 0x29);
        TEST("LD  (SP-128), IY", 0xFD, 0xCB, 0x80, 0x29);
        TEST("LD  (SP+7FFFFFH), IX", DDIR_IW, 0xDD, 0xCB, 0xFF, 0xFF, 0x7F, 0x29);
        TEST("LD  (SP-8000H), IY",   DDIR_IB, 0xFD, 0xCB, 0x00, 0x80, 0x29);

        TEST("LD  (0ABCDEFH), BC",   DDIR_IB, 0xED, 0x43, 0xEF, 0xCD, 0xAB);
        TEST("LD  (0ABCDEF01H), DE", DDIR_IW, 0xED, 0x53, 0x01, 0xEF, 0xCD, 0xAB);
        TEST("LD  (0ABCDEFH), HL",   DDIR_IB, 0x22, 0xEF, 0xCD, 0xAB);
        TEST("LDW (56789ABCH), HL",  DDIR_IW, 0x22, 0xBC, 0x9A, 0x78, 0x56);
        TEST("LD  (0ABCDEFH), IX",   DDIR_IB, 0xDD, 0x22, 0xEF, 0xCD, 0xAB);
        TEST("LD  (0ABCDEF01H), IY", DDIR_IW, 0xFD, 0x22, 0x01, 0xEF, 0xCD, 0xAB);
        TEST("LD  (0ABCDEFH), SP",   DDIR_IB, 0xED, 0x73, 0xEF, 0xCD, 0xAB);
        ATEST(0x10000, "DDIR LW", DDIR_LW);
        CTEST(0x10002, 0x10000, "LD  (0ABCDEFH), SP",
              DDIR_IBL, 0xED, 0x73, 0xEF, 0xCD, 0xAB);
    }
}

void test_exchange() {
    if (isZ380()) {
        TEST("EX A, A'", 0xCB, 0x37);
        TEST("EX B, B'", 0xCB, 0x30);
        TEST("EX C, C'", 0xCB, 0x31);
        TEST("EX D, D'", 0xCB, 0x32);
        TEST("EX E, E'", 0xCB, 0x33);
        TEST("EX H, H'", 0xCB, 0x34);
        TEST("EX L, L'", 0xCB, 0x35);
    }

    TEST("EX HL,DE",  0xEB);
    TEST("ex de,hl",  0xEB);
    if (isZ380()) {
        TEST("EX BC, DE", 0xED, 0x05);
        TEST("EX BC, HL", 0xED, 0x0D);
        TEST("EX BC, IX", 0xED, 0x03);
        TEST("EX BC, IY", 0xED, 0x0B);
        TEST("EX DE, BC", 0xED, 0x05);
        TEST("EX HL, BC", 0xED, 0x0D);
        TEST("EX IX, BC", 0xED, 0x03);
        TEST("EX IY, BC", 0xED, 0x0B);
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0x1002, 0x1002, "EX IY, BC", 0xED, 0x0B);

        TEST("EX DE, IX", 0xED, 0x13);
        TEST("EX DE, IY", 0xED, 0x1B);
        TEST("EX IX, DE", 0xED, 0x13);
        TEST("EX IY, DE", 0xED, 0x1B);
        ATEST(0x1000, "DDIR W", DDIR_W);
        CTEST(0x1002, 0x1002, "EX IX, DE", 0xED, 0x13);

        TEST("EX HL, IX", 0xED, 0x33);
        TEST("EX HL, IY", 0xED, 0x3B);
        TEST("EX IX, HL", 0xED, 0x33);
        TEST("EX IY, HL", 0xED, 0x3B);
        ATEST(0x1000, "DDIR IB,LW", DDIR_IBL);
        CERRT(0x1002, 0x1000, "EX IY, HL",
              SUBOPTIMAL_INSTRUCTION, "EX IY, HL", DDIR_LW, 0xED, 0x3B);

        TEST("EX IX, IY", 0xED, 0x2B);
        TEST("EX IY, IX", 0xED, 0x2B);
        ATEST(0x1000, "DDIR W,IW", DDIR_IWW);
        CERRT(0x1002, 0x1000, "EX IY, IX",
              SUBOPTIMAL_INSTRUCTION, "EX IY, IX", DDIR_W, 0xED, 0x2B);
    }

    TEST("EX AF,AF'", 0x08);
    if (isZ380()) {
        TEST("EX BC, BC'", 0xED, 0xCB, 0x30);
        TEST("EX DE, DE'", 0xED, 0xCB, 0x31);
        TEST("EX HL, HL'", 0xED, 0xCB, 0x33);
        TEST("EX IX, IX'", 0xED, 0xCB, 0x34);
        TEST("EX IY, IY'", 0xED, 0xCB, 0x35);
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0x1002, 0x1002, "EX HL, HL'", 0xED, 0xCB, 0x33);
        ATEST(0x1000, "DDIR W", DDIR_W);
        CTEST(0x1002, 0x1002, "EX IY, IY'", 0xED, 0xCB, 0x35);
    }

    TEST("EX (SP),HL", 0xE3);
    TEST("EX HL,(SP)", 0xE3);
    TEST("EX (SP),IX", 0xDD, 0xE3);
    TEST("EX IX,(SP)", 0xDD, 0xE3);
    TEST("EX (SP),IY", 0xFD, 0xE3);
    TEST("EX IY,(SP)", 0xFD, 0xE3);
    if (isZ380()) {
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0x1002, 0x1002, "EX (SP),HL", 0xE3);
        ATEST(0x1000, "DDIR W", DDIR_W);
        CTEST(0x1002, 0x1002, "EX IY,(SP)", 0xFD, 0xE3);
    }

    TEST("EXX", 0xD9);
    if (isZ380()) {
        TEST("EXXX",  0xDD, 0xD9);
        TEST("EXXY",  0xFD, 0xD9);
        TEST("EXALL", 0xED, 0xD9);

        TEST("SWAP BC", 0xED, 0x0E);
        TEST("SWAP DE", 0xED, 0x1E);
        TEST("SWAP HL", 0xED, 0x3E);
        TEST("SWAP IX", 0xDD, 0x3E);
        TEST("SWAP IY", 0xFD, 0x3E);
    }
}

void test_stack() {
    TEST("PUSH BC", 0xC5);
    TEST("PUSH DE", 0xD5);
    TEST("PUSH HL", 0xE5);
    TEST("PUSH AF", 0xF5);
    TEST("PUSH IX", 0xDD, 0xE5);
    TEST("PUSH IY", 0xFD, 0xE5);
    if (isZ380()) {
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0x1002, 0x1002, "PUSH DE", 0xD5);

        TEST("PUSH SR", 0xED, 0xC5);
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0x1002, 0x1002, "PUSH SR", 0xED, 0xC5);
    }

    TEST("POP BC", 0xC1);
    TEST("POP DE", 0xD1);
    TEST("POP HL", 0xE1);
    TEST("POP AF", 0xF1);
    TEST("POP IX", 0xDD, 0xE1);
    TEST("POP IY", 0xFD, 0xE1);
    if (isZ380()) {
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0x1002, 0x1002, "POP IX", 0xDD, 0xE1);

        TEST("POP SR", 0xED, 0xC1);
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0x1002, 0x1002, "POP SR", 0xED, 0xC1);
    }

    TEST("RET",    0xC9);
    TEST("RET NZ", 0xC0);
    TEST("RET Z",  0xC8);
    TEST("RET NC", 0xD0);
    TEST("RET C",  0xD8);
    TEST("RET PO", 0xE0);
    TEST("RET PE", 0xE8);
    TEST("RET P",  0xF0);
    TEST("RET M",  0xF8);

    TEST("RETN", 0xED, 0x45);
    TEST("RETI", 0xED, 0x4D);
    if (isZ380()) {
        TEST("RETB",  0xED, 0x55);
    } else {
        ERUI("RETB");
    }
}

void test_jump() {
    TEST("JP    1234H", 0xC3, 0x34, 0x12);
    TEST("jp nz,1234h", 0xC2, 0x34, 0x12);
    TEST("JP  Z,1234H", 0xCA, 0x34, 0x12);
    TEST("JP NC,1234H", 0xD2, 0x34, 0x12);
    TEST("JP  C,1234H", 0xDA, 0x34, 0x12);
    TEST("JP PO,1234H", 0xE2, 0x34, 0x12);
    TEST("JP PE,1234H", 0xEA, 0x34, 0x12);
    TEST("JP P, 1234H", 0xF2, 0x34, 0x12);
    TEST("JP M, 1234H", 0xFA, 0x34, 0x12);
    if (isZ380()) {
        TEST("extmode on");
        TEST("JP 1234H",                 0xC3, 0x34, 0x12);
        TEST("JP NC, 123456H",  DDIR_IB, 0xD2, 0x56, 0x34, 0x12);
        TEST("JP P, 12345678H", DDIR_IW, 0xF2, 0x78, 0x56, 0x34, 0x12);
        TEST("extmode off");
        TEST("JP 1234H",  0xC3, 0x34, 0x12);
        ERRT("JP NC, 123456H", OVERFLOW_RANGE,
             "123456H",   0xD2, 0x56, 0x34);
        ERRT("JP P, 12345678H", OVERFLOW_RANGE,
             "12345678H", 0xF2, 0x78, 0x56);
    }

    TEST("JP (HL)", 0xE9);
    TEST("JP (IX)", 0xDD, 0xE9);
    TEST("JP (IY)", 0xFD, 0xE9);

    TEST("CALL 1234H",    0xCD, 0x34, 0x12);
    TEST("CALL NZ,1234H", 0xC4, 0x34, 0x12);
    TEST("CALL Z,1234H",  0xCC, 0x34, 0x12);
    TEST("CALL NC,1234H", 0xD4, 0x34, 0x12);
    TEST("CALL C,1234H",  0xDC, 0x34, 0x12);
    TEST("CALL PO,1234H", 0xE4, 0x34, 0x12);
    TEST("CALL PE,1234H", 0xEC, 0x34, 0x12);
    TEST("CALL P,1234H",  0xF4, 0x34, 0x12);
    TEST("CALL M,1234H",  0xFC, 0x34, 0x12);
    if (isZ380()) {
        TEST("extmode on");
        TEST("CALL 1234H",                 0xCD, 0x34, 0x12);
        TEST("CALL NC, 123456H",  DDIR_IB, 0xD4, 0x56, 0x34, 0x12);
        TEST("CALL P, 12345678H", DDIR_IW, 0xF4, 0x78, 0x56, 0x34, 0x12);
        TEST("extmode off");
        TEST("CALL 1234H", 0xCD, 0x34, 0x12);
        ERRT("CALL NC, 123456H",  OVERFLOW_RANGE,
             "123456H",    0xD4, 0x56, 0x34);
        ERRT("CALL P, 12345678H", OVERFLOW_RANGE,
             "12345678H",  0xF4, 0x78, 0x56);
    }

    if (isZ380()) {
        ATEST(0x1000, "CALR 1082H", 0xED, 0xCD, 0x7F);
        ATEST(0x1000, "CALR 2083H", 0xDD, 0xCD, 0x7F, 0x10);
        ATEST(0x1000, "CALR 9005H", 0xFD, 0xCD, 0x00, 0x80, 0x00,);

        ATEST(0XF000, "CALR NZ, 0EF83H", 0xED, 0xC4, 0x80);
        ATEST(0XF000, "CALR Z, 7004H",   0xDD, 0xCC, 0x00, 0x80);
        ATEST(0XF000, "CALR NC, 6005H",  0xFD, 0xD4, 0x00, 0x70, 0xFF);
        ATEST(0X1000, "CALR C, 1082H",   0xED, 0xDC, 0x7F);
        ATEST(0X1000, "CALR PO, 9003H",  0xDD, 0xE4, 0xFF, 0x7F);
        ATEST(0X1000, "CALR PE, 9005H",  0xFD, 0xEC, 0x00, 0x80, 0x00);
        ATEST(0X1000, "CALR P, 1003H",   0xED, 0xF4, 0x00);
        ATEST(0X1000, "CALR M, 1000H",   0xED, 0xFC, 0xFD);
        AERRT(0xFFF0, "CALR 10072H",
              OVERFLOW_RANGE, "10072H", 0xED, 0xCD, 0x7F);
        AERRT(0xF000, "CALR 11004H",
              OVERFLOW_RANGE, "11004H", 0xDD, 0xCD, 0x00, 0x20);
        AERRT(0x1000, "CALR 11005H",
              OVERFLOW_RANGE, "11005H", 0xFD, 0xCD, 0x00, 0x00, 0x01);
    }

    ATEST(0x1000, "JR    1000H", 0x18, 0xFE);
    ATEST(0x1000, "JR NZ,1004H", 0x20, 0x02);
    ATEST(0x1000, "JR  Z,1081H", 0x28, 0x7F);
    ATEST(0x1000, "JR NC,0F82H", 0x30, 0x80);
    ATEST(0x1000, "JR  C,0F82H", 0x38, 0x80);
    ATEST(0x1000, "JR  C,1081H", 0x38, 0x7F);
    ATEST(0x1000, "JR  C,0F82H", 0x38, 0x80);
    ATEST(0x1000, "JR $+80H",    0x18, 0x7E);
    if (isZ380()) {
        ATEST(0x1000, "JR 2083H",     0xDD, 0x18, 0x7F, 0x10);
        ATEST(0x1000, "JR 9005H",     0xFD, 0x18, 0x00, 0x80, 0x00);

        ATEST(0x1000, "JR NZ, 3004H", 0xDD, 0x20, 0x00, 0x20);
        ATEST(0x1000, "JR Z, 0A005H", 0xFD, 0x28, 0x00, 0x90, 0x00);
        ATEST(0xF000, "JR NC, 7004H", 0xDD, 0x30, 0x00, 0x80);
        ATEST(0xF000, "JR C, 6005H",  0xFD, 0x38, 0x00, 0x70, 0xFF);
        ATEST(0x1000, "JR C, 1004H",  0x38, 0x02);
        ATEST(0x1000, "JR C, 1000H",  0x38, 0xFE);
        AERRT(0xFFFFFF80, "JR C, 000000001H",
              OVERFLOW_RANGE, "000000001H", 0x38, 0x7F);
        AERRT(0x0000007D, "JR C, 0FFFFFFFFH",
              OVERFLOW_RANGE, "0FFFFFFFFH", 0x38, 0x80);
        AERRT(0xFFF0, "JR C, 10071H",
              OVERFLOW_RANGE, "10071H", 0x38, 0x7F);
        AERRT(0xF000, "JR C, 11004H",
              OVERFLOW_RANGE, "11004H", 0xDD, 0x38, 0x00, 0x20);
        AERRT(0x1000, "JR C, 11005H",
              OVERFLOW_RANGE, "11005H", 0xFD, 0x38, 0x00, 0x00, 0x01);
    } else {
        AERRT(0x1000, "JR  C,1082H", OPERAND_TOO_FAR, "1082H", 0x38, 0x80);
        AERRT(0x1000, "JR  C,0F81H", OPERAND_TOO_FAR, "0F81H", 0x38, 0x7F);
    }

    ATEST(0x1000, "DJNZ 1000H",  0x10, 0xFE);
    ATEST(0x1000, "DJNZ 1081H",  0x10, 0x7F);
    ATEST(0x1000, "DJNZ 0F82H",  0x10, 0x80);
    if (isZ380()) {
        ATEST(0x1000, "DJNZ 9003H",  0xDD, 0x10, 0xFF, 0x7F);
        ATEST(0x1000, "DJNZ 9005H",  0xFD, 0x10, 0x00, 0x80, 0x00);
        AERRT(0xFFFFFF80, "DJNZ 000000001H", OVERFLOW_RANGE, "000000001H", 0x10, 0x7F);
        AERRT(0x0000007D, "DJNZ 0FFFFFFFFH", OVERFLOW_RANGE, "0FFFFFFFFH", 0x10, 0x80);
    } else {
        AERRT(0x1000, "DJNZ 1082H",  OPERAND_TOO_FAR, "1082H", 0x10, 0x80);
        AERRT(0x1000, "DJNZ 0F81H",  OPERAND_TOO_FAR, "0F81H", 0x10, 0x7F);
    }
}

void test_incr_decr() {
    TEST("INC A", 0x3C);
    TEST("INC B", 0x04);
    TEST("INC C", 0x0C);
    TEST("INC D", 0x14);
    TEST("INC E", 0x1C);
    TEST("INC H", 0x24);
    TEST("INC L", 0x2C);

    TEST("INC (HL)", 0x34);
    TEST("INC (IX+2)", 0xDD, 0x34, 0x02);
    TEST("INC (IY-2)", 0xFD, 0x34, 0xFE);
    if (isZ380()) {
        TEST("INC (IX+128)",     DDIR_IB, 0xDD, 0x34, 0x80, 0x00);
        TEST("INC (IY+128)",     DDIR_IB, 0xFD, 0x34, 0x80, 0x00);
        TEST("INC (IY+123456H)", DDIR_IW, 0xFD, 0x34, 0x56, 0x34, 0x12);
    } else {
        ERRT("INC (IX+128)", OVERFLOW_RANGE, "(IX+128)", 0xDD, 0x34, 0x80);
        ERRT("INC (IY+128)", OVERFLOW_RANGE, "(IY+128)", 0xFD, 0x34, 0x80);
    }

    TEST("DEC A", 0x3D);
    TEST("DEC B", 0x05);
    TEST("DEC C", 0x0D);
    TEST("DEC D", 0x15);
    TEST("DEC E", 0x1D);
    TEST("DEC H", 0x25);
    TEST("DEC L", 0x2D);
    if (isZ380()) {
        TEST("DEC IXU", 0xDD, 0x25);
        TEST("DEC IXL", 0xDD, 0x2D);
        TEST("DEC IYU", 0xFD, 0x25);
        TEST("DEC IYL", 0xFD, 0x2D);
    }

    TEST("DEC (HL)", 0x35);
    TEST("DEC (IX+2)", 0xDD, 0x35, 0x02);
    TEST("DEC (IY-2)", 0xFD, 0x35, 0xFE);
    if (isZ380()) {
        TEST("DEC (IX-129)",     DDIR_IB, 0xDD, 0x35, 0x7F, 0xFF);
        TEST("DEC (IY-129)",     DDIR_IB, 0xFD, 0x35, 0x7F, 0xFF);
        TEST("DEC (IY+123456H)", DDIR_IW, 0xFD, 0x35, 0x56, 0x34, 0x12);
    } else {
        ERRT("DEC (IX-129)", OVERFLOW_RANGE, "(IX-129)", 0xDD, 0x35, 0x7F);
        ERRT("DEC (IY-129)", OVERFLOW_RANGE, "(IY-129)", 0xFD, 0x35, 0x7F);
    }

    TEST("INC BC", 0x03);
    TEST("INC DE", 0x13);
    TEST("INC HL", 0x23);
    TEST("INC SP", 0x33);
    TEST("INC IX", 0xDD, 0x23);
    TEST("INC IY", 0xFD, 0x23);
    if (isZ380()) {
        TEST("INCW BC", 0x03);
        TEST("INCW DE", 0x13);
        TEST("INCW HL", 0x23);
        TEST("INCW SP", 0x33);
        TEST("INCW IX", 0xDD, 0x23);
        TEST("INCW IY", 0xFD, 0x23);
    }

    TEST("DEC BC", 0x0B);
    TEST("DEC DE", 0x1B);
    TEST("DEC HL", 0x2B);
    TEST("DEC SP", 0x3B);
    TEST("DEC IX", 0xDD, 0x2B);
    TEST("DEC IY", 0xFD, 0x2B);
    if (isZ380()) {
        TEST("DECW BC", 0x0B);
        TEST("DECW DE", 0x1B);
        TEST("DECW HL", 0x2B);
        TEST("DECW SP", 0x3B);
        TEST("DECW IX", 0xDD, 0x2B);
        TEST("DECW IY", 0xFD, 0x2B);
    }
}

void test_alu_8bit() {
    TEST("RLCA",  0x07);
    TEST("RLC A", 0xCB, 0x07);
    TEST("RLC B", 0xCB, 0x00);
    TEST("RLC C", 0xCB, 0x01);
    TEST("RLC D", 0xCB, 0x02);
    TEST("RLC E", 0xCB, 0x03);
    TEST("RLC H", 0xCB, 0x04);
    TEST("RLC L", 0xCB, 0x05);
    TEST("RLC (HL)", 0xCB, 0x06);
    TEST("RLC (IX+127)", 0xDD, 0xCB, 0x7F, 0x06);
    TEST("RLC (IY-128)", 0xFD, 0xCB, 0x80, 0x06);
    if (isZ380()) {
        TEST("RLC (IY-8000H)",   DDIR_IB, 0xFD, 0xCB, 0x00, 0x80, 0x06);
        TEST("RLC (IY-800000H)", DDIR_IW, 0xFD, 0xCB, 0x00, 0x00, 0x80, 0x06);
    }

    TEST("RRCA",  0x0F);
    TEST("RRC A", 0xCB, 0x0F);
    TEST("RRC B", 0xCB, 0x08);
    TEST("RRC C", 0xCB, 0x09);
    TEST("RRC D", 0xCB, 0x0A);
    TEST("RRC E", 0xCB, 0x0B);
    TEST("RRC H", 0xCB, 0x0C);
    TEST("RRC L", 0xCB, 0x0D);
    TEST("RRC (HL)", 0xCB, 0x0E);
    TEST("RRC (IX+127)", 0xDD, 0xCB, 0x7F, 0x0E);
    TEST("RRC (IY-128)", 0xFD, 0xCB, 0x80, 0x0E);
    if (isZ380()) {
        TEST("RRC (IY-8000H)",   DDIR_IB, 0xFD, 0xCB, 0x00, 0x80, 0x0E);
        TEST("RRC (IY-800000H)", DDIR_IW, 0xFD, 0xCB, 0x00, 0x00, 0x80, 0x0E);
    }

    TEST("RLA",  0x17);
    TEST("RL A", 0xCB, 0x17);
    TEST("RL B", 0xCB, 0x10);
    TEST("RL C", 0xCB, 0x11);
    TEST("RL D", 0xCB, 0x12);
    TEST("RL E", 0xCB, 0x13);
    TEST("RL H", 0xCB, 0x14);
    TEST("RL L", 0xCB, 0x15);
    TEST("RL (HL)", 0xCB, 0x16);
    TEST("RL  (IX+127)", 0xDD, 0xCB, 0x7F, 0x16);
    TEST("RL  (IY-128)", 0xFD, 0xCB, 0x80, 0x16);
    if (isZ380()) {
        TEST("RL (IY-8000H)",   DDIR_IB, 0xFD, 0xCB, 0x00, 0x80, 0x16);
        TEST("RL (IY-800000H)", DDIR_IW, 0xFD, 0xCB, 0x00, 0x00, 0x80, 0x16);
    }

    TEST("RRA",  0x1F);
    TEST("RR A", 0xCB, 0x1F);
    TEST("RR B", 0xCB, 0x18);
    TEST("RR C", 0xCB, 0x19);
    TEST("RR D", 0xCB, 0x1A);
    TEST("RR E", 0xCB, 0x1B);
    TEST("RR H", 0xCB, 0x1C);
    TEST("RR L", 0xCB, 0x1D);
    TEST("RR (HL)", 0xCB, 0x1E);
    TEST("RR  (IX+127)", 0xDD, 0xCB, 0x7F, 0x1E);
    TEST("RR  (IY-128)", 0xFD, 0xCB, 0x80, 0x1E);
    if (isZ380()) {
        TEST("RR (IY-8000H)",   DDIR_IB, 0xFD, 0xCB, 0x00, 0x80, 0x1E);
        TEST("RR (IY-800000H)", DDIR_IW, 0xFD, 0xCB, 0x00, 0x00, 0x80, 0x1E);
    }

    TEST("SLA A", 0xCB, 0x27);
    TEST("SLA B", 0xCB, 0x20);
    TEST("SLA C", 0xCB, 0x21);
    TEST("SLA D", 0xCB, 0x22);
    TEST("SLA E", 0xCB, 0x23);
    TEST("SLA H", 0xCB, 0x24);
    TEST("SLA L", 0xCB, 0x25);
    TEST("SLA (HL)", 0xCB, 0x26);
    TEST("SLA (IX+127)", 0xDD, 0xCB, 0x7F, 0x26);
    TEST("SLA (IY-128)", 0xFD, 0xCB, 0x80, 0x26);
    if (isZ380()) {
        TEST("SLA (IY-8000H)",   DDIR_IB, 0xFD, 0xCB, 0x00, 0x80, 0x26);
        TEST("SLA (IY-800000H)", DDIR_IW, 0xFD, 0xCB, 0x00, 0x00, 0x80, 0x26);
    }

    TEST("SRA A", 0xCB, 0x2F);
    TEST("SRA B", 0xCB, 0x28);
    TEST("SRA C", 0xCB, 0x29);
    TEST("SRA D", 0xCB, 0x2A);
    TEST("SRA E", 0xCB, 0x2B);
    TEST("SRA H", 0xCB, 0x2C);
    TEST("SRA L", 0xCB, 0x2D);
    TEST("SRA (HL)", 0xCB, 0x2E);
    TEST("SRA (IX+127)", 0xDD, 0xCB, 0x7F, 0x2E);
    TEST("SRA (IY-128)", 0xFD, 0xCB, 0x80, 0x2E);
    if (isZ380()) {
        TEST("SRA (IY-8000H)",   DDIR_IB, 0xFD, 0xCB, 0x00, 0x80, 0x2E);
        TEST("SRA (IY-800000H)", DDIR_IW, 0xFD, 0xCB, 0x00, 0x00, 0x80, 0x2E);
    }

    TEST("SRL A", 0xCB, 0x3F);
    TEST("SRL B", 0xCB, 0x38);
    TEST("SRL C", 0xCB, 0x39);
    TEST("SRL D", 0xCB, 0x3A);
    TEST("SRL E", 0xCB, 0x3B);
    TEST("SRL H", 0xCB, 0x3C);
    TEST("SRL L", 0xCB, 0x3D);
    TEST("SRL (HL)", 0xCB, 0x3E);
    TEST("SRL (IX+127)", 0xDD, 0xCB, 0x7F, 0x3E);
    TEST("SRL (IY-128)", 0xFD, 0xCB, 0x80, 0x3E);
    if (isZ380()) {
        TEST("SRL (IX+128)", DDIR_IB, 0xDD, 0xCB, 0x80, 0x00, 0x3E);
        TEST("SRL (IX-129)", DDIR_IB, 0xDD, 0xCB, 0x7F, 0xFF, 0x3E);
    } else {
        ERRT("SRL (IX+128)", OVERFLOW_RANGE, "(IX+128)", 0xDD, 0xCB, 0x80, 0x3E);
        ERRT("SRL (IX-129)", OVERFLOW_RANGE, "(IX-129)", 0xDD, 0xCB, 0x7F, 0x3E);
    }

    TEST("RRD", 0xED, 0x67);
    TEST("RLD", 0xED, 0x6F);

    TEST("DAA", 0x27);
    TEST("NEG", 0xED, 0x44);
    TEST("CPL", 0x2F);
    if (isZ380()) {
        TEST("NEG A",  0xED, 0x44);
        TEST("CPL A",  0x2F);
    } else {
        ERRT("NEG A", OPERAND_NOT_ALLOWED, "A");
        ERRT("CPL A", OPERAND_NOT_ALLOWED, "A");
    }
    if (isZ380()) {
        TEST("EXTS A", 0xED, 0x65);
        TEST("EXTS",   0xED, 0x65);
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0x1002, 0x1002, "EXTS A",  0xED, 0x65);
        ATEST(0x1000, "DDIR W",  DDIR_W);
        CTEST(0x1002, 0x1002, "EXTS",    0xED, 0x65);
    } else {
        ERUI("EXTS");
    }

    TEST("ADD A,A", 0x87);
    TEST("ADD A,B", 0x80);
    TEST("ADD A,C", 0x81);
    TEST("ADD A,D", 0x82);
    TEST("ADD A,E", 0x83);
    TEST("ADD A,H", 0x84);
    TEST("ADD A,L", 0x85);
    if (isZ380()) {
        TEST("ADD A, IXU", 0xDD, 0x84);
        TEST("ADD A, IXL", 0xDD, 0x85);
        TEST("ADD A, IYU", 0xFD, 0x84);
        TEST("ADD A, IYL", 0xFD, 0x85);
    }
    TEST("ADD A,10B",  0xC6, 0x02);
    TEST("ADD A,(HL)", 0x86);
    TEST("ADD A,(IX+2)", 0xDD, 0x86, 0x02);
    TEST("ADD A,(IY-2)", 0xFD, 0x86, 0xFE);
    if (isZ380()) {
        TEST("ADD A, (IY+1234H)",   DDIR_IB, 0xFD, 0x86, 0x34, 0x12);
        TEST("ADD A, (IY+123456H)", DDIR_IW, 0xFD, 0x86, 0x56, 0x34, 0x12);
    }

    if (isZ380()) {
        TEST("ADD A", 0x87);
        TEST("ADD B", 0x80);
        TEST("ADD C", 0x81);
        TEST("ADD D", 0x82);
        TEST("ADD E", 0x83);
        TEST("ADD H", 0x84);
        TEST("ADD L", 0x85);
        TEST("ADD IXU", 0xDD, 0x84);
        TEST("ADD IXL", 0xDD, 0x85);
        TEST("ADD IYU", 0xFD, 0x84);
        TEST("ADD IYL", 0xFD, 0x85);

        TEST("ADD 10B", 0xC6, 0x02);
        TEST("ADD (HL)", 0x86);
        TEST("ADD (IX+2)", 0xDD, 0x86, 0x02);
        TEST("ADD (IY-2)", 0xFD, 0x86, 0xFE);
    }
    if (isZ380()) {
        TEST("ADD (IY+1234H)",   DDIR_IB, 0xFD, 0x86, 0x34, 0x12);
        TEST("ADD (IY+123456H)", DDIR_IW, 0xFD, 0x86, 0x56, 0x34, 0x12);
    }

    TEST("ADC A,A", 0x8F);
    TEST("ADC A,B", 0x88);
    TEST("ADC A,C", 0x89);
    TEST("ADC A,D", 0x8A);
    TEST("ADC A,E", 0x8B);
    TEST("ADC A,H", 0x8C);
    TEST("ADC A,L", 0x8D);
    if (isZ380()) {
        TEST("ADC A, IXU", 0xDD, 0x8C);
        TEST("ADC A, IXL", 0xDD, 0x8D);
        TEST("ADC A, IYU", 0xFD, 0x8C);
        TEST("ADC A, IYL", 0xFD, 0x8D);
    }
    TEST("ADC A,255",  0xCE, 0xFF);
    TEST("ADC A,(HL)", 0x8E);
    TEST("ADC A,(IX+2)", 0xDD, 0x8E, 0x02);
    TEST("ADC A,(IY-2)", 0xFD, 0x8E, 0xFE);
    if (isZ380()) {
        TEST("ADC A, (IY+1234H)",   DDIR_IB, 0xFD, 0x8E, 0x34, 0x12);
        TEST("ADC A, (IY+123456H)", DDIR_IW, 0xFD, 0x8E, 0x56, 0x34, 0x12);
    }

    if (isZ380()) {
        TEST("ADC A", 0x8F);
        TEST("ADC B", 0x88);
        TEST("ADC C", 0x89);
        TEST("ADC D", 0x8A);
        TEST("ADC E", 0x8B);
        TEST("ADC H", 0x8C);
        TEST("ADC L", 0x8D);
        TEST("ADC IXU", 0xDD, 0x8C);
        TEST("ADC IXL", 0xDD, 0x8D);
        TEST("ADC IYU", 0xFD, 0x8C);
        TEST("ADC IYL", 0xFD, 0x8D);

        TEST("ADC 255", 0xCE, 0xFF);
        TEST("ADC (HL)", 0x8E);
        TEST("ADC (IX+2)", 0xDD, 0x8E, 0x02);
        TEST("ADC (IY-2)", 0xFD, 0x8E, 0xFE);
    }
    if (isZ380()) {
        TEST("ADC (IY+1234H)",   DDIR_IB, 0xFD, 0x8E, 0x34, 0x12);
        TEST("ADC (IY+123456H)", DDIR_IW, 0xFD, 0x8E, 0x56, 0x34, 0x12);
    }

    TEST("SUB A,A", 0x97);
    TEST("SUB A,B", 0x90);
    TEST("SUB A,C", 0x91);
    TEST("SUB A,D", 0x92);
    TEST("SUB A,E", 0x93);
    TEST("SUB A,H", 0x94);
    TEST("SUB A,L", 0x95);
    if (isZ380()) {
        TEST("SUB A, IXU", 0xDD, 0x94);
        TEST("SUB A, IXL", 0xDD, 0x95);
        TEST("SUB A, IYU", 0xFD, 0x94);
        TEST("SUB A, IYL", 0xFD, 0x95);
    }
    TEST("SUB A", 0x97);
    TEST("SUB B", 0x90);
    TEST("SUB C", 0x91);
    TEST("SUB D", 0x92);
    TEST("SUB E", 0x93);
    TEST("SUB H", 0x94);
    TEST("SUB L", 0x95);
    if (isZ380()) {
        TEST("SUB IXU", 0xDD, 0x94);
        TEST("SUB IXL", 0xDD, 0x95);
        TEST("SUB IYU", 0xFD, 0x94);
        TEST("SUB IYL", 0xFD, 0x95);
    }
    TEST("SUB A,-2",   0xD6, 0xFE);
    TEST("SUB A,(HL)", 0x96);
    TEST("SUB A,(IX+2)", 0xDD, 0x96, 0x02);
    TEST("SUB A,(IY-2)", 0xFD, 0x96, 0xFE);
    if (isZ380()) {
        TEST("SUB A, (IY+1234H)",   DDIR_IB, 0xFD, 0x96, 0x34, 0x12);
        TEST("SUB A, (IY+123456H)", DDIR_IW, 0xFD, 0x96, 0x56, 0x34, 0x12);
    }

    TEST("SUB -2",   0xD6, 0xFE);
    TEST("SUB (HL)", 0x96);
    TEST("SUB (IX+2)", 0xDD, 0x96, 0x02);
    TEST("SUB (IY-2)", 0xFD, 0x96, 0xFE);
    if (isZ380()) {
        TEST("SUB (IY+1234H)",   DDIR_IB, 0xFD, 0x96, 0x34, 0x12);
        TEST("SUB (IY+123456H)", DDIR_IW, 0xFD, 0x96, 0x56, 0x34, 0x12);
    }

    TEST("SBC A,A", 0x9F);
    TEST("SBC A,B", 0x98);
    TEST("SBC A,C", 0x99);
    TEST("SBC A,D", 0x9A);
    TEST("SBC A,E", 0x9B);
    TEST("SBC A,H", 0x9C);
    TEST("SBC A,L", 0x9D);
    if (isZ380()) {
        TEST("SBC A, IXU", 0xDD, 0x9C);
        TEST("SBC A, IXL", 0xDD, 0x9D);
        TEST("SBC A, IYU", 0xFD, 0x9C);
        TEST("SBC A, IYL", 0xFD, 0x9D);
   }

    TEST("SBC A,177O", 0xDE, 0x7F);
    TEST("SBC A,(HL)", 0x9E);
    TEST("SBC A,(IX+2)", 0xDD, 0x9E, 0x02);
    TEST("SBC A,(IY-2)", 0xFD, 0x9E, 0xFE);
    if (isZ380()) {
        TEST("SBC A, (IY+1234H)",   DDIR_IB, 0xFD, 0x9E, 0x34, 0x12);
        TEST("SBC A, (IY+123456H)", DDIR_IW, 0xFD, 0x9E, 0x56, 0x34, 0x12);
    }
    if (isZ380()) {
        TEST("SBC A", 0x9F);
        TEST("SBC B", 0x98);
        TEST("SBC C", 0x99);
        TEST("SBC D", 0x9A);
        TEST("SBC E", 0x9B);
        TEST("SBC H", 0x9C);
        TEST("SBC L", 0x9D);
        TEST("SBC IXU", 0xDD, 0x9C);
        TEST("SBC IXL", 0xDD, 0x9D);
        TEST("SBC IYU", 0xFD, 0x9C);
        TEST("SBC IYL", 0xFD, 0x9D);

        TEST("SBC 177O", 0xDE, 0x7F);
        TEST("SBC (HL)", 0x9E);
        TEST("SBC (IX+2)", 0xDD, 0x9E, 0x02);
        TEST("SBC (IY-2)", 0xFD, 0x9E, 0xFE);
    }
    if (isZ380()) {
        TEST("SBC (IY+1234H)",   DDIR_IB, 0xFD, 0x9E, 0x34, 0x12);
        TEST("SBC (IY+123456H)", DDIR_IW, 0xFD, 0x9E, 0x56, 0x34, 0x12);
    }

    TEST("AND A,A", 0xA7);
    TEST("AND A,B", 0xA0);
    TEST("AND A,C", 0xA1);
    TEST("AND A,D", 0xA2);
    TEST("AND A,E", 0xA3);
    TEST("AND A,H", 0xA4);
    TEST("AND A,L", 0xA5);
    if (isZ380()) {
        TEST("AND A, IXU", 0xDD, 0xA4);
        TEST("AND A, IXL", 0xDD, 0xA5);
        TEST("AND A, IYU", 0xFD, 0xA4);
        TEST("AND A, IYL", 0xFD, 0xA5);
    }

    TEST("AND A", 0xA7);
    TEST("AND B", 0xA0);
    TEST("AND C", 0xA1);
    TEST("AND D", 0xA2);
    TEST("AND E", 0xA3);
    TEST("AND H", 0xA4);
    TEST("AND L", 0xA5);
    if (isZ380()) {
        TEST("AND IXU", 0xDD, 0xA4);
        TEST("AND IXL", 0xDD, 0xA5);
        TEST("AND IYU", 0xFD, 0xA4);
        TEST("AND IYL", 0xFD, 0xA5);
    }

    TEST("AND A,~0FH", 0xE6, 0xF0);
    TEST("AND A,(HL)", 0xA6);
    TEST("AND A,(IX+2)", 0xDD, 0xA6, 0x02);
    TEST("AND A,(IY-2)", 0xFD, 0xA6, 0xFE);
    if (isZ380()) {
        TEST("AND A, (IY+1234H)",   DDIR_IB, 0xFD, 0xA6, 0x34, 0x12);
        TEST("AND A, (IY+123456H)", DDIR_IW, 0xFD, 0xA6, 0x56, 0x34, 0x12);
    }

    TEST("AND ~0FH", 0xE6, 0xF0);
    TEST("AND (HL)", 0xA6);
    TEST("AND (IX+2)", 0xDD, 0xA6, 0x02);
    TEST("AND (IY-2)", 0xFD, 0xA6, 0xFE);
    if (isZ380()) {
        TEST("AND (IY+1234H)",   DDIR_IB, 0xFD, 0xA6, 0x34, 0x12);
        TEST("AND (IY+123456H)", DDIR_IW, 0xFD, 0xA6, 0x56, 0x34, 0x12);
    }

    TEST("XOR A,A", 0xAF);
    TEST("XOR A,B", 0xA8);
    TEST("XOR A,C", 0xA9);
    TEST("XOR A,D", 0xAA);
    TEST("XOR A,E", 0xAB);
    TEST("XOR A,H", 0xAC);
    TEST("XOR A,L", 0xAD);
    if (isZ380()) {
        TEST("XOR A, IXU", 0xDD, 0xAC);
        TEST("XOR A, IXL", 0xDD, 0xAD);
        TEST("XOR A, IYU", 0xFD, 0xAC);
        TEST("XOR A, IYL", 0xFD, 0xAD);
    }

    TEST("XOR A", 0xAF);
    TEST("XOR B", 0xA8);
    TEST("XOR C", 0xA9);
    TEST("XOR D", 0xAA);
    TEST("XOR E", 0xAB);
    TEST("XOR H", 0xAC);
    TEST("XOR L", 0xAD);
    if (isZ380()) {
        TEST("XOR IXU", 0xDD, 0xAC);
        TEST("XOR IXL", 0xDD, 0xAD);
        TEST("XOR IYU", 0xFD, 0xAC);
        TEST("XOR IYL", 0xFD, 0xAD);
    }

    TEST("XOR A,~001B",0xEE, 0xFE);
    TEST("XOR A,(HL)", 0xAE);
    TEST("XOR A,(IX+2)", 0xDD, 0xAE, 0x02);
    TEST("XOR A,(IY-2)", 0xFD, 0xAE, 0xFE);
    if (isZ380()) {
        TEST("XOR A, (IY+1234H)",   DDIR_IB, 0xFD, 0xAE, 0x34, 0x12);
        TEST("XOR A, (IY+123456H)", DDIR_IW, 0xFD, 0xAE, 0x56, 0x34, 0x12);
    }

    TEST("XOR ~001B",0xEE, 0xFE);
    TEST("XOR (HL)", 0xAE);
    TEST("XOR (IX+2)", 0xDD, 0xAE, 0x02);
    TEST("XOR (IY-2)", 0xFD, 0xAE, 0xFE);
    if (isZ380()) {
        TEST("XOR (IY+1234H)",   DDIR_IB, 0xFD, 0xAE, 0x34, 0x12);
        TEST("XOR (IY+123456H)", DDIR_IW, 0xFD, 0xAE, 0x56, 0x34, 0x12);
    }

    TEST("OR A,A", 0xB7);
    TEST("OR A,B", 0xB0);
    TEST("OR A,C", 0xB1);
    TEST("OR A,D", 0xB2);
    TEST("OR A,E", 0xB3);
    TEST("OR A,H", 0xB4);
    TEST("OR A,L", 0xB5);
    if (isZ380()) {
        TEST("OR A, IXU", 0xDD, 0xB4);
        TEST("OR A, IXL", 0xDD, 0xB5);
        TEST("OR A, IYU", 0xFD, 0xB4);
        TEST("OR A, IYL", 0xFD, 0xB5);
    }

    TEST("OR A", 0xB7);
    TEST("OR B", 0xB0);
    TEST("OR C", 0xB1);
    TEST("OR D", 0xB2);
    TEST("OR E", 0xB3);
    TEST("OR H", 0xB4);
    TEST("OR L", 0xB5);
    if (isZ380()) {
        TEST("OR IXU", 0xDD, 0xB4);
        TEST("OR IXL", 0xDD, 0xB5);
        TEST("OR IYU", 0xFD, 0xB4);
        TEST("OR IYL", 0xFD, 0xB5);
    }

    TEST("OR A,+127", 0xF6, 0x7F);
    TEST("OR A,(HL)", 0xB6);
    TEST("OR A,(IX+2)", 0xDD, 0xB6, 0x02);
    TEST("OR A,(IY-2)", 0xFD, 0xB6, 0xFE);
    if (isZ380()) {
        TEST("OR A, (IY+1234H)",   DDIR_IB, 0xFD, 0xB6, 0x34, 0x12);
        TEST("OR A, (IY+123456H)", DDIR_IW, 0xFD, 0xB6, 0x56, 0x34, 0x12);
    }

    TEST("OR +127", 0xF6, 0x7F);
    TEST("OR (HL)", 0xB6);
    TEST("OR (IX+2)", 0xDD, 0xB6, 0x02);
    TEST("OR (IY-2)", 0xFD, 0xB6, 0xFE);
    if (isZ380()) {
        TEST("OR (IY+1234H)",   DDIR_IB, 0xFD, 0xB6, 0x34, 0x12);
        TEST("OR (IY+123456H)", DDIR_IW, 0xFD, 0xB6, 0x56, 0x34, 0x12);
    }

    TEST("CP A,A", 0xBF);
    TEST("CP A,B", 0xB8);
    TEST("CP A,C", 0xB9);
    TEST("CP A,D", 0xBA);
    TEST("CP A,E", 0xBB);
    TEST("CP A,H", 0xBC);
    TEST("CP A,L", 0xBD);
    if (isZ380()) {
        TEST("CP A, IXU", 0xDD, 0xBC);
        TEST("CP A, IXL", 0xDD, 0xBD);
        TEST("CP A, IYU", 0xFD, 0xBC);
        TEST("CP A, IYL", 0xFD, 0xBD);
    }

    TEST("CP A", 0xBF);
    TEST("CP B", 0xB8);
    TEST("CP C", 0xB9);
    TEST("CP D", 0xBA);
    TEST("CP E", 0xBB);
    TEST("CP H", 0xBC);
    TEST("CP L", 0xBD);
    if (isZ380()) {
        TEST("CP IXU", 0xDD, 0xBC);
        TEST("CP IXL", 0xDD, 0xBD);
        TEST("CP IYU", 0xFD, 0xBC);
        TEST("CP IYL", 0xFD, 0xBD);
    }

    TEST("CP A,-128", 0xFE, 0x80);
    TEST("CP A,(HL)", 0xBE);
    TEST("CP A,(IX+2)", 0xDD, 0xBE, 0x02);
    TEST("CP A,(IY-2)", 0xFD, 0xBE, 0xFE);
    if (isZ380()) {
        TEST("CP A, (IY+1234H)",   DDIR_IB, 0xFD, 0xBE, 0x34, 0x12);
        TEST("CP A, (IY+123456H)", DDIR_IW, 0xFD, 0xBE, 0x56, 0x34, 0x12);
    }

    TEST("CP -128", 0xFE, 0x80);
    TEST("CP (HL)", 0xBE);
    TEST("CP (IX+2)", 0xDD, 0xBE, 0x02);
    TEST("CP (IY-2)", 0xFD, 0xBE, 0xFE);
    if (isZ380()) {
        TEST("CP (IY+1234H)",   DDIR_IB, 0xFD, 0xBE, 0x34, 0x12);
        TEST("CP (IY+123456H)", DDIR_IW, 0xFD, 0xBE, 0x56, 0x34, 0x12);
    }

    if (isZ180() || isZ380()) {
        TEST("TST A", 0xED, 0x3C);
        TEST("TST B", 0xED, 0x04);
        TEST("TST C", 0xED, 0x0C);
        TEST("TST D", 0xED, 0x14);
        TEST("TST E", 0xED, 0x1C);
        TEST("TST H", 0xED, 0x24);
        TEST("TST L", 0xED, 0x2C);
        TEST("TST 80H", 0xED, 0x64, 0x80);
    }        
}

void test_alu_16bit() {
    if (isZ380()) {
        TEST("NEGW  HL", 0xED, 0x54);
        TEST("NEGW",     0xED, 0x54);
        TEST("EXTSW HL", 0xED, 0x75);
        TEST("EXTSW",    0xED, 0x75);
        ERRT("NEG  HL", OPERAND_NOT_ALLOWED, "HL");
        ERRT("EXTS HL", OPERAND_NOT_ALLOWED, "HL");
    } else {
        ERRT("NEG  HL", OPERAND_NOT_ALLOWED, "HL");
        ERUI("NEGW");
        ERUI("EXTS");
    }

    if (isZ380()) {
        TEST("RLW BC", 0xED, 0xCB, 0x10);
        TEST("RLW DE", 0xED, 0xCB, 0x11);
        TEST("RLW HL", 0xED, 0xCB, 0x13);
        TEST("RLW IX", 0xED, 0xCB, 0x14);
        TEST("RLW IY", 0xED, 0xCB, 0x15);
        TEST("RLW (HL)",     0xED, 0xCB, 0x12);
        TEST("RLW (IX+127)", 0xDD, 0xCB, 0x7F, 0x12);
        TEST("RLW (IY-128)", 0xFD, 0xCB, 0x80, 0x12);
        TEST("RLW (IY-8000H)",   DDIR_IB, 0xFD, 0xCB, 0x00, 0x80, 0x12);
        TEST("RLW (IY-800000H)", DDIR_IW, 0xFD, 0xCB, 0x00, 0x00, 0x80, 0x12);

        TEST("RLCW BC", 0xED, 0xCB, 0x00);
        TEST("RLCW DE", 0xED, 0xCB, 0x01);
        TEST("RLCW HL", 0xED, 0xCB, 0x03);
        TEST("RLCW IX", 0xED, 0xCB, 0x04);
        TEST("RLCW IY", 0xED, 0xCB, 0x05);
        TEST("RLCW (HL)",     0xED, 0xCB, 0x02);
        TEST("RLCW (IX+127)", 0xDD, 0xCB, 0x7F, 0x02);
        TEST("RLCW (IY-128)", 0xFD, 0xCB, 0x80, 0x02);
        TEST("RLCW (IY-8000H)",   DDIR_IB, 0xFD, 0xCB, 0x00, 0x80, 0x02);
        TEST("RLCW (IY-800000H)", DDIR_IW, 0xFD, 0xCB, 0x00, 0x00, 0x80, 0x02);

        TEST("RRW BC", 0xED, 0xCB, 0x18);
        TEST("RRW DE", 0xED, 0xCB, 0x19);
        TEST("RRW HL", 0xED, 0xCB, 0x1B);
        TEST("RRW IX", 0xED, 0xCB, 0x1C);
        TEST("RRW IY", 0xED, 0xCB, 0x1D);
        TEST("RRW (HL)",     0xED, 0xCB, 0x1A);
        TEST("RRW (IX+127)", 0xDD, 0xCB, 0x7F, 0x1A);
        TEST("RRW (IY-128)", 0xFD, 0xCB, 0x80, 0x1A);
        TEST("RRW (IY-8000H)",   DDIR_IB, 0xFD, 0xCB, 0x00, 0x80, 0x1A);
        TEST("RRW (IY-800000H)", DDIR_IW, 0xFD, 0xCB, 0x00, 0x00, 0x80, 0x1A);

        TEST("RRCW BC", 0xED, 0xCB, 0x08);
        TEST("RRCW DE", 0xED, 0xCB, 0x09);
        TEST("RRCW HL", 0xED, 0xCB, 0x0B);
        TEST("RRCW IX", 0xED, 0xCB, 0x0C);
        TEST("RRCW IY", 0xED, 0xCB, 0x0D);
        TEST("RRCW (HL)",     0xED, 0xCB, 0x0A);
        TEST("RRCW (IX+127)", 0xDD, 0xCB, 0x7F, 0x0A);
        TEST("RRCW (IY-128)", 0xFD, 0xCB, 0x80, 0x0A);
        TEST("RRCW (IY-8000H)",   DDIR_IB, 0xFD, 0xCB, 0x00, 0x80, 0x0A);
        TEST("RRCW (IY-800000H)", DDIR_IW, 0xFD, 0xCB, 0x00, 0x00, 0x80, 0x0A);

        TEST("SLAW BC", 0xED, 0xCB, 0x20);
        TEST("SLAW DE", 0xED, 0xCB, 0x21);
        TEST("SLAW HL", 0xED, 0xCB, 0x23);
        TEST("SLAW IX", 0xED, 0xCB, 0x24);
        TEST("SLAW IY", 0xED, 0xCB, 0x25);
        TEST("SLAW (HL)",     0xED, 0xCB, 0x22);
        TEST("SLAW (IX+127)", 0xDD, 0xCB, 0x7F, 0x22);
        TEST("SLAW (IY-128)", 0xFD, 0xCB, 0x80, 0x22);
        TEST("SLAW (IY-8000H)",   DDIR_IB, 0xFD, 0xCB, 0x00, 0x80, 0x22);
        TEST("SLAW (IY-800000H)", DDIR_IW, 0xFD, 0xCB, 0x00, 0x00, 0x80, 0x22);

        TEST("SRAW BC", 0xED, 0xCB, 0x28);
        TEST("SRAW DE", 0xED, 0xCB, 0x29);
        TEST("SRAW HL", 0xED, 0xCB, 0x2B);
        TEST("SRAW IX", 0xED, 0xCB, 0x2C);
        TEST("SRAW IY", 0xED, 0xCB, 0x2D);
        TEST("SRAW (HL)",     0xED, 0xCB, 0x2A);
        TEST("SRAW (IX+127)", 0xDD, 0xCB, 0x7F, 0x2A);
        TEST("SRAW (IY-128)", 0xFD, 0xCB, 0x80, 0x2A);
        TEST("SRAW (IY-8000H)",   DDIR_IB, 0xFD, 0xCB, 0x00, 0x80, 0x2A);
        TEST("SRAW (IY-800000H)", DDIR_IW, 0xFD, 0xCB, 0x00, 0x00, 0x80, 0x2A);

        TEST("SRLW BC", 0xED, 0xCB, 0x38);
        TEST("SRLW DE", 0xED, 0xCB, 0x39);
        TEST("SRLW HL", 0xED, 0xCB, 0x3B);
        TEST("SRLW IX", 0xED, 0xCB, 0x3C);
        TEST("SRLW IY", 0xED, 0xCB, 0x3D);
        TEST("SRLW (HL)",     0xED, 0xCB, 0x3A);
        TEST("SRLW (IX+127)", 0xDD, 0xCB, 0x7F, 0x3A);
        TEST("SRLW (IY-128)", 0xFD, 0xCB, 0x80, 0x3A);
        TEST("SRLW (IY-8000H)",   DDIR_IB, 0xFD, 0xCB, 0x00, 0x80, 0x3A);
        TEST("SRLW (IY-800000H)", DDIR_IW, 0xFD, 0xCB, 0x00, 0x00, 0x80, 0x3A);
    }

    TEST("ADD HL,BC", 0x09);
    TEST("ADD HL,DE", 0x19);
    TEST("ADD HL,HL", 0x29);
    TEST("ADD HL,SP", 0x39);
    if (isZ380()) {
        TEST("extmode on");
        TEST("ADD HL, (1234H)",              0xED, 0xC6, 0x34, 0x12);
        TEST("ADD HL, (123456H)",   DDIR_IB, 0xED, 0xC6, 0x56, 0x34, 0x12);
        TEST("ADD HL, (12345678H)", DDIR_IW, 0xED, 0xC6, 0x78, 0x56, 0x34, 0x12);
        TEST("extmode off");
        TEST("ADD HL, (1234H)",                                    0xED, 0xC6, 0x34, 0x12);
        ERRT("ADD HL, (123456H)",   OVERFLOW_RANGE,   "(123456H)", 0xED, 0xC6, 0x56, 0x34);
        ERRT("ADD HL, (12345678H)", OVERFLOW_RANGE, "(12345678H)", 0xED, 0xC6, 0x78, 0x56);

        TEST("extmode on");
        TEST("ADD SP, 1234H",              0xED, 0x82, 0x34, 0x12);
        TEST("ADD SP, 123456H",   DDIR_IB, 0xED, 0x82, 0x56, 0x34, 0x12);
        TEST("ADD SP, 12345678H", DDIR_IW, 0xED, 0x82, 0x78, 0x56, 0x34, 0x12);
        TEST("extmode off");
        TEST("ADD SP, 1234H",                                  0xED, 0x82, 0x34, 0x12);
        ERRT("ADD SP, 123456H",   OVERFLOW_RANGE,   "123456H", 0xED, 0x82, 0x56, 0x34);
        ERRT("ADD SP, 12345678H", OVERFLOW_RANGE, "12345678H", 0xED, 0x82, 0x78, 0x56);

        TEST("ADDW HL, BC", 0xED, 0x84);
        TEST("ADDW HL, DE", 0xED, 0x85);
        TEST("ADDW HL, HL", 0xED, 0x87);
        TEST("ADDW HL, IX", 0xDD, 0x87);
        TEST("ADDW HL, IY", 0xFD, 0x87);
        TEST("ADDW HL, 1234H",    0xED, 0x86, 0x34, 0x12);
        TEST("ADDW HL, (IX-128)", 0xDD, 0xC6, 0x80);
        TEST("ADDW HL, (IY+127)", 0xFD, 0xC6, 0x7F);
        TEST("ADDW HL, (IX-8000H)",   DDIR_IB, 0xDD, 0xC6, 0x00, 0x80);
        TEST("ADDW HL, (IX-800000H)", DDIR_IW, 0xDD, 0xC6, 0x00, 0x00, 0x80);

        TEST("ADDW BC", 0xED, 0x84);
        TEST("ADDW DE", 0xED, 0x85);
        TEST("ADDW HL", 0xED, 0x87);
        TEST("ADDW IX", 0xDD, 0x87);
        TEST("ADDW IY", 0xFD, 0x87);
        TEST("ADDW 1234H",    0xED, 0x86, 0x34, 0x12);
        TEST("ADDW (IX-128)", 0xDD, 0xC6, 0x80);
        TEST("ADDW (IY+127)", 0xFD, 0xC6, 0x7F);
        TEST("ADDW (IX-8000H)",   DDIR_IB, 0xDD, 0xC6, 0x00, 0x80);
        TEST("ADDW (IX-800000H)", DDIR_IW, 0xDD, 0xC6, 0x00, 0x00, 0x80);
    }

    TEST("ADD IX,BC", 0xDD, 0x09);
    TEST("ADD IX,DE", 0xDD, 0x19);
    ERRT("ADD IX,HL", REGISTER_NOT_ALLOWED, "HL", 0xDD, 0x29);
    TEST("ADD IX,SP", 0xDD, 0x39);
    TEST("ADD IX,IX", 0xDD, 0x29);

    TEST("ADD IY,BC", 0xFD, 0x09);
    TEST("ADD IY,DE", 0xFD, 0x19);
    ERRT("ADD IY,HL", REGISTER_NOT_ALLOWED, "HL", 0xFD, 0x29);
    TEST("ADD IY,SP", 0xFD, 0x39);
    TEST("ADD IY,IY", 0xFD, 0x29);

    TEST("ADC HL,BC", 0xED, 0x4A);
    TEST("ADC HL,DE", 0xED, 0x5A);
    TEST("ADC HL,HL", 0xED, 0x6A);
    TEST("ADC HL,SP", 0xED, 0x7A);

    if (isZ380()) {
        TEST("ADCW HL, BC", 0xED, 0x8C);
        TEST("ADCW HL, DE", 0xED, 0x8D);
        TEST("ADCW HL, HL", 0xED, 0x8F);
        TEST("ADCW HL, IX", 0xDD, 0x8F);
        TEST("ADCW HL, IY", 0xFD, 0x8F);
        TEST("ADCW HL, 1234H",    0xED, 0x8E, 0x34, 0x12);
        TEST("ADCW HL, (IX-128)", 0xDD, 0xCE, 0x80);
        TEST("ADCW HL, (IY+127)", 0xFD, 0xCE, 0x7F);
        TEST("ADCW HL, (IX-8000H)",   DDIR_IB, 0xDD, 0xCE, 0x00, 0x80);
        TEST("ADCW HL, (IX-800000H)", DDIR_IW, 0xDD, 0xCE, 0x00, 0x00, 0x80);

        TEST("ADCW BC", 0xED, 0x8C);
        TEST("ADCW DE", 0xED, 0x8D);
        TEST("ADCW HL", 0xED, 0x8F);
        TEST("ADCW IX", 0xDD, 0x8F);
        TEST("ADCW IY", 0xFD, 0x8F);
        TEST("ADCW 1234H",    0xED, 0x8E, 0x34, 0x12);
        TEST("ADCW (IX-128)", 0xDD, 0xCE, 0x80);
        TEST("ADCW (IY+127)", 0xFD, 0xCE, 0x7F);
        TEST("ADCW (IX-8000H)",   DDIR_IB, 0xDD, 0xCE, 0x00, 0x80);
        TEST("ADCW (IX-800000H)", DDIR_IW, 0xDD, 0xCE, 0x00, 0x00, 0x80);
    }

    if (isZ380()) {
        TEST("extmode on");
        TEST("SUB HL, (1234H)",              0xED, 0xD6, 0x34, 0x12);
        TEST("SUB HL, (123456H)",   DDIR_IB, 0xED, 0xD6, 0x56, 0x34, 0x12);
        TEST("SUB HL, (12345678H)", DDIR_IW, 0xED, 0xD6, 0x78, 0x56, 0x34, 0x12);
        TEST("extmode off");
        TEST("SUB HL, (1234H)",                                    0xED, 0xD6, 0x34, 0x12);
        ERRT("SUB HL, (123456H)",   OVERFLOW_RANGE,   "(123456H)", 0xED, 0xD6, 0x56, 0x34);
        ERRT("SUB HL, (12345678H)", OVERFLOW_RANGE, "(12345678H)", 0xED, 0xD6, 0x78, 0x56);

        TEST("extmode on");
        TEST("SUB SP, 1234H",              0xED, 0x92, 0x34, 0x12);
        TEST("SUB SP, 123456H",   DDIR_IB, 0xED, 0x92, 0x56, 0x34, 0x12);
        TEST("SUB SP, 12345678H", DDIR_IW, 0xED, 0x92, 0x78, 0x56, 0x34, 0x12);
        TEST("extmode off");
        TEST("SUB SP, 1234H",                                  0xED, 0x92, 0x34, 0x12);
        ERRT("SUB SP, 123456H",   OVERFLOW_RANGE,   "123456H", 0xED, 0x92, 0x56, 0x34);
        ERRT("SUB SP, 12345678H", OVERFLOW_RANGE, "12345678H", 0xED, 0x92, 0x78, 0x56);

        TEST("SUBW HL, BC", 0xED, 0x94);
        TEST("SUBW HL, DE", 0xED, 0x95);
        TEST("SUBW HL, HL", 0xED, 0x97);
        TEST("SUBW HL, IX", 0xDD, 0x97);
        TEST("SUBW HL, IY", 0xFD, 0x97);
        TEST("SUBW HL, 1234H",    0xED, 0x96, 0x34, 0x12);
        TEST("SUBW HL, (IX-128)", 0xDD, 0xD6, 0x80);
        TEST("SUBW HL, (IY+127)", 0xFD, 0xD6, 0x7F);
        TEST("SUBW HL, (IX-8000H)",   DDIR_IB, 0xDD, 0xD6, 0x00, 0x80);
        TEST("SUBW HL, (IX-800000H)", DDIR_IW, 0xDD, 0xD6, 0x00, 0x00, 0x80);

        TEST("SUBW BC", 0xED, 0x94);
        TEST("SUBW DE", 0xED, 0x95);
        TEST("SUBW HL", 0xED, 0x97);
        TEST("SUBW IX", 0xDD, 0x97);
        TEST("SUBW IY", 0xFD, 0x97);
        TEST("SUBW 1234H",    0xED, 0x96, 0x34, 0x12);
        TEST("SUBW (IX-128)", 0xDD, 0xD6, 0x80);
        TEST("SUBW (IY+127)", 0xFD, 0xD6, 0x7F);
        TEST("SUBW (IX-8000H)",   DDIR_IB, 0xDD, 0xD6, 0x00, 0x80);
        TEST("SUBW (IX-800000H)", DDIR_IW, 0xDD, 0xD6, 0x00, 0x00, 0x80);
    }

    TEST("SBC HL,BC", 0xED, 0x42);
    TEST("SBC HL,DE", 0xED, 0x52);
    TEST("SBC HL,HL", 0xED, 0x62);
    TEST("SBC HL,SP", 0xED, 0x72);

    if (isZ380()) {
        TEST("SBCW HL, BC", 0xED, 0x9C);
        TEST("SBCW HL, DE", 0xED, 0x9D);
        TEST("SBCW HL, HL", 0xED, 0x9F);
        TEST("SBCW HL, IX", 0xDD, 0x9F);
        TEST("SBCW HL, IY", 0xFD, 0x9F);
        TEST("SBCW HL, 1234H",    0xED, 0x9E, 0x34, 0x12);
        TEST("SBCW HL, (IX-128)", 0xDD, 0xDE, 0x80);
        TEST("SBCW HL, (IY+127)", 0xFD, 0xDE, 0x7F);
        TEST("SBCW HL, (IX-8000H)",   DDIR_IB, 0xDD, 0xDE, 0x00, 0x80);
        TEST("SBCW HL, (IX-800000H)", DDIR_IW, 0xDD, 0xDE, 0x00, 0x00, 0x80);

        TEST("SBCW BC", 0xED, 0x9C);
        TEST("SBCW DE", 0xED, 0x9D);
        TEST("SBCW HL", 0xED, 0x9F);
        TEST("SBCW IX", 0xDD, 0x9F);
        TEST("SBCW IY", 0xFD, 0x9F);
        TEST("SBCW 1234H",    0xED, 0x9E, 0x34, 0x12);
        TEST("SBCW (IX-128)", 0xDD, 0xDE, 0x80);
        TEST("SBCW (IY+127)", 0xFD, 0xDE, 0x7F);
        TEST("SBCW (IX-8000H)",   DDIR_IB, 0xDD, 0xDE, 0x00, 0x80);
        TEST("SBCW (IX-800000H)", DDIR_IW, 0xDD, 0xDE, 0x00, 0x00, 0x80);
    }

    if (isZ380()) {
        TEST("CPW HL, BC", 0xED, 0xBC);
        TEST("CPW HL, DE", 0xED, 0xBD);
        TEST("CPW HL, HL", 0xED, 0xBF);
        TEST("CPW HL, IX", 0xDD, 0xBF);
        TEST("CPW HL, IY", 0xFD, 0xBF);
        TEST("CPW HL, 1234H",    0xED, 0xBE, 0x34, 0x12);
        TEST("CPW HL, (IX-128)", 0xDD, 0xFE, 0x80);
        TEST("CPW HL, (IY+127)", 0xFD, 0xFE, 0x7F);
        TEST("CPW HL, (IX-8000H)",   DDIR_IB, 0xDD, 0xFE, 0x00, 0x80);
        TEST("CPW HL, (IX-800000H)", DDIR_IW, 0xDD, 0xFE, 0x00, 0x00, 0x80);

        TEST("CPW BC", 0xED, 0xBC);
        TEST("CPW DE", 0xED, 0xBD);
        TEST("CPW HL", 0xED, 0xBF);
        TEST("CPW IX", 0xDD, 0xBF);
        TEST("CPW IY", 0xFD, 0xBF);
        TEST("CPW 1234H",    0xED, 0xBE, 0x34, 0x12);
        TEST("CPW (IX-128)", 0xDD, 0xFE, 0x80);
        TEST("CPW (IY+127)", 0xFD, 0xFE, 0x7F);
        TEST("CPW (IX-8000H)",   DDIR_IB, 0xDD, 0xFE, 0x00, 0x80);
        TEST("CPW (IX-800000H)", DDIR_IW, 0xDD, 0xFE, 0x00, 0x00, 0x80);
    }

    if (isZ380()) {
        TEST("ANDW HL, BC", 0xED, 0xA4);
        TEST("ANDW HL, DE", 0xED, 0xA5);
        TEST("ANDW HL, HL", 0xED, 0xA7);
        TEST("ANDW HL, IX", 0xDD, 0xA7);
        TEST("ANDW HL, IY", 0xFD, 0xA7);
        TEST("ANDW HL, 1234H",    0xED, 0xA6, 0x34, 0x12);
        TEST("ANDW HL, (IX-128)", 0xDD, 0xE6, 0x80);
        TEST("ANDW HL, (IY+127)", 0xFD, 0xE6, 0x7F);
        TEST("ANDW HL, (IX-8000H)",   DDIR_IB, 0xDD, 0xE6, 0x00, 0x80);
        TEST("ANDW HL, (IX-800000H)", DDIR_IW, 0xDD, 0xE6, 0x00, 0x00, 0x80);

        TEST("ANDW BC", 0xED, 0xA4);
        TEST("ANDW DE", 0xED, 0xA5);
        TEST("ANDW HL", 0xED, 0xA7);
        TEST("ANDW IX", 0xDD, 0xA7);
        TEST("ANDW IY", 0xFD, 0xA7);
        TEST("ANDW 1234H",    0xED, 0xA6, 0x34, 0x12);
        TEST("ANDW (IX-128)", 0xDD, 0xE6, 0x80);
        TEST("ANDW (IY+127)", 0xFD, 0xE6, 0x7F);
        TEST("ANDW (IX-8000H)",   DDIR_IB, 0xDD, 0xE6, 0x00, 0x80);
        TEST("ANDW (IX-800000H)", DDIR_IW, 0xDD, 0xE6, 0x00, 0x00, 0x80);

        TEST("ORW HL, BC", 0xED, 0xB4);
        TEST("ORW HL, DE", 0xED, 0xB5);
        TEST("ORW HL, HL", 0xED, 0xB7);
        TEST("ORW HL, IX", 0xDD, 0xB7);
        TEST("ORW HL, IY", 0xFD, 0xB7);
        TEST("ORW HL, 1234H",    0xED, 0xB6, 0x34, 0x12);
        TEST("ORW HL, (IX-128)", 0xDD, 0xF6, 0x80);
        TEST("ORW HL, (IY+127)", 0xFD, 0xF6, 0x7F);
        TEST("ORW HL, (IX-8000H)",   DDIR_IB, 0xDD, 0xF6, 0x00, 0x80);
        TEST("ORW HL, (IX-800000H)", DDIR_IW, 0xDD, 0xF6, 0x00, 0x00, 0x80);

        TEST("ORW BC", 0xED, 0xB4);
        TEST("ORW DE", 0xED, 0xB5);
        TEST("ORW HL", 0xED, 0xB7);
        TEST("ORW IX", 0xDD, 0xB7);
        TEST("ORW IY", 0xFD, 0xB7);
        TEST("ORW 1234H",    0xED, 0xB6, 0x34, 0x12);
        TEST("ORW (IX-128)", 0xDD, 0xF6, 0x80);
        TEST("ORW (IY+127)", 0xFD, 0xF6, 0x7F);
        TEST("ORW (IX-8000H)",   DDIR_IB, 0xDD, 0xF6, 0x00, 0x80);
        TEST("ORW (IX-800000H)", DDIR_IW, 0xDD, 0xF6, 0x00, 0x00, 0x80);

        TEST("XORW HL, BC", 0xED, 0xAC);
        TEST("XORW HL, DE", 0xED, 0xAD);
        TEST("XORW HL, HL", 0xED, 0xAF);
        TEST("XORW HL, IX", 0xDD, 0xAF);
        TEST("XORW HL, IY", 0xFD, 0xAF);
        TEST("XORW HL, 1234H",    0xED, 0xAE, 0x34, 0x12);
        TEST("XORW HL, (IX-128)", 0xDD, 0xEE, 0x80);
        TEST("XORW HL, (IY+127)", 0xFD, 0xEE, 0x7F);
        TEST("XORW HL, (IX-8000H)",   DDIR_IB, 0xDD, 0xEE, 0x00, 0x80);
        TEST("XORW HL, (IX-800000H)", DDIR_IW, 0xDD, 0xEE, 0x00, 0x00, 0x80);

        TEST("XORW BC", 0xED, 0xAC);
        TEST("XORW DE", 0xED, 0xAD);
        TEST("XORW HL", 0xED, 0xAF);
        TEST("XORW IX", 0xDD, 0xAF);
        TEST("XORW IY", 0xFD, 0xAF);
        TEST("XORW 1234H",    0xED, 0xAE, 0x34, 0x12);
        TEST("XORW (IX-128)", 0xDD, 0xEE, 0x80);
        TEST("XORW (IY+127)", 0xFD, 0xEE, 0x7F);
        TEST("XORW (IX-8000H)",   DDIR_IB, 0xDD, 0xEE, 0x00, 0x80);
        TEST("XORW (IX-800000H)", DDIR_IW, 0xDD, 0xEE, 0x00, 0x00, 0x80);
    }

    if (isZ180() || isZ380()) {
        TEST("MLT BC", 0xED, 0x4C);
        TEST("MLT DE", 0xED, 0x5C);
        TEST("MLT HL", 0xED, 0x6C);
        TEST("MLT SP", 0xED, 0x7C);
    } else {
        ERUI("MLT BC");
    }

    if (isZ380()) {
        TEST("MULTW HL, BC", 0xED, 0xCB, 0x90);
        TEST("MULTW HL, DE", 0xED, 0xCB, 0x91);
        TEST("MULTW HL, HL", 0xED, 0xCB, 0x93);
        TEST("MULTW HL, IX", 0xED, 0xCB, 0x94);
        TEST("MULTW HL, IY", 0xED, 0xCB, 0x95);
        TEST("MULTW HL, 1234H",    0xED, 0xCB, 0x97, 0x34, 0x12);
        TEST("MULTW HL, (IX-128)", 0xDD, 0xCB, 0x80, 0x92);
        TEST("MULTW HL, (IY+127)", 0xFD, 0xCB, 0x7F, 0x92);
        TEST("MULTW HL, (IX+7FFFH)",   DDIR_IB, 0xDD, 0xCB, 0xFF, 0x7F, 0x92);
        TEST("MULTW HL, (IY-800000H)", DDIR_IW, 0xFD, 0xCB, 0x00, 0x00, 0x80, 0x92);

        TEST("MULTW BC", 0xED, 0xCB, 0x90);
        TEST("MULTW DE", 0xED, 0xCB, 0x91);
        TEST("MULTW HL", 0xED, 0xCB, 0x93);
        TEST("MULTW IX", 0xED, 0xCB, 0x94);
        TEST("MULTW IY", 0xED, 0xCB, 0x95);
        TEST("MULTW 1234H",    0xED, 0xCB, 0x97, 0x34, 0x12);
        TEST("MULTW (IX-128)", 0xDD, 0xCB, 0x80, 0x92);
        TEST("MULTW (IY+127)", 0xFD, 0xCB, 0x7F, 0x92);
        TEST("MULTW (IX+7FFFH)",   DDIR_IB, 0xDD, 0xCB, 0xFF, 0x7F, 0x92);
        TEST("MULTW (IY-800000H)", DDIR_IW, 0xFD, 0xCB, 0x00, 0x00, 0x80, 0x92);
    }

    if (isZ380()) {
        TEST("MULTUW HL, BC", 0xED, 0xCB, 0x98);
        TEST("MULTUW HL, DE", 0xED, 0xCB, 0x99);
        TEST("MULTUW HL, HL", 0xED, 0xCB, 0x9B);
        TEST("MULTUW HL, IX", 0xED, 0xCB, 0x9C);
        TEST("MULTUW HL, IY", 0xED, 0xCB, 0x9D);
        TEST("MULTUW HL, 1234H",    0xED, 0xCB, 0x9F, 0x34, 0x12);
        TEST("MULTUW HL, (IX-128)", 0xDD, 0xCB, 0x80, 0x9A);
        TEST("MULTUW HL, (IY+127)", 0xFD, 0xCB, 0x7F, 0x9A);
        TEST("MULTUW HL, (IX+7FFFH)",   DDIR_IB, 0xDD, 0xCB, 0xFF, 0x7F, 0x9A);
        TEST("MULTUW HL, (IY-800000H)", DDIR_IW, 0xFD, 0xCB, 0x00, 0x00, 0x80, 0x9A);

        TEST("MULTUW BC", 0xED, 0xCB, 0x98);
        TEST("MULTUW DE", 0xED, 0xCB, 0x99);
        TEST("MULTUW HL", 0xED, 0xCB, 0x9B);
        TEST("MULTUW IX", 0xED, 0xCB, 0x9C);
        TEST("MULTUW IY", 0xED, 0xCB, 0x9D);
        TEST("MULTUW 1234H",    0xED, 0xCB, 0x9F, 0x34, 0x12);
        TEST("MULTUW (IX-128)", 0xDD, 0xCB, 0x80, 0x9A);
        TEST("MULTUW (IY+127)", 0xFD, 0xCB, 0x7F, 0x9A);
        TEST("MULTUW (IX+7FFFH)",   DDIR_IB, 0xDD, 0xCB, 0xFF, 0x7F, 0x9A);
        TEST("MULTUW (IY-800000H)", DDIR_IW, 0xFD, 0xCB, 0x00, 0x00, 0x80, 0x9A);
    }

    if (isZ380()) {
        TEST("DIVUW HL, BC", 0xED, 0xCB, 0xB8);
        TEST("DIVUW HL, DE", 0xED, 0xCB, 0xB9);
        TEST("DIVUW HL, HL", 0xED, 0xCB, 0xBB);
        TEST("DIVUW HL, IX", 0xED, 0xCB, 0xBC);
        TEST("DIVUW HL, IY", 0xED, 0xCB, 0xBD);
        TEST("DIVUW HL, 1234H",    0xED, 0xCB, 0xBF, 0x34, 0x12);
        TEST("DIVUW HL, (IX-128)", 0xDD, 0xCB, 0x80, 0xBA);
        TEST("DIVUW HL, (IY+127)", 0xFD, 0xCB, 0x7F, 0xBA);
        TEST("DIVUW HL, (IY-8000H)",   DDIR_IB, 0xFD, 0xCB, 0x00, 0x80, 0xBA);
        TEST("DIVUW HL, (IY-800000H)", DDIR_IW, 0xFD, 0xCB, 0x00, 0x00, 0x80, 0xBA);

        TEST("DIVUW BC", 0xED, 0xCB, 0xB8);
        TEST("DIVUW DE", 0xED, 0xCB, 0xB9);
        TEST("DIVUW HL", 0xED, 0xCB, 0xBB);
        TEST("DIVUW IX", 0xED, 0xCB, 0xBC);
        TEST("DIVUW IY", 0xED, 0xCB, 0xBD);
        TEST("DIVUW 1234H",    0xED, 0xCB, 0xBF, 0x34, 0x12);
        TEST("DIVUW (IX-128)", 0xDD, 0xCB, 0x80, 0xBA);
        TEST("DIVUW HL, (IY+127)", 0xFD, 0xCB, 0x7F, 0xBA);
        TEST("DIVUW (IY-8000H)",   DDIR_IB, 0xFD, 0xCB, 0x00, 0x80, 0xBA);
        TEST("DIVUW (IY-800000H)", DDIR_IW, 0xFD, 0xCB, 0x00, 0x00, 0x80, 0xBA);
    }
}

void test_io() {
    TEST("IN A,(0F0H)", 0xDB, 0xF0);
    ERRT("IN A,(-1)",   OVERFLOW_RANGE, "(-1)",  0xDB, 0xFF);
    ERRT("IN A,(256)",  OVERFLOW_RANGE, "(256)", 0xDB, 0x00);
    if (isZ380()) {
        TEST("INA A, (1234H)",              0xED, 0xDB, 0x34, 0x12);
        TEST("INA A, (123456H)"  , DDIR_IB, 0xED, 0xDB, 0x56, 0x34, 0x12);
        TEST("INA A, (12345678H)", DDIR_IW, 0xED, 0xDB, 0x78, 0x56, 0x34, 0x12);

        TEST("INAW HL, (1234H)",              0xFD, 0xDB, 0x34, 0x12);
        TEST("INAW HL, (123456H)",   DDIR_IB, 0xFD, 0xDB, 0x56, 0x34, 0x12);
        TEST("INAW HL, (12345678H)", DDIR_IW, 0xFD, 0xDB, 0x78, 0x56, 0x34, 0x12);
    } else {
        ERUI("INA");
        ERUI("INAW");
    }
    if (isZ180() || isZ380()) {
        TEST("IN0 A, (0F0H)", 0xED, 0x38, 0xF0);
        TEST("IN0 B, (0F0H)", 0xED, 0x00, 0xF0);
        TEST("IN0 C, (0F0H)", 0xED, 0x08, 0xF0);
        TEST("IN0 D, (0F0H)", 0xED, 0x10, 0xF0);
        TEST("IN0 E, (0F0H)", 0xED, 0x18, 0xF0);
        TEST("IN0 H, (0F0H)", 0xED, 0x20, 0xF0);
        TEST("IN0 L, (0F0H)", 0xED, 0x28, 0xF0);
    } else {
        ERUI("IN0  B, (0F0H)");
    }
    if (isZ380()) {
        TEST("IN0 (0F0H)", 0xED, 0x30, 0xF0);
    }

    TEST("OUT (0F1H),A", 0xD3, 0xF1);
    ERRT("OUT (-1),A",   OVERFLOW_RANGE, "(-1),A",  0xD3, 0xFF);
    ERRT("OUT (256),A",  OVERFLOW_RANGE, "(256),A", 0xD3, 0x00);
    if (isZ380()) {
        TEST("OUTA (1234H), A",              0xED, 0xD3, 0x34, 0x12);
        TEST("OUTA (123456H), A",   DDIR_IB, 0xED, 0xD3, 0x56, 0x34, 0x12);
        TEST("OUTA (12345678H), A", DDIR_IW, 0xED, 0xD3, 0x78, 0x56, 0x34, 0x12);

        TEST("OUTAW (1234H), HL",              0xFD, 0xD3, 0x34, 0x12);
        TEST("OUTAW (123456H), HL",   DDIR_IB, 0xFD, 0xD3, 0x56, 0x34, 0x12);
        TEST("OUTAW (12345678H), HL", DDIR_IW, 0xFD, 0xD3, 0x78, 0x56, 0x34, 0x12);
    } else {
        ERUI("OUTA");
        ERUI("OUTAW");
    }
    if (isZ180() || isZ380()) {
        TEST("OUT0 (0F1H), A", 0xED, 0x39, 0xF1);
        TEST("OUT0 (0F1H), B", 0xED, 0x01, 0xF1);
        TEST("OUT0 (0F1H), C", 0xED, 0x09, 0xF1);
        TEST("OUT0 (0F1H), D", 0xED, 0x11, 0xF1);
        TEST("OUT0 (0F1H), E", 0xED, 0x19, 0xF1);
        TEST("OUT0 (0F1H), H", 0xED, 0x21, 0xF1);
        TEST("OUT0 (0F1H), L", 0xED, 0x29, 0xF1);
    } else {
        ERUI("OUT0 (0F1H), C");
    }

    TEST("IN A,(C)", 0xED, 0x78);
    TEST("IN B,(C)", 0xED, 0x40);
    TEST("IN C,(C)", 0xED, 0x48);
    TEST("IN D,(C)", 0xED, 0x50);
    TEST("IN E,(C)", 0xED, 0x58);
    TEST("IN H,(C)", 0xED, 0x60);
    TEST("IN L,(C)", 0xED, 0x68);
    ERRT("IN (HL),(C)", OPERAND_NOT_ALLOWED, "(HL),(C)");

    if (isZ380()) {
        TEST("INW BC, (C)", 0xDD, 0x40);
        TEST("INW DE, (C)", 0xDD, 0x50);
        TEST("INW HL, (C)", 0xDD, 0x78);
    }

    TEST("OUT (C),A", 0xED, 0x79);
    TEST("OUT (C),B", 0xED, 0x41);
    TEST("OUT (C),C", 0xED, 0x49);
    TEST("OUT (C),D", 0xED, 0x51);
    TEST("OUT (C),E", 0xED, 0x59);
    TEST("OUT (C),H", 0xED, 0x61);
    TEST("OUT (C),L", 0xED, 0x69);
    ERRT("OUT (C),(HL)", OPERAND_NOT_ALLOWED, "(C),(HL)");
    if (isZ380()) {
        TEST("OUT (C), 56H", 0xED, 0x71, 0x56);
    }

    if (isZ380()) {
        TEST("OUTW (C), BC",    0xDD, 0x41);
        TEST("OUTW (C), DE",    0xDD, 0x51);
        TEST("OUTW (C), HL",    0xDD, 0x79);
        TEST("OUTW (C), 1234H", 0xFD, 0x79, 0x34, 0x12);
    }

    if (isZ180() || isZ380()) {
        TEST("TSTIO 23H", 0xED, 0x74, 0x23);
    } else {
        ERUI("TSTIO");
    }

    if (isZ380()) {
        TEST("LDCTL SR, A",  0xDD, 0xC8);
        TEST("LDCTL SR, HL", 0xED, 0xC8);
        TEST("LDCTL SR, 18", 0xDD, 0xCA, 0x12);
        ATEST(0x1000, "DDIR W",  DDIR_W);
        CTEST(0x1002, 0x1002, "LDCTL SR, HL", 0xED, 0xC8);
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0x1002, 0x1002, "LDCTL SR, HL", 0xED, 0xC8);

        TEST("LDCTL DSR, A",  0xED, 0xD8);
        TEST("LDCTL XSR, A",  0xDD, 0xD8);
        TEST("LDCTL YSR, A",  0xFD, 0xD8);
        TEST("LDCTL DSR, 34H", 0xED, 0xDA, 0x34);
        TEST("LDCTL XSR, 56H", 0xDD, 0xDA, 0x56);
        TEST("LDCTL YSR, 78H", 0xFD, 0xDA, 0x78);

        TEST("LDCTL HL, SR", 0xED, 0xC0);
        TEST("LDCTL A, DSR", 0xED, 0xD0);
        TEST("LDCTL A, XSR", 0xDD, 0xD0);
        TEST("LDCTL A, YSR", 0xFD, 0xD0);
        ATEST(0x1000, "DDIR W",  DDIR_W);
        CTEST(0x1002, 0x1002, "LDCTL HL, SR", 0xED, 0xC0);
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0x1002, 0x1002, "LDCTL HL, SR", 0xED, 0xC0);
    } else {
        ERUI("LDCTL");
    }
}

void test_block() {
    TEST("LDI",  0xED, 0xA0);
    TEST("LDD",  0xED, 0xA8);
    TEST("LDIR", 0xED, 0xB0);
    TEST("LDDR", 0xED, 0xB8);
    TEST("CPI",  0xED, 0xA1);
    TEST("CPD",  0xED, 0xA9);
    TEST("CPIR", 0xED, 0xB1);
    TEST("CPDR", 0xED, 0xB9);
    if (isZ380()) {
        TEST("LDIW",  0xED, 0xE0);
        TEST("LDIRW", 0xED, 0xF0);
        TEST("LDDW",  0xED, 0xE8);
        TEST("LDDRW", 0xED, 0xF8);
        ATEST(0x1000, "DDIR W",  DDIR_W);
        CTEST(0x1002, 0x1002, "LDIW",    0xED, 0xE0);
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0x1002, 0x1002, "LDIRW",   0xED, 0xF0);
        ATEST(0x1000, "DDIR W",  DDIR_W);
        CTEST(0x1002, 0x1002, "LDDW",    0xED, 0xE8);
        ATEST(0x1000, "DDIR LW", DDIR_LW);
        CTEST(0x1002, 0x1002, "LDDRW",   0xED, 0xF8);
    } else {
        ERUI("LDIW");
        ERUI("LDIRW");
        ERUI("LDDW");
        ERUI("LDDRW");
    }

    TEST("INI",  0xED, 0xA2);
    TEST("IND",  0xED, 0xAA);
    TEST("INIR", 0xED, 0xB2);
    TEST("INDR", 0xED, 0xBA);
    TEST("OUTI", 0xED, 0xA3);
    TEST("OUTD", 0xED, 0xAB);
    TEST("OTIR", 0xED, 0xB3);
    TEST("OTDR", 0xED, 0xBB);

    if (isZ180() || isZ380()) {
        TEST("OTIM",  0xED, 0x83);
        TEST("OTIMR", 0xED, 0x93);
        TEST("OTDM",  0xED, 0x8B);
        TEST("OTDMR", 0xED, 0x9B);
    } else {
        ERUI("OTIM");
        ERUI("OTIMR");
        ERUI("OTDM");
        ERUI("OTDMR");
    }

    if (isZ380()) {
        TEST("INIW",  0xED, 0xE2);
        TEST("INDW",  0xED, 0xEA);
        TEST("INIRW", 0xED, 0xF2);
        TEST("INDRW", 0xED, 0xFA);
        TEST("OUTIW", 0xED, 0xE3);
        TEST("OUTDW", 0xED, 0xEB);
        TEST("OTIRW", 0xED, 0xF3);
        TEST("OTDRW", 0xED, 0xFB);
    } else {
        ERUI("INIW");
        ERUI("INDW");
        ERUI("INIRW");
        ERUI("INDRW");
        ERUI("OUTIW");
        ERUI("OUTDW");
        ERUI("OTIRW");
        ERUI("OTDRW");
    }
}

void test_inherent() {
    TEST("DI",  0xF3);
    TEST("EI",  0xFB);
    if (isZ380()) {
        TEST("DI 34H", 0xDD, 0xF3, 0x34);
        TEST("EI 34H", 0xDD, 0xFB, 0x34);
    } else {
        ERRT("DI 23H", OPERAND_NOT_ALLOWED, "23H");
        ERRT("EI 45H", OPERAND_NOT_ALLOWED, "45H");
    }

    TEST("SCF", 0x37);
    TEST("CCF", 0x3F);

    TEST("NOP",  0x00);
    TEST("HALT", 0x76);
    if (isZ180() || isZ380()) {
        TEST("SLP", 0xED, 0x76);
    } else {
        ERUI("SLP");
    }

    TEST("IM 0", 0xED, 0x46);
    TEST("IM 1", 0xED, 0x56);
    TEST("IM 2", 0xED, 0x5E);
    if (isZ380()) {
        TEST("IM 3", 0xED, 0x4E);
    } else {
        ERRT("IM 3",  ILLEGAL_OPERAND, "3",  0xED, 0x46);
    }
    ERRT("IM -1", ILLEGAL_OPERAND, "-1", 0xED, 0x46);

    if (isZ380()) {
        TEST("BTEST", 0xED, 0xCF);
        TEST("MTEST", 0xDD, 0xCF);

        TEST("SETC LW",  0xDD, 0xF7);
        TEST("SETC LCK", 0xED, 0xF7);
        TEST("SETC XM",  0xFD, 0xF7);

        TEST("RESC LW",  0xDD, 0xFF);
        TEST("RESC LCK", 0xED, 0xFF);
        ERRT("RESC XM", OPERAND_NOT_ALLOWED, "XM");
    }
}

void test_restart() {
    TEST("RST 00H", 0xC7);
    TEST("RST 08H", 0xCF);
    TEST("RST 10H", 0xD7);
    TEST("RST 18H", 0xDF);
    TEST("RST 20H", 0xE7);
    TEST("RST 28H", 0xEF);
    TEST("RST 30H", 0xF7);
    TEST("RST 38H", 0xFF);
    ERRT("RST 39H", ILLEGAL_OPERAND, "39H", 0xC7);
    ERRT("RST 40H", ILLEGAL_OPERAND, "40H", 0xC7);
    ERRT("RST -1",  ILLEGAL_OPERAND, "-1",  0xC7);
}

void test_bitop() {
    TEST("BIT 7,A", 0xCB, 0x7F);
    TEST("BIT 0,B", 0xCB, 0x40);
    TEST("BIT 1,C", 0xCB, 0x49);
    TEST("BIT 2,D", 0xCB, 0x52);
    TEST("BIT 3,E", 0xCB, 0x5B);
    TEST("BIT 4,H", 0xCB, 0x64);
    TEST("BIT 5,L", 0xCB, 0x6D);
    TEST("BIT 6,(HL)", 0xCB, 0x76);
    TEST("BIT 0,(IX-128)", 0xDD, 0xCB, 0x80, 0x46);
    TEST("BIT 5,(IY+127)", 0xFD, 0xCB, 0x7F, 0x6E);

    ERRT("BIT 8,A",  ILLEGAL_BIT_NUMBER, "8,A",  0xCB, 0x47);
    ERRT("BIT -1,A", ILLEGAL_BIT_NUMBER, "-1,A", 0xCB, 0x7F);
    if (isZ380()) {
        TEST("BIT 2,(IX-129)", DDIR_IB, 0xDD, 0xCB, 0x7F, 0xFF, 0x56);
        TEST("BIT 2,(IX+128)", DDIR_IB, 0xDD, 0xCB, 0x80, 0x00, 0x56);
    } else {
        ERRT("BIT 2,(IX-129)", OVERFLOW_RANGE, "(IX-129)", 0xDD, 0xCB, 0x7F, 0x56);
        ERRT("BIT 2,(IX+128)", OVERFLOW_RANGE, "(IX+128)", 0xDD, 0xCB, 0x80, 0x56);
    }

    TEST("RES 7,A", 0xCB, 0xBF);
    TEST("RES 0,B", 0xCB, 0x80);
    TEST("RES 1,C", 0xCB, 0x89);
    TEST("RES 2,D", 0xCB, 0x92);
    TEST("RES 3,E", 0xCB, 0x9B);
    TEST("RES 4,H", 0xCB, 0xA4);
    TEST("RES 5,L", 0xCB, 0xAD);
    TEST("RES 6,(HL)", 0xCB, 0xB6);
    TEST("RES 1,(IX-128)", 0xDD, 0xCB, 0x80, 0x8E);
    TEST("RES 6,(IY+127)", 0xFD, 0xCB, 0x7F, 0xB6);

    ERRT("RES 8,A",  ILLEGAL_BIT_NUMBER, "8,A",  0xCB, 0x87);
    ERRT("RES -1,A", ILLEGAL_BIT_NUMBER, "-1,A", 0xCB, 0xBF);
    if (isZ380()) {
        TEST("RES 2,(IY-129)", DDIR_IB, 0xFD, 0xCB, 0x7F, 0xFF, 0x96);
        TEST("RES 2,(IY+128)", DDIR_IB, 0xFD, 0xCB, 0x80, 0x00, 0x96);
    } else {
        ERRT("RES 2,(IY-129)", OVERFLOW_RANGE, "(IY-129)", 0xFD, 0xCB, 0x7F, 0x96);
        ERRT("RES 2,(IY+128)", OVERFLOW_RANGE, "(IY+128)", 0xFD, 0xCB, 0x80, 0x96);
    }

    TEST("SET 7,A", 0xCB, 0xFF);
    TEST("SET 0,B", 0xCB, 0xC0);
    TEST("SET 1,C", 0xCB, 0xC9);
    TEST("SET 2,D", 0xCB, 0xD2);
    TEST("SET 3,E", 0xCB, 0xDB);
    TEST("SET 4,H", 0xCB, 0xE4);
    TEST("SET 5,L", 0xCB, 0xED);
    TEST("SET 6,(HL)", 0xCB, 0xF6);
    TEST("SET 2,(IX-128)", 0xDD, 0xCB, 0x80, 0xD6);
    TEST("SET 7,(IY+127)", 0xFD, 0xCB, 0x7F, 0xFE);

    ERRT("SET 8,(IX-128)", ILLEGAL_BIT_NUMBER, "8,(IX-128)", 0xDD, 0xCB, 0x80, 0xC6);
    ERRT("SET -1,(IX+1)",  ILLEGAL_BIT_NUMBER, "-1,(IX+1)",  0xDD, 0xCB, 0x01, 0xFE);
    if (isZ380()) {
        TEST("SET 2,(IX-129)", DDIR_IB, 0xDD, 0xCB, 0x7F, 0xFF, 0xD6);
        TEST("SET 2,(IX+128)", DDIR_IB, 0xDD, 0xCB, 0x80, 0x00, 0xD6);
    } else {
        ERRT("SET 2,(IX-129)", OVERFLOW_RANGE, "(IX-129)", 0xDD, 0xCB, 0x7F, 0xD6);
        ERRT("SET 2,(IX+128)", OVERFLOW_RANGE, "(IX+128)", 0xDD, 0xCB, 0x80, 0xD6);
    }
}

void test_ddir() {
    if (isZ380()) {
        ERRT("DDIR W,LW",  ILLEGAL_COMBINATION, "LW", 0xDD, 0xC0);
        ERRT("DDIR LW,W",  ILLEGAL_COMBINATION, "W",  0xFD, 0xC0);
        ERRT("DDIR IB,IW", ILLEGAL_COMBINATION, "IW", 0xDD, 0xC3);
        ERRT("DDIR IW,IB", ILLEGAL_COMBINATION, "IB", 0xFD, 0xC3);
    } else {
        ERUI("DDIR");
        return;
    }

    ATEST(0x1000, "DDIR W",  DDIR_W);
    CTEST(0x1002, 0x1002, "POP HL",  0xE1);
    ATEST(0x1000, "DDIR LW", DDIR_LW);
    CTEST(0x1002, 0x1002, "POP HL",  0xE1);

    TEST("extmode on");
    TEST("JP 1234H",              0xC3, 0x34, 0x12);
    TEST("JP 123456H",   DDIR_IB, 0xC3, 0x56, 0x34, 0x12);
    TEST("JP 12345678H", DDIR_IW, 0xC3, 0x78, 0x56, 0x34, 0x12);
    ATEST(0x1000, "DDIR W",     DDIR_W);
    CERRT(0x1002, 0x1002, "JP 1234H",
          PREFIX_HAS_NO_EFFECT,   "1234H", 0xC3, 0x34, 0x12);
    ATEST(0x1000, "DDIR W",     DDIR_W);
    CERRT(0x1002, 0x1002, "JP 123456H",
          PREFIX_HAS_NO_EFFECT, "123456H", 0xC3, 0x56, 0x34);
    ATEST(0x1000, "DDIR IB,W",  DDIR_IBW);
    CERRT(0x1002, 0x1002, "JP 1234H",
          SUBOPTIMAL_INSTRUCTION, "1234H", 0xC3, 0x34, 0x12, 0x00);
    ATEST(0x1000, "DDIR W,IW",  DDIR_IWW);
    CERRT(0x1002, 0x1002, "JP 1234H",
          SUBOPTIMAL_INSTRUCTION, "1234H", 0xC3, 0x34, 0x12, 0x00, 0x00);
    ATEST(0x1000, "DDIR IB",    DDIR_IB);
    CTEST(0x1002, 0x1002, "JP 1234H",   0xC3, 0x34, 0x12, 0x00);
    ATEST(0x1000, "DDIR LW",    DDIR_LW);
    CERRT(0x1002, 0x1002, "JP 1234H",
          PREFIX_HAS_NO_EFFECT,     "1234H", 0xC3, 0x34, 0x12);
    ATEST(0x1000, "DDIR LW",      DDIR_LW);
    CERRT(0x1002, 0x1002, "JP 12345678H",
          PREFIX_HAS_NO_EFFECT, "12345678H", 0xC3, 0x78, 0x56);
    ATEST(0x1000, "DDIR LW,IB", DDIR_IBL);
    CERRT(0x1002, 0x1002, "JP 1234H",
          SUBOPTIMAL_INSTRUCTION, "1234H", 0xC3, 0x34, 0x12, 0x00);
    ATEST(0x1000, "DDIR IW,LW", DDIR_IWL);
    CERRT(0x1002, 0x1002, "JP 1234H",
          SUBOPTIMAL_INSTRUCTION, "1234H", 0xC3, 0x34, 0x12, 0x00, 0x00);
    ATEST(0x1000, "DDIR IW",    DDIR_IW);
    CTEST(0x1002, 0x1002, "JP 1234H",   0xC3, 0x34, 0x12, 0x00, 0x00);
    TEST("extmode off");
    TEST("JP 1234H",                                  0xC3, 0x34, 0x12);
    ERRT("JP 123456H",   OVERFLOW_RANGE,   "123456H", 0xC3, 0x56, 0x34);
    ERRT("JP 12345678H", OVERFLOW_RANGE, "12345678H", 0xC3, 0x78, 0x56);

    TEST("LD HL, (1234H)",              0x2A, 0x34, 0x12);
    TEST("LD HL, (123456H)",   DDIR_IB, 0x2A, 0x56, 0x34, 0x12);
    TEST("LD HL, (12345678H)", DDIR_IW, 0x2A, 0x78, 0x56, 0x34, 0x12);

    ATEST(0x1000, "DDIR W",         DDIR_W);
    CTEST(0x1002, 0x1002, "LD HL, (1234H)", 0x2A, 0x34, 0x12);
    ATEST(0x1000, "DDIR IB,W",      DDIR_IBW);
    CTEST(0x1002, 0x1002, "LD HL, (1234H)", 0x2A, 0x34, 0x12, 0x00);
    ATEST(0x1000, "DDIR W,IW",      DDIR_IWW);
    CTEST(0x1002, 0x1002, "LD HL, (1234H)", 0x2A, 0x34, 0x12, 0x00, 0x00);
    ATEST(0x1000, "DDIR IB",        DDIR_IB);
    CTEST(0x1002, 0x1002, "LD HL, (1234H)", 0x2A, 0x34, 0x12, 0x00);
    ATEST(0x1000, "DDIR LW",        DDIR_LW);
    CTEST(0x1002, 0x1002, "LD HL, (1234H)", 0x2A, 0x34, 0x12);
    ATEST(0x1000, "DDIR LW,IB",     DDIR_IBL);
    CTEST(0x1002, 0x1002, "LD HL, (1234H)", 0x2A, 0x34, 0x12, 0x00);
    ATEST(0x1000, "DDIR IW,LW",     DDIR_IWL);
    CTEST(0x1002, 0x1002, "LD HL, (1234H)", 0x2A, 0x34, 0x12, 0x00, 0x00);
    ATEST(0x1000, "DDIR IW",        DDIR_IW);
    CTEST(0x1002, 0x1002, "LD HL, (1234H)", 0x2A, 0x34, 0x12, 0x00, 0x00);

    TEST("lwordmode on");
    TEST("LD HL, 1234H",              0x21, 0x34, 0x12);
    TEST("LD HL, 123456H",   DDIR_IB, 0x21, 0x56, 0x34, 0x12);
    TEST("LD HL, 12345678H", DDIR_IW, 0x21, 0x78, 0x56, 0x34, 0x12);
    TEST("lwordmode off");
    TEST("LD HL, 1234H",               0x21, 0x34, 0x12);
    ERRT("LD HL, 123456H",   OVERFLOW_RANGE,   "123456H", 0x21, 0x56, 0x34);
    ERRT("LD HL, 12345678H", OVERFLOW_RANGE, "12345678H", 0x21, 0x78, 0x56);
    ATEST(0x1000, "DDIR W",       DDIR_W);
    CERRT(0x1002, 0x1002, "LD HL, 1234H",
          PREFIX_HAS_NO_EFFECT, "1234H", 0x21, 0x34, 0x12);
    ATEST(0x1000, "DDIR IB,W",    DDIR_IBW);
    CERRT(0x1002, 0x1002, "LD HL, 1234H",
          PREFIX_HAS_NO_EFFECT, "1234H", 0x21, 0x34, 0x12);
    ATEST(0x1000, "DDIR W,IW",    DDIR_IWW);
    CERRT(0x1002, 0x1002, "LD HL, 1234H",
          PREFIX_HAS_NO_EFFECT, "1234H", 0x21, 0x34, 0x12);
    ATEST(0x1000, "DDIR IB",      DDIR_IB);
    CERRT(0x1002, 0x1002, "LD HL, 1234H",
          PREFIX_HAS_NO_EFFECT, "1234H", 0x21, 0x34, 0x12);
    ATEST(0x1000,"DDIR LW",       DDIR_LW);
    CTEST(0x1002, 0x1002, "LD HL, 1234H", 0x21, 0x34, 0x12);
    ATEST(0x1000, "DDIR LW,IB",   DDIR_IBL);
    CTEST(0x1002, 0x1002, "LD HL, 1234H", 0x21, 0x34, 0x12, 0x00);
    ATEST(0x1000, "DDIR LW",      DDIR_LW);
    CTEST(0x1002, 0x1000, "LD HL, 123456H", DDIR_IBL, 0x21, 0x56, 0x34, 0x12);
    ATEST(0x1000, "DDIR IW,LW",   DDIR_IWL);
    CTEST(0x1002, 0x1002, "LD HL, 1234H", 0x21, 0x34, 0x12, 0x00, 0x00);
    ATEST(0x1000, "DDIR LW",      DDIR_LW);
    CTEST(0x1002, 0x1000, "LD HL, 12345678H", DDIR_IWL, 0x21, 0x78, 0x56, 0x34, 0x12);
    ATEST(0x1000, "DDIR IW",      DDIR_IW);
    CERRT(0x1002, 0x1002, "LD HL, 1234H",
          PREFIX_HAS_NO_EFFECT, "1234H", 0x21, 0x34, 0x12);

    TEST("LD HL, (IX+34H)",              0xDD, 0xCB, 0x34, 0x33);
    TEST("LD HL, (IX+1234H)",   DDIR_IB, 0xDD, 0xCB, 0x34, 0x12, 0x33);
    TEST("LD HL, (IX+123456H)", DDIR_IW, 0xDD, 0xCB, 0x56, 0x34, 0x12, 0x33);
    ERRT("LD HL, (IX+12345678H)", OVERFLOW_RANGE,
         "(IX+12345678H)",               0xDD, 0xCB, 0x78, 0x33);

    ATEST(0x1000,"DDIR W",          DDIR_W);
    CTEST(0x1002, 0x1002, "LD HL, (IX+34H)", 0xDD, 0xCB, 0x34, 0x33);
    ATEST(0x1000, "DDIR IB,W",       DDIR_IBW);
    CTEST(0x1002, 0x1002, "LD HL, (IX+34H)", 0xDD, 0xCB, 0x34, 0x00, 0x33);
    ATEST(0x1000, "DDIR W,IW",       DDIR_IWW);
    CTEST(0x1002, 0x1002, "LD HL, (IX+34H)", 0xDD, 0xCB, 0x34, 0x00, 0x00, 0x33);
    ATEST(0x1000, "DDIR IB",         DDIR_IB);
    CTEST(0x1002, 0x1002, "LD HL, (IX+34H)", 0xDD, 0xCB, 0x34, 0x00, 0x33);
    ATEST(0x1000, "DDIR LW",         DDIR_LW);
    CTEST(0x1002, 0x1002, "LD HL, (IX+34H)", 0xDD, 0xCB, 0x34, 0x33);
    ATEST(0x1000, "DDIR LW,IB",      DDIR_IBL);
    CTEST(0x1002, 0x1002, "LD HL, (IX+34H)", 0xDD, 0xCB, 0x34, 0x00, 0x33);
    ATEST(0x1000, "DDIR IW,LW",      DDIR_IWL);
    CTEST(0x1002, 0x1002, "LD HL, (IX+34H)", 0xDD, 0xCB, 0x34, 0x00, 0x00, 0x33);
    ATEST(0x1000, "DDIR IW",         DDIR_IW);
    CTEST(0x1002, 0x1002, "LD HL, (IX+34H)", 0xDD, 0xCB, 0x34, 0x00, 0x00, 0x33);
}

void test_comment() {
    COMM("RST 18H        ; comment", "; comment", 0xDF);
    COMM("LD B , B       ; comment", "; comment", 0x40);
    COMM("NOP            ; comment", "; comment", 0x00);
    COMM("LD BC , 0BEEFH ; comment", "; comment", 0x01, 0xEF, 0xBE);
    COMM("LD HL , ( 5678H ) ; comment", "; comment", 0x2A, 0x78, 0x56);
    COMM("CALL C , 1234H ; comment", "; comment", 0xDC, 0x34, 0x12);
    COMM("RET         ; comment", "; comment", 0xC9);
    COMM("RET NZ      ; comment", "; comment", 0xC0);

    COMM("IM 2           ; comment", "; comment", 0xED, 0x5E);
    COMM("BIT 0 , B      ; comment", "; comment", 0xCB, 0x40);
    COMM("BIT 6 , ( HL ) ; comment", "; comment", 0xCB, 0x76);
    COMM("INC ( IX + 2 ) ; comment", "; comment", 0xDD, 0x34, 0x02);
    COMM("LD ( IY - 2 ) , B  ; comment", "; comment", 0xFD, 0x70, 0xFE);
    COMM("ADD A , ( IY - 2 ) ; comment", "; comment", 0xFD, 0x86, 0xFE);
    COMM("EX AF , AF'        ; comment", "; comment", 0x08);
    COMM("LD ( 0ABCDH ) , IX ; comment", "; comment", 0xDD, 0x22, 0xCD, 0xAB);
    COMM("LD IX , ( 5678H )  ; comment", "; comment", 0xDD, 0x2A, 0x78, 0x56);
    COMM("EX ( SP ) , IX     ; comment", "; comment", 0xDD, 0xE3);
    COMM("JP ( IX )          ; comment", "; comment", 0xDD, 0xE9);

    ACOMM(0x1000, "JR 1000H     ; comment", "; comment", 0x18, 0xFE);
    ACOMM(0x1000, "JR NZ , 1004H; comment", "; comment", 0x20, 0x02);
}

void test_undefined_symbol() {
    ERUS("LD  B,UNDEF",   "UNDEF",     0x06, 0x00);
    ERUS("LD BC,UNDEF",   "UNDEF",     0x01, 0x00, 0x00);
    ERUS("LD (UNDEF),A",  "UNDEF),A",  0x32, 0x00, 0x00);
    ERUS("LD A,(UNDEF)",  "UNDEF)",    0x3A, 0x00, 0x00);
    ERUS("LD (UNDEF),HL", "UNDEF),HL", 0x22, 0x00, 0x00);
    ERUS("LD HL,(UNDEF)", "UNDEF)",    0x2A, 0x00, 0x00);
    ERUS("JP    UNDEF",   "UNDEF",     0xC3, 0x00, 0x00);
    ERUS("JP NZ,UNDEF",   "UNDEF",     0xC2, 0x00, 0x00);
    ERUS("CALL    UNDEF", "UNDEF",     0xCD, 0x00, 0x00);
    ERUS("CALL NZ,UNDEF", "UNDEF",     0xC4, 0x00, 0x00);
    ERUS("ADD  A,UNDEF",  "UNDEF",     0xC6, 0x00);
    ERUS("OUT (UNDEF),A", "UNDEF),A",  0xD3, 0x00);
    ERUS("IN  A,(UNDEF)", "UNDEF)",    0xDB, 0x00);
    ERUS("RST UNDEF",     "UNDEF",     0xC7);

    ERUS("LD (UNDEF),BC",        "UNDEF),BC",      0xED, 0x43, 0x00, 0x00);
    ERUS("LD BC,(UNDEF)",        "UNDEF)",         0xED, 0x4B, 0x00, 0x00);
    ERUS("IM UNDEF",             "UNDEF",          0xED, 0x46);
    ERUS("BIT UNDEF,B",          "UNDEF,B",        0xCB, 0x40);
    ERUS("LD (UNDEF),IY",        "UNDEF),IY",      0xFD, 0x22, 0x00, 0x00);
    ERUS("LD IY,(UNDEF)",        "UNDEF)",         0xFD, 0x2A, 0x00, 0x00);
    ERUS("INC (IX+UNDEF)",       "UNDEF)",         0xDD, 0x34, 0x00);
    ERUS("LD (IY-UNDEF),B",      "UNDEF),B",       0xFD, 0x70, 0x00);
    ERUS("LD (IY-2),UNDEF",      "UNDEF",          0xFD, 0x36, 0xFE, 0x00);
    ERUS("RLC (IX+UNDEF)",       "UNDEF)",         0xDD, 0xCB, 0x00, 0x06);
    ERUS("BIT UNDEF,(IX-128)",   "UNDEF,(IX-128)", 0xDD, 0xCB, 0x80, 0x46);
    ERUS("RES 7,(IX-UNDEF)",     "UNDEF)",         0xDD, 0xCB, 0x00, 0xBE);
    ERUS("SET UNDEF,(IX-UNDEF)", "UNDEF,(IX-UNDEF)", 0xDD, 0xCB, 0x00, 0xC6);

    AERUS(0x1000, "JR UNDEF",    "UNDEF", 0x18, 0x00);
    AERUS(0x1000, "JR NZ,UNDEF", "UNDEF", 0x20, 0x00);
    AERUS(0x1000, "DJNZ UNDEF",  "UNDEF", 0x10, 0x00);

    COMM("DB -128, 255 ; comment", "; comment", 0x80, 0xFF);
    COMM("DB 'TEXT'    ; comment", "; comment", 0x54, 0x45, 0x58, 0x54);
    COMM("DW -128, 255 ; comment", "; comment", 0x80, 0xFF, 0xFF, 0x00);
    COMM("DL 12345678H ; comment", "; comment", 0x78, 0x56, 0x34, 0x12);
    COMM("DEFB -128, 255 ; comment", "; comment", 0x80, 0xFF);
    COMM("DEFB 'TEXT'    ; comment", "; comment", 0x54, 0x45, 0x58, 0x54);
    COMM("DEFM 'TEXT'    ; comment", "; comment", 0x54, 0x45, 0x58, 0x54);
    COMM("DEFW -128, 255 ; comment", "; comment", 0x80, 0xFF, 0xFF, 0x00);
}

void test_data_constant() {
    TEST("DB -128, 255", 0x80, 0xFF);
    TEST(R"(DB 'A', '"')", 0x41, 0x22);
    TEST("DB '9'-'0'",   0x09);
    TEST("DB ''''",      0x27);
    ERRT("DB '''",       MISSING_CLOSING_QUOTE, "'''");
    TEST("DB 'A''B',0",  0x41, 0x27, 0x42, 0x00);
    ERRT("DB 'A''B,0",   MISSING_CLOSING_QUOTE, "'A''B,0");
    TEST("DW -128, 255", 0x80, 0xFF, 0xFF, 0x00);
    TEST("DW 'A''B'",    0x41, 0x27, 0x42, 0x00);
    ERRT("DW 'A''B",     MISSING_CLOSING_QUOTE, "'A''B");
    TEST("DL 12345678H", 0x78, 0x56, 0x34, 0x12);
    TEST(R"(DL 'A''B"C')", 0x41, 0x27, 0x42, 0x22, 0x43, 0x00, 0x00, 0x00);
    ERRT(R"(DL 'A''B"C)",  MISSING_CLOSING_QUOTE, R"('A''B"C)");
    TEST("DEFB -128, 255", 0x80, 0xFF);
    TEST(R"(DEFB 'A', '"')", 0x41, 0x22);
    TEST("DEFB '9'-'0'",   0x09);
    TEST("DEFB ''''",      0x27);
    ERRT("DEFB '''",       MISSING_CLOSING_QUOTE, "'''");
    TEST("DEFB 'A''B',0",  0x41, 0x27, 0x42, 0x00);
    ERRT("DEFB 'A''B,0",   MISSING_CLOSING_QUOTE, "'A''B,0");
    TEST("DEFW -128, 255", 0x80, 0xFF, 0xFF, 0x00);
    TEST("DEFW 'A''B'",    0x41, 0x27, 0x42, 0x00);
    ERRT("DEFW 'A''B",     MISSING_CLOSING_QUOTE, "'A''B");
    TEST(R"(DEFM 'A''B"C')", 0x41, 0x27, 0x42, 0x22, 0x43);
    ERUS("DB 1, UNDEF, 2", "UNDEF, 2", 0x01, 0x00, 0x02);
    ERUS("DW 1, UNDEF, 2", "UNDEF, 2", 0x01, 0x00, 0x00, 0x00, 0x02, 0x00);
    ERUS("DL 1, UNDEF, 2", "UNDEF, 2",
         0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00);
    ERUS("DEFB 1, UNDEF, 2", "UNDEF, 2", 0x01, 0x00, 0x02);
    ERUS("DEFM 1, UNDEF, 2", "UNDEF, 2", 0x01, 0x00, 0x02);
    ERUS("DEFW 1, UNDEF, 2", "UNDEF, 2", 0x01, 0x00, 0x00, 0x00, 0x02, 0x00);

    ERRT("DB '"
         "1234567890" "1234567890" "1234567890" "1234567890" "1234567890" "1234567890"
         "1234567890'",
         NO_MEMORY,
         "567890'",
         0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30,
         0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30,
         0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30,
         0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30,
         0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30,
         0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30,
         0x31, 0x32, 0x33, 0x34);

    ERRT("DW "
         "1234H, 5678H, 9ABCH, 0DEF0H, 1234H, 5678H, 9ABCH, 0DEF0H, "
         "1234H, 5678H, 9ABCH, 0DEF0H, 1234H, 5678H, 9ABCH, 0DEF0H, "
         "1234H, 5678H, 9ABCH, 0DEF0H, 1234H, 5678H, 9ABCH, 0DEF0H, "
         "1234H, 5678H, 9ABCH, 0DEF0H, 1234H, 5678H, 9ABCH, 0DEH, "
         "0AAAAH, 0BBBBH",
         NO_MEMORY,
         "0AAAAH, 0BBBBH",
         0x34, 0x12, 0x78, 0x56, 0xBC, 0x9A, 0xF0, 0xDE, 0x34, 0x12, 0x78, 0x56, 0xBC, 0x9A, 0xF0, 0xDE,
         0x34, 0x12, 0x78, 0x56, 0xBC, 0x9A, 0xF0, 0xDE, 0x34, 0x12, 0x78, 0x56, 0xBC, 0x9A, 0xF0, 0xDE,
         0x34, 0x12, 0x78, 0x56, 0xBC, 0x9A, 0xF0, 0xDE, 0x34, 0x12, 0x78, 0x56, 0xBC, 0x9A, 0xF0, 0xDE,
         0x34, 0x12, 0x78, 0x56, 0xBC, 0x9A, 0xF0, 0xDE, 0x34, 0x12, 0x78, 0x56, 0xBC, 0x9A, 0xDE, 0x00);
}

// clang-format on

void run_tests(const char *cpu) {
    assembler.setCpu(cpu);
    RUN_TEST(test_load_registers);
    RUN_TEST(test_load_immediate);
    RUN_TEST(test_load);
    RUN_TEST(test_store);
    RUN_TEST(test_exchange);
    RUN_TEST(test_stack);
    RUN_TEST(test_jump);
    RUN_TEST(test_incr_decr);
    RUN_TEST(test_alu_8bit);
    RUN_TEST(test_alu_16bit);
    RUN_TEST(test_io);
    RUN_TEST(test_block);
    RUN_TEST(test_inherent);
    RUN_TEST(test_restart);
    RUN_TEST(test_bitop);
    RUN_TEST(test_ddir);
    RUN_TEST(test_comment);
    RUN_TEST(test_undefined_symbol);
    RUN_TEST(test_data_constant);
}

// Local Variables:
// mode: c++
// c-basic-offset: 4
// tab-width: 4
// End:
// vim: set ft=cpp et ts=4 sw=4:
