/*
 *      Interactive disassembler (IDA).
 *      Copyright (c) 1990-99 by Ilfak Guilfanov.
 *      ALL RIGHTS RESERVED.
 *                              E-mail: ig@datarescue.com
 *
 *      Hitchi H8
 *
 */

#include "h8.hpp"

//lint -estring(958,member) padding is required

//--------------------------------------------------------------------------
struct map_t
{
  proctype_t proc;
  nameNum itype;
  ushort op1;
  ushort op2;
};

#define MAP2         nameNum(H8_last + 1)
#define MAP3         nameNum(H8_last + 2)
#define MAP4         nameNum(H8_last + 3)
#define MAP014       nameNum(H8_last + 4)
#define EXIT_40      nameNum(H8_last + 5)
#define EXIT_54      nameNum(H8_last + 6)
#define EXIT_56      nameNum(H8_last + 7)
#define EXIT_59      nameNum(H8_last + 8)
#define EXIT_5D      nameNum(H8_last + 9)
#define EXIT_7B      nameNum(H8_last + 10)

static const ushort OPTYPE = 0x7F;
static const ushort i3       =  1; // zero bit + immediate 3 bits in high nibble
static const ushort i8       =  2; // immediate 8 bits
static const ushort i16      =  3; // immediate 16 bits
static const ushort i32      =  4; // immediate 32 bits
static const ushort rCCR     =  5; // CCR
static const ushort rEXR     =  6; // EXR
static const ushort rLB      =  7; // register number in low nibble  (r0l..r7h)
static const ushort rHB      =  8; // register number in high nibble (r0l..r7h)
static const ushort rLW      =  9; // register number in low nibble  (r0..e7)
static const ushort rHW      = 10; // register number in high nibble (r0..e7)
static const ushort rLL0     = 11; // register number in low nibble
                                  // (er0..er7) high bit is zero
static const ushort rHL0     = 12; // register number in high nibble
                                  // (er0..er7) high bit is zero
static const ushort rLL1     = 13; // register number in low nibble
                                  // (er0..er7) high bit is one
static const ushort rHL1     = 14; // register number in high nibble
                                  // (er0..er7) high bit is one
static const ushort C1       = 15; // constant #1
static const ushort C2       = 16; // constant #2
static const ushort C4       = 17; // constant #4
static const ushort savedHL0 = 18; // same as rHL0 but uses code3
static const ushort savedAA  = 19; // absolute address in code3
static const ushort j8       = 20; // branch displacement 8 bit
static const ushort j16      = 21; // branch displacement 16 bit
static const ushort atHL     = 22; // @ERx
static const ushort aa8      = 23; // 8bit address
static const ushort aa16     = 24; // 16bit address
static const ushort aa24     = 25; // 24bit address
static const ushort aa32     = 26; // 32bit address
static const ushort rMACH    = 27; // MACH
static const ushort rMACL    = 28; // MACL
static const ushort d16      = 29; // @(d:16, ERs)
static const ushort ai8      = 30; // @@a8
static const ushort rV0      = 31; // 16bit or 32bit register depending
                                   // on the processor mode
static const ushort C8       = 32; // constant #8
static const ushort rVBR     = 33; // VBR
static const ushort rSBR     = 34; // SBR
static const ushort i4L      = 35; // immediate 4 bits in low nibble
static const ushort i4H      = 36; // immediate 4 bits in high nibble
static const ushort rL       = 37; // register number in low  nibble (depends of aux_pref)
static const ushort rH       = 38; // register number in high nibble (depends of aux_pref)
static const ushort Cxh      = 39; // fake imm operand, hidden

static const ushort NEXT     = 0x0080;  // read next byte

static const ushort CMD_SIZE = 0x0F00;
static const ushort B        = 0x0100;  // .b
static const ushort W        = 0x0200;  // .w
static const ushort L        = 0x0400;  // .l
static const ushort V        = 0x0800;  // .w or .l

static const ushort zL       = 0x1000; // low  nibble should be zero
static const ushort zH       = 0x2000; // high nibble should be zero
static const ushort MANUAL   = 0x4000; // manual processing
static const ushort X        = 0x8000; // no explicit postfix


//--------------------------------------------------------------------------
static const map_t map[256] =
{
  { P300,       H8_nop,         NEXT|zL|zH,     0,               }, // 00
  { P300,       MAP2,           0,              0,               }, // 01
  { P300,       MAP2,           0,              0,               }, // 02
  { P300,       MAP2,           0,              0,               }, // 03
  { P300,       H8_orc,         i8,             rCCR,            }, // 04
  { P300,       H8_xorc,        i8,             rCCR,            }, // 05
  { P300,       H8_andc,        i8,             rCCR,            }, // 06
  { P300,       H8_ldc,         B | i8,         rCCR,            }, // 07
  { P300,       H8_add,         B | NEXT | rHB, rLB,             }, // 08
  { P300,       H8_add,         W | NEXT | rHW, rLW,             }, // 09
  { P300,       MAP2,           0,              0,               }, // 0A
  { P300,       MAP2,           0,              0,               }, // 0B
  { P300,       H8_mov,         B | NEXT | rHB, rLB,             }, // 0C
  { P300,       H8_mov,         W | NEXT | rHW, rLW,             }, // 0D
  { P300,       H8_addx,        NEXT | rHB,     rLB,             }, // 0E
  { P300,       MAP2,           0,              0,               }, // 0F

  { P300,       MAP2,           0,              0,               }, // 10
  { P300,       MAP2,           0,              0,               }, // 11
  { P300,       MAP2,           0,              0,               }, // 12
  { P300,       MAP2,           0,              0,               }, // 13
  { P300,       H8_or,          B | NEXT | rHB, rLB              }, // 14
  { P300,       H8_xor,         B | NEXT | rHB, rLB              }, // 15
  { P300,       H8_and,         B | NEXT | rHB, rLB              }, // 16
  { P300,       MAP2,           0,              0,               }, // 17
  { P300,       H8_sub,         B | NEXT | rHB, rLB              }, // 18
  { P300,       H8_sub,         W | NEXT | rHW, rLW,             }, // 19
  { P300,       MAP2,           0,              0,               }, // 1A
  { P300,       MAP2,           0,              0,               }, // 1B
  { P300,       H8_cmp,         B | NEXT | rHB, rLB              }, // 1C
  { P300,       H8_cmp,         W | NEXT | rHW, rLW,             }, // 1D
  { P300,       H8_subx,        NEXT | rHB,     rLB,             }, // 1E
  { P300,       MAP2,           0,              0,               }, // 1F

  { P300,       H8_mov,         B | aa8,        rLB,             }, // 20
  { P300,       H8_mov,         B | aa8,        rLB,             }, // 21
  { P300,       H8_mov,         B | aa8,        rLB,             }, // 22
  { P300,       H8_mov,         B | aa8,        rLB,             }, // 23
  { P300,       H8_mov,         B | aa8,        rLB,             }, // 24
  { P300,       H8_mov,         B | aa8,        rLB,             }, // 25
  { P300,       H8_mov,         B | aa8,        rLB,             }, // 26
  { P300,       H8_mov,         B | aa8,        rLB,             }, // 27
  { P300,       H8_mov,         B | aa8,        rLB,             }, // 28
  { P300,       H8_mov,         B | aa8,        rLB,             }, // 29
  { P300,       H8_mov,         B | aa8,        rLB,             }, // 2A
  { P300,       H8_mov,         B | aa8,        rLB,             }, // 2B
  { P300,       H8_mov,         B | aa8,        rLB,             }, // 2C
  { P300,       H8_mov,         B | aa8,        rLB,             }, // 2D
  { P300,       H8_mov,         B | aa8,        rLB,             }, // 2E
  { P300,       H8_mov,         B | aa8,        rLB,             }, // 2F

  { P300,       H8_mov,         B | rLB,        B | aa8,         }, // 30
  { P300,       H8_mov,         B | rLB,        B | aa8,         }, // 31
  { P300,       H8_mov,         B | rLB,        B | aa8,         }, // 32
  { P300,       H8_mov,         B | rLB,        B | aa8,         }, // 33
  { P300,       H8_mov,         B | rLB,        B | aa8,         }, // 34
  { P300,       H8_mov,         B | rLB,        B | aa8,         }, // 35
  { P300,       H8_mov,         B | rLB,        B | aa8,         }, // 36
  { P300,       H8_mov,         B | rLB,        B | aa8,         }, // 37
  { P300,       H8_mov,         B | rLB,        B | aa8,         }, // 38
  { P300,       H8_mov,         B | rLB,        B | aa8,         }, // 39
  { P300,       H8_mov,         B | rLB,        B | aa8,         }, // 3A
  { P300,       H8_mov,         B | rLB,        B | aa8,         }, // 3B
  { P300,       H8_mov,         B | rLB,        B | aa8,         }, // 3C
  { P300,       H8_mov,         B | rLB,        B | aa8,         }, // 3D
  { P300,       H8_mov,         B | rLB,        B | aa8,         }, // 3E
  { P300,       H8_mov,         B | rLB,        B | aa8,         }, // 3F

  { P300,       EXIT_40,         0,             0,               }, // 40
  { P300,       H8_brn,         j8,             0,               }, // 41
  { P300,       H8_bhi,         j8,             0,               }, // 42
  { P300,       H8_bls,         j8,             0,               }, // 43
  { P300,       H8_bcc,         j8,             0,               }, // 44
  { P300,       H8_bcs,         j8,             0,               }, // 45
  { P300,       H8_bne,         j8,             0,               }, // 46
  { P300,       H8_beq,         j8,             0,               }, // 47
  { P300,       H8_bvc,         j8,             0,               }, // 48
  { P300,       H8_bvs,         j8,             0,               }, // 49
  { P300,       H8_bpl,         j8,             0,               }, // 4A
  { P300,       H8_bmi,         j8,             0,               }, // 4B
  { P300,       H8_bge,         j8,             0,               }, // 4C
  { P300,       H8_blt,         j8,             0,               }, // 4D
  { P300,       H8_bgt,         j8,             0,               }, // 4E
  { P300,       H8_ble,         j8,             0,               }, // 4F

  { P300,       H8_mulxu,       B | NEXT | rHB, rLW,             }, // 50
  { P300,       H8_divxu,       B | NEXT | rHB, rLW,             }, // 51
  { P30A,       H8_mulxu,       W | NEXT | rHW, rLL0,            }, // 52
  { P30A,       H8_divxu,       W | NEXT | rHW, rLL0,            }, // 53
  { P300,       EXIT_54,        0,              0,               }, // 54
  { P300,       H8_bsr,         j8,             0,               }, // 55
  { P300,       EXIT_56,        0,              0,               }, // 56
  { P300,       H8_trapa,       MANUAL,         0,               }, // 57
  { P300,       MAP2,           0,              0,               }, // 58
  { P300,       EXIT_59,        0,              0,               }, // 59
  { P300,       H8_jmp,         aa24,           0,               }, // 5A
  { P300,       H8_jmp,         ai8,            0,               }, // 5B
  { P300,       H8_bsr,         NEXT|zL|zH| j16,0,               }, // 5C
  { P300,       EXIT_5D,        0,              0,               }, // 5D
  { P300,       H8_jsr,         aa24,           0,               }, // 5E
  { P300,       H8_jsr,         ai8,            0,               }, // 5F

  { P300,       H8_bset,        NEXT | rHB,     rLB,             }, // 60
  { P300,       H8_bnot,        NEXT | rHB,     rLB,             }, // 61
  { P300,       H8_bclr,        NEXT | rHB,     rLB,             }, // 62
  { P300,       H8_btst,        NEXT | rHB,     rLB,             }, // 63
  { P300,       H8_or,          W | NEXT | rHW, rLW              }, // 64
  { P300,       H8_xor,         W | NEXT | rHW, rLW              }, // 65
  { P300,       H8_and,         W | NEXT | rHW, rLW              }, // 66
  { P300,       H8_bst,         NEXT | i3,      rLB,             }, // 67
  { P300,       H8_mov,         B | NEXT | atHL,rLB,             }, // 68
  { P300,       H8_mov,         W | NEXT | atHL,rLW,             }, // 69
  { P300,       MAP2,           0,              0,               }, // 6A
  { P300,       H8_mov,         MANUAL,         0,               }, // 6B
  { P300,       H8_mov,         MANUAL,         0,               }, // 6C
  { P300,       H8_mov,         MANUAL,         0,               }, // 6D
  { P300,       H8_mov,         B | NEXT | d16, rLB,             }, // 6E
  { P300,       H8_mov,         W | NEXT | d16, rLW,             }, // 6F

  { P300,       H8_bset,        NEXT | i3,      rLB,             }, // 70
  { P300,       H8_bnot,        NEXT | i3,      rLB,             }, // 71
  { P300,       H8_bclr,        NEXT | i3,      rLB,             }, // 72
  { P300,       H8_btst,        NEXT | i3,      rLB,             }, // 73
  { P300,       H8_bor,         NEXT | i3,      rLB,             }, // 74
  { P300,       H8_bxor,        NEXT | i3,      rLB,             }, // 75
  { P300,       H8_band,        NEXT | i3,      rLB,             }, // 76
  { P300,       H8_bld,         NEXT | i3,      rLB,             }, // 77
  { P300,       H8_mov,         MANUAL,         0,               }, // 78
  { P300,       MAP2,           0,              0,               }, // 79
  { P300,       MAP2,           0,              0,               }, // 7A
  { P300,       EXIT_7B,        0,              0,               }, // 7B
  { P300,       MAP3,           0,              0,               }, // 7C
  { P300,       MAP3,           0,              0,               }, // 7D
  { P300,       MAP3,           0,              0,               }, // 7E
  { P300,       MAP3,           0,              0,               }, // 7F

  { P300,       H8_add,         B | i8,         rLB,             }, // 80
  { P300,       H8_add,         B | i8,         rLB,             }, // 81
  { P300,       H8_add,         B | i8,         rLB,             }, // 82
  { P300,       H8_add,         B | i8,         rLB,             }, // 83
  { P300,       H8_add,         B | i8,         rLB,             }, // 84
  { P300,       H8_add,         B | i8,         rLB,             }, // 85
  { P300,       H8_add,         B | i8,         rLB,             }, // 86
  { P300,       H8_add,         B | i8,         rLB,             }, // 87
  { P300,       H8_add,         B | i8,         rLB,             }, // 88
  { P300,       H8_add,         B | i8,         rLB,             }, // 89
  { P300,       H8_add,         B | i8,         rLB,             }, // 8A
  { P300,       H8_add,         B | i8,         rLB,             }, // 8B
  { P300,       H8_add,         B | i8,         rLB,             }, // 8C
  { P300,       H8_add,         B | i8,         rLB,             }, // 8D
  { P300,       H8_add,         B | i8,         rLB,             }, // 8E
  { P300,       H8_add,         B | i8,         rLB,             }, // 8F

  { P300,       H8_addx,        i8,             rLB,             }, // 90
  { P300,       H8_addx,        i8,             rLB,             }, // 91
  { P300,       H8_addx,        i8,             rLB,             }, // 92
  { P300,       H8_addx,        i8,             rLB,             }, // 93
  { P300,       H8_addx,        i8,             rLB,             }, // 94
  { P300,       H8_addx,        i8,             rLB,             }, // 95
  { P300,       H8_addx,        i8,             rLB,             }, // 96
  { P300,       H8_addx,        i8,             rLB,             }, // 97
  { P300,       H8_addx,        i8,             rLB,             }, // 98
  { P300,       H8_addx,        i8,             rLB,             }, // 99
  { P300,       H8_addx,        i8,             rLB,             }, // 9A
  { P300,       H8_addx,        i8,             rLB,             }, // 9B
  { P300,       H8_addx,        i8,             rLB,             }, // 9C
  { P300,       H8_addx,        i8,             rLB,             }, // 9D
  { P300,       H8_addx,        i8,             rLB,             }, // 9E
  { P300,       H8_addx,        i8,             rLB,             }, // 9F

  { P300,       H8_cmp,         B | i8,         rLB,             }, // A0
  { P300,       H8_cmp,         B | i8,         rLB,             }, // A1
  { P300,       H8_cmp,         B | i8,         rLB,             }, // A2
  { P300,       H8_cmp,         B | i8,         rLB,             }, // A3
  { P300,       H8_cmp,         B | i8,         rLB,             }, // A4
  { P300,       H8_cmp,         B | i8,         rLB,             }, // A5
  { P300,       H8_cmp,         B | i8,         rLB,             }, // A6
  { P300,       H8_cmp,         B | i8,         rLB,             }, // A7
  { P300,       H8_cmp,         B | i8,         rLB,             }, // A8
  { P300,       H8_cmp,         B | i8,         rLB,             }, // A9
  { P300,       H8_cmp,         B | i8,         rLB,             }, // AA
  { P300,       H8_cmp,         B | i8,         rLB,             }, // AB
  { P300,       H8_cmp,         B | i8,         rLB,             }, // AC
  { P300,       H8_cmp,         B | i8,         rLB,             }, // AD
  { P300,       H8_cmp,         B | i8,         rLB,             }, // AE
  { P300,       H8_cmp,         B | i8,         rLB,             }, // AF

  { P300,       H8_subx,        i8,             rLB,             }, // B0
  { P300,       H8_subx,        i8,             rLB,             }, // B1
  { P300,       H8_subx,        i8,             rLB,             }, // B2
  { P300,       H8_subx,        i8,             rLB,             }, // B3
  { P300,       H8_subx,        i8,             rLB,             }, // B4
  { P300,       H8_subx,        i8,             rLB,             }, // B5
  { P300,       H8_subx,        i8,             rLB,             }, // B6
  { P300,       H8_subx,        i8,             rLB,             }, // B7
  { P300,       H8_subx,        i8,             rLB,             }, // B8
  { P300,       H8_subx,        i8,             rLB,             }, // B9
  { P300,       H8_subx,        i8,             rLB,             }, // BA
  { P300,       H8_subx,        i8,             rLB,             }, // BB
  { P300,       H8_subx,        i8,             rLB,             }, // BC
  { P300,       H8_subx,        i8,             rLB,             }, // BD
  { P300,       H8_subx,        i8,             rLB,             }, // BE
  { P300,       H8_subx,        i8,             rLB,             }, // BF

  { P300,       H8_or,          B | i8,         rLB,             }, // C0
  { P300,       H8_or,          B | i8,         rLB,             }, // C1
  { P300,       H8_or,          B | i8,         rLB,             }, // C2
  { P300,       H8_or,          B | i8,         rLB,             }, // C3
  { P300,       H8_or,          B | i8,         rLB,             }, // C4
  { P300,       H8_or,          B | i8,         rLB,             }, // C5
  { P300,       H8_or,          B | i8,         rLB,             }, // C6
  { P300,       H8_or,          B | i8,         rLB,             }, // C7
  { P300,       H8_or,          B | i8,         rLB,             }, // C8
  { P300,       H8_or,          B | i8,         rLB,             }, // C9
  { P300,       H8_or,          B | i8,         rLB,             }, // CA
  { P300,       H8_or,          B | i8,         rLB,             }, // CB
  { P300,       H8_or,          B | i8,         rLB,             }, // CC
  { P300,       H8_or,          B | i8,         rLB,             }, // CD
  { P300,       H8_or,          B | i8,         rLB,             }, // CE
  { P300,       H8_or,          B | i8,         rLB,             }, // CF

  { P300,       H8_xor,         B | i8,         rLB,             }, // D0
  { P300,       H8_xor,         B | i8,         rLB,             }, // D1
  { P300,       H8_xor,         B | i8,         rLB,             }, // D2
  { P300,       H8_xor,         B | i8,         rLB,             }, // D3
  { P300,       H8_xor,         B | i8,         rLB,             }, // D4
  { P300,       H8_xor,         B | i8,         rLB,             }, // D5
  { P300,       H8_xor,         B | i8,         rLB,             }, // D6
  { P300,       H8_xor,         B | i8,         rLB,             }, // D7
  { P300,       H8_xor,         B | i8,         rLB,             }, // D8
  { P300,       H8_xor,         B | i8,         rLB,             }, // D9
  { P300,       H8_xor,         B | i8,         rLB,             }, // DA
  { P300,       H8_xor,         B | i8,         rLB,             }, // DB
  { P300,       H8_xor,         B | i8,         rLB,             }, // DC
  { P300,       H8_xor,         B | i8,         rLB,             }, // DD
  { P300,       H8_xor,         B | i8,         rLB,             }, // DE
  { P300,       H8_xor,         B | i8,         rLB,             }, // DF

  { P300,       H8_and,         B | i8,         rLB,             }, // E0
  { P300,       H8_and,         B | i8,         rLB,             }, // E1
  { P300,       H8_and,         B | i8,         rLB,             }, // E2
  { P300,       H8_and,         B | i8,         rLB,             }, // E3
  { P300,       H8_and,         B | i8,         rLB,             }, // E4
  { P300,       H8_and,         B | i8,         rLB,             }, // E5
  { P300,       H8_and,         B | i8,         rLB,             }, // E6
  { P300,       H8_and,         B | i8,         rLB,             }, // E7
  { P300,       H8_and,         B | i8,         rLB,             }, // E8
  { P300,       H8_and,         B | i8,         rLB,             }, // E9
  { P300,       H8_and,         B | i8,         rLB,             }, // EA
  { P300,       H8_and,         B | i8,         rLB,             }, // EB
  { P300,       H8_and,         B | i8,         rLB,             }, // EC
  { P300,       H8_and,         B | i8,         rLB,             }, // ED
  { P300,       H8_and,         B | i8,         rLB,             }, // EE
  { P300,       H8_and,         B | i8,         rLB,             }, // EF

  { P300,       H8_mov,         B | rLB,        B | i8,          }, // F0
  { P300,       H8_mov,         B | rLB,        B | i8,          }, // F1
  { P300,       H8_mov,         B | rLB,        B | i8,          }, // F2
  { P300,       H8_mov,         B | rLB,        B | i8,          }, // F3
  { P300,       H8_mov,         B | rLB,        B | i8,          }, // F4
  { P300,       H8_mov,         B | rLB,        B | i8,          }, // F5
  { P300,       H8_mov,         B | rLB,        B | i8,          }, // F6
  { P300,       H8_mov,         B | rLB,        B | i8,          }, // F7
  { P300,       H8_mov,         B | rLB,        B | i8,          }, // F8
  { P300,       H8_mov,         B | rLB,        B | i8,          }, // F9
  { P300,       H8_mov,         B | rLB,        B | i8,          }, // FA
  { P300,       H8_mov,         B | rLB,        B | i8,          }, // FB
  { P300,       H8_mov,         B | rLB,        B | i8,          }, // FC
  { P300,       H8_mov,         B | rLB,        B | i8,          }, // FD
  { P300,       H8_mov,         B | rLB,        B | i8,          }, // FE
  { P300,       H8_mov,         B | rLB,        B | i8,          }, // FF

};


//--------------------------------------------------------------------------
static const map_t map2_01[16] =
{
  { P300,       H8_mov,         MANUAL,         0,               }, // 01 0?
  { P300,       H8_ldm,         MANUAL,         0,               }, // 01 1?
  { P300,       H8_ldm,         MANUAL,         0,               }, // 01 2?
  { P300,       H8_ldm,         MANUAL,         0,               }, // 01 3?
  { P300,       MAP014,         0,              0,               }, // 01 4?
  { none,       H8_null,        0,              0,               }, // 01 5?
  { P2600,      H8_mac,         0,              0,               }, // 01 6?
  { none,       H8_null,        0,              0,               }, // 01 7?
  { P300,       H8_sleep,       zL,             0,               }, // 01 8?
  { none,       H8_null,        0,              0,               }, // 01 9?
  { P2600,      H8_clrmac,      zL,             0,               }, // 01 A?
  { none,       H8_null,        0,              0,               }, // 01 B?
  { P300,       MAP3,           0,              0,               }, // 01 C?
  { P300,       MAP3,           0,              0,               }, // 01 D?
  { P300,       H8_tas,         MANUAL,         0,               }, // 01 E?
  { P300,       MAP3,           0,              0,               }, // 01 F?
};

//--------------------------------------------------------------------------
static const map_t map2_02[16] =
{
  { P300,       H8_stc,         B | rCCR,       rLB,             }, // 02 0?
  { P300,       H8_stc,         B | rEXR,       rLB,             }, // 02 1?
  { P2600,      H8_stmac,       rMACH,          rLL0,            }, // 02 2?
  { P2600,      H8_stmac,       rMACL,          rLL0,            }, // 02 3?
  { none,       H8_null,        0,              0,               }, // 02 4?
  { none,       H8_null,        0,              0,               }, // 02 5?
  { PSX,        H8_stc,         L | rVBR,       rLL0,            }, // 02 6?
  { PSX,        H8_stc,         L | rSBR,       rLL0,            }, // 02 7?
  { none,       H8_null,        0,              0,               }, // 02 8?
  { none,       H8_null,        0,              0,               }, // 02 9?
  { none,       H8_null,        0,              0,               }, // 02 A?
  { none,       H8_null,        0,              0,               }, // 02 B?
  { none,       H8_null,        0,              0,               }, // 02 C?
  { none,       H8_null,        0,              0,               }, // 02 D?
  { none,       H8_null,        0,              0,               }, // 02 E?
  { none,       H8_null,        0,              0,               }, // 02 F?
};

//--------------------------------------------------------------------------
static const map_t map2_03[16] =
{
  { P300,       H8_ldc,         B | rLB,        rCCR,            }, // 03 0?
  { P300,       H8_ldc,         B | rLB,        rEXR,            }, // 03 1?
  { P2600,      H8_ldmac,       rLL0,           rMACH,           }, // 03 2?
  { P2600,      H8_ldmac,       rLL0,           rMACL,           }, // 03 3?
  { none,       H8_null,        0,              0,               }, // 03 4?
  { none,       H8_null,        0,              0,               }, // 03 5?
  { none,       H8_null,        0,              0,               }, // 03 6?
  { none,       H8_null,        0,              0,               }, // 03 7?
  { none,       H8_null,        0,              0,               }, // 03 8?
  { none,       H8_null,        0,              0,               }, // 03 9?
  { none,       H8_null,        0,              0,               }, // 03 A?
  { none,       H8_null,        0,              0,               }, // 03 B?
  { none,       H8_null,        0,              0,               }, // 03 C?
  { none,       H8_null,        0,              0,               }, // 03 D?
  { none,       H8_null,        0,              0,               }, // 03 E?
  { none,       H8_null,        0,              0,               }, // 03 F?
};

//--------------------------------------------------------------------------
static const map_t map2_0A[16] =
{
  { P300,       H8_inc,         B | Cxh,        rLB,             }, // 0A 0?
  { none,       H8_null,        0,              0,               }, // 0A 1?
  { none,       H8_null,        0,              0,               }, // 0A 2?
  { none,       H8_null,        0,              0,               }, // 0A 3?
  { none,       H8_null,        0,              0,               }, // 0A 4?
  { none,       H8_null,        0,              0,               }, // 0A 5?
  { none,       H8_null,        0,              0,               }, // 0A 6?
  { none,       H8_null,        0,              0,               }, // 0A 7?
  { P30A,       H8_add,         L | rHL1,       rLL0,            }, // 0A 8?
  { P30A,       H8_add,         L | rHL1,       rLL0,            }, // 0A 9?
  { P30A,       H8_add,         L | rHL1,       rLL0,            }, // 0A A?
  { P30A,       H8_add,         L | rHL1,       rLL0,            }, // 0A B?
  { P30A,       H8_add,         L | rHL1,       rLL0,            }, // 0A C?
  { P30A,       H8_add,         L | rHL1,       rLL0,            }, // 0A D?
  { P30A,       H8_add,         L | rHL1,       rLL0,            }, // 0A E?
  { P30A,       H8_add,         L | rHL1,       rLL0,            }, // 0A F?
};

//--------------------------------------------------------------------------
static const map_t map2_0B[16] =
{
  { P300,       H8_adds,        C1,             rV0,             }, // 0B 0?
  { none,       H8_null,        0,              0,               }, // 0B 1?
  { none,       H8_null,        0,              0,               }, // 0B 2?
  { none,       H8_null,        0,              0,               }, // 0B 3?
  { none,       H8_null,        0,              0,               }, // 0B 4?
  { P300,       H8_inc,         W | C1,         rLW,             }, // 0B 5?
  { none,       H8_null,        0,              0,               }, // 0B 6?
  { P30A,       H8_inc,         L | C1,         rLL0,            }, // 0B 7?
  { P300,       H8_adds,        C2,             rV0,             }, // 0B 8?
  { P30A,       H8_adds,        C4,             rLL0,            }, // 0B 9?
  { none,       H8_null,        0,              0,               }, // 0B A?
  { none,       H8_null,        0,              0,               }, // 0B B?
  { none,       H8_null,        0,              0,               }, // 0B C?
  { P300,       H8_inc,         W | C2,         rLW,             }, // 0B D?
  { none,       H8_null,        0,              0,               }, // 0B E?
  { P30A,       H8_inc,         L | C2,         rLL0,            }, // 0B F?
};

//--------------------------------------------------------------------------
static const map_t map2_0F[16] =
{
  { P300,       H8_daa,         rLB,            0,               }, // 0F 0?
  { none,       H8_null,        0,              0,               }, // 0F 1?
  { none,       H8_null,        0,              0,               }, // 0F 2?
  { none,       H8_null,        0,              0,               }, // 0F 3?
  { none,       H8_null,        0,              0,               }, // 0F 4?
  { none,       H8_null,        0,              0,               }, // 0F 5?
  { none,       H8_null,        0,              0,               }, // 0F 6?
  { none,       H8_null,        0,              0,               }, // 0F 7?
  { P30A,       H8_mov,         L | rLL0,       rHL1,            }, // 0F 8?
  { P30A,       H8_mov,         L | rLL0,       rHL1,            }, // 0F 9?
  { P30A,       H8_mov,         L | rLL0,       rHL1,            }, // 0F A?
  { P30A,       H8_mov,         L | rLL0,       rHL1,            }, // 0F B?
  { P30A,       H8_mov,         L | rLL0,       rHL1,            }, // 0F C?
  { P30A,       H8_mov,         L | rLL0,       rHL1,            }, // 0F D?
  { P30A,       H8_mov,         L | rLL0,       rHL1,            }, // 0F E?
  { P30A,       H8_mov,         L | rLL0,       rHL1,            }, // 0F F?
};

//--------------------------------------------------------------------------
static const map_t map2_10[16] =
{
  { P300,       H8_shll,        B | Cxh,        rLB,             }, // 10 0?
  { P300,       H8_shll,        W | Cxh,        rLW,             }, // 10 1?
  { PSX,        H8_shll,        W | C4,         rLW,             }, // 10 2?
  { P30A,       H8_shll,        L | Cxh,        rLL0             }, // 10 3?
  { P300,       H8_shll,        B | C2,         rLB,             }, // 10 4?
  { P300,       H8_shll,        W | C2,         rLW,             }, // 10 5?
  { PSX,        H8_shll,        W | C8,         rLW,             }, // 10 6?
  { P30A,       H8_shll,        L | C2,         rLL0,            }, // 10 7?
  { P300,       H8_shal,        B | Cxh,        rLB,             }, // 10 8?
  { P300,       H8_shal,        W | Cxh,        rLW,             }, // 10 9?
  { PSX,        H8_shll,        B | C4,         rLB,             }, // 10 A?
  { P30A,       H8_shal,        L | Cxh,        rLL0,            }, // 10 B?
  { P300,       H8_shal,        B | C2,         rLB,             }, // 10 C?
  { P300,       H8_shal,        W | C2,         rLW,             }, // 10 D?
  { none,       H8_null,        0,              0,               }, // 10 E?
  { P30A,       H8_shal,        L | C2,         rLL0,            }, // 10 F?
};

//--------------------------------------------------------------------------
static const map_t map2_11[16] =
{
  { P300,       H8_shlr,        B | Cxh,        rLB,             }, // 11 0?
  { P300,       H8_shlr,        W | Cxh,        rLW,             }, // 11 1?
  { PSX,        H8_shlr,        W | C4,         rLW,             }, // 11 2?
  { P30A,       H8_shlr,        L | Cxh,        rLL0             }, // 11 3?
  { P300,       H8_shlr,        B | C2,         rLB,             }, // 11 4?
  { P300,       H8_shlr,        W | C2,         rLW,             }, // 11 5?
  { PSX,        H8_shlr,        W | C8,         rLW,             }, // 11 6?
  { P30A,       H8_shlr,        L | C2,         rLL0,            }, // 11 7?
  { P300,       H8_shar,        B | Cxh,        rLB,             }, // 11 8?
  { P300,       H8_shar,        W | Cxh,        rLW,             }, // 11 9?
  { PSX,        H8_shlr,        B | C4,         rLB,             }, // 11 A?
  { P30A,       H8_shar,        L | Cxh,        rLL0,            }, // 11 B?
  { P300,       H8_shar,        B | C2,         rLB,             }, // 11 C?
  { P300,       H8_shar,        W | C2,         rLW,             }, // 11 D?
  { none,       H8_null,        0,              0,               }, // 11 E?
  { P30A,       H8_shar,        L | C2,         rLL0,            }, // 11 F?
};

//--------------------------------------------------------------------------
static const map_t map2_12[16] =
{
  { P300,       H8_rotxl,       B | Cxh,        rLB,             }, // 12 0?
  { P300,       H8_rotxl,       W | Cxh,        rLW,             }, // 12 1?
  { none,       H8_null,        0,              0,               }, // 12 2?
  { P30A,       H8_rotxl,       L | Cxh,        rLL0,            }, // 12 3?
  { P300,       H8_rotxl,       B | C2,         rLB,             }, // 12 4?
  { P300,       H8_rotxl,       W | C2,         rLW,             }, // 12 5?
  { none,       H8_null,        0,              0,               }, // 12 6?
  { P30A,       H8_rotxl,       L | C2,         rLL0,            }, // 12 7?
  { P300,       H8_rotl,        B | Cxh,        rLB,             }, // 12 8?
  { P300,       H8_rotl,        W | Cxh,        rLW,             }, // 12 9?
  { none,       H8_null,        0,              0,               }, // 12 A?
  { P30A,       H8_rotl,        L | Cxh,        rLL0,            }, // 12 B?
  { P300,       H8_rotl,        B | C2,         rLB,             }, // 12 C?
  { P300,       H8_rotl,        W | C2,         rLW,             }, // 12 D?
  { none,       H8_null,        0,              0,               }, // 12 E?
  { P30A,       H8_rotl,        L | C2,         rLL0,            }, // 12 F?
};

//--------------------------------------------------------------------------
static const map_t map2_13[16] =
{
  { P300,       H8_rotxr,       B | Cxh,        rLB,             }, // 13 0?
  { P300,       H8_rotxr,       W | Cxh,        rLW,             }, // 13 1?
  { none,       H8_null,        0,              0,               }, // 13 2?
  { P30A,       H8_rotxr,       L | Cxh,        rLL0,            }, // 13 3?
  { P300,       H8_rotxr,       B | C2,         rLB,             }, // 13 4?
  { P300,       H8_rotxr,       W | C2,         rLW,             }, // 13 5?
  { none,       H8_null,        0,              0,               }, // 13 6?
  { P30A,       H8_rotxr,       L | C2,         rLL0,            }, // 13 7?
  { P300,       H8_rotr,        B | Cxh,        rLB,             }, // 13 8?
  { P300,       H8_rotr,        W | Cxh,        rLW,             }, // 13 9?
  { none,       H8_null,        0,              0,               }, // 13 A?
  { P30A,       H8_rotr,        L | Cxh,        rLL0,            }, // 13 B?
  { P300,       H8_rotr,        B | C2,         rLB,             }, // 13 C?
  { P300,       H8_rotr,        W | C2,         rLW,             }, // 13 D?
  { none,       H8_null,        0,              0,               }, // 13 E?
  { P30A,       H8_rotr,        L | C2,         rLL0,            }, // 13 F?
};

//--------------------------------------------------------------------------
static const map_t map2_17[16] =
{
  { P300,       H8_not,         B | rLB,        0,               }, // 17 0?
  { P300,       H8_not,         W | rLW,        0,               }, // 17 1?
  { none,       H8_null,        0,              0,               }, // 17 2?
  { P30A,       H8_not,         L | rLL0,       0,               }, // 17 3?
  { none,       H8_null,        0,              0,               }, // 17 4?
  { P300,       H8_extu,        W | Cxh,        rLW,             }, // 17 5?
  { PSX,        H8_extu,        L | C2,         rLL0,            }, // 17 6?
  { P30A,       H8_extu,        L | Cxh,        rLL0,            }, // 17 7?
  { P300,       H8_neg,         B | rLB,        0,               }, // 17 8?
  { P300,       H8_neg,         W | rLW,        0,               }, // 17 9?
  { none,       H8_null,        0,              0,               }, // 17 A?
  { P30A,       H8_neg,         L | rLL0,       0,               }, // 17 B?
  { none,       H8_null,        0,              0,               }, // 17 C?
  { P300,       H8_exts,        W | Cxh,        rLW,             }, // 17 D?
  { PSX,        H8_exts,        L | C2,         rLL0,            }, // 17 E?
  { P30A,       H8_exts,        L | Cxh,        rLL0,            }, // 17 F?
};

//--------------------------------------------------------------------------
static const map_t map2_1A[16] =
{
  { P300,       H8_dec,         B | Cxh,        rLB,             }, // 1A 0?
  { none,       H8_null,        0,              0,               }, // 1A 1?
  { none,       H8_null,        0,              0,               }, // 1A 2?
  { none,       H8_null,        0,              0,               }, // 1A 3?
  { none,       H8_null,        0,              0,               }, // 1A 4?
  { none,       H8_null,        0,              0,               }, // 1A 5?
  { none,       H8_null,        0,              0,               }, // 1A 6?
  { none,       H8_null,        0,              0,               }, // 1A 7?
  { P30A,       H8_sub,         L | rHL1,       rLL0,            }, // 1A 8?
  { P30A,       H8_sub,         L | rHL1,       rLL0,            }, // 1A 9?
  { P30A,       H8_sub,         L | rHL1,       rLL0,            }, // 1A A?
  { P30A,       H8_sub,         L | rHL1,       rLL0,            }, // 1A B?
  { P30A,       H8_sub,         L | rHL1,       rLL0,            }, // 1A C?
  { P30A,       H8_sub,         L | rHL1,       rLL0,            }, // 1A D?
  { P30A,       H8_sub,         L | rHL1,       rLL0,            }, // 1A E?
  { P30A,       H8_sub,         L | rHL1,       rLL0,            }, // 1A F?
};

//--------------------------------------------------------------------------
static const map_t map2_1B[16] =
{
  { P300,       H8_subs,        C1,             rV0,             }, // 1B 0?
  { none,       H8_null,        0,              0,               }, // 1B 1?
  { none,       H8_null,        0,              0,               }, // 1B 2?
  { none,       H8_null,        0,              0,               }, // 1B 3?
  { none,       H8_null,        0,              0,               }, // 1B 4?
  { P300,       H8_dec,         W | C1,         rLW,             }, // 1B 5?
  { none,       H8_null,        0,              0,               }, // 1B 6?
  { P30A,       H8_dec,         L | C1,         rLL0,            }, // 1B 7?
  { P300,       H8_subs,        C2,             rV0,             }, // 1B 8?
  { P30A,       H8_subs,        C4,             rLL0,            }, // 1B 9?
  { none,       H8_null,        0,              0,               }, // 1B A?
  { none,       H8_null,        0,              0,               }, // 1B B?
  { none,       H8_null,        0,              0,               }, // 1B C?
  { P300,       H8_dec,         W | C2,         rLW,             }, // 1B D?
  { none,       H8_null,        0,              0,               }, // 1B E?
  { P30A,       H8_dec,         L | C2,         rLL0,            }, // 1B F?
};

//--------------------------------------------------------------------------
static const map_t map2_1F[16] =
{
  { P300,       H8_das,         rLB,            0,               }, // 1F 0?
  { none,       H8_null,        0,              0,               }, // 1F 1?
  { none,       H8_null,        0,              0,               }, // 1F 2?
  { none,       H8_null,        0,              0,               }, // 1F 3?
  { none,       H8_null,        0,              0,               }, // 1F 4?
  { none,       H8_null,        0,              0,               }, // 1F 5?
  { none,       H8_null,        0,              0,               }, // 1F 6?
  { none,       H8_null,        0,              0,               }, // 1F 7?
  { P30A,       H8_cmp,         L | rHL1,       rLL0,            }, // 1F 8?
  { P30A,       H8_cmp,         L | rHL1,       rLL0,            }, // 1F 9?
  { P30A,       H8_cmp,         L | rHL1,       rLL0,            }, // 1F A?
  { P30A,       H8_cmp,         L | rHL1,       rLL0,            }, // 1F B?
  { P30A,       H8_cmp,         L | rHL1,       rLL0,            }, // 1F C?
  { P30A,       H8_cmp,         L | rHL1,       rLL0,            }, // 1F D?
  { P30A,       H8_cmp,         L | rHL1,       rLL0,            }, // 1F E?
  { P30A,       H8_cmp,         L | rHL1,       rLL0,            }, // 1F F?
};

//--------------------------------------------------------------------------
static const map_t map2_58[16] =
{
  { P300,       H8_bra,         zL | j16,       0,               }, // 58 0?
  { P300,       H8_brn,         zL | j16,       0,               }, // 58 1?
  { P300,       H8_bhi,         zL | j16,       0,               }, // 58 2?
  { P300,       H8_bls,         zL | j16,       0,               }, // 58 3?
  { P300,       H8_bcc,         zL | j16,       0,               }, // 58 4?
  { P300,       H8_bcs,         zL | j16,       0,               }, // 58 5?
  { P300,       H8_bne,         zL | j16,       0,               }, // 58 6?
  { P300,       H8_beq,         zL | j16,       0,               }, // 58 7?
  { P300,       H8_bvc,         zL | j16,       0,               }, // 58 8?
  { P300,       H8_bvs,         zL | j16,       0,               }, // 58 9?
  { P300,       H8_bpl,         zL | j16,       0,               }, // 58 A?
  { P300,       H8_bmi,         zL | j16,       0,               }, // 58 B?
  { P300,       H8_bge,         zL | j16,       0,               }, // 58 C?
  { P300,       H8_blt,         zL | j16,       0,               }, // 58 D?
  { P300,       H8_bgt,         zL | j16,       0,               }, // 58 E?
  { P300,       H8_ble,         zL | j16,       0,               }, // 58 F?
};

//--------------------------------------------------------------------------
static const map_t map2_6A[16] =
{
  { P300,       H8_mov,         B | aa16,       rLB,             }, // 6A 0?
  { P300,       MAP4,           0,              0,               }, // 6A 1?
  { P300,       H8_mov,         B | aa32,       rLB,             }, // 6A 2?
  { P300,       MAP4,           0,              0,               }, // 6A 3?
  { P300,       H8_movfpe,      B | X | aa16,   rLB,             }, // 6A 4?
  { none,       H8_null,        0,              0,               }, // 6A 5?
  { none,       H8_null,        0,              0,               }, // 6A 6?
  { none,       H8_null,        0,              0,               }, // 6A 7?
  { P300,       H8_mov,         B | aa16,       rLB,             }, // 6A 8?
  { none,       H8_null,        0,              0,               }, // 6A 9?
  { P300,       H8_mov,         B | aa32,       rLB,             }, // 6A A?
  { none,       H8_null,        0,              0,               }, // 6A B?
  { P300,       H8_movtpe,      rLB,            B | aa16,        }, // 6A C?
  { none,       H8_null,        0,              0,               }, // 6A D?
  { none,       H8_null,        0,              0,               }, // 6A E?
  { none,       H8_null,        0,              0,               }, // 6A F?
};

//--------------------------------------------------------------------------
static const map_t map2_6A_h8sx[16] =
{
  { P300,       H8_mov,         B | aa16,       rLB,             }, // 6A 0?
  { P300,       H8_null,        0,              0,               }, // 6A 1?
  { P300,       H8_mov,         B | aa32,       rLB,             }, // 6A 2?
  { P300,       H8_null,        0,              0,               }, // 6A 3?
  { P300,       H8_movfpe,      B | X | aa16,   rLB,             }, // 6A 4?
  { none,       H8_null,        0,              0,               }, // 6A 5?
  { none,       H8_null,        0,              0,               }, // 6A 6?
  { none,       H8_null,        0,              0,               }, // 6A 7?
  { P300,       H8_mov,         B | rLB,        B | aa16,        }, // 6A 8?
  { none,       H8_null,        0,              0,               }, // 6A 9?
  { P300,       H8_mov,         B | rLB,        B | aa32,        }, // 6A A?
  { none,       H8_null,        0,              0,               }, // 6A B?
  { P300,       H8_movtpe,      rLB,            B | aa16,        }, // 6A C?
  { PSX,        H8_mov,         B | i4L,        B | aa16,        }, // 6A D?
  { none,       H8_null,        0,              0,               }, // 6A E?
  { PSX,        H8_mov,         B | i4L,        B | aa32,        }, // 6A F?
};

//--------------------------------------------------------------------------
static const map_t map2_6B_h8sx[16] =
{
  { P300,       H8_mov,         W | aa16,       rLW,             }, // 6A 0?
  { P300,       H8_null,        0,              0,               }, // 6A 1?
  { P300,       H8_mov,         W | aa32,       rLW,             }, // 6A 2?
  { P300,       H8_null,        0,              0,               }, // 6A 3?
  { P300,       H8_null,        0,              0,               }, // 6A 4?
  { none,       H8_null,        0,              0,               }, // 6A 5?
  { none,       H8_null,        0,              0,               }, // 6A 6?
  { none,       H8_null,        0,              0,               }, // 6A 7?
  { P300,       H8_mov,         W | rLW,        W | aa16,        }, // 6A 8?
  { none,       H8_null,        0,              0,               }, // 6A 9?
  { P300,       H8_mov,         W | rLW,        W | aa32,        }, // 6A A?
  { none,       H8_null,        0,              0,               }, // 6A B?
  { P300,       H8_null,        0,              0,               }, // 6A C?
  { PSX,        H8_mov,         W | i4L,        W | aa16,        }, // 6A D?
  { none,       H8_null,        0,              0,               }, // 6A E?
  { PSX,        H8_mov,         W | i4L,        W | aa32,        }, // 6A F?
};

//--------------------------------------------------------------------------
static const map_t map2_79[16] =
{
  { P300,       H8_mov,         W | i16,        rLW              }, // 79 0?
  { P300,       H8_add,         W | i16,        rLW              }, // 79 1?
  { P300,       H8_cmp,         W | i16,        rLW              }, // 79 2?
  { P300,       H8_sub,         W | i16,        rLW              }, // 79 3?
  { P300,       H8_or,          W | i16,        rLW              }, // 79 4?
  { P300,       H8_xor,         W | i16,        rLW              }, // 79 5?
  { P300,       H8_and,         W | i16,        rLW              }, // 79 6?
  { none,       H8_null,        0,              0,               }, // 79 7?
  { none,       H8_null,        0,              0,               }, // 79 8?
  { none,       H8_null,        0,              0,               }, // 79 9?
  { none,       H8_null,        0,              0,               }, // 79 A?
  { none,       H8_null,        0,              0,               }, // 79 B?
  { none,       H8_null,        0,              0,               }, // 79 C?
  { none,       H8_null,        0,              0,               }, // 79 D?
  { none,       H8_null,        0,              0,               }, // 79 E?
  { none,       H8_null,        0,              0,               }, // 79 F?
};

//--------------------------------------------------------------------------
static const map_t map2_7A[16] =
{
  { P30A,       H8_mov,         L | i32,        rLL0,            }, // 7A 0?
  { P30A,       H8_add,         L | i32,        rLL0,            }, // 7A 1?
  { P30A,       H8_cmp,         L | i32,        rLL0,            }, // 7A 2?
  { P30A,       H8_sub,         L | i32,        rLL0,            }, // 7A 3?
  { P30A,       H8_or,          L | i32,        rLL0,            }, // 7A 4?
  { P30A,       H8_xor,         L | i32,        rLL0,            }, // 7A 5?
  { P30A,       H8_and,         L | i32,        rLL0,            }, // 7A 6?
  { none,       H8_null,        0,              0,               }, // 7A 7?
  { none,       H8_null,        0,              0,               }, // 7A 8?
  { none,       H8_null,        0,              0,               }, // 7A 9?
  { none,       H8_null,        0,              0,               }, // 7A A?
  { none,       H8_null,        0,              0,               }, // 7A B?
  { none,       H8_null,        0,              0,               }, // 7A C?
  { none,       H8_null,        0,              0,               }, // 7A D?
  { none,       H8_null,        0,              0,               }, // 7A E?
  { none,       H8_null,        0,              0,               }, // 7A F?
};

//--------------------------------------------------------------------------
static const map_t map3_01C05[8] =
{
  { P300,       H8_mulxs,       B | NEXT | rHB, rLW,             }, // 01 C0 50
  { none,       H8_null,        0,              0,               }, // 01 C0 51
  { P30A,       H8_mulxs,       W | NEXT | rHW, rLL0,            }, // 01 C0 52
  { none,       H8_null,        0,              0,               }, // 01 C0 53
  { none,       H8_null,        0,              0,               }, // 01 C0 54
  { none,       H8_null,        0,              0,               }, // 01 C0 55
  { none,       H8_null,        0,              0,               }, // 01 C0 56
  { none,       H8_null,        0,              0,               }, // 01 C0 57
};

//--------------------------------------------------------------------------
static const map_t map3_01D05[8] =
{
  { none,       H8_null,        0,              0,               }, // 01 D0 50
  { P300,       H8_divxs,       B | NEXT | rHB, rLW,             }, // 01 D0 51
  { none,       H8_null,        0,              0,               }, // 01 D0 52
  { P30A,       H8_divxs,       W | NEXT | rHW, rLL0,            }, // 01 D0 53
  { none,       H8_null,        0,              0,               }, // 01 D0 54
  { none,       H8_null,        0,              0,               }, // 01 D0 55
  { none,       H8_null,        0,              0,               }, // 01 D0 56
  { none,       H8_null,        0,              0,               }, // 01 D0 57
};

//--------------------------------------------------------------------------
static const map_t map3_01F06[8] =
{
  { none,       H8_null,        0,              0,               }, // 01 F0 60
  { none,       H8_null,        0,              0,               }, // 01 F0 61
  { none,       H8_null,        0,              0,               }, // 01 F0 62
  { none,       H8_null,        0,              0,               }, // 01 F0 63
  { P30A,       H8_or,          L | NEXT | rHL0,rLL0,            }, // 01 F0 64
  { P30A,       H8_xor,         L | NEXT | rHL0,rLL0,            }, // 01 F0 65
  { P30A,       H8_and,         L | NEXT | rHL0,rLL0,            }, // 01 F0 66
  { none,       H8_null,        0,              0,               }, // 01 F0 67
};

//--------------------------------------------------------------------------
static const map_t map3_7Cr06[8] =
{
  { none,       H8_null,        0,              0,               }, // 7C r0 60
  { none,       H8_null,        0,              0,               }, // 7C r0 61
  { none,       H8_null,        0,              0,               }, // 7C r0 62
  { P300,       H8_btst,        NEXT | rHB | zL,savedHL0,        }, // 7C r0 63
  { none,       H8_null,        0,              0,               }, // 7C r0 64
  { none,       H8_null,        0,              0,               }, // 7C r0 65
  { none,       H8_null,        0,              0,               }, // 7C r0 66
  { none,       H8_null,        0,              0,               }, // 7C r0 67
};

//--------------------------------------------------------------------------
static const map_t map3_7Cr07[8] =
{
  { none,       H8_null,        0,              0,               }, // 7C r0 70
  { none,       H8_null,        0,              0,               }, // 7C r0 71
  { none,       H8_null,        0,              0,               }, // 7C r0 72
  { P300,       H8_btst,        NEXT | i3 | zL, savedHL0,        }, // 7C r0 73
  { P300,       H8_bor,         NEXT | i3 | zL, savedHL0,        }, // 7C r0 74
  { P300,       H8_bxor,        NEXT | i3 | zL, savedHL0,        }, // 7C r0 75
  { P300,       H8_band,        NEXT | i3 | zL, savedHL0,        }, // 7C r0 76
  { P300,       H8_bld,         NEXT | i3 | zL, savedHL0,        }, // 7C r0 77
};

//--------------------------------------------------------------------------
static const map_t map3_7Dr06[8] =
{
  { P300,       H8_bset,        NEXT | rHB | zL,savedHL0,        }, // 7D r0 60
  { P300,       H8_bnot,        NEXT | rHB | zL,savedHL0,        }, // 7D r0 61
  { P300,       H8_bclr,        NEXT | rHB | zL,savedHL0,        }, // 7D r0 62
  { none,       H8_null,        0,              0,               }, // 7D r0 63
  { none,       H8_null,        0,              0,               }, // 7D r0 64
  { none,       H8_null,        0,              0,               }, // 7D r0 65
  { none,       H8_null,        0,              0,               }, // 7D r0 66
  { P300,       H8_bst,         NEXT | i3  | zL,savedHL0,        }, // 7D r0 67
};

//--------------------------------------------------------------------------
static const map_t map3_7Dr07[8] =
{
  { P300,       H8_bset,        NEXT | i3 | zL, savedHL0,        }, // 7D r0 70
  { P300,       H8_bnot,        NEXT | i3 | zL, savedHL0,        }, // 7D r0 71
  { P300,       H8_bclr,        NEXT | i3 | zL, savedHL0,        }, // 7D r0 72
  { none,       H8_null,        0,              0,               }, // 7D r0 73
  { none,       H8_null,        0,              0,               }, // 7D r0 74
  { none,       H8_null,        0,              0,               }, // 7D r0 75
  { none,       H8_null,        0,              0,               }, // 7D r0 76
  { none,       H8_null,        0,              0,               }, // 7D r0 77
};

//--------------------------------------------------------------------------
static const map_t map3_7Eaa6[8] =
{
  { none,       H8_null,        0,              0,               }, // 7E aa 60
  { none,       H8_null,        0,              0,               }, // 7E aa 61
  { none,       H8_null,        0,              0,               }, // 7E aa 62
  { P300,       H8_btst,        NEXT | rHB | zL,savedAA,         }, // 7E r0 63
  { none,       H8_null,        0,              0,               }, // 7E aa 64
  { none,       H8_null,        0,              0,               }, // 7E aa 65
  { none,       H8_null,        0,              0,               }, // 7E aa 66
  { none,       H8_null,        0,              0,               }, // 7E aa 67
};

//--------------------------------------------------------------------------
static const map_t map3_7Eaa7[8] =
{
  { none,       H8_null,        0,              0,               }, // 7E aa 70
  { none,       H8_null,        0,              0,               }, // 7E aa 71
  { none,       H8_null,        0,              0,               }, // 7E aa 72
  { P300,       H8_btst,        NEXT | i3 | zL, savedAA,         }, // 7E aa 73
  { P300,       H8_bor,         NEXT | i3 | zL, savedAA,         }, // 7E aa 74
  { P300,       H8_bxor,        NEXT | i3 | zL, savedAA,         }, // 7E aa 75
  { P300,       H8_band,        NEXT | i3 | zL, savedAA,         }, // 7E aa 76
  { P300,       H8_bld,         NEXT | i3 | zL, savedAA,         }, // 7E aa 77
};

//--------------------------------------------------------------------------
static const map_t map3_7Faa6[8] =
{
  { P300,       H8_bset,        NEXT | rHB | zL,savedAA,         }, // 7F aa 60
  { P300,       H8_bnot,        NEXT | rHB | zL,savedAA,         }, // 7F aa 61
  { P300,       H8_bclr,        NEXT | rHB | zL,savedAA,         }, // 7F aa 62
  { none,       H8_null,        0,              0,               }, // 7F aa 63
  { none,       H8_null,        0,              0,               }, // 7F aa 64
  { none,       H8_null,        0,              0,               }, // 7F aa 65
  { none,       H8_null,        0,              0,               }, // 7F aa 66
  { P300,       H8_bst,         NEXT | i3  | zL,savedAA,         }, // 7F aa 67
};

//--------------------------------------------------------------------------
static const map_t map3_7Faa7[8] =
{
  { P300,       H8_bset,        NEXT | i3 | zL, savedAA,         }, // 7F r0 70
  { P300,       H8_bnot,        NEXT | i3 | zL, savedAA,         }, // 7F r0 71
  { P300,       H8_bclr,        NEXT | i3 | zL, savedAA,         }, // 7F r0 72
  { none,       H8_null,        0,              0,               }, // 7F aa 73
  { none,       H8_null,        0,              0,               }, // 7F aa 74
  { none,       H8_null,        0,              0,               }, // 7F aa 75
  { none,       H8_null,        0,              0,               }, // 7F aa 76
  { none,       H8_null,        0,              0,               }, // 7F aa 77
};

//--------------------------------------------------------------------------
struct map2_pointer_t
{
  uchar prefix;
  const map_t *map;
};

static const map2_pointer_t map2[] =
{
  { 0x01, map2_01 },
  { 0x02, map2_02 },
  { 0x03, map2_03 },
  { 0x0A, map2_0A },
  { 0x0B, map2_0B },
  { 0x0F, map2_0F },
  { 0x10, map2_10 },
  { 0x11, map2_11 },
  { 0x12, map2_12 },
  { 0x13, map2_13 },
  { 0x17, map2_17 },
  { 0x1A, map2_1A },
  { 0x1B, map2_1B },
  { 0x1F, map2_1F },
  { 0x58, map2_58 },
  { 0x6A, map2_6A },
  { 0x79, map2_79 },
  { 0x7A, map2_7A },
};

struct map3_pointer_t
{
  uint32 prefix;
  uint32 mask;           // bit set means that the bit is ignored
  const map_t *map;
};

static const map3_pointer_t map3[] =
{
  { 0x01C05, 0x000, map3_01C05 },
  { 0x01D05, 0x000, map3_01D05 },
  { 0x01F06, 0x000, map3_01F06 },
  { 0x7C006, 0xF00, map3_7Cr06 },
  { 0x7C007, 0xF00, map3_7Cr07 },
  { 0x7D006, 0xF00, map3_7Dr06 },
  { 0x7D007, 0xF00, map3_7Dr07 },
  { 0x7E006, 0xFF0, map3_7Eaa6 },
  { 0x7E007, 0xFF0, map3_7Eaa7 },
  { 0x7F006, 0xFF0, map3_7Faa6 },
  { 0x7F007, 0xFF0, map3_7Faa7 },
};

static bool op_reg(const insn_t &insn, op_t &x, uint8 reg, ushort place, uint16 aux_assumed = aux_none);
static void op_imm(const insn_t &insn, op_t &x, uval_t val);
static void op_imm_8(op_t &x, uint8 val);
static void op_imm_3(op_t &x, uint8 val);
static bool op_aa_8(const insn_t &insn, op_t &x, uint8 val, op_dtype_t dtyp);
static bool op_reglist(op_t &x, uint8 reg, uint8 delta, bool is_inc);

//--------------------------------------------------------------------------------------
// possible address ranges for the Absolute Address operands
//
//--------------------------------------------------------------------------------------
// addressing   |  normal mode     |  advanced mode H8/300H  |   advanced mode H8S
//--------------+------------------+-------------------------+--------------------------
//   @aa:8      | H'FF00 to H'FFFF |   H'FFFF00 to H'FFFFFF  | H'FFFFFF00 to H'FFFFFFFF   (upper bits are 1s)
//--------------+------------------+-------------------------+--------------------------
//   @aa:16     | H'0000 to H'FFFF |   H'000000 to H'007FFF, | H'00000000 to H'00007FFF,  (sign extension)
//              |                  |   H'FF8000 to H'FFFFFF  | H'FFFF8000 to H'FFFFFFFF
//--------------+------------------+-------------------------+--------------------------
//   @aa:24     | H'0000 to H'FFFF |   H'000000 to H'FFFFFF  | H'00000000 to H'00FFFFFF   (upper bits are 0s)
//--------------+------------------+-------------------------+--------------------------
//   @aa:32     |                  |                         | H'00000000 to H'FFFFFFFF
//--------------+------------------+-------------------------+--------------------------

// NB: the 8-bit address already has upper bits set to 1s by the decoder
void h8_t::trimaddr(op_t &x)
{
  if ( x.szfl & disp_32 )
    return;
  bool mem_advanced = advanced() && !is_tiny();
  if ( x.szfl & disp_16 )
  {
    if ( x.type == o_mem && mem_advanced && (x.addr & 0x8000) != 0 )
      x.addr |= 0xFFFF0000; // sign extend
  }
  if ( !mem_advanced )
    x.addr &= 0x00FFFF; // 64K address space
  else if ( !is_h8s() )
    x.addr &= 0xFFFFFF; // 16-Mbyte address space
  x.addr = trunc_uval(x.addr);
}

//--------------------------------------------------------------------------
static void get_disp(insn_t &insn, op_t &x, bool disp32)
{
  x.offb = (uchar)insn.size;
  if ( !disp32 )
  {
    x.szfl |= disp_16;
    x.addr = short(insn.get_next_word());
  }
  else
  {
    x.szfl |= disp_32;
    x.addr = insn.get_next_dword();
  }
}

//--------------------------------------------------------------------------
static void opimm8(insn_t &insn, op_t &x)
{
  x.offb = (uchar)insn.size;
  x.type = o_imm;
  x.dtype = dt_byte;
  x.value = insn.get_next_byte();
}

//--------------------------------------------------------------------------
static void opreg8(op_t &x, uint16 reg)
{
  x.type = o_reg;
  x.dtype = dt_byte;
  x.reg = reg;
}

//--------------------------------------------------------------------------
void h8_t::opatHL(op_t &x, op_dtype_t dtyp)
{
  x.type = o_phrase;
  x.dtype = dtyp;
  x.reg = r0() + ((code>>4) & 7);
  x.phtype = ph_normal;
}

//--------------------------------------------------------------------------
static void oppost(op_t &x, uint16 reg, op_dtype_t dtyp)
{
  x.type   = o_phrase;
  x.dtype  = dtyp;
  x.reg    = reg;
  x.phtype = ph_post_inc;
}

//--------------------------------------------------------------------------
void h8_t::opdsp16(insn_t &insn, op_t &x, op_dtype_t dtyp)
{
  x.type = o_displ;
  x.dtype = dtyp;
  x.reg = r0() + ((code>>4) & 7);
  get_disp(insn, x, false);
  if ( is_off(get_flags(insn.ea), -1) )
    x.addr = ushort(x.addr);
}

//--------------------------------------------------------------------------
void h8_t::opdsp32(insn_t &insn, op_t &x, op_dtype_t dtyp)
{
  x.type = o_displ;
  x.dtype = dtyp;
  x.reg = r0() + ((code>>4) & 7);
  get_disp(insn, x, true);
}

//--------------------------------------------------------------------------
static void opreg(op_t &x, uint16 reg, op_dtype_t dtyp)
{
  switch ( dtyp )
  {
    case dt_byte:
      reg += R0H;
      break;
    case dt_word:
      reg += R0;
      break;
    case dt_dword:
      reg += ER0;
      break;
  }
  x.type = o_reg;
  x.dtype = dtyp;
  x.reg = reg;
}

//--------------------------------------------------------------------------
static char calc_dtyp(ushort flags)
{
  op_dtype_t dtyp;
  if ( flags & B )
    dtyp = dt_byte;
  else if ( flags & W )
    dtyp = dt_word;
  else if ( flags & L )
    dtyp = dt_dword;
  else
    dtyp = dt_code;
  return dtyp;
}

//--------------------------------------------------------------------------
bool h8_t::read_operand(insn_t &insn, op_t &x, ushort _flags)
{
  if ( _flags & NEXT )
    code = insn.get_next_byte();
  if ( (_flags & zL) && (code & 0x0F) != 0 )
    return false;
  if ( (_flags & zH) && (code & 0xF0) != 0 )
    return false;

  switch ( _flags & OPTYPE )
  {
    case 0:       // none
      break;
    case i3:      // immediate 3 bits
      x.type = o_imm;
      x.dtype = dt_byte;
      x.value = (code >> 4) & 7;
      break;
    case i4L:     // immediate 4 bits
      x.type = o_imm;
      x.dtype = dt_byte;
      x.value = code & 0xF;
      break;
    case i4H:     // immediate 4 bits
      x.type = o_imm;
      x.value = (code >> 4) & 0xF;
      x.dtype = calc_dtyp(_flags);
      break;
    case i8:      // immediate 8 bits
      opimm8(insn, x);
      break;
    case i16:     // immediate 16 bits
      x.offb = (uchar)insn.size;
      x.type = o_imm;
      x.dtype = dt_word;
      x.value = insn.get_next_word();
      break;
    case i32:     // immediate 32 bits
      if ( !advanced() )
        return false;
      x.offb = (uchar)insn.size;
      x.type = o_imm;
      x.dtype = dt_dword;
      x.value = insn.get_next_dword();
      break;
    case rCCR:    // CCR
      opreg8(x, CCR);
      break;
    case rEXR:    // EXR
      opreg8(x, EXR);
      break;
    case rVBR:
      x.type = o_reg;
      x.dtype = dt_dword;
      x.reg = VBR;
      break;
    case rSBR:
      x.type = o_reg;
      x.dtype = dt_dword;
      x.reg = SBR;
      break;
    case rLB:     // register number in low nibble  (r0l..r7h)
      opreg8(x, R0H + (code & 15));
      break;
    case rHB:     // register number in high nibble (r0l..r7h)
      opreg8(x, R0H + ((code>>4) & 15));
      break;
    case rLW:     // register number in low nibble  (r0..e7)
LW:
      x.type = o_reg;
      x.dtype = dt_word;
      x.reg = R0 + (code & 15);
      break;
    case rHW:     // register number in high nibble (r0..e7)
      x.type = o_reg;
      x.dtype = dt_word;
      x.reg = R0 + ((code>>4) & 15);
      break;
    case rV0:     // register number in low nibble
      if ( (code & 0x08) != 0 )
        return false;
      if ( !advanced() )
        goto LW;
      goto LL;
    case rLL0:    // register number in low nibble
      if ( (code & 0x08) != 0 )
        return false;
      if ( !advanced() )
        return false;
LL:
      x.type = o_reg;
      x.dtype = dt_dword;
      x.reg = ER0 + (code & 7);
      break;
    case rHL0:    // register number in high nibble
      if ( (code & 0x80) != 0 )
        return false;
      if ( !advanced() )
        return false;
HL:
      x.type = o_reg;
      x.dtype = dt_dword;
      x.reg = ER0 + ((code>>4) & 7);
      break;
    case rMACH:
      x.type = o_reg;
      x.dtype = dt_dword;
      x.reg = MACH;
      break;
    case rMACL:
      x.type = o_reg;
      x.dtype = dt_dword;
      x.reg = MACL;
      break;
    case savedHL0:      // @ERx
      if ( (code3 & 0x80) != 0 )
        return false;
      x.type = o_phrase;
      x.dtype = dt_dword;
      x.reg = r0() + ((code3>>4) & 7);
      x.phtype = ph_normal;
      break;
    case atHL:          // @ERx
      opatHL(x, calc_dtyp(_flags));
      break;
    case rLL1:    // register number in low nibble
      if ( (code & 0x08) == 0 )
        return false;
      if ( !advanced() )
        return false;
      goto LL;
    case rHL1:    // register number in high nibble
      if ( (code & 0x80) == 0 )
        return false;
      if ( !advanced() )
        return false;
      goto HL;
    case C1:      // constant #1
      x.type = o_imm;
      x.dtype = dt_byte;
      x.value = 1;
      break;
    case C2:      // constant #2
      x.type = o_imm;
      x.dtype = dt_byte;
      x.value = 2;
      break;
    case C4:      // constant #4
      x.type = o_imm;
      x.dtype = dt_byte;
      x.value = 4;
      break;
    case C8:      // constant #8
      x.type = o_imm;
      x.dtype = dt_byte;
      x.value = 8;
      break;
    case Cxh:     // hidden o_imm op
      x.type = o_imm;
      x.dtype = calc_dtyp(_flags);
      x.value = 1;
      x.clr_shown();
      break;
    case savedAA:
      x.type = o_mem;
      x.dtype = dt_byte;
      x.addr = ~0xFF | code3;
      trimaddr(x);
      break;
    case j8:
      x.offb = (uchar)insn.size;
      x.type = o_near;
      x.dtype = dt_code;
      {
        signed char disp = insn.get_next_byte();
        x.addr = insn.ip + insn.size + disp;
        x.addr &= ~1;
      }
      break;
    case j16:
      x.offb = (uchar)insn.size;
      x.type = o_near;
      x.dtype = dt_code;
      {
        signed short disp = insn.get_next_word();
        x.addr = insn.ip + insn.size + disp;
        x.addr &= ~1;
        x.szfl |= disp_16;
      }
      break;
    case aa8:
      if ( !is_h8sx() )
      {
        x.offb = (uchar)insn.size;
        x.type = o_mem;
        x.dtype = calc_dtyp(_flags);
        x.addr = ~0xFF | insn.get_next_byte();
        trimaddr(x);
      }
      else
      {
        uint8 val = insn.get_next_byte();
        op_aa_8(insn, x, val, calc_dtyp(_flags));
      }
      break;
    case ai8:
      x.offb = (uchar)insn.size;
      x.type = o_mem;
      x.memtype = mem_ind;
      x.dtype = advanced() ? dt_dword : dt_word;
      x.addr = insn.get_next_byte();
      break;
    case aa16:
      x.type = o_mem;
      x.dtype = calc_dtyp(_flags);
      get_disp(insn, x, false);
      trimaddr(x);
      break;
    case aa32:
      x.type = o_mem;
      x.dtype = calc_dtyp(_flags);
      get_disp(insn, x, true);
      break;
    case aa24:          // 24bit address (16bit in !advanced())
      x.offb = (uchar)insn.size;
      x.type = o_near;
      x.dtype = calc_dtyp(_flags);
      {
        uint32 high = insn.get_next_byte();
        if ( !advanced() && high != 0 )
          return false;
        x.addr = (high << 16) | insn.get_next_word();
        x.szfl |= advanced() ? disp_24 : disp_16;
      }
      break;
    case d16:           // @(d:16, ERs)
      opdsp16(insn, x, calc_dtyp(_flags));
      break;
    default:
      INTERR(10092);
  }
  return true;
}

//--------------------------------------------------------------------------
// 01 4?
bool h8_t::map014(insn_t &insn)
{
  switch ( code )
  {
    case 0x40:
      opreg8(insn.Op2, CCR);
      break;
    case 0x41:
      opreg8(insn.Op2, EXR);
      break;
    default:
      return false;
  }

  insn.itype = H8_ldc;
  code = insn.get_next_byte();
  op_dtype_t dtyp = dt_word;
  switch ( code )
  {
    case 0x04:
      insn.itype = H8_orc;
      dtyp = dt_byte;
      opimm8(insn, insn.Op1);
      break;
    case 0x05:
      insn.itype = H8_xorc;
      dtyp = dt_byte;
      opimm8(insn, insn.Op1);
      break;
    case 0x06:
      insn.itype = H8_andc;
      dtyp = dt_byte;
      opimm8(insn, insn.Op1);
      break;
    case 0x07:
      dtyp = dt_byte;
      opimm8(insn, insn.Op1);
      break;
    case 0x69:
      code = insn.get_next_byte();
      if ( code & 0x0F )
        return false;
      opatHL(insn.Op1, dtyp);
      break;
    case 0x6B:
      insn.Op1.type = o_mem;
      insn.Op1.dtype = dtyp;
      code = insn.get_next_byte();
      switch ( code & 0x70 )
      {
        case 0x00:
          get_disp(insn, insn.Op1, false);
          break;
        case 0x20:
          get_disp(insn, insn.Op1, true);
          break;
        default:
          return false;
      }
      trimaddr(insn.Op1);
      break;
    case 0x6D:
      code = insn.get_next_byte();
      if ( code & 0x0F )
        return false;
      oppost(insn.Op1, r0() + ((code>>4) & 7), dtyp);
      break;
    case 0x6F:
      code = insn.get_next_byte();
      if ( code & 0x0F )
        return false;
      opdsp16(insn, insn.Op1, dtyp);
      break;
    case 0x78:
      code = insn.get_next_byte();
      if ( code & 0x8F )
        return false;
      if ( insn.get_next_byte() != 0x6B )
        return false;
      code3 = insn.get_next_byte();
      if ( (code3 & 0x70) != 0x20 )
        return false;
      opdsp32(insn, insn.Op1, dtyp);
      code = code3;
      break;
    default:
      return false;
  }
  if ( insn.itype == H8_ldc )
    insn.auxpref = (dtyp == dt_word) ? aux_word : aux_byte;
  return true;
}

//--------------------------------------------------------------------------
// 6A 1?
// 6A 3?
bool h8_t::map4(insn_t &insn)
{
  uchar pref = code;
  insn.Op2.type = o_mem;
  insn.Op2.dtype = dt_byte;
  get_disp(insn, insn.Op2, pref >= 0x30);
  trimaddr(insn.Op2);
  uchar pcode = insn.get_next_byte();
  code = insn.get_next_byte();
  if ( code & 0x0F )
    return false;
  if ( pcode >= 0x60 && pcode <= 0x63 )
  {
    opreg8(insn.Op1, R0H + (code >> 4));
  }
  else
  {
    insn.Op1.type = o_imm;
    insn.Op1.dtype = dt_byte;
    insn.Op1.value = (code >> 4) & 7;
    if ( pcode >= 0x70 && pcode <= 0x73 )
      if ( code & 0x80 )
        return false;
  }
  switch ( pref )
  {
    case 0x10:
    case 0x30:
      switch ( pcode )
      {
        case 0x63:
        case 0x73:
          insn.itype = H8_btst;
          break;
        case 0x74:
          insn.itype = H8_bor;
          break;
        case 0x75:
          insn.itype = H8_bxor;
          break;
        case 0x76:
          insn.itype = H8_band;
          break;
        case 0x77:
          insn.itype = H8_bld;
          break;
        default:
          return false;
      }
      break;

    case 0x18:
    case 0x38:
      switch ( pcode )
      {
        case 0x60:
        case 0x70:
          insn.itype = H8_bset;
          break;
        case 0x61:
        case 0x71:
          insn.itype = H8_bnot;
          break;
        case 0x62:
        case 0x72:
          insn.itype = H8_bclr;
          break;
        case 0x67:
          insn.itype = H8_bst;
          break;
      }
      break;

    default:
      return false;
  }
  return true;
}

//--------------------------------------------------------------------------
inline void swap_Op1_Op2(insn_t &insn)
{
  op_t x = insn.Op1;
  insn.Op1 = insn.Op2;
  insn.Op2 = x;
  insn.Op1.n = 0;
  insn.Op2.n = 1;
}

//--------------------------------------------------------------------------
int h8_t::ana(insn_t *pinsn)
{
  insn_t &insn = *pinsn;
  code = insn.get_next_byte();
  uchar code0 = code;

  op_dtype_t dtyp;
  int idx = code;
  const map_t *m = map;
  int i = -1;
  bool noswap = false;
  while ( 1 )
  {
    uint32 p3;
    m += idx;
    if ( (m->proc & ptype) == 0 )
      return 0;
    insn.itype = m->itype;
    switch ( insn.itype )
    {
      case H8_null:
        return 0;

      case EXIT_40:
        return exit_40(insn);

      case EXIT_54:
        return exit_54_56(insn, H8_rts, H8_rtsl);

      case EXIT_56:
        return exit_54_56(insn, H8_rte, H8_rtel);

      case EXIT_59:
        return exit_59_5D(insn, H8_jmp, H8_bra);

      case EXIT_5D:
        return exit_59_5D(insn, H8_jsr, H8_bsr);

      case EXIT_7B:
        return exit_7B(insn);

      case H8_ldm:              // 01 [123]?
        if ( !advanced() )
          return false;
        if ( code & 15 )
          return 0;
        insn.Op2.nregs = (code >> 4) + 1;
        if ( insn.get_next_byte() != 0x6D )
          return 0;
        code = insn.get_next_byte();
        if ( (code & 0x78) != 0x70 )
          return 0;
        insn.auxpref = aux_long;                // .l
        insn.Op1.type   = o_phrase;
        insn.Op1.phtype = ph_post_inc;
        insn.Op1.dtype  = dt_dword;
        insn.Op1.phrase = ER7;
        insn.Op2.type   = o_reglist;
        insn.Op2.dtype  = dt_dword;
        insn.Op2.reg    = ER0 + (code & 7);
        if ( (code & 0x80) == 0 )
          insn.Op2.reg -= insn.Op2.nregs - 1;
        switch ( insn.Op2.nregs )
        {
          case 2:
            if ( insn.Op2.reg != ER0
              && insn.Op2.reg != ER2
              && insn.Op2.reg != ER4
              && insn.Op2.reg != ER6 )
            {
              return 0;
            }
            break;
          case 3:
          case 4:
            if ( insn.Op2.reg != ER0
              && insn.Op2.reg != ER4 )
            {
              return 0;
            }
            break;
        }
        break;

      case H8_mac:              // 01 6?
        if ( code & 15 )
          return 0;
        if ( insn.get_next_byte() != 0x6D )
          return 0;
        code = insn.get_next_byte();
        if ( code & 0x88 )
          return 0;
        oppost(insn.Op1, ER0 + ((code>>4) & 7),  dt_dword);
        oppost(insn.Op2, ER0 + ( code     & 7),  dt_dword);
        break;

      case H8_mov:
        if ( (m->op1 & MANUAL) == 0 )
        {
          if ( code0 == 0xC || code0 == 0xD )
            noswap = true;
          break;
        }
        switch ( code )
        {
          case 0x00:            // 01 0?
            if ( !advanced() )
              return false;
            insn.auxpref = aux_long;
            dtyp = dt_dword;
            switch ( insn.get_next_byte() )
            {
              case 0x69:
                code = insn.get_next_byte();
                if ( code & 0x08 )
                  return 0;
                opatHL(insn.Op1, dtyp);
                opreg(insn.Op2, code & 7, dtyp);
                break;
              case 0x6B:
                goto MOVABS;
              case 0x6D:
                goto MOVPOST;
              case 0x6F:
                code = insn.get_next_byte();
                opdsp16(insn, insn.Op1, dtyp);
                opreg(insn.Op2, code & 7, dtyp);
                break;
              case 0x78:
                code = insn.get_next_byte();
                if ( code & 0x0F )
                  return 0;
                if ( insn.get_next_byte() != 0x6B )
                  return 0;
                goto MOVDISP32;
              default:
                return 0;
            }
            break;
          case 0x6B:            // mov.w @aa, Rd
            if ( is_h8sx() )
              return h8sx_6B(insn);

            insn.auxpref = aux_word;
            dtyp = dt_word;
MOVABS:
            code = insn.get_next_byte();
            insn.Op1.type = o_mem;
            insn.Op1.dtype = dtyp;
            switch ( (code >> 4) & 7 )
            {
              case 0x0:
                get_disp(insn, insn.Op1, false);
                break;
              case 0x2:
                get_disp(insn, insn.Op1, true);
                break;
              default:
                return 0;
            }
            trimaddr(insn.Op1);
            opreg(insn.Op2, code & 15, dtyp);
            break;
          case 0x6C:            // byte  mov.b @ERs+, Rd
            dtyp = dt_byte;
            insn.auxpref = aux_byte;
            goto MOVPOST;
          case 0x6D:            // word  mov.w @ERs+, Rd
            dtyp = dt_word;
            insn.auxpref = aux_word;
MOVPOST:
            code = insn.get_next_byte();
            if ( dtyp == dt_dword && (code & 0x08) )
              return 0;
            switch ( code & 0xF0 )
            {
              case 0x70:        // pop
                insn.itype = H8_pop;
                opreg(insn.Op1, (code & 15), dtyp);
                break;
              case 0xF0:        // push
                insn.itype = H8_push;
                opreg(insn.Op1, (code & 15), dtyp);
                break;
              default:          // mov
                oppost(insn.Op1, r0() + ((code>>4) & 7), dtyp);
                opreg(insn.Op2, (code & 15), dtyp);
                break;
            }
            break;
          case 0x78:            // 78 ?0 6A 2?
            if ( is_h8sx() )
              return h8sx_78(insn);
            {
              code = insn.get_next_byte();
              if ( code & 0x8F )
                return 0;
              switch ( insn.get_next_byte() )
              {
                case 0x6A:        // byte
                  insn.auxpref = aux_byte;
                  dtyp = dt_byte;
                  break;
                case 0x6B:        // word
                  dtyp = dt_word;
                  insn.auxpref = aux_word;
                  break;
                default:
                  return 0;
              }
MOVDISP32:
              code3 = insn.get_next_byte();
              if ( (code3 & 0x70) != 0x20 )
                return 0;
              opdsp32(insn, insn.Op1, dtyp);
              opreg(insn.Op2, code3 & 15, dtyp);
              code = code3;       // to swap operands if required
            }
            break;
          default:
            return 0;
        }
        break;

      case H8_tas:
        if ( code != 0xE0 )
          return 0;
        if ( insn.get_next_byte() != 0x7B )
          return 0;
        code = insn.get_next_byte();
        if ( (code & 0x8F) != 0x0C )
          return 0;
        opatHL(insn.Op1, dt_byte);
        break;

      case H8_trapa:
        code = insn.get_next_byte();
        if ( (code & 0xC3) != 0x0 )
          return 0;
        insn.Op1.type = o_imm;
        insn.Op1.dtype = dt_byte;
        insn.Op1.value = code >> 4;
        break;

      case MAP2:
        if ( is_h8sx() )
        {
          switch ( code )
          {
            case 0x01: return h8sx_01(insn);
            case 0x03: return h8sx_03(insn);
            case 0x0A: return h8sx_0A(insn);
            case 0x0F: return h8sx_0F(insn);
            case 0x10: return h8sx_10(insn);
            case 0x11: return h8sx_11(insn);
            case 0x1A: return h8sx_1A(insn);
            case 0x1F: return h8sx_1F(insn);
            case 0x6A: return h8sx_6A(insn);
            case 0x79: return h8sx_79(insn);
            case 0x7A: return h8sx_7A(insn);
          }
        }
        for ( i=0; i < qnumber(map2); i++ )
          if ( map2[i].prefix == code )
            break;
        if ( i >= qnumber(map2) )
          INTERR(10093);
        m = map2[i].map;
        code = insn.get_next_byte();
        idx = code >> 4;
        continue;

      case MAP3:
        if ( is_h8sx() )
        {
          switch ( code )
          {
            case 0x7C: return h8sx_7C(insn);
            case 0x7D: return h8sx_7D(insn);
            case 0x7E: return h8sx_7E(insn);
            case 0x7F: return h8sx_7F(insn);
          }
        }
        if ( i == -1 )
        {
          code3 = insn.get_next_byte();
          p3 = (code << 12);
        }
        else
        {
          code3 = code;
          p3 = (map2[i].prefix << 12);
        }
        code = insn.get_next_byte();
        p3 |= (code3<<4) | (code>>4);
        for ( i=0; i < qnumber(map3); i++ )
          if ( map3[i].prefix == (p3 & ~map3[i].mask) )
            break;
        if ( i == qnumber(map3) )
          return 0;
        m = map3[i].map;
        idx = code & 7;
        continue;

      case MAP4:
        if ( !map4(insn) )
          return 0;
        break;

      case MAP014:
        if ( !map014(insn) )
          return 0;
        break;
    }
    break;
  }

  // m points to the target map entry
  if ( (m->op1 & X) == 0 ) switch ( m->op1 & CMD_SIZE )
  {
    case B: insn.auxpref = aux_byte; break;
    case W: insn.auxpref = aux_word; break;
    case L: insn.auxpref = aux_long; break;
    case V: insn.auxpref = advanced() ? aux_long : aux_word; break;
  }
  if ( !read_operand(insn, insn.Op1, m->op1) )
    return 0;
  if ( !read_operand(insn, insn.Op2, m->op2) )
    return 0;

  if ( code & 0x80 ) switch ( insn.itype )
  {
    case H8_bor:  insn.itype = H8_bior;   break;
    case H8_bxor: insn.itype = H8_bixor;  break;
    case H8_band: insn.itype = H8_biand;  break;
    case H8_bld:  insn.itype = H8_bild;   break;
    case H8_bst:  insn.itype = H8_bist;   break;
    case H8_btst:
    case H8_bset:
    case H8_bnot:
    case H8_bclr:
      if ( insn.Op1.type == o_imm )
        return 0;
      break;
    case H8_ldc:
      insn.itype = H8_stc;
      goto SWAP;
    case H8_ldm:
      insn.itype = H8_stm;
      [[fallthrough]];
    case H8_mov:
SWAP:
      if ( !noswap )
      {
        swap_Op1_Op2(insn);
        if ( insn.Op2.type == o_imm )
          return 0;
        if ( insn.Op2.type == o_phrase && insn.Op2.phtype == ph_post_inc )
          insn.Op2.phtype = ph_pre_dec;
      }
      break;
  }
  return insn.size;
}

//--------------------------------------------------------------------------
inline uint8 hi_ni(uint8 reg)
{
  return (reg >> 4) & 0xF;
}

//--------------------------------------------------------------------------
inline void shift_Op1(insn_t &insn)
{
  insn.Op2 = insn.Op1;
  insn.Op2.n = 1;
}

//--------------------------------------------------------------------------
int h8_t::exit_40(insn_t &insn)
{
  insn.itype = H8_bra;
  insn.Op1.offb = (uchar)insn.size;
  insn.Op1.type = o_near;
  insn.Op1.dtype = dt_code;

  signed char displ = insn.get_next_byte();
  if ( is_h8sx() && (displ & 1) != 0 )
    insn.itype = H8_bras;
  displ &= ~1;
  insn.Op1.addr = insn.ip + insn.size + displ;
  return insn.size;
}

//--------------------------------------------------------------------------
int h8_t::exit_54_56(insn_t &insn, uint8 rts, uint8 rtsl)
{
  code = insn.get_next_byte();

  if ( code == 0x70 )
  {
    insn.itype = rts;
    return insn.size;
  }
  else if ( is_h8sx() )
  {
    insn.itype = rtsl;
    uint8 hiNi = (code >> 4) & 0xF;
    if ( hiNi > 3 )
      return 0;
    bool res = hiNi == 0
             ? read_operand(insn, insn.Op1, rLL0)
             : op_reglist(insn.Op1, code & 0x0F, hiNi, true);
    insn.Op1.dtype = dt_code;
    return res ? insn.size : 0;
  }
  return 0;
}

//--------------------------------------------------------------------------
int h8_t::exit_59_5D(insn_t &insn, uint16 jump, uint16 branch)
{
  insn.itype = jump;
  code = insn.get_next_byte();
  if ( (code & 0x8F) == 0 )
  { // JMP @ERn
    return op_phrase(insn, insn.Op1, code >> 4, ph_normal, dt_code) ? insn.size : 0;
  }
  if ( !is_h8sx() )
    return 0;

  if ( (code & 0x80) != 0 )
  { // JMP @@vec:7
    insn.Op1.type = o_mem;
    insn.Op1.memtype = mem_vec7;
    insn.Op1.dtype = advanced() ? dt_dword : dt_word;
    insn.Op1.addr = /* (0x80 + (code & ~0x80)) */ code * (advanced() ? 4 : 2);
    return insn.size;
  }

  if ( code == 8 )
  { // JMP @aa:32
    return read_operand(insn, insn.Op1, W | aa32) ? insn.size : 0;
  }

  insn.itype = branch;
  insn.Op1.type = o_pcidx;
  insn.Op1.dtype = dt_code;
  regnum_t r;
  switch ( code & 0x0F )
  {
    case 5: // BRA Rn.B
      r = R0L;
      insn.Op1.szfl |= idx_byte;
      break;
    case 6: // BRA Rn.W
      r = R0;
      insn.Op1.szfl |= idx_word;
      break;
    case 7: // BRA ERn.L
      r = ER0;
      insn.Op1.szfl |= idx_long;
      break;
    default:
      return 0;
  }
  insn.Op1.reg = r + (code>>4);

  return insn.size;
}

//--------------------------------------------------------------------------
int h8_t::exit_7B(insn_t &insn)
{
  code = insn.get_next_byte();

  if ( code == 0x5C || code == 0xD4 )
  {
    insn.itype = H8_eepmov;
    insn.auxpref = code == 0x5C ? aux_byte : aux_word;
    return insn.get_next_word() == 0x598F ? insn.size : 0;
  }
  if ( !is_h8sx() )
    return 0;

  insn.itype = H8_movmd;
  switch ( code )
  {
    case 0x94:
      insn.auxpref = aux_byte;
      return insn.size;
    case 0xA4:
      insn.auxpref = aux_word;
      return insn.size;
    case 0xB4:
      insn.auxpref = aux_long;
      return insn.size;
    case 0x84:
      insn.itype = H8_movsd;
      insn.auxpref = aux_byte;
      return read_operand(insn, insn.Op1, j16) ? insn.size : 0;
  }
  return 0;
}

//--------------------------------------------------------------------------
static bool insn_or_xor_and(insn_t &insn);

// for insn_sh_neg() and others
#define SET_BYTE  0x0001        // .B insn set
#define SET_WORD  0x0002        // .W insn set
#define SET_LONG  0x0004        // .L insn set
#define SET_BIT_1 0x0010        // btst, bor, bxor, band, bld
#define SET_BIT_2 0x0020        // bclr, bset, bst, bnot

static bool insn_sh_neg(insn_t &insn, uint8 byte4, uint8 byte5, uint16 mask);
static bool insn_addcmp(insn_t &insn, uint8 bt);
static bool insn_addcmp_reg(insn_t &insn, uint8 byte2, uint8 byte3, bool swap, uint16 mask);
static bool insn_addcmp_i3(insn_t &insn, uint8 byte2, uint8 byte3);
static bool insn_addcmp_i8(insn_t &insn, uint8 byte4, uint8 byte5);
static bool insn_addx_reg(insn_t &insn, op_t &x, uint8 byte2, uint8 byte3, uint16 mask, ushort place);
static bool insn_addx_reg_Op1(insn_t &insn, uint8 byte2, uint8 byte3, uint16 mask, ushort place);
static bool insn_addx_i8(insn_t &insn, uint8 byte4, uint8 byte5);
static bool insn_bit(insn_t &insn, uint8 byte2, uint8 byte3, uint16 mask);

//--------------------------------------------------------------------------
int h8_t::h8sx_01(insn_t &insn)
{
  code = insn.get_next_byte();

  bool success = false;
  switch ( code )
  {
    case 0x00:
    case 0x01:
    case 0x02:
    case 0x03:
      insn.auxpref = aux_long;
      success = h8sx_010_00dd(insn);
      break;
    case 0x04:
    case 0x05:
    case 0x06:
    case 0x07:
      success = h8sx_010_01dd(insn, aux_long);
      break;
    case 0x08:
      insn.auxpref = aux_long;
      success = h8sx_0108(insn);
      break;
    case 0x09:
      insn.auxpref = aux_long;
      success = h8sx_0109_010A(insn, insn.Op1, insn.Op2);
      break;
    case 0x0A:
      insn.auxpref = aux_long;
      success = h8sx_0109_010A(insn, insn.Op2, insn.Op1);
      break;
    case 0x0D:
      insn.auxpref = aux_long;
      success = h8sx_010D(insn);
      break;
    case 0x0E:
      insn.auxpref = aux_long;
      success = h8sx_010E(insn);
      break;
    case 0x10:
    case 0x20:
    case 0x30:
      success = h8sx_ldm(insn);
      break;
    case 0x40:
      success = insn_ldc(insn, insn.get_next_byte(), CCR);
      break;
    case 0x41:
      success = h8sx_01_exr(insn);
      break;
    case 0x50:
    case 0x51:
    case 0x52:
    case 0x53:
      insn.auxpref = aux_word;
      success = h8sx_010_00dd(insn);
      break;
    case 0x54:
    case 0x55:
    case 0x56:
    case 0x57:
      success = h8sx_010_01dd(insn, aux_word);
      break;
    case 0x58:
      insn.auxpref = aux_word;
      success = h8sx_0108(insn);
      break;
    case 0x59:
      insn.auxpref = aux_word;
      success = h8sx_0109_010A(insn, insn.Op1, insn.Op2);
      break;
    case 0x5A:
      insn.auxpref = aux_word;
      success = h8sx_0109_010A(insn, insn.Op2, insn.Op1);
      break;
    case 0x5D:
      insn.auxpref = aux_word;
      success = h8sx_010D(insn);
      break;
    case 0x5E:
      insn.auxpref = aux_word;
      success = h8sx_010E(insn);
      break;
    case 0x60:
      success = insn_mac(insn);
      break;
    case 0x70:
    case 0x71:
    case 0x72:
    case 0x73:
      insn.auxpref = aux_byte;
      success = h8sx_010_00dd(insn);
      break;
    case 0x74:
    case 0x75:
    case 0x76:
    case 0x77:
      success = h8sx_010_01dd(insn, aux_byte);
      break;
    case 0x78:
      insn.auxpref = aux_byte;
      success = h8sx_0108(insn);
      break;
    case 0x79:
      insn.auxpref = aux_byte;
      success = h8sx_0109_010A(insn, insn.Op1, insn.Op2);
      break;
    case 0x7A:
      insn.auxpref = aux_byte;
      success = h8sx_0109_010A(insn, insn.Op2, insn.Op1);
      break;
    case 0x7D:
      insn.auxpref = aux_byte;
      success = h8sx_010D(insn);
      break;
    case 0x5F:
    case 0x7F:
      success = insn_mova(insn);
      break;
    case 0x80:
      insn.itype = H8_sleep;
      success = true;
      break;
    case 0xA0:
      insn.itype = H8_clrmac;
      success = true;
      break;
    case 0xE0:
      success = insn_tas(insn);
      break;
    case 0xF0:
      success = insn_or_xor_and(insn);
      break;
    default:
      success = h8sx_01_other(insn);
      break;
  }
  return success ? insn.size : 0;
}

//--------------------------------------------------------------------------
int h8_t::h8sx_03(insn_t &insn)
{
  code = insn.get_next_byte();
  switch ( hi_ni(code) )
  {
    case 0:
      insn.itype = H8_ldc;
      insn.auxpref = aux_byte;
      read_operand(insn, insn.Op2, rCCR);
      break;
    case 1:
      insn.itype = H8_ldc;
      insn.auxpref = aux_byte;
      read_operand(insn, insn.Op2, rEXR);
      break;
    case 2:
      insn.itype = H8_ldmac;
      read_operand(insn, insn.Op2, rMACH);
      break;
    case 3:
      insn.itype = H8_ldmac;
      read_operand(insn, insn.Op2, rMACL);
      break;
    case 6:
      insn.itype = H8_ldc;
      insn.auxpref = aux_long;
      read_operand(insn, insn.Op2, rVBR);
      break;
    case 7:
      insn.itype = H8_ldc;
      insn.auxpref = aux_long;
      read_operand(insn, insn.Op2, rSBR);
      break;
    case 8: // 100x
    case 9: // 100x
      {
        uint8 byte2 = insn.get_next_byte();
        uint8 byte3 = insn.get_next_byte();
        if ( byte2 == 0x10 )
          insn.itype = H8_shll;
        else if ( byte2 == 0x11 )
          insn.itype = H8_shlr;
        else
          return 0;
        switch ( byte3 >> 4 )
        {
          case 0: insn.auxpref = aux_byte; insn.Op1.dtype = dt_byte; break;
          case 1: insn.auxpref = aux_word; insn.Op1.dtype = dt_word; break;
          case 3: insn.auxpref = aux_long; insn.Op1.dtype = dt_dword; break;
          default: return 0;
        }
        insn.Op1.type = o_imm;
        insn.Op1.value = code & 0x1F;
        return op_reg(insn, insn.Op2, byte3, rL) ? insn.size : 0;
      }
    default:
      return 0;
  }
  return op_reg(insn, insn.Op1, code, rL, aux_long /* for ldmac */) ? insn.size : 0;
}

//--------------------------------------------------------------------------
static int op_imm3_reg(insn_t &insn, uint8 byte1)
{
  uint8 hiNi = (byte1 >> 4) & 7;
  bool isword = (byte1 & 0x80) == 0;   // else long

  bool res = true;
  if ( isword )
  {
    insn.auxpref = aux_word;
    insn.Op1.type = o_imm;
    insn.Op1.dtype = dt_word;
    insn.Op1.value = hiNi;
  }
  else
  {
    insn.auxpref = aux_long;
    if ( byte1 & 8 )
    {
      byte1 &= 7;
      insn.Op1.type = o_imm;
      insn.Op1.dtype = dt_dword;
      insn.Op1.value = hiNi;
    }
    else
    {
      res = op_reg(insn, insn.Op1, hiNi, rL);
    }
  }
  return res && op_reg(insn, insn.Op2, byte1, rL) ? insn.size : 0;
}

//--------------------------------------------------------------------------
int h8_t::h8sx_0A(insn_t &insn)
{
  code = insn.get_next_byte();

  if ( hi_ni(code) == 0 )
  {
    insn.itype = H8_inc;
    insn.auxpref = aux_byte;
    read_operand(insn, insn.Op1, B | Cxh);
    return op_reg(insn, insn.Op2, code, rL) ? insn.size : 0;
  }

  insn.itype = H8_add;
  return op_imm3_reg(insn, code);
}

//--------------------------------------------------------------------------
int h8_t::h8sx_0F(insn_t &insn)
{
  code = insn.get_next_byte();

  if ( hi_ni(code) == 0 )
  {
    insn.itype = H8_daa;
    return op_reg(insn, insn.Op1, code, rL, aux_byte) ? insn.size : 0;
  }

  insn.itype = H8_mov;
  return op_imm3_reg(insn, code);
}

//--------------------------------------------------------------------------
int h8_t::unpack_8bit_shift(const map_t *m, insn_t &insn, uint16 itype, uint16 itype2)
{
  code = insn.get_next_byte();
  uint8 hiNi = hi_ni(code);

  if ( hiNi == 3 )
  {
    insn.itype = itype;
    insn.auxpref = aux_long;
    if ( !op_reg(insn, insn.Op1, code & 7, rL) )
      return 0;
    shift_Op1(insn);
    op_imm(insn, insn.Op1, 4);
    if ( (code & 8) == 0 )
      insn.Op1.clr_shown();
    return insn.size;
  }
  else if ( hiNi == 7 )
  {
    insn.itype = itype;
    insn.auxpref = aux_long;
    op_imm(insn, insn.Op1, code & 8 ? 8 : 2);
    return op_reg(insn, insn.Op2, code & 7, rL) ? insn.size : 0;
  }
  else if ( hiNi == 0xF )
  {
    insn.itype = code & 8 ? itype : itype2;
    insn.auxpref = aux_long;
    op_imm(insn, insn.Op1, code & 8 ? 16 : 2);
    return op_reg(insn, insn.Op2, code & 7, rL) ? insn.size : 0;
  }

  return use_leaf_map(insn, m, hiNi) ? insn.size : 0;
}

//--------------------------------------------------------------------------
int h8_t::h8sx_10(insn_t &insn)
{
  return unpack_8bit_shift(&map2_10[0], insn, H8_shll, H8_shal);
}

//--------------------------------------------------------------------------
int h8_t::h8sx_11(insn_t &insn)
{
  return unpack_8bit_shift(&map2_11[0], insn, H8_shlr, H8_shar);
}

//--------------------------------------------------------------------------
int h8_t::h8sx_1A(insn_t &insn)
{
  code = insn.get_next_byte();
  uint8 hiNi = hi_ni(code);

  if ( hiNi == 0 )
  {
    insn.itype = H8_dec;
    insn.auxpref = aux_byte;
    read_operand(insn, insn.Op1, B | Cxh);
    return op_reg(insn, insn.Op2, code, rL) ? insn.size : 0;
  }

  insn.itype = H8_sub;
  return op_imm3_reg(insn, code);
}

//--------------------------------------------------------------------------
int h8_t::h8sx_1F(insn_t &insn)
{
  code = insn.get_next_byte();
  uint8 hiNi = hi_ni(code);

  if ( hiNi == 0 )
  {
    insn.itype = H8_das;
    return op_reg(insn, insn.Op1, code, rL, aux_byte) ? insn.size : 0;
  }

  insn.itype = H8_cmp;
  return op_imm3_reg(insn, code);
}

//--------------------------------------------------------------------------
int h8_t::h8sx_6A(insn_t &insn)
{
  code = insn.get_next_byte();
  uint8 hiNi = (code >> 4) & 0x0F;
  uint8 loNi = code & 0x0F;

  if ( code != 0x10
    && code != 0x15
    && code != 0x18
    && code != 0x30
    && code != 0x35
    && code != 0x38 )
  {
    return use_leaf_map(insn, &map2_6A_h8sx[0], hiNi) ? insn.size : 0;
  }
  if ( !read_operand(insn, insn.Op1, B | (hiNi == 1 ? aa16 : aa32)) )
    return 0;

  uint8 byte2 = insn.get_next_byte();
  uint8 byte3 = insn.get_next_byte();

  if ( loNi == 5 )
  {
    if ( byte3 & 0x0F )
      return 0;

    insn.auxpref = aux_byte;
    return op_from_byte(insn, insn.Op2, byte2)
        && insn_addcmp(insn, byte3) ? insn.size : 0;
  }
  else if ( loNi == 0 )
  {
    return insn_addcmp_reg(insn, byte2, byte3, false, SET_BYTE)
        || insn_bit(insn, byte2, byte3, SET_BIT_1)
        || insn_bra(insn, byte2, byte3)
        || insn_bfld_bfst(insn, byte2, byte3, true) ? insn.size : 0;
  }
  // ( loNi == 8 )
  return insn_sh_neg(insn, byte2, byte3, SET_BYTE)
      || insn_addcmp_i8(insn, byte2, byte3)
      || insn_addcmp_reg(insn, byte2, byte3, true, SET_BYTE)
      || insn_bit(insn, byte2, byte3, SET_BIT_2)
      || insn_bra(insn, byte2, byte3)
      || insn_bfld_bfst(insn, byte2, byte3, false) ? insn.size : 0;
}

//--------------------------------------------------------------------------
int h8_t::h8sx_6B(insn_t &insn)
{
  code = insn.get_next_byte();
  uint8 hiNi = (code >> 4) & 0x0F;
  uint8 loNi = code & 0x0F;

  if ( code != 0x10
    && code != 0x15
    && code != 0x18
    && code != 0x30
    && code != 0x35
    && code != 0x38 )
    return use_leaf_map(insn, &map2_6B_h8sx[0], hiNi) ? insn.size : 0;

  if ( !read_operand(insn, insn.Op1, W | (hiNi == 1 ? aa16 : aa32)) )
    return 0;

  uint8 byte2 = insn.get_next_byte();
  uint8 byte3 = insn.get_next_byte();

  if ( loNi == 5 )
  {
    if ( byte3 & 0x0F )
      return 0;

    insn.auxpref = aux_word;
    return op_from_byte(insn, insn.Op2, byte2)
        && insn_addcmp(insn, byte3) ? insn.size : 0;
  }
  else if ( loNi == 0 )
  {
    return insn_addcmp_reg(insn, byte2, byte3, false, SET_WORD) ? insn.size : 0;
  }
  // ( loNi == 8 )
  return insn_addcmp_reg(insn, byte2, byte3, true, SET_WORD)
      || insn_addcmp_i3(insn, byte2, byte3)
      || insn_sh_neg(insn, byte2, byte3, SET_WORD) ? insn.size : 0;
}

//--------------------------------------------------------------------------
int h8_t::h8sx_78(insn_t &insn)
{
  code = insn.get_next_byte();
  uint8 hiNi = hi_ni(code);
  uint8 loNi = code & 0x0F;

  if ( loNi > 9 )
    return 0;

  uint8 byte2 = insn.get_next_byte();
  uint8 byte3 = insn.get_next_byte();

  if ( loNi <= 7 )
  {
    if ( byte2 == 0x6A )
    {
      insn.auxpref = aux_byte;
      if ( hiNi & 8 )
        return 0;
    }
    else if ( byte2 == 0x6B )
    {
      insn.auxpref = hiNi & 8 ? aux_long : aux_word;
      hiNi &= ~8;
    }
    else
      return 0;

    if ( !op_displ_regidx(insn, insn.Op1, loNi, true, hiNi) )
      return 0;

    if ( loNi <= 3 )
    {
      insn.itype = H8_mov;
      op_reg(insn, insn.Op2, byte3, rL);
      bool swap;
      switch ( byte3 & 0xF0 )
      {
        case 0xA0: swap = true; break;
        case 0x20: swap = false; break;
        default: return 0;
      }
      if ( swap )
        swap_Op1_Op2(insn);
      return insn.size;
    }
    // 3 < loNi <= 7
    uint8 byte4 = insn.get_next_byte();
    uint8 byte5 = insn.get_next_byte();

    if ( byte3 == 0x28 )
    {
      return insn_sh_neg(insn, byte4, byte5, SET_BYTE | SET_WORD | SET_LONG)
          || insn_addcmp_i8(insn, byte4, byte5) ? insn.size : 0;
    }
    // else if ( byte3 == 0x24 ) doc error?
    else if ( byte3 == 0x2C )
    {
      if ( byte5 & 0x0F )
        return 0;
      return op_from_byte(insn, insn.Op2, byte4)
          && insn_addcmp(insn, byte5) ? insn.size : 0;
    }

    return 0;
  } // loNi <= 7

  if ( byte2 == 0x7A )
    return insn_mova_reg(insn, byte3, hi_ni(code), false);

  if ( loNi == 8 )
  {
    if ( byte2 == 0x10 )
      insn.itype = H8_shll;
    else if ( byte2 == 0x11 )
      insn.itype = H8_shlr;
    else
      return 0;
    switch ( byte3 & 0xF0 )
    {
      case 0x00: insn.auxpref = aux_byte; break;
      case 0x10: insn.auxpref = aux_word; break;
      case 0x30: insn.auxpref = aux_long; break;
      default: return 0;
    }
    return read_operand(insn, insn.Op1, rHB)
        && op_reg(insn, insn.Op2, byte3, rL) ? insn.size : 0;
  }

  return 0;
}

//--------------------------------------------------------------------------
int h8_t::h8sx_79(insn_t &insn)
{
  code = insn.get_next_byte();
  uint8 hiNi = (code >> 4) & 0xF;

  if ( hiNi <= 6 )
    return use_leaf_map(insn, &map2_79[0], hiNi) ? insn.size : 0;

  insn.itype = H8_mov;
  insn.auxpref = aux_word;
  if ( !read_operand(insn, insn.Op1, i16) )
    return 0;

  uint8 byte2 = insn.get_next_byte();
  uint8 byte3 = insn.get_next_byte();
  if ( byte3 != 0 )
    return 0;

  return op_from_byte(insn, insn.Op2, byte2) ? insn.size : 0;
}

//--------------------------------------------------------------------------
int h8_t::h8sx_7A(insn_t &insn)
{
  code = insn.get_next_byte();
  uint8 hiNi = (code >> 4) & 0xF;

  if ( hiNi <= 6 )
  {
    if ( hiNi == 0 )
      insn.itype = H8_mov;
    else if ( !insn_addcmp(insn, code) )
      return 0;
    insn.auxpref = aux_long;
    ushort op1_imm = code & 8 ? i16 : i32;
    return op_reg(insn, insn.Op2, code & 7, rL)
        && read_operand(insn, insn.Op1, op1_imm) ? insn.size : 0;
  }
  else if ( 8 <= hiNi && hiNi <= 0xD )
  {
    return insn_mova_reg(insn, code, 0, true);
  }
  else
  {
    insn.itype = H8_mov;
    insn.auxpref = aux_long;
    ushort op1_imm;
    if ( code == 0x74 )
      op1_imm = i32;
    else if ( code == 0x7C )
      op1_imm = i16;
    else
      return 0;
    if ( !read_operand(insn, insn.Op1, op1_imm) )
      return 0;

    uint8 byte2 = insn.get_next_byte();
    uint8 byte3 = insn.get_next_byte();
    if ( byte3 != 0 )
      return 0;

    return op_from_byte(insn, insn.Op2, byte2) ? insn.size : 0;
  }
}

//--------------------------------------------------------------------------
int h8_t::h8sx_7C(insn_t &insn)
{
  code = insn.get_next_byte();

  bool isword = (code & 0x80) == 0x80;   // else - byte
  op_phrase(insn, insn.Op1, (code >> 4) & 0x07, ph_normal);
  uint8 loNi = code & 0x0F;

  uint8 byte2 = insn.get_next_byte();
  uint8 byte3 = insn.get_next_byte();

  if ( loNi == 5 )
  {
    insn.auxpref = isword ? aux_word : aux_byte;
    return op_from_byte(insn, insn.Op2, byte2)
        && insn_addcmp(insn, byte3) ? insn.size : 0;
  }

  if ( loNi == 1 && (byte2 == 0x09 || byte2 == 0x19)
    || loNi == 0 && (byte2 == 0x0E || byte2 == 0x1E) )
  {
    return insn_addx_reg(insn, insn.Op2, byte2, byte3, SET_BYTE | SET_WORD, rL | zH) ? insn.size : 0;
  }
  if ( loNi != 0 )
    return 0;

  return insn_addcmp_reg(insn, byte2, byte3, false, isword ? SET_WORD : SET_BYTE)
      || insn_bit(insn, byte2, byte3, SET_BIT_1)
      || insn_bra(insn, byte2, byte3)
      || insn_bfld_bfst(insn, byte2, byte3, true) ? insn.size : 0;
}

//--------------------------------------------------------------------------
int h8_t::h8sx_7D(insn_t &insn)
{
  code = insn.get_next_byte();

  bool isword = (code & 0x80) == 0x80;   // else - byte
  op_phrase(insn, insn.Op1, (code >> 4) & 0x07, ph_normal);
  uint8 loNi = code & 0x0F;

  uint8 byte2 = insn.get_next_byte();
  uint8 byte3 = insn.get_next_byte();

  if ( loNi == 1 )
  {
    shift_Op1(insn);
    return insn_addx_reg(insn, insn.Op1, byte2, byte3, SET_WORD, rH | zL)
        || insn_addx_imm(insn, insn.Op1, byte2, byte3, SET_WORD, true) ? insn.size : 0;
  }
  if ( loNi != 0 )
    return 0;

  return insn_sh_neg(insn, byte2, byte3, (isword ? SET_WORD : SET_BYTE))
      || insn_bit(insn, byte2, byte3, SET_BIT_2)
      || !isword && insn_addx_i8(insn, byte2, byte3)
      || insn_addcmp_reg(insn, byte2, byte3, true, isword ? SET_WORD : SET_BYTE)
      || !isword && insn_addcmp_i8(insn, byte2, byte3)
      || insn_bfld_bfst(insn, byte2, byte3, false)
      || insn_addcmp_i3(insn, byte2, byte3)
      || insn_addx_reg_Op1(insn, byte2, byte3, SET_BYTE, rH | zL) ? insn.size : 0;
}

//--------------------------------------------------------------------------
int h8_t::h8sx_7E(insn_t &insn)
{
  code = insn.get_next_byte();
  op_aa_8(insn, insn.Op1, code, dt_byte);

  uint8 byte2 = insn.get_next_byte();
  uint8 byte3 = insn.get_next_byte();

  return insn_addcmp_reg(insn, byte2, byte3, false, SET_BYTE)
      || insn_bra(insn, byte2, byte3)
      || insn_bit(insn, byte2, byte3, SET_BIT_1)
      || insn_bfld_bfst(insn, byte2, byte3, true) ? insn.size : 0;
}

//--------------------------------------------------------------------------
int h8_t::h8sx_7F(insn_t &insn)
{
  code = insn.get_next_byte();
  op_aa_8(insn, insn.Op1, code, dt_byte);

  uint8 byte2 = insn.get_next_byte();
  uint8 byte3 = insn.get_next_byte();

  return insn_addcmp_reg(insn, byte2, byte3, true, SET_BYTE)
      || insn_addcmp_i8(insn, byte2, byte3)
      || insn_sh_neg(insn, byte2, byte3, SET_BYTE)
      || insn_bit(insn, byte2, byte3, SET_BIT_2)
      || insn_bfld_bfst(insn, byte2, byte3, false) ? insn.size : 0;
}

//--------------------------------------------------------------------------
bool h8_t::h8sx_010_00dd(insn_t &insn)
{
  uint8 byte2 = insn.get_next_byte();
  uint8 byte3 = insn.get_next_byte();

  if ( byte2 == 0x7A && code != 0x01
    || (byte2 == 0x09 || byte2 == 0x19 || byte2 == 0x79) && code != 0x51 )
  {
    return false;
  }

  if ( !op_reg(insn, insn.Op2, byte3, rL) )
    return false;

  if ( insn_addx_reg(insn, insn.Op1, byte2, byte3, SET_WORD | SET_LONG, rH) )
    return true;
  if ( insn_addx_imm(insn, insn.Op1, byte2, byte3, SET_WORD | SET_LONG, false) )
    return true;

  uint8 hiNi = (byte3 >> 4) & 7;
  bool swap = (byte3 & 0x80) != 0;

  if ( code == 0 && byte2 == 0x6D && hiNi == 7 )
  {
    // pop, push
    insn.itype = swap ? H8_push : H8_pop;
    insn.Op1 = insn.Op2; insn.Op1.n = 0;
    insn.Op2.type = 0;
    return true;
  }

  insn.itype = H8_mov;
  if ( !read_1st_op(insn, byte2, hiNi) )
    return false;
  if ( swap )
  {
    swap_Op1_Op2(insn);
    if ( insn.Op2.type == o_phrase && insn.Op2.phtype != ph_normal )
      insn.Op2.phtype ^= 3;  // swap pre- & post-, see h8.hpp
  }

  return true;
}

//--------------------------------------------------------------------------
bool h8_t::h8sx_010_01dd(insn_t &insn, uint16 postfix)
{
  uint8 byte2 = insn.get_next_byte();
  uint8 byte3 = insn.get_next_byte();

  if ( byte3 & 0x80 )
    return false;
  uint8 loNi = byte3 & 0xF;
  uint8 hiNi = byte3 >> 4;

  insn.auxpref = postfix;
  if ( !read_1st_op(insn, byte2, hiNi) )
    return false;

  uint8 byte4 = insn.get_next_byte();
  uint8 byte5 = insn.get_next_byte();

  switch ( loNi )
  {
    case 8:
      return postfix == aux_byte
           ? insn_addx_reg_Op1(insn, byte4, byte5, SET_BYTE, rH | zL)
          || insn_addcmp_i8(insn, byte4, byte5)
          || insn_addx_i8(insn, byte4, byte5)
          || insn_sh_neg(insn, byte4, byte5, SET_BYTE)
           : insn_sh_neg(insn, byte4, byte5, postfix == aux_word ? SET_WORD : SET_LONG);

    case 0xC:
      if ( (byte5 & 0x0F) != 0 )
        return false;
      return op_from_byte(insn, insn.Op2, byte4)
          && insn_addcmp(insn, byte5);

    case 0:
      if ( !(code == 0x76 && byte2 == 0x6C) )
        return false;
      return insn_addx_reg(insn, insn.Op2, byte4, byte5, SET_BYTE, rL | zH);
    case 1:
      if ( (code != 0x04 || byte2 != 0x69)
        && (code != 0x06 || byte2 != 0x6D)
        && (code != 0x54 || byte2 != 0x69)
        && (code != 0x56 || byte2 != 0x6D) )
      {
        return false;
      }
      return insn_addx_reg(insn, insn.Op2, byte4, byte5, SET_WORD | SET_LONG, rL | zH);

    case 0xD:
      if ( (code != 0x04 || byte2 != 0x69)
        && (code != 0x06 || byte2 != 0x6D)
        && (code != 0x54 || byte2 != 0x69)
        && (code != 0x56 || byte2 != 0x6D)
        && (code != 0x74 || byte2 != 0x68)
        && (code != 0x76 || byte2 != 0x6C) )
      {
        return false;
      }
      if ( byte5 == 0x10 )
        insn.itype = H8_addx;
      else if ( byte5 == 0x30 )
        insn.itype = H8_subx;
      else
        return false;

      if ( !( (byte4 & 0xF8) == 0 || (byte4 & 0xF0) == 0xA0 ) )
        return false;
      op_phrase(insn, insn.Op2, byte4 & 7, ph_normal);
      if ( (byte4 & 0xF0) == 0xA0 )
        insn.Op2.phtype = ph_post_dec;
      return insn.size != 0;

    case 9:
      if ( (code != 0x04 || byte2 != 0x69)
        && (code != 0x06 || byte2 != 0x6D)
        && (code != 0x54 || byte2 != 0x69)
        && (code != 0x56 || byte2 != 0x6D) )
      {
        return false;
      }

      shift_Op1(insn);
      return insn_addx_reg(insn, insn.Op1, byte4, byte5, SET_BYTE | SET_WORD | SET_LONG, rH | zL)
          || insn_addx_imm(insn, insn.Op1, byte4, byte5, SET_WORD | SET_LONG, true);
  }

  return false;
}

//--------------------------------------------------------------------------
bool h8_t::h8sx_0108(insn_t &insn)
{
  uint8 byte2 = insn.get_next_byte();
  uint8 byte3 = insn.get_next_byte();

  insn.itype = H8_mov;
  return op_from_byte(insn, insn.Op1, byte2)
      && op_from_byte(insn, insn.Op2, byte3);
}

//--------------------------------------------------------------------------
bool h8_t::h8sx_0109_010A(insn_t &insn, op_t &regop, op_t &genop)
{
  uint8 byte2 = insn.get_next_byte();
  uint8 byte3 = insn.get_next_byte();

  return insn_addcmp(insn, byte3)
      && op_reg(insn, regop, byte3, rL)
      && op_from_byte(insn, genop, byte2);
}

//--------------------------------------------------------------------------
bool h8_t::h8sx_010D(insn_t &insn)
{
  uint8 byte2 = insn.get_next_byte();

  insn.itype = H8_mov;
  return read_operand(insn, insn.Op1, i8)
      && op_from_byte(insn, insn.Op2, byte2);
}

//--------------------------------------------------------------------------
bool h8_t::h8sx_010E(insn_t &insn)
{
  uint8 byte2 = insn.get_next_byte();
  uint8 byte3 = insn.get_next_byte();

  return op_from_byte(insn, insn.Op2, byte2)
      && insn_addcmp(insn, byte3)
      && read_operand(insn, insn.Op1, byte3 & 8 ? i32 : i16);
}

//--------------------------------------------------------------------------
// any register range
bool h8_t::h8sx_ldm(insn_t &insn)
{
  uint8 byte2 = insn.get_next_byte();
  uint8 byte3 = insn.get_next_byte();
  if ( byte2 != 0x6D )
    return false;

  uint8 hiNi = byte3 & 0xF0;
  uint8 loNi = byte3 & 0x0F;
  if ( loNi & 8 )
    return false;

  uint8 delta = code >> 4;

  insn.auxpref = aux_long;
  if ( hiNi == 0x70 )
  {
    insn.itype = H8_ldm;
    return op_phrase(insn, insn.Op1, 7, ph_post_inc)
        && op_reglist(insn.Op2, loNi, delta, true);
  }
  else if ( hiNi == 0xF0 )
  {
    insn.itype = H8_stm;
    return op_reglist(insn.Op1, loNi, delta, false)
        && op_phrase(insn, insn.Op2, 7, ph_pre_dec);
  }
  return false;
}

//--------------------------------------------------------------------------
bool h8_t::insn_ldc(insn_t &insn, uint8 byte2, regnum_t reg)
{
  uint8 byte3 = insn.get_next_byte();
  uint8 hiNi = (byte3 & 0x70) >> 4;
  bool swap = (byte3 & 0x80) != 0;

  insn.itype = H8_ldc;
  insn.auxpref = aux_word;

  insn.Op2.type = o_reg;
  insn.Op2.dtype = dt_word;
  insn.Op2.reg = reg;

  if ( byte2 == 0x78 )
  {
    if ( byte3 & 0x8F )
      return false;

    uint16 opcode3 = insn.get_next_word();
    if ( opcode3 == 0x6BA0 )
      swap = true;
    else if ( opcode3 == 0x6B20 )
      swap = false;
    else
      return false;
    code = byte3;
    opdsp32(insn, insn.Op1, dt_word);
  }
  else
  {
    if ( !read_1st_op(insn, byte2, hiNi) )
      return false;
  }

  if ( swap )
  {
    insn.itype = H8_stc;
    swap_Op1_Op2(insn);
    if ( insn.Op2.type == o_phrase && insn.Op2.phtype != ph_normal )
      insn.Op2.phtype ^= 3;  // swap pre- & post-, see h8.hpp
  }
  return true;
}

//--------------------------------------------------------------------------
bool h8_t::h8sx_01_exr(insn_t &insn)
{
  uint8 byte2 = insn.get_next_byte();

  if ( byte2 == 4 )
  {
    insn.itype = H8_orc;
  }
  else if ( byte2 == 5 )
  {
    insn.itype = H8_xorc;
  }
  else if ( byte2 == 6 )
  {
    insn.itype = H8_andc;
  }
  else if ( byte2 == 7 )
  {
    insn.itype = H8_ldc;
    insn.auxpref = aux_byte;
  }
  else
  {
    code = 0x40;
    return insn_ldc(insn, byte2, EXR);
  }

  insn.Op2.type = o_reg;
  insn.Op2.dtype = dt_word;
  insn.Op2.reg = EXR;
  return read_operand(insn, insn.Op1, i8);
}

//--------------------------------------------------------------------------
bool h8_t::insn_mac(insn_t &insn)
{
  uint8 byte2 = insn.get_next_byte();
  uint8 byte3 = insn.get_next_byte();

  if ( byte2 != 0x6D && (byte3 & 0x88) != 0 )
    return 0;

  insn.itype = H8_mac;
  return op_phrase(insn, insn.Op1, byte3 >> 4, ph_post_inc)
      && op_phrase(insn, insn.Op2, byte3 & 0x0F, ph_post_inc);
}

//--------------------------------------------------------------------------
static bool insn_mova_op(insn_t &insn, uint8 opcode)
{
  switch ( (opcode >> 4) & 0xF )
  {
    case 0x8:
      insn.itype     = H8_movab;
      insn.Op1.dtype = dt_byte;
      insn.Op1.szfl |= idx_byte;
      break;
    case 0x9:
      insn.itype     = H8_movab;
      insn.Op1.dtype = dt_byte;
      insn.Op1.szfl |= idx_word;
      break;
    case 0xA:
      insn.itype     = H8_movaw;
      insn.Op1.dtype = dt_word;
      insn.Op1.szfl |= idx_byte;
      break;
    case 0xB:
      insn.itype     = H8_movaw;
      insn.Op1.dtype = dt_word;
      insn.Op1.szfl |= idx_word;
      break;
    case 0xC:
      insn.itype     = H8_moval;
      insn.Op1.dtype = dt_dword;
      insn.Op1.szfl |= idx_byte;
      break;
    case 0xD:
      insn.itype     = H8_moval;
      insn.Op1.dtype = dt_dword;
      insn.Op1.szfl |= idx_word;
      break;
    default:
      return false;
  }
  return true;
}

//--------------------------------------------------------------------------
bool h8_t::insn_mova(insn_t &insn)
{
  uint8 byte2 = insn.get_next_byte();
  uint8 byte3 = insn.get_next_byte();

  if ( !insn_mova_op(insn, byte3) )
    return false;

  op_t ea;
  memset(&ea, 0, sizeof(ea));
  insn.auxpref = insn.Op1.szfl & idx_byte ? aux_byte : aux_word;
  if ( !op_from_byte(insn, ea, byte2) )
    return false;
  insn.auxpref = aux_none;

  byte3 & 8 ? opdsp32(insn, insn.Op1, insn.Op1.dtype) : opdsp16(insn, insn.Op1, insn.Op1.dtype);

  insn.Op1.idxt = ea.type;
  insn.Op1.offo = ea.offb;
  insn.Op1.phrase = ea.phrase;
  insn.Op1.idxdt = ea.phtype;
  insn.Op1.value = ea.addr;
  insn.Op1.idxsz = ea.szfl;
  if ( insn.Op1.idxt == o_displ
    || insn.Op1.idxt == o_mem )
  {
    insn.Op1.flags |= OF_OUTER_DISP;
  }

  insn.Op1.displtype = dt_movaop1;

  insn.auxpref = aux_long;
  return op_reg(insn, insn.Op2, byte3 & 7, rL);
}

//--------------------------------------------------------------------------
int h8_t::insn_mova_reg(insn_t &insn, uint8 opcode, uint8 rs, bool is_reg_equal)
{
  if ( !insn_mova_op(insn, opcode) )
    return 0;

  opcode & 8 ? opdsp16(insn, insn.Op1, insn.Op1.dtype) : opdsp32(insn, insn.Op1, insn.Op1.dtype);

  insn.Op1.idxt = o_reg;
  rs = is_reg_equal ? opcode & 7 : rs & 0xF;
  insn.Op1.reg = (insn.Op1.szfl & idx_byte ? (is_reg_equal ? R0L : R0H) : R0)
                + (is_reg_equal ? opcode & 7 : rs & 0xF);
  insn.Op1.idxsz = insn.Op1.szfl;

  insn.Op1.displtype = dt_movaop1;
  insn.Op1.dtype = dt_dword;

  insn.auxpref = aux_long;
  return op_reg(insn, insn.Op2, opcode & 7, rL) ? insn.size : 0;
}

//--------------------------------------------------------------------------
bool h8_t::insn_tas(insn_t &insn)
{
  uint8 byte2 = insn.get_next_byte();
  uint8 byte3 = insn.get_next_byte();

  if ( !(byte2 == 0x7B && (byte3 & 0x8F) == 0x0C) )
    return false;

  insn.itype = H8_tas;
  return op_phrase(insn, insn.Op1, byte3 >> 4, ph_normal);
}

//--------------------------------------------------------------------------
static bool insn_or_xor_and(insn_t &insn)
{
  uint8 byte2 = insn.get_next_byte();
  uint8 byte3 = insn.get_next_byte();
  if ( byte3 & 0x88 )
    return false;

  if ( byte2 == 0x64 )
    insn.itype = H8_or;
  else if ( byte2 == 0x65 )
    insn.itype = H8_xor;
  else if ( byte2 == 0x66 )
    insn.itype = H8_and;
  else
    return false;

  insn.auxpref = aux_long;
  return op_reg(insn, insn.Op1, byte3, rH)
      && op_reg(insn, insn.Op2, byte3, rL);
}

//--------------------------------------------------------------------------
bool h8_t::h8sx_01_other(insn_t &insn)
{
  uint8 byte2 = insn.get_next_byte();
  uint8 byte3 = insn.get_next_byte();

  uint8 byte1 = code;
  code = byte3;
  switch ( byte1 )
  {
    case 0xC0:
      insn.itype = H8_mulxs;
      if ( byte2 == 0x50 )
      {
        insn.auxpref = aux_byte;
        return read_operand(insn, insn.Op1, rHB)
            && read_operand(insn, insn.Op2, rLW);
      }
      else if ( byte2 == 0x52 )
      {
        insn.auxpref = aux_word;
        return read_operand(insn, insn.Op1, rHW)
            && read_operand(insn, insn.Op2, rLL0);
      }
      return false;

    case 0xD0:
      insn.itype = H8_divxs;
      if ( byte2 == 0x51 )
      {
        insn.auxpref = aux_byte;
        return read_operand(insn, insn.Op1, rHB)
            && read_operand(insn, insn.Op2, rLW);
      }
      else if ( byte2 == 0x53 )
      {
        insn.auxpref = aux_word;
        return read_operand(insn, insn.Op1, rHW)
            && read_operand(insn, insn.Op2, rLL0);
      }
      return false;

    case 0xC2:
      insn.itype = H8_muls;
      if ( byte2 == 0x50 )
      {
        insn.auxpref = aux_word;
        return read_operand(insn, insn.Op1, rHW)
            && read_operand(insn, insn.Op2, rLW);
      }
      else if ( byte2 == 0x52 )
      {
        insn.auxpref = aux_long;
        return read_operand(insn, insn.Op1, rHL0)
            && read_operand(insn, insn.Op2, rLL0);
      }
      return false;

    case 0xD2:
      insn.itype = H8_divs;
      if ( byte2 == 0x51 )
      {
        insn.auxpref = aux_word;
        return read_operand(insn, insn.Op1, rHW)
            && read_operand(insn, insn.Op2, rLW);
      }
      else if ( byte2 == 0x53 )
      {
        insn.auxpref = aux_long;
        return read_operand(insn, insn.Op1, rHL0)
            && read_operand(insn, insn.Op2, rLL0);
      }
      return false;

    case 0xC3:
      if ( byte2 != 0x52 )
        return false;
      insn.itype = H8_mulsu;
      insn.auxpref = aux_long;
      return read_operand(insn, insn.Op1, rHL0)
          && read_operand(insn, insn.Op2, rLL0);

    case 0xC4:
      insn.itype = H8_mulxs;
      if ( byte2 == 0x50 )
      {
        insn.auxpref = aux_byte;
        return read_operand(insn, insn.Op1, B | i4H)
            && read_operand(insn, insn.Op2, rLW);
      }
      else if ( byte2 == 0x52 )
      {
        insn.auxpref = aux_word;
        return read_operand(insn, insn.Op1, W | i4H)
            && read_operand(insn, insn.Op2, rLL0);
      }
      return false;

    case 0xD4:
      insn.itype = H8_divxs;
      if ( byte2 == 0x51 )
      {
        insn.auxpref = aux_byte;
        return read_operand(insn, insn.Op1, B | i4H)
            && read_operand(insn, insn.Op2, rLW);
      }
      else if ( byte2 == 0x53 )
      {
        insn.auxpref = aux_word;
        return read_operand(insn, insn.Op1, W | i4H)
            && read_operand(insn, insn.Op2, rLL0);
      }
      return false;

    case 0xC6:
      insn.itype = H8_muls;
      if ( byte2 == 0x50 )
      {
        insn.auxpref = aux_word;
        return read_operand(insn, insn.Op1, W | i4H)
            && read_operand(insn, insn.Op2, rLW);
      }
      else if ( byte2 == 0x52 )
      {
        insn.auxpref = aux_long;
        return read_operand(insn, insn.Op1, L | i4H)
            && read_operand(insn, insn.Op2, rLL0);
      }
      return false;

    case 0xD6:
      insn.itype = H8_divs;
      if ( byte2 == 0x51 )
      {
        insn.auxpref = aux_word;
        return read_operand(insn, insn.Op1, W | i4H)
            && read_operand(insn, insn.Op2, rLW);
      }
      else if ( byte2 == 0x53 )
      {
        insn.auxpref = aux_long;
        return read_operand(insn, insn.Op1, L | i4H)
            && read_operand(insn, insn.Op2, rLL0);
      }
      return false;

    case 0xC7:
      if ( byte2 != 0x52 )
        return false;
      insn.itype = H8_mulsu;
      insn.auxpref = aux_long;
      return read_operand(insn, insn.Op1, L | i4H)
          && read_operand(insn, insn.Op2, rLL0);

    case 0xCA:
      insn.itype = H8_mulu;
      if ( byte2 == 0x50 )
      {
        insn.auxpref = aux_word;
        return read_operand(insn, insn.Op1, rHW)
            && read_operand(insn, insn.Op2, rLW);
      }
      else if ( byte2 == 0x52 )
      {
        insn.auxpref = aux_long;
        return read_operand(insn, insn.Op1, rHL0)
            && read_operand(insn, insn.Op2, rLL0);
      }
      return false;

    case 0xDA:
      insn.itype = H8_divu;
      if ( byte2 == 0x51 )
      {
        insn.auxpref = aux_word;
        return read_operand(insn, insn.Op1, rHW)
            && read_operand(insn, insn.Op2, rLW);
      }
      else if ( byte2 == 0x53 )
      {
        insn.auxpref = aux_long;
        return read_operand(insn, insn.Op1, rHL0)
            && read_operand(insn, insn.Op2, rLL0);
      }
      return false;

    case 0xCB:
      if ( byte2 != 0x52 )
        return false;
      insn.itype = H8_muluu;
      insn.auxpref = aux_long;
      return read_operand(insn, insn.Op1, rHL0)
          && read_operand(insn, insn.Op2, rLL0);

    case 0xCC:
      insn.itype = H8_mulxu;
      if ( byte2 == 0x50 )
      {
        insn.auxpref = aux_byte;
        return read_operand(insn, insn.Op1, B | i4H)
            && read_operand(insn, insn.Op2, rLW);
      }
      else if ( byte2 == 0x52 )
      {
        insn.auxpref = aux_word;
        return read_operand(insn, insn.Op1, W | i4H)
            && read_operand(insn, insn.Op2, rLL0);
      }
      return false;

    case 0xDC:
      insn.itype = H8_divxu;
      if ( byte2 == 0x51 )
      {
        insn.auxpref = aux_byte;
        return read_operand(insn, insn.Op1, B | i4H)
            && read_operand(insn, insn.Op2, rLW);
      }
      else if ( byte2 == 0x53 )
      {
        insn.auxpref = aux_word;
        return read_operand(insn, insn.Op1, W | i4H)
            && read_operand(insn, insn.Op2, rLL0);
      }
      return false;

    case 0xCE:
      insn.itype = H8_mulu;
      if ( byte2 == 0x50 )
      {
        insn.auxpref = aux_word;
        return read_operand(insn, insn.Op1, W | i4H)
            && read_operand(insn, insn.Op2, rLW);
      }
      else if ( byte2 == 0x52 )
      {
        insn.auxpref = aux_long;
        return read_operand(insn, insn.Op1, L | i4H)
            && read_operand(insn, insn.Op2, rLL0);
      }
      return false;

    case 0xDE:
      insn.itype = H8_divu;
      if ( byte2 == 0x51 )
      {
        insn.auxpref = aux_word;
        return read_operand(insn, insn.Op1, W | i4H)
            && read_operand(insn, insn.Op2, rLW);
      }
      else if ( byte2 == 0x53 )
      {
        insn.auxpref = aux_long;
        return read_operand(insn, insn.Op1, L | i4H)
            && read_operand(insn, insn.Op2, rLL0);
      }
      return false;

    case 0xCF:
      if ( byte2 != 0x52 )
        return false;
      insn.itype = H8_muluu;
      insn.auxpref = aux_long;
      return read_operand(insn, insn.Op1, L | i4H)
          && read_operand(insn, insn.Op2, rLL0);
  }
  return false;
}

//--------------------------------------------------------------------------
inline op_dtype_t dtype_by_auxpref(const insn_t &insn)
{
  CASSERT(aux_byte == dt_byte + 1 && aux_word == dt_word + 1 && aux_long == dt_dword + 1);
  // x.dtype = insn.auxpref == aux_long ? dt_dword : insn.auxpref == aux_word ? dt_word : dt_byte;
  return op_dtype_t(insn.auxpref - 1);
}

//--------------------------------------------------------------------------
static bool sh_ops_imm(insn_t &insn, nameNum itype, uint16 ap, uint8 v, bool shown)
{
  insn.itype = itype;
  insn.auxpref = ap;
  shift_Op1(insn);
  insn.Op1.type = o_imm;
  insn.Op1.dtype = dtype_by_auxpref(insn);
  insn.Op1.value = v;
  if ( !shown )
    insn.Op1.clr_shown();
  return true;
}

//--------------------------------------------------------------------------
#define M1    if ( !(SET_BYTE & mask) ) return false
#define M2    if ( !(SET_WORD & mask) ) return false
#define M3    if ( !(SET_LONG & mask) ) return false
#define MB1   if ( !(SET_BIT_1 & mask) ) return false
#define MB2   if ( !(SET_BIT_2 & mask) ) return false

//--------------------------------------------------------------------------
static bool insn_sh_neg(insn_t &insn, uint8 byte4, uint8 byte5, uint16 mask)
{
  uint16 opcode2 = (byte4 << 8) | byte5;
  switch ( opcode2 )
  {
    case 0x1000: M1; return sh_ops_imm(insn, H8_shll, aux_byte, 1, false); // SHLL.B
    case 0x1040: M1; return sh_ops_imm(insn, H8_shll, aux_byte, 2, true);  // SHLL.B #2
    case 0x10A0: M1; return sh_ops_imm(insn, H8_shll, aux_byte, 4, true);  // SHLL.B #4
    case 0x1010: M2; return sh_ops_imm(insn, H8_shll, aux_word, 1, false); // SHLL.W
    case 0x1050: M2; return sh_ops_imm(insn, H8_shll, aux_word, 2, true);  // SHLL.W #2
    case 0x1020: M2; return sh_ops_imm(insn, H8_shll, aux_word, 4, true);  // SHLL.W #4
    case 0x1060: M2; return sh_ops_imm(insn, H8_shll, aux_word, 8, true);  // SHLL.W #8
    case 0x1030: M3; return sh_ops_imm(insn, H8_shll, aux_long, 1, false); // SHLL.L
    case 0x1070: M3; return sh_ops_imm(insn, H8_shll, aux_long, 2, true);  // SHLL.L #2
    case 0x1038: M3; return sh_ops_imm(insn, H8_shll, aux_long, 4, true);  // SHLL.L #4
    case 0x1078: M3; return sh_ops_imm(insn, H8_shll, aux_long, 8, true);  // SHLL.L #8
    case 0x10F8: M3; return sh_ops_imm(insn, H8_shll, aux_long, 16, true); // SHLL.L #16

    case 0x1100: M1; return sh_ops_imm(insn, H8_shlr, aux_byte, 1, false); // SHLR.B
    case 0x1140: M1; return sh_ops_imm(insn, H8_shlr, aux_byte, 2, true);  // SHLR.B #2
    case 0x11A0: M1; return sh_ops_imm(insn, H8_shlr, aux_byte, 4, true);  // SHLR.B #4
    case 0x1110: M2; return sh_ops_imm(insn, H8_shlr, aux_word, 1, false); // SHLR.W
    case 0x1150: M2; return sh_ops_imm(insn, H8_shlr, aux_word, 2, true);  // SHLR.W #2
    case 0x1120: M2; return sh_ops_imm(insn, H8_shlr, aux_word, 4, true);  // SHLR.W #4
    case 0x1160: M2; return sh_ops_imm(insn, H8_shlr, aux_word, 8, true);  // SHLR.W #8
    case 0x1130: M3; return sh_ops_imm(insn, H8_shlr, aux_long, 1, false); // SHLR.L
    case 0x1170: M3; return sh_ops_imm(insn, H8_shlr, aux_long, 2, true);  // SHLR.L #2
    case 0x1138: M3; return sh_ops_imm(insn, H8_shlr, aux_long, 4, true);  // SHLR.L #4
    case 0x1178: M3; return sh_ops_imm(insn, H8_shlr, aux_long, 8, true);  // SHLR.L #8
    case 0x11F8: M3; return sh_ops_imm(insn, H8_shlr, aux_long, 16, true); // SHLR.L #16

    case 0x1080: M1; return sh_ops_imm(insn, H8_shal, aux_byte, 1, false); // SHAL.B
    case 0x10C0: M1; return sh_ops_imm(insn, H8_shal, aux_byte, 2, true);  // SHAL.B #2
    case 0x1090: M2; return sh_ops_imm(insn, H8_shal, aux_word, 1, false); // SHAL.W
    case 0x10D0: M2; return sh_ops_imm(insn, H8_shal, aux_word, 2, true);  // SHAL.W #2
    case 0x10B0: M3; return sh_ops_imm(insn, H8_shal, aux_long, 1, false); // SHAL.L
    case 0x10F0: M3; return sh_ops_imm(insn, H8_shal, aux_long, 2, true);  // SHAL.L #2

    case 0x1180: M1; return sh_ops_imm(insn, H8_shar, aux_byte, 1, false); // SHAR.B
    case 0x11C0: M1; return sh_ops_imm(insn, H8_shar, aux_byte, 2, true);  // SHAR.B #2
    case 0x1190: M2; return sh_ops_imm(insn, H8_shar, aux_word, 1, false); // SHAR.W
    case 0x11D0: M2; return sh_ops_imm(insn, H8_shar, aux_word, 2, true);  // SHAR.W #2
    case 0x11B0: M3; return sh_ops_imm(insn, H8_shar, aux_long, 1, false); // SHAR.L
    case 0x11F0: M3; return sh_ops_imm(insn, H8_shar, aux_long, 2, true);  // SHAR.L #2

    case 0x1280: M1; return sh_ops_imm(insn, H8_rotl, aux_byte, 1, false); // ROTL.B
    case 0x12C0: M1; return sh_ops_imm(insn, H8_rotl, aux_byte, 2, true);  // ROTL.B #2
    case 0x1290: M2; return sh_ops_imm(insn, H8_rotl, aux_word, 1, false); // ROTL.W
    case 0x12D0: M2; return sh_ops_imm(insn, H8_rotl, aux_word, 2, true);  // ROTL.W #2
    case 0x12B0: M3; return sh_ops_imm(insn, H8_rotl, aux_long, 1, false); // ROTL.L
    case 0x12F0: M3; return sh_ops_imm(insn, H8_rotl, aux_long, 2, true);  // ROTL.L #2

    case 0x1380: M1; return sh_ops_imm(insn, H8_rotr, aux_byte, 1, false); // ROTR.B
    case 0x13C0: M1; return sh_ops_imm(insn, H8_rotr, aux_byte, 2, true);  // ROTR.B #2
    case 0x1390: M2; return sh_ops_imm(insn, H8_rotr, aux_word, 1, false); // ROTR.W
    case 0x13D0: M2; return sh_ops_imm(insn, H8_rotr, aux_word, 2, true);  // ROTR.W #2
    case 0x13B0: M3; return sh_ops_imm(insn, H8_rotr, aux_long, 1, false); // ROTR.L
    case 0x13F0: M3; return sh_ops_imm(insn, H8_rotr, aux_long, 2, true);  // ROTR.L #2

    case 0x1200: M1; return sh_ops_imm(insn, H8_rotxl, aux_byte, 1, false); // ROTXL.B
    case 0x1240: M1; return sh_ops_imm(insn, H8_rotxl, aux_byte, 2, true);  // ROTXL.B #2
    case 0x1210: M2; return sh_ops_imm(insn, H8_rotxl, aux_word, 1, false); // ROTXL.W
    case 0x1250: M2; return sh_ops_imm(insn, H8_rotxl, aux_word, 2, true);  // ROTXL.W #2
    case 0x1230: M3; return sh_ops_imm(insn, H8_rotxl, aux_long, 1, false); // ROTXL.L
    case 0x1270: M3; return sh_ops_imm(insn, H8_rotxl, aux_long, 2, true);  // ROTXL.L #2

    case 0x1300: M1; return sh_ops_imm(insn, H8_rotxr, aux_byte, 1, false); // ROTXR.B
    case 0x1340: M1; return sh_ops_imm(insn, H8_rotxr, aux_byte, 2, true);  // ROTXR.B #2
    case 0x1310: M2; return sh_ops_imm(insn, H8_rotxr, aux_word, 1, false); // ROTXR.W
    case 0x1350: M2; return sh_ops_imm(insn, H8_rotxr, aux_word, 2, true);  // ROTXR.W #2
    case 0x1330: M3; return sh_ops_imm(insn, H8_rotxr, aux_long, 1, false); // ROTXR.L
    case 0x1370: M3; return sh_ops_imm(insn, H8_rotxr, aux_long, 2, true);  // ROTXR.L #2

    case 0x17D0: M2; return sh_ops_imm(insn, H8_exts, aux_word, 1, false); // EXTS.W
    case 0x17F0: M3; return sh_ops_imm(insn, H8_exts, aux_long, 1, false); // EXTS.L
    case 0x17E0: M3; return sh_ops_imm(insn, H8_exts, aux_long, 2, true);  // EXTS.L #2

    case 0x1750: M2; return sh_ops_imm(insn, H8_extu, aux_word, 1, false); // EXTU.W
    case 0x1770: M3; return sh_ops_imm(insn, H8_extu, aux_long, 1, false); // EXTU.L
    case 0x1760: M3; return sh_ops_imm(insn, H8_extu, aux_long, 2, true);  // EXTU.L #2

    case 0x1700: M1; insn.itype = H8_not; insn.auxpref = aux_byte; return true; // NOT.B
    case 0x1710: M2; insn.itype = H8_not; insn.auxpref = aux_word; return true; // NOT.W
    case 0x1730: M3; insn.itype = H8_not; insn.auxpref = aux_long; return true; // NOT.L

    case 0x1780: M1; insn.itype = H8_neg; insn.auxpref = aux_byte; return true; // NEG.B
    case 0x1790: M2; insn.itype = H8_neg; insn.auxpref = aux_word; return true; // NEG.W
    case 0x17B0: M3; insn.itype = H8_neg; insn.auxpref = aux_long; return true; // NEG.L
  }

  return false;
}

//--------------------------------------------------------------------------
static bool insn_addcmp(insn_t &insn, uint8 bt)
{
  switch ( bt >> 4 )
  {
    case 0x1: insn.itype = H8_add; break;
    case 0x2: insn.itype = H8_cmp; break;
    case 0x3: insn.itype = H8_sub; break;
    case 0x4: insn.itype = H8_or ; break;
    case 0x5: insn.itype = H8_xor; break;
    case 0x6: insn.itype = H8_and; break;
    default: return false;
  }
  return true;
}

//--------------------------------------------------------------------------
static bool insn_addcmp_reg(insn_t &insn, uint8 byte2, uint8 byte3, bool swap, uint16 mask)
{
  switch ( byte2 )
  {
    case 0x08: M1; insn.auxpref = aux_byte; insn.itype = H8_add; break; // ADD.B
    case 0x09: M2; insn.auxpref = aux_word; insn.itype = H8_add; break; // ADD.W
    case 0x18: M1; insn.auxpref = aux_byte; insn.itype = H8_sub; break; // SUB.B
    case 0x19: M2; insn.auxpref = aux_word; insn.itype = H8_sub; break; // SUB.W
    case 0x1C: M1; insn.auxpref = aux_byte; insn.itype = H8_cmp; break; // CMP.B
    case 0x1D: M2; insn.auxpref = aux_word; insn.itype = H8_cmp; break; // CMP.W
    case 0x14: M1; insn.auxpref = aux_byte; insn.itype = H8_or ; break; // OR.B
    case 0x64: M2; insn.auxpref = aux_word; insn.itype = H8_or ; break; // OR.W
    case 0x15: M1; insn.auxpref = aux_byte; insn.itype = H8_xor; break; // XOR.B
    case 0x65: M2; insn.auxpref = aux_word; insn.itype = H8_xor; break; // XOR.W
    case 0x16: M1; insn.auxpref = aux_byte; insn.itype = H8_and; break; // AND.B
    case 0x66: M2; insn.auxpref = aux_word; insn.itype = H8_and; break; // AND.W
    default: return false;
  }

  bool res;
  if ( swap )
  {
    shift_Op1(insn);
    res = op_reg(insn, insn.Op1, byte3, rH | zL);
  }
  else
  {
    res = op_reg(insn, insn.Op2, byte3, rL | zH);
  }
  return res;
}

//--------------------------------------------------------------------------
static bool insn_addcmp_i3(insn_t &insn, uint8 byte2, uint8 byte3)
{
  if ( byte3 & 0x8F )
    return 0;

  switch ( byte2 )
  {
    case 0x0A: insn.auxpref = aux_word; insn.itype = H8_add; break; // ADD.W #xx:3
    case 0x1A: insn.auxpref = aux_word; insn.itype = H8_sub; break; // SUB.W #xx:3
    case 0x1F: insn.auxpref = aux_word; insn.itype = H8_cmp; break; // CMP.W #xx:3
    default: return false;
  }

  shift_Op1(insn);
  op_imm_3(insn.Op1, byte3);
  return true;
}

//--------------------------------------------------------------------------
static bool insn_addcmp_i8(insn_t &insn, uint8 byte4, uint8 byte5)
{
  switch ( byte4 )
  {
    case 0x80: insn.itype = H8_add; break;
    case 0xA0: insn.itype = H8_cmp; break;
    case 0xA1: insn.itype = H8_sub; break;
    case 0xC0: insn.itype = H8_or;  break;
    case 0xD0: insn.itype = H8_xor; break;
    case 0xE0: insn.itype = H8_and; break;
    default: return false;
  }

  shift_Op1(insn);

  insn.auxpref = aux_byte;
  insn.Op1.type  = o_imm;
  insn.Op1.dtype = dt_byte;
  insn.Op1.value = byte5;
  return true;
}

//--------------------------------------------------------------------------
static bool insn_addx_reg(insn_t &insn, op_t &x, uint8 byte2, uint8 byte3, uint16 mask, ushort place)
{
  switch ( byte2 )
  {
    case 0x0E: // ADDX.B
      M1;
      insn.auxpref = aux_byte;
      insn.itype = H8_addx;
      break;
    case 0x1E: // SUBX.B
      M1;
      insn.auxpref = aux_byte;
      insn.itype = H8_subx;
      break;

    case 0x09: // ADDX.W
      M2;
      insn.auxpref = aux_word;
      insn.itype = H8_addx;
      break;
    case 0x19: // SUBX.W
      M2;
      insn.auxpref = aux_word;
      insn.itype = H8_subx;
      break;

    case 0x0A: // ADDX.L
      insn.itype = H8_addx;
      goto ADDXL;
    case 0x1A: // SUBX.L
      insn.itype = H8_subx;
ADDXL:
      M3;
      if ( (byte3 & 0x80) != 0x80 )
        return false;
      byte3 &= ~0x80;
      insn.auxpref = aux_long;
      break;

    default:
      return false;
  }
  return op_reg(insn, x, byte3, place);
}

//--------------------------------------------------------------------------
static bool insn_addx_reg_Op1(insn_t &insn, uint8 byte2, uint8 byte3, uint16 mask, ushort place)
{
  op_t op;
  memset(&op, 0, sizeof(op));
  if ( !insn_addx_reg(insn, op, byte2, byte3, mask, place ) )
    return false;
  shift_Op1(insn);
  insn.Op1.type = op.type;
  insn.Op1.reg = op.reg;
  insn.Op1.dtype = op.dtype;
  return true;
}

//--------------------------------------------------------------------------
bool h8_t::insn_addx_imm(insn_t &insn, op_t &x, uint8 byte2, uint8 byte3, uint16 mask, bool check_byte3)
{
  if ( check_byte3 && (byte3 & 0x0F) != 0 )
    return false;

  switch ( byte3 & 0xF0 )
  {
    case 0x10:
      insn.itype = H8_addx;
      break;
    case 0x30:
      insn.itype = H8_subx;
      break;
    default:
      return false;
  }

  switch ( byte2 )
  {
    case 0x79:  // .W
      M2;
      insn.auxpref = aux_word;
      return read_operand(insn, x, i16);
    case 0x7A:  // .L
      M3;
      insn.auxpref = aux_long;
      return read_operand(insn, x, i32);
  }
  return false;
}

//--------------------------------------------------------------------------
static bool insn_addx_i8(insn_t &insn, uint8 byte4, uint8 byte5)
{
  switch ( byte4 )
  {
    case 0x90:
      insn.itype = H8_addx;
      break;
    case 0xB0:
      insn.itype = H8_subx;
      break;
    default:
      return false;
  }

  shift_Op1(insn);

  insn.auxpref = aux_byte;
  insn.Op1.type  = o_imm;
  insn.Op1.dtype = dt_byte;
  insn.Op1.value = byte5;
  return true;
}

//--------------------------------------------------------------------------
static bool insn_bit_reg(insn_t &insn, uint8 byte2, uint8 byte3, uint16 mask)
{
  switch ( byte2 )
  {
    case 0x60:
      MB2;
      switch ( byte3 & 0x0F )
      {
        case 0: insn.itype = H8_bset;   break;
        case 6: insn.itype = H8_bsetne; break;
        case 7: insn.itype = H8_bseteq; break;
        default: return false;
      }
      break;
    case 0x61:
      MB2;
      if ( byte3 & 0x0F )
        return false;
      insn.itype = H8_bnot;
      break;
    case 0x62:
      MB2;
      switch ( byte3 & 0x0F )
      {
        case 0: insn.itype = H8_bclr;   break;
        case 6: insn.itype = H8_bclrne; break;
        case 7: insn.itype = H8_bclreq; break;
        default: return false;
      }
      break;

    case 0x63:
      MB1;
      if ( byte3 & 0x0F )
        return false;
      insn.itype = H8_btst;
      break;
    default:
      return false;
  }

  shift_Op1(insn);
  return op_reg(insn, insn.Op1, byte3, rH, aux_byte);
}

//--------------------------------------------------------------------------
static bool insn_bit_i3(insn_t &insn, uint8 byte2, uint8 byte3, uint16 mask)
{
  switch ( byte2 )
  {
    case 0x67:
      MB2;
      switch ( byte3 & 0x8F )
      {
        case 0x00: insn.itype = H8_bst;   break;
        case 0x07: insn.itype = H8_bstz;  break;
        case 0x80: insn.itype = H8_bist;  break;
        case 0x87: insn.itype = H8_bistz; break;
        default: return false;
      }
      break;
    case 0x70:
      MB2;
      switch ( byte3 & 0x8F )
      {
        case 0x00: insn.itype = H8_bset;   break;
        case 0x06: insn.itype = H8_bsetne; break;
        case 0x07: insn.itype = H8_bseteq; break;
        default: return false;
      }
      break;
    case 0x71:
      MB2;
      if ( byte3 & 0x8F )
        return false;
      insn.itype = H8_bnot;
      break;
    case 0x72:
      MB2;
      switch ( byte3 & 0x8F )
      {
        case 0x00: insn.itype = H8_bclr;   break;
        case 0x06: insn.itype = H8_bclrne; break;
        case 0x07: insn.itype = H8_bclreq; break;
        default: return false;
      }
      break;

    case 0x73:
      MB1;
      if ( byte3 & 0x8F )
        return false;
      insn.itype = H8_btst;
      break;
    case 0x74:
      MB1;
      if ( byte3 & 0x0F )
        return false;
      insn.itype = byte3 & 0x80 ? H8_bior : H8_bor;
      break;
    case 0x75:
      MB1;
      if ( byte3 & 0x0F )
        return false;
      insn.itype = byte3 & 0x80 ? H8_bixor : H8_bxor;
      break;
    case 0x76:
      MB1;
      if ( byte3 & 0x0F )
        return false;
      insn.itype = byte3 & 0x80 ? H8_biand : H8_band;
      break;
    case 0x77:
      MB1;
      if ( byte3 & 0x0F )
        return false;
      insn.itype = byte3 & 0x80 ? H8_bild : H8_bld;
      break;
    default:
      return false;
  }
  shift_Op1(insn);
  op_imm_3(insn.Op1, byte3);
  return true;
}

//--------------------------------------------------------------------------
static bool insn_bit(insn_t &insn, uint8 byte2, uint8 byte3, uint16 mask)
{
  return insn_bit_reg(insn, byte2, byte3, mask)
      || insn_bit_i3(insn, byte2, byte3, mask);
}

//--------------------------------------------------------------------------
bool h8_t::insn_bra(insn_t &insn, uint8 byte2, uint8 byte3)
{
  if ( (byte2 & 0xF0) == 0x40 )
  {
    if ( byte3 & 1 )
      return 0;
    insn.itype = byte2 & 8 ? H8_brabs : H8_brabc;
    shift_Op1(insn);
    op_imm_8(insn.Op1, byte2 & 7);
    insn.Op3.type = o_near;
    insn.Op3.dtype = dt_code;
    insn.Op3.offb = (uchar)insn.size - 1;
    signed char disp = byte3;
    insn.Op3.addr = insn.ip + insn.size + disp;
    insn.Op3.addr &= ~1;
    return insn.size != 0;
  }

  if ( byte2 == 0x58 )
    insn.itype = byte3 & 0x80 ? H8_brabs : H8_brabc;
  else if ( byte2 == 0x5C )
    insn.itype = byte3 & 0x80 ? H8_bsrbs : H8_bsrbc;
  else
    return false;

  if ( byte3 & 0x0F )
    return false;
  shift_Op1(insn);
  op_imm_8(insn.Op1, (byte3 >> 4) & 7);
  return read_operand(insn, insn.Op3, j16);
}

//--------------------------------------------------------------------------
bool h8_t::insn_bfld_bfst(insn_t &insn, uint8 byte2, uint8 byte3, bool is_bfld)
{
  if ( (byte2 & 0xF0) != 0xF0 )
    return false;

  if ( is_bfld )
  {
    insn.itype = H8_bfld;
    shift_Op1(insn);
    op_imm_8(insn.Op1, byte3);
    code = byte2;
    return read_operand(insn, insn.Op3, rLB);
  }
  else
  {
    insn.itype = H8_bfst;
    insn.Op3 = insn.Op1; insn.Op3.n = 2;
    code = byte2;
    op_imm_8(insn.Op2, byte3);
    return read_operand(insn, insn.Op1, rLB);
  }
}

//--------------------------------------------------------------------------
bool h8_t::use_leaf_map(insn_t &insn, const map_t *m, uint8 idx)
{
  m += idx;
  if ( (m->proc & ptype) == 0
    || m->itype == H8_null
    || m->itype >= H8_last )
  {
    return false;
  }
  insn.itype = m->itype;
  if ( (m->op1 & X) == 0 ) switch ( m->op1 & CMD_SIZE )
  {
    case B: insn.auxpref = aux_byte; break;
    case W: insn.auxpref = aux_word; break;
    case L: insn.auxpref = aux_long; break;
    case V: insn.auxpref = advanced() ? aux_long : aux_word; break;
  }

  return read_operand(insn, insn.Op1, m->op1)
      && read_operand(insn, insn.Op2, m->op2);
}

//--------------------------------------------------------------------------
bool h8_t::op_from_byte(insn_t &insn, op_t &x, uint8 byte2)
{
  QASSERT(10308, insn.auxpref != aux_none);

  uint8 hiNi = hi_ni(byte2);
  uint8 loNi = byte2 & 0x0F;

  switch ( hiNi )
  {
    case 0x0:
    case 0x1:
    case 0x2:
    case 0x3:
      return op_phrase_displ2(insn, x, loNi, hiNi);
    case 0x4:
      return loNi == 0 ? read_operand(insn, x, aa16)
           : loNi == 8 ? read_operand(insn, x, aa32) : false;
    case 0x8:
    case 0x9:
    case 0xA:
    case 0xB:
      return op_phrase_prepost(insn, x, loNi, hiNi);
    case 0xC:
    case 0xD:
    case 0xE:
    case 0xF:
      return op_displ_regidx(insn, x, hiNi, (loNi & 8) != 0, loNi & ~8);
  }
  return false;
}

//--------------------------------------------------------------------------
bool h8_t::read_1st_op(insn_t &insn, uint8 byte2, uint8 byte3_hiNi)
{
  uint8 code_2bits = code & 3;
  switch ( byte2 )
  {
    case 0x68:
      return code >= 0x71
          && code <= 0x77
          && op_phrase_displ2(insn, insn.Op1, byte3_hiNi, code_2bits);
    case 0x69:
      return op_phrase_displ2(insn, insn.Op1, byte3_hiNi, code_2bits);
    case 0x6B:
      if ( code_2bits != 0 )
        return false;
      if ( !(byte3_hiNi == 0 || byte3_hiNi == 2) )
        return false;
      return read_operand(insn, insn.Op1, byte3_hiNi == 0 ? aa16 | L : aa32 | L);
    case 0x6C:
      if ( (code & 0xF0) != 0x70 )
        return false;
      // no break;
    case 0x6D:
      return op_phrase_prepost(insn, insn.Op1, byte3_hiNi, code_2bits);
    case 0x6E:
      if ( (code & 0xF0) != 0x70 )
        return false;
      // no break;
    case 0x6F:
      return op_displ_regidx(insn, insn.Op1, code, false, byte3_hiNi);
  }
  return false;
}

//--------------------------------------------------------------------------
static bool op_reg(const insn_t &insn, op_t &x, uint8 reg, ushort place, uint16 aux_assumed)
{
  QASSERT(10303, (place & OPTYPE) == rH || (place & OPTYPE) == rL);
  QASSERT(10304, insn.auxpref != aux_none || aux_assumed != aux_none);

  static const regnum_t base_reg[] = { regnum_t(-1), R0H, R0, ER0 };

  if ( place & zH && reg & 0xF0
    || place & zL && reg & 0x0F )
  {
    return false;
  }

  if ( (place & OPTYPE) == rH )
    reg >>= 4;
  reg &= 0x0F;
  if ( insn.auxpref == aux_long && reg & 8 )
    return false;

  x.type = o_reg;
  if ( insn.auxpref != aux_none )
  {
    x.reg = base_reg[insn.auxpref] + reg;
    x.dtype = dtype_by_auxpref(insn);
  }
  else
  {
    x.reg = base_reg[aux_assumed] + reg;
    x.dtype = aux_assumed - 1;
  }
  return true;
}

//--------------------------------------------------------------------------
bool h8_t::op_phrase(const insn_t &insn, op_t &x, uint8 reg, int pht, op_dtype_t dtype)
{
  QASSERT(10305, insn.auxpref != aux_none || dtype != aux_byte);
  if ( reg & 8 )
    return false;
  x.type = o_phrase;
  x.dtype = insn.auxpref != aux_none ? dtype_by_auxpref(insn) : dtype;
  x.reg = r0() + reg;
  x.phtype = pht;
  return true;
}

//--------------------------------------------------------------------------
bool h8_t::op_phrase_prepost(const insn_t &insn, op_t &x, uint8 reg, uint8 selector)
{
  selector &= 3;
  op_dtype_t dtyp = selector == 0 ? ph_post_inc
    : selector == 1 ? ph_pre_inc
    : selector == 2 ? ph_post_dec : ph_pre_dec;
  return op_phrase(insn, x, reg, dtyp);
}

//--------------------------------------------------------------------------
bool h8_t::op_phrase_displ2(const insn_t &insn, op_t &x, uint8 reg, uint8 displ)
{
  QASSERT(10298, insn.auxpref != aux_none);
  if ( reg & 8 )
    return false;
  if ( displ == 0 )
  {
    return op_phrase(insn, x, reg, ph_normal);
  }
  x.type = o_displ;
  x.dtype = dtype_by_auxpref(insn);
  x.reg  = ER0 + reg;
  x.addr = insn.auxpref == aux_long ? displ << 2 :
           insn.auxpref == aux_word ? displ << 1 : displ;
  x.szfl |= disp_2;
  return true;
}

//--------------------------------------------------------------------------
static void op_imm(const insn_t &insn, op_t &x, uval_t val)
{
  x.type = o_imm;
  x.value = val;
  x.dtype = dtype_by_auxpref(insn);
}

//--------------------------------------------------------------------------
static void op_imm_8(op_t &x, uint8 val)
{
  x.type = o_imm;
  x.dtype = dt_byte;
  x.value = val;
}

//--------------------------------------------------------------------------
static void op_imm_3(op_t &x, uint8 val)
{
  x.type = o_imm;
  x.dtype = dt_byte;
  x.value = (val >> 4) & 7;
}

//--------------------------------------------------------------------------
bool h8_t::op_displ_regidx(insn_t &insn, op_t &x, uint8 selector, bool is_32, uint8 reg)
{
  if ( reg & 8 )
    return false;

  regnum_t r;
  switch ( selector & 3 )
  {
    case 0:
      r = ER0;
      break;
    case 1:
      x.displtype = dt_regidx;
      r = R0L;
      x.szfl |= idx_byte;
      break;
    case 2:
      x.displtype = dt_regidx;
      r = R0;
      x.szfl |= idx_word;
      break;
    case 3:
      x.displtype = dt_regidx;
      r = ER0;
      x.szfl |= idx_long;
      break;
  }
  is_32 ? opdsp32(insn, x, dtype_by_auxpref(insn)) : opdsp16(insn, x, dtype_by_auxpref(insn));
  x.reg  = r + reg;
  return true;
}

//--------------------------------------------------------------------------
static bool op_aa_8(const insn_t &insn, op_t &x, uint8 val, op_dtype_t dtyp)
{
  x.type = o_mem;
  x.offb = (uchar)insn.size - sizeof(val);
  x.dtype = dtyp;
  x.addr = val;
  x.memtype = mem_sbr;
  return true;
}

//--------------------------------------------------------------------------
static bool op_reglist(op_t &x, uint8 reg, uint8 delta, bool is_inc)
{
  x.type  = o_reglist;
  x.dtype = dt_dword;
  x.nregs = delta + 1;
  if ( is_inc && reg >= delta )
    x.reg = ER0 + reg - delta;
  else if ( !is_inc && reg + delta <= 7 )
    x.reg = ER0 + reg;
  else
    return false;
  return true;
}
