4254 lines
146 KiB
C++
4254 lines
146 KiB
C++
/*
|
|
* 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 &= 0x00FFFFL; // 64K address space
|
|
else if ( !is_h8s() )
|
|
x.addr &= 0xFFFFFFL; // 16-Mbyte address space
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
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 ®op, 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;
|
|
}
|