uvmac/src/M68K/M68KITAB.c

3073 lines
69 KiB
C

/*
M68KITAB.c
Copyright (C) 2007 Paul C. Pratt
You can redistribute this file and/or modify it under the terms
of version 2 of the GNU General Public License as published by
the Free Software Foundation. You should have received a copy
of the license along with this file; see the file COPYING.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
license for more details.
*/
/*
Motorola 68K Instructions TABle
*/
#ifndef AllFiles
#include "SYSDEPNS.h"
#endif
#include "UI/MYOSGLUE.h"
#include "EMCONFIG.h"
#include "GLOBGLUE.h"
#include "M68K/M68KITAB.h"
struct WorkR {
/* expected size : 8 bytes */
uint32_t opcode;
uint32_t opsize;
uint16_t MainClass;
#if WantCycByPriOp
uint16_t Cycles;
#endif
DecOpR DecOp;
};
typedef struct WorkR WorkR;
#define b76(p) ((p->opcode >> 6) & 3)
#define b8(p) ((p->opcode >> 8) & 1)
#define mode(p) ((p->opcode >> 3) & 7)
#define reg(p) (p->opcode & 7)
#define md6(p) ((p->opcode >> 6) & 7)
#define rg9(p) ((p->opcode >> 9) & 7)
enum {
kAddrValidAny,
kAddrValidData,
kAddrValidDataAlt,
kAddrValidControl,
kAddrValidControlAlt,
kAddrValidAltMem,
kAddrValidDataNoCn, /* no constants (immediate data) */
kNumAddrValids
};
#define kAddrValidMaskAny (1 << kAddrValidAny)
#define kAddrValidMaskData (1 << kAddrValidData)
#define kAddrValidMaskDataAlt (1 << kAddrValidDataAlt)
#define kAddrValidMaskControl (1 << kAddrValidControl)
#define kAddrValidMaskControlAlt (1 << kAddrValidControlAlt)
#define kAddrValidMaskAltMem (1 << kAddrValidAltMem)
#define kAddrValidMaskDataNoCn (1 << kAddrValidDataNoCn)
#define CheckInSet(v, m) (0 != ((1 << (v)) & (m)))
#define kAvgCycPerInstr (10 * kCycleScale + (40 * kCycleScale / 64))
LOCALFUNC uint8_t GetAMdRegSz(WorkR *p)
{
uint8_t CurAMd;
switch (p->opsize) {
case 1:
CurAMd = kAMdRegB;
break;
case 2:
default: /* keep compiler happy */
CurAMd = kAMdRegW;
break;
case 4:
CurAMd = kAMdRegL;
break;
}
return CurAMd;
}
LOCALFUNC uint8_t GetAMdIndirectSz(WorkR *p)
{
uint8_t CurAMd;
switch (p->opsize) {
case 1:
CurAMd = kAMdIndirectB;
break;
case 2:
default: /* keep compiler happy */
CurAMd = kAMdIndirectW;
break;
case 4:
CurAMd = kAMdIndirectL;
break;
}
return CurAMd;
}
#if WantCycByPriOp
LOCALFUNC uint16_t OpEACalcCyc(WorkR *p, uint8_t m, uint8_t r)
{
uint16_t v;
switch (m) {
case 0:
case 1:
v = 0;
break;
case 2:
v = ((4 == p->opsize)
? (8 * kCycleScale + 2 * RdAvgXtraCyc)
: (4 * kCycleScale + RdAvgXtraCyc));
break;
case 3:
v = ((4 == p->opsize)
? (8 * kCycleScale + 2 * RdAvgXtraCyc)
: (4 * kCycleScale + RdAvgXtraCyc));
break;
case 4:
v = ((4 == p->opsize)
? (10 * kCycleScale + 2 * RdAvgXtraCyc)
: (6 * kCycleScale + RdAvgXtraCyc));
break;
case 5:
v = ((4 == p->opsize)
? (12 * kCycleScale + 3 * RdAvgXtraCyc)
: (8 * kCycleScale + 2 * RdAvgXtraCyc));
break;
case 6:
v = ((4 == p->opsize)
? (14 * kCycleScale + 3 * RdAvgXtraCyc)
: (10 * kCycleScale + 2 * RdAvgXtraCyc));
break;
case 7:
switch (r) {
case 0:
v = ((4 == p->opsize)
? (12 * kCycleScale + 3 * RdAvgXtraCyc)
: (8 * kCycleScale + 2 * RdAvgXtraCyc));
break;
case 1:
v = ((4 == p->opsize)
? (16 * kCycleScale + 4 * RdAvgXtraCyc)
: (12 * kCycleScale + 3 * RdAvgXtraCyc));
break;
case 2:
v = ((4 == p->opsize)
? (12 * kCycleScale + 3 * RdAvgXtraCyc)
: (8 * kCycleScale + 2 * RdAvgXtraCyc));
break;
case 3:
v = ((4 == p->opsize)
? (14 * kCycleScale + 3 * RdAvgXtraCyc)
: (10 * kCycleScale + 2 * RdAvgXtraCyc));
break;
case 4:
v = ((4 == p->opsize)
? (8 * kCycleScale + 2 * RdAvgXtraCyc)
: (4 * kCycleScale + RdAvgXtraCyc));
break;
default:
v = 0;
break;
}
break;
default: /* keep compiler happy */
v = 0;
break;
}
return v;
}
#endif
#if WantCycByPriOp
LOCALFUNC uint16_t OpEADestCalcCyc(WorkR *p, uint8_t m, uint8_t r)
{
uint16_t v;
switch (m) {
case 0:
case 1:
v = 0;
break;
case 2:
v = ((4 == p->opsize)
? (8 * kCycleScale + 2 * WrAvgXtraCyc)
: (4 * kCycleScale + WrAvgXtraCyc));
break;
case 3:
v = ((4 == p->opsize)
? (8 * kCycleScale + 2 * WrAvgXtraCyc)
: (4 * kCycleScale + WrAvgXtraCyc));
break;
case 4:
v = ((4 == p->opsize)
? (8 * kCycleScale + 2 * WrAvgXtraCyc)
: (4 * kCycleScale + WrAvgXtraCyc));
break;
case 5:
v = ((4 == p->opsize)
? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc)
: (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc));
break;
case 6:
v = ((4 == p->opsize)
? (14 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc)
: (10 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc));
break;
case 7:
switch (r) {
case 0:
v = ((4 == p->opsize)
? (12 * kCycleScale
+ RdAvgXtraCyc + 2 * WrAvgXtraCyc)
: (8 * kCycleScale
+ RdAvgXtraCyc + WrAvgXtraCyc));
break;
case 1:
v = ((4 == p->opsize)
? (16 * kCycleScale
+ 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc)
: (12 * kCycleScale
+ 2 * RdAvgXtraCyc + WrAvgXtraCyc));
break;
default:
v = 0;
break;
}
break;
default: /* keep compiler happy */
v = 0;
break;
}
return v;
}
#endif
LOCALPROC SetDcoArgFields(WorkR *p, bool src,
uint8_t CurAMd, uint8_t CurArgDat)
{
if (src) {
p->DecOp.y.v[0].AMd = CurAMd;
p->DecOp.y.v[0].ArgDat = CurArgDat;
} else {
p->DecOp.y.v[1].AMd = CurAMd;
p->DecOp.y.v[1].ArgDat = CurArgDat;
}
}
LOCALFUNC bool CheckValidAddrMode(WorkR *p,
uint8_t m, uint8_t r, uint8_t v, bool src)
{
uint8_t CurAMd = 0; /* init to keep compiler happy */
uint8_t CurArgDat = 0;
bool IsOk;
switch (m) {
case 0:
CurAMd = GetAMdRegSz(p);
CurArgDat = r;
IsOk = CheckInSet(v,
kAddrValidMaskAny | kAddrValidMaskData
| kAddrValidMaskDataAlt | kAddrValidMaskDataNoCn);
break;
case 1:
CurAMd = GetAMdRegSz(p);
CurArgDat = r + 8;
IsOk = CheckInSet(v, kAddrValidMaskAny);
break;
case 2:
CurAMd = GetAMdIndirectSz(p);
CurArgDat = r + 8;
IsOk = CheckInSet(v,
kAddrValidMaskAny | kAddrValidMaskData
| kAddrValidMaskDataAlt | kAddrValidMaskControl
| kAddrValidMaskControlAlt | kAddrValidMaskAltMem
| kAddrValidMaskDataNoCn);
break;
case 3:
switch (p->opsize) {
case 1:
if (7 == r) {
CurAMd = kAMdAPosInc7B;
} else {
CurAMd = kAMdAPosIncB;
}
break;
case 2:
default: /* keep compiler happy */
CurAMd = kAMdAPosIncW;
break;
case 4:
CurAMd = kAMdAPosIncL;
break;
}
CurArgDat = r + 8;
IsOk = CheckInSet(v,
kAddrValidMaskAny | kAddrValidMaskData
| kAddrValidMaskDataAlt | kAddrValidMaskAltMem
| kAddrValidMaskDataNoCn);
break;
case 4:
switch (p->opsize) {
case 1:
if (7 == r) {
CurAMd = kAMdAPreDec7B;
} else {
CurAMd = kAMdAPreDecB;
}
break;
case 2:
default: /* keep compiler happy */
CurAMd = kAMdAPreDecW;
break;
case 4:
CurAMd = kAMdAPreDecL;
break;
}
CurArgDat = r + 8;
IsOk = CheckInSet(v,
kAddrValidMaskAny | kAddrValidMaskData
| kAddrValidMaskDataAlt | kAddrValidMaskAltMem
| kAddrValidMaskDataNoCn);
break;
case 5:
switch (p->opsize) {
case 1:
CurAMd = kAMdADispB;
break;
case 2:
default: /* keep compiler happy */
CurAMd = kAMdADispW;
break;
case 4:
CurAMd = kAMdADispL;
break;
}
CurArgDat = r + 8;
IsOk = CheckInSet(v,
kAddrValidMaskAny | kAddrValidMaskData
| kAddrValidMaskDataAlt | kAddrValidMaskControl
| kAddrValidMaskControlAlt | kAddrValidMaskAltMem
| kAddrValidMaskDataNoCn);
break;
case 6:
switch (p->opsize) {
case 1:
CurAMd = kAMdAIndexB;
break;
case 2:
default: /* keep compiler happy */
CurAMd = kAMdAIndexW;
break;
case 4:
CurAMd = kAMdAIndexL;
break;
}
CurArgDat = r + 8;
IsOk = CheckInSet(v,
kAddrValidMaskAny | kAddrValidMaskData
| kAddrValidMaskDataAlt | kAddrValidMaskControl
| kAddrValidMaskControlAlt | kAddrValidMaskAltMem
| kAddrValidMaskDataNoCn);
break;
case 7:
switch (r) {
case 0:
switch (p->opsize) {
case 1:
CurAMd = kAMdAbsWB;
break;
case 2:
default: /* keep compiler happy */
CurAMd = kAMdAbsWW;
break;
case 4:
CurAMd = kAMdAbsWL;
break;
}
IsOk = CheckInSet(v,
kAddrValidMaskAny | kAddrValidMaskData
| kAddrValidMaskDataAlt
| kAddrValidMaskControl
| kAddrValidMaskControlAlt
| kAddrValidMaskAltMem
| kAddrValidMaskDataNoCn);
break;
case 1:
switch (p->opsize) {
case 1:
CurAMd = kAMdAbsLB;
break;
case 2:
default: /* keep compiler happy */
CurAMd = kAMdAbsLW;
break;
case 4:
CurAMd = kAMdAbsLL;
break;
}
IsOk = CheckInSet(v,
kAddrValidMaskAny | kAddrValidMaskData
| kAddrValidMaskDataAlt
| kAddrValidMaskControl
| kAddrValidMaskControlAlt
| kAddrValidMaskAltMem
| kAddrValidMaskDataNoCn);
break;
case 2:
switch (p->opsize) {
case 1:
CurAMd = kAMdPCDispB;
break;
case 2:
default: /* keep compiler happy */
CurAMd = kAMdPCDispW;
break;
case 4:
CurAMd = kAMdPCDispL;
break;
}
IsOk = CheckInSet(v,
kAddrValidMaskAny | kAddrValidMaskData
| kAddrValidMaskControl
| kAddrValidMaskDataNoCn);
break;
case 3:
switch (p->opsize) {
case 1:
CurAMd = kAMdPCIndexB;
break;
case 2:
default: /* keep compiler happy */
CurAMd = kAMdPCIndexW;
break;
case 4:
CurAMd = kAMdPCIndexL;
break;
}
IsOk = CheckInSet(v,
kAddrValidMaskAny | kAddrValidMaskData
| kAddrValidMaskControl
| kAddrValidMaskDataNoCn);
break;
case 4:
switch (p->opsize) {
case 1:
CurAMd = kAMdImmedB;
break;
case 2:
default: /* keep compiler happy */
CurAMd = kAMdImmedW;
break;
case 4:
CurAMd = kAMdImmedL;
break;
}
IsOk = CheckInSet(v,
kAddrValidMaskAny | kAddrValidMaskData);
break;
default:
IsOk = false;
break;
}
break;
default: /* keep compiler happy */
IsOk = false;
break;
}
if (IsOk) {
SetDcoArgFields(p, src, CurAMd, CurArgDat);
}
return IsOk;
}
#if WantCycByPriOp
LOCALFUNC bool LeaPeaEACalcCyc(WorkR *p, uint8_t m, uint8_t r)
{
uint16_t v;
UnusedParam(p);
switch (m) {
case 2:
v = 0;
break;
case 5:
v = (4 * kCycleScale + RdAvgXtraCyc);
break;
case 6:
v = (8 * kCycleScale + RdAvgXtraCyc);
break;
case 7:
switch (r) {
case 0:
v = (4 * kCycleScale + RdAvgXtraCyc);
break;
case 1:
v = (8 * kCycleScale + 2 * RdAvgXtraCyc);
break;
case 2:
v = (4 * kCycleScale + RdAvgXtraCyc);
break;
case 3:
v = (8 * kCycleScale + RdAvgXtraCyc);
break;
default:
v = 0;
break;
}
break;
default: /* keep compiler happy */
v = 0;
break;
}
return v;
}
#endif
LOCALFUNC bool IsValidAddrMode(WorkR *p)
{
return CheckValidAddrMode(p,
mode(p), reg(p), kAddrValidAny, false);
}
LOCALFUNC bool CheckDataAltAddrMode(WorkR *p)
{
return CheckValidAddrMode(p,
mode(p), reg(p), kAddrValidDataAlt, false);
}
LOCALFUNC bool CheckDataAddrMode(WorkR *p)
{
return CheckValidAddrMode(p,
mode(p), reg(p), kAddrValidData, false);
}
LOCALFUNC bool CheckControlAddrMode(WorkR *p)
{
return CheckValidAddrMode(p,
mode(p), reg(p), kAddrValidControl, false);
}
LOCALFUNC bool CheckControlAltAddrMode(WorkR *p)
{
return CheckValidAddrMode(p,
mode(p), reg(p), kAddrValidControlAlt, false);
}
LOCALFUNC bool CheckAltMemAddrMode(WorkR *p)
{
return CheckValidAddrMode(p,
mode(p), reg(p), kAddrValidAltMem, false);
}
LOCALPROC FindOpSizeFromb76(WorkR *p)
{
p->opsize = 1 << b76(p);
#if 0
switch (b76(p)) {
case 0 :
p->opsize = 1;
break;
case 1 :
p->opsize = 2;
break;
case 2 :
p->opsize = 4;
break;
}
#endif
}
LOCALFUNC uint8_t OpSizeOffset(WorkR *p)
{
uint8_t v;
switch (p->opsize) {
case 1 :
v = 0;
break;
case 2 :
v = 1;
break;
case 4 :
default :
v = 2;
break;
}
return v;
}
LOCALFUNC uint32_t octdat(uint32_t x)
{
if (x == 0) {
return 8;
} else {
return x;
}
}
LOCALPROCUSEDONCE DeCode0(WorkR *p)
{
if (b8(p) == 1) {
if (mode(p) == 1) {
/* MoveP 0000ddd1mm001aaa */
#if WantCycByPriOp
switch (b76(p)) {
case 0:
p->Cycles = (16 * kCycleScale + 4 * RdAvgXtraCyc);
break;
case 1:
p->Cycles = (24 * kCycleScale + 6 * RdAvgXtraCyc);
break;
case 2:
p->Cycles = (16 * kCycleScale
+ 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc);
break;
case 3:
default: /* keep compiler happy */
p->Cycles = (24 * kCycleScale
+ 2 * RdAvgXtraCyc + 4 * WrAvgXtraCyc);
break;
}
#endif
if (CheckValidAddrMode(p, 1, reg(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, 0, rg9(p),
kAddrValidAny, false))
{
p->MainClass = kIKindMoveP0 + b76(p);
}
} else {
/* dynamic bit, Opcode = 0000ddd1ttmmmrrr */
if (mode(p) == 0) {
p->opsize = 4;
#if WantCycByPriOp
switch (b76(p)) {
case 0: /* BTst */
p->Cycles = (6 * kCycleScale + RdAvgXtraCyc);
break;
case 1: /* BChg */
p->Cycles = (8 * kCycleScale + RdAvgXtraCyc);
break;
case 2: /* BClr */
p->Cycles = (10 * kCycleScale + RdAvgXtraCyc);
break;
case 3: /* BSet */
p->Cycles = (8 * kCycleScale + RdAvgXtraCyc);
break;
}
#endif
p->MainClass = kIKindBTstL + b76(p);
SetDcoArgFields(p, true, kAMdRegL, rg9(p));
SetDcoArgFields(p, false, kAMdRegL, reg(p));
} else {
p->opsize = 1;
p->MainClass = kIKindBTstB + b76(p);
SetDcoArgFields(p, true, kAMdRegB, rg9(p));
if (b76(p) == 0) { /* BTst */
if (CheckDataAddrMode(p)) {
#if WantCycByPriOp
p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
}
} else {
if (CheckDataAltAddrMode(p)) {
#if WantCycByPriOp
p->Cycles = (8 * kCycleScale
+ RdAvgXtraCyc + WrAvgXtraCyc);
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
}
}
}
}
} else {
if (rg9(p) == 4) {
/* static bit 00001010ssmmmrrr */
if (mode(p) == 0) {
p->opsize = 4;
#if WantCycByPriOp
switch (b76(p)) {
case 0: /* BTst */
p->Cycles =
(10 * kCycleScale + 2 * RdAvgXtraCyc);
break;
case 1: /* BChg */
p->Cycles =
(12 * kCycleScale + 2 * RdAvgXtraCyc);
break;
case 2: /* BClr */
p->Cycles =
(14 * kCycleScale + 2 * RdAvgXtraCyc);
break;
case 3: /* BSet */
p->Cycles =
(12 * kCycleScale + 2 * RdAvgXtraCyc);
break;
}
#endif
SetDcoArgFields(p, true, kAMdImmedB, 0);
SetDcoArgFields(p, false, kAMdRegL, reg(p));
p->MainClass = kIKindBTstL + b76(p);
} else {
p->opsize = 1;
SetDcoArgFields(p, true, kAMdImmedB, 0);
p->MainClass = kIKindBTstB + b76(p);
if (b76(p) == 0) { /* BTst */
if (CheckValidAddrMode(p,
mode(p), reg(p), kAddrValidDataNoCn, false))
{
#if WantCycByPriOp
p->Cycles =
(8 * kCycleScale + 2 * RdAvgXtraCyc);
p->Cycles +=
OpEACalcCyc(p, mode(p), reg(p));
#endif
}
} else {
if (CheckDataAltAddrMode(p)) {
#if WantCycByPriOp
p->Cycles = (12 * kCycleScale
+ 2 * RdAvgXtraCyc + WrAvgXtraCyc);
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
}
}
}
} else
if (b76(p) == 3) {
#if Use68020
if (rg9(p) < 3) {
/* CHK2 or CMP2 00000ss011mmmrrr */
switch ((p->opcode >> 9) & 3) {
case 0 :
p->opsize = 1;
break;
case 1 :
p->opsize = 2;
break;
case 2 :
p->opsize = 4;
break;
}
p->DecOp.y.v[0].ArgDat = p->opsize;
/* size */
if (CheckControlAddrMode(p)) {
#if WantCycByPriOp
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindCHK2orCMP2;
}
} else
if (rg9(p) >= 5) {
switch ((p->opcode >> 9) & 3) {
case 1 :
p->opsize = 1;
break;
case 2 :
p->opsize = 2;
break;
case 3 :
p->opsize = 4;
break;
}
p->DecOp.y.v[0].ArgDat = p->opsize;
if ((mode(p) == 7) && (reg(p) == 4)) {
/* CAS2 00001ss011111100 */
p->MainClass = kIKindCAS2;
} else {
/* CAS 00001ss011mmmrrr */
if (CheckDataAltAddrMode(p)) {
p->MainClass = kIKindCAS;
}
}
} else
if (rg9(p) == 3) {
/* CALLM or RTM 0000011011mmmrrr */
p->MainClass = kIKindCallMorRtm;
} else
#endif
{
p->MainClass = kIKindIllegal;
}
} else
if (rg9(p) == 6) {
/* CMPI 00001100ssmmmrrr */
#if 0
if (CheckDataAltAddrMode(p)) {
p->MainClass = kIKindCmpI;
}
#endif
FindOpSizeFromb76(p);
if (CheckValidAddrMode(p, 7, 4, kAddrValidAny, true))
if (CheckValidAddrMode(p,
mode(p), reg(p), kAddrValidDataNoCn, false))
{
#if WantCycByPriOp
if (0 == mode(p)) {
p->Cycles = (4 == p->opsize)
? (14 * kCycleScale + 3 * RdAvgXtraCyc)
: (8 * kCycleScale + 2 * RdAvgXtraCyc);
} else {
p->Cycles = (4 == p->opsize)
? (12 * kCycleScale + 3 * RdAvgXtraCyc)
: (8 * kCycleScale + 2 * RdAvgXtraCyc);
}
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindCmpB + OpSizeOffset(p);
}
} else if (rg9(p) == 7) {
#if Use68020
/* MoveS 00001110ssmmmrrr */
FindOpSizeFromb76(p);
p->DecOp.y.v[0].ArgDat = p->opsize;
if (CheckAltMemAddrMode(p)) {
#if WantCycByPriOp
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindMoveS;
}
#else
p->MainClass = kIKindIllegal;
#endif
} else {
if ((mode(p) == 7) && (reg(p) == 4)) {
switch (rg9(p)) {
case 0:
#if WantCycByPriOp
p->Cycles =
(20 * kCycleScale + 3 * RdAvgXtraCyc);
#endif
p->MainClass = (0 != b76(p))
? kIKindOrISR : kIKindOrICCR;
break;
case 1:
#if WantCycByPriOp
p->Cycles =
(20 * kCycleScale + 3 * RdAvgXtraCyc);
#endif
p->MainClass = (0 != b76(p))
? kIKindAndISR : kIKindAndICCR;
break;
case 5:
#if WantCycByPriOp
p->Cycles =
(20 * kCycleScale + 3 * RdAvgXtraCyc);
#endif
p->MainClass = (0 != b76(p))
? kIKindEorISR : kIKindEorICCR;
break;
default:
p->MainClass = kIKindIllegal;
break;
}
} else {
switch (rg9(p)) {
case 0:
#if 0
if (CheckDataAltAddrMode(p)) {
p->MainClass = kIKindOrI;
}
#endif
FindOpSizeFromb76(p);
if (CheckValidAddrMode(p, 7, 4,
kAddrValidAny, true))
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidDataAlt, false))
{
#if WantCycByPriOp
if (0 != mode(p)) {
p->Cycles = (4 == p->opsize)
? (20 * kCycleScale
+ 3 * RdAvgXtraCyc
+ 2 * WrAvgXtraCyc)
: (12 * kCycleScale
+ 2 * RdAvgXtraCyc
+ WrAvgXtraCyc);
} else {
p->Cycles = (4 == p->opsize)
? (16 * kCycleScale
+ 3 * RdAvgXtraCyc)
: (8 * kCycleScale
+ 2 * RdAvgXtraCyc);
}
p->Cycles +=
OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindOrI;
}
break;
case 1:
#if 0
if (CheckDataAltAddrMode(p)) {
p->MainClass = kIKindAndI;
}
#endif
FindOpSizeFromb76(p);
if (CheckValidAddrMode(p, 7, 4,
kAddrValidAny, true))
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidDataAlt, false))
{
#if WantCycByPriOp
if (0 != mode(p)) {
p->Cycles = (4 == p->opsize)
? (20 * kCycleScale
+ 3 * RdAvgXtraCyc
+ 2 * WrAvgXtraCyc)
: (12 * kCycleScale
+ 2 * RdAvgXtraCyc
+ WrAvgXtraCyc);
} else {
p->Cycles = (4 == p->opsize)
? (14 * kCycleScale
+ 3 * RdAvgXtraCyc)
: (8 * kCycleScale
+ 2 * RdAvgXtraCyc);
}
p->Cycles +=
OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindAndI;
}
break;
case 2:
#if 0
if (CheckDataAltAddrMode(p)) {
p->MainClass = kIKindSubI;
}
#endif
FindOpSizeFromb76(p);
if (CheckValidAddrMode(p, 7, 4,
kAddrValidAny, true))
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidDataAlt, false))
{
#if WantCycByPriOp
if (0 != mode(p)) {
p->Cycles = (4 == p->opsize)
? (20 * kCycleScale
+ 3 * RdAvgXtraCyc
+ 2 * WrAvgXtraCyc)
: (12 * kCycleScale
+ 2 * RdAvgXtraCyc
+ WrAvgXtraCyc);
} else {
p->Cycles = (4 == p->opsize)
? (16 * kCycleScale
+ 3 * RdAvgXtraCyc)
: (8 * kCycleScale
+ 2 * RdAvgXtraCyc);
}
p->Cycles +=
OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindSubB + OpSizeOffset(p);
}
break;
case 3:
#if 0
if (CheckDataAltAddrMode(p)) {
p->MainClass = kIKindAddI;
}
#endif
FindOpSizeFromb76(p);
if (CheckValidAddrMode(p, 7, 4,
kAddrValidAny, true))
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidDataAlt, false))
{
#if WantCycByPriOp
if (0 != mode(p)) {
p->Cycles = (4 == p->opsize)
? (20 * kCycleScale
+ 3 * RdAvgXtraCyc
+ 2 * WrAvgXtraCyc)
: (12 * kCycleScale
+ 2 * RdAvgXtraCyc
+ WrAvgXtraCyc);
} else {
p->Cycles = (4 == p->opsize)
? (16 * kCycleScale
+ 3 * RdAvgXtraCyc)
: (8 * kCycleScale
+ 2 * RdAvgXtraCyc);
}
p->Cycles +=
OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindAddB + OpSizeOffset(p);
}
break;
case 5:
#if 0
if (CheckDataAltAddrMode(p)) {
p->MainClass = kIKindEorI;
}
#endif
FindOpSizeFromb76(p);
if (CheckValidAddrMode(p, 7, 4,
kAddrValidAny, true))
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidDataAlt, false))
{
#if WantCycByPriOp
if (0 != mode(p)) {
p->Cycles = (4 == p->opsize)
? (20 * kCycleScale
+ 3 * RdAvgXtraCyc
+ 2 * WrAvgXtraCyc)
: (12 * kCycleScale
+ 2 * RdAvgXtraCyc
+ WrAvgXtraCyc);
} else {
p->Cycles = (4 == p->opsize)
? (16 * kCycleScale
+ 3 * RdAvgXtraCyc)
: (8 * kCycleScale
+ 2 * RdAvgXtraCyc);
}
p->Cycles +=
OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindEorI;
}
break;
default:
/* for compiler. should be 0, 1, 2, 3, or 5 */
p->MainClass = kIKindIllegal;
break;
}
}
}
}
}
LOCALPROCUSEDONCE DeCode1(WorkR *p)
{
p->opsize = 1;
if (md6(p) == 1) { /* MOVEA */
p->MainClass = kIKindIllegal;
} else if (mode(p) == 1) {
/* not allowed for byte sized move */
p->MainClass = kIKindIllegal;
} else {
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, md6(p), rg9(p),
kAddrValidDataAlt, false))
{
#if WantCycByPriOp
p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
p->Cycles += OpEADestCalcCyc(p, md6(p), rg9(p));
#endif
p->MainClass = kIKindMoveB;
}
}
}
LOCALPROCUSEDONCE DeCode2(WorkR *p)
{
p->opsize = 4;
if (md6(p) == 1) { /* MOVEA */
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, 1, rg9(p),
kAddrValidAny, false))
{
#if WantCycByPriOp
p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindMoveAL;
p->DecOp.y.v[1].ArgDat = rg9(p);
}
} else {
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, md6(p), rg9(p),
kAddrValidDataAlt, false))
{
#if WantCycByPriOp
p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
p->Cycles += OpEADestCalcCyc(p, md6(p), rg9(p));
#endif
p->MainClass = kIKindMoveL;
}
}
}
LOCALPROCUSEDONCE DeCode3(WorkR *p)
{
p->opsize = 2;
if (md6(p) == 1) { /* MOVEA */
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, 1, rg9(p),
kAddrValidAny, false))
{
#if WantCycByPriOp
p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindMoveAW;
p->DecOp.y.v[1].ArgDat = rg9(p);
}
} else {
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, md6(p), rg9(p),
kAddrValidDataAlt, false))
{
#if WantCycByPriOp
p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
p->Cycles += OpEADestCalcCyc(p, md6(p), rg9(p));
#endif
p->MainClass = kIKindMoveW;
}
}
}
#if WantCycByPriOp
#if WantCloserCyc
#define MoveAvgN 0
#else
#define MoveAvgN 3
#endif
LOCALFUNC uint16_t MoveMEACalcCyc(WorkR *p, uint8_t m, uint8_t r)
{
uint16_t v;
UnusedParam(p);
switch (m) {
case 2:
case 3:
case 4:
v = (8 * kCycleScale + 2 * RdAvgXtraCyc);
break;
case 5:
v = (12 * kCycleScale + 3 * RdAvgXtraCyc);
break;
case 6:
v = (14 * kCycleScale + 3 * RdAvgXtraCyc);
break;
case 7:
switch (r) {
case 0:
v = (12 * kCycleScale + 3 * RdAvgXtraCyc);
break;
case 1:
v = (16 * kCycleScale + 4 * RdAvgXtraCyc);
break;
default:
v = 0;
break;
}
break;
default: /* keep compiler happy */
v = 0;
break;
}
return v;
}
#endif
LOCALPROCUSEDONCE DeCode4(WorkR *p)
{
if (b8(p) != 0) {
switch (b76(p)) {
case 0:
#if Use68020
/* Chk.L 0100ddd100mmmrrr */
p->opsize = 4;
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidData, false))
if (CheckValidAddrMode(p, 0, rg9(p),
kAddrValidAny, true))
{
#if WantCycByPriOp
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindChkL;
}
#else
p->MainClass = kIKindIllegal;
#endif
break;
case 1:
p->MainClass = kIKindIllegal;
break;
case 2:
/* Chk.W 0100ddd110mmmrrr */
p->opsize = 2;
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidData, false))
if (CheckValidAddrMode(p, 0, rg9(p),
kAddrValidAny, true))
{
#if WantCycByPriOp
p->Cycles = (10 * kCycleScale + RdAvgXtraCyc);
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindChkW;
}
break;
case 3:
default: /* keep compiler happy */
#if Use68020
if ((0 == mode(p)) && (4 == rg9(p))) {
/* EXTB.L */
SetDcoArgFields(p, false,
kAMdRegL, reg(p));
p->MainClass = kIKindEXTBL;
} else
#endif
{
/* Lea 0100aaa111mmmrrr */
if (CheckControlAddrMode(p)) {
#if WantCycByPriOp
p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
p->Cycles +=
LeaPeaEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindLea;
p->DecOp.y.v[0].ArgDat = rg9(p);
}
}
break;
}
} else {
switch (rg9(p)) {
case 0:
if (b76(p) != 3) {
/* NegX 01000000ssmmmrrr */
FindOpSizeFromb76(p);
if (CheckDataAltAddrMode(p)) {
#if WantCycByPriOp
if (0 != mode(p)) {
p->Cycles = (4 == p->opsize)
? (12 * kCycleScale
+ RdAvgXtraCyc + 2 * WrAvgXtraCyc)
: (8 * kCycleScale
+ RdAvgXtraCyc + WrAvgXtraCyc);
} else {
p->Cycles = (4 == p->opsize)
? (6 * kCycleScale + RdAvgXtraCyc)
: (4 * kCycleScale + RdAvgXtraCyc);
}
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindNegXB + OpSizeOffset(p);
}
} else {
#if Use68020
/* reference seems incorrect to say not for 68000 */
#endif
/* Move from SR 0100000011mmmrrr */
p->opsize = 2;
if (CheckDataAltAddrMode(p)) {
#if WantCycByPriOp
p->Cycles =
(12 * kCycleScale + 2 * RdAvgXtraCyc);
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindMoveSREa;
}
}
break;
case 1:
if (b76(p) != 3) {
/* Clr 01000010ssmmmrrr */
FindOpSizeFromb76(p);
if (CheckDataAltAddrMode(p)) {
#if WantCycByPriOp
if (0 != mode(p)) {
p->Cycles = (4 == p->opsize)
? (12 * kCycleScale
+ RdAvgXtraCyc + 2 * WrAvgXtraCyc)
: (8 * kCycleScale
+ RdAvgXtraCyc + WrAvgXtraCyc);
} else {
p->Cycles = (4 == p->opsize)
? (6 * kCycleScale + RdAvgXtraCyc)
: (4 * kCycleScale + RdAvgXtraCyc);
}
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindClr;
}
} else {
#if Use68020
/* Move from CCR 0100001011mmmrrr */
p->opsize = 2;
if (CheckDataAltAddrMode(p)) {
#if WantCycByPriOp
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindMoveCCREa;
}
#else
p->MainClass = kIKindIllegal;
#endif
}
break;
case 2:
if (b76(p) != 3) {
/* Neg 01000100ssmmmrrr */
FindOpSizeFromb76(p);
if (CheckDataAltAddrMode(p)) {
#if WantCycByPriOp
if (0 != mode(p)) {
p->Cycles = (4 == p->opsize)
? (12 * kCycleScale
+ RdAvgXtraCyc + 2 * WrAvgXtraCyc)
: (8 * kCycleScale
+ RdAvgXtraCyc + WrAvgXtraCyc);
} else {
p->Cycles = (4 == p->opsize)
? (6 * kCycleScale + RdAvgXtraCyc)
: (4 * kCycleScale + RdAvgXtraCyc);
}
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindNegB + OpSizeOffset(p);
}
} else {
/* Move to CCR 0100010011mmmrrr */
p->opsize = 2;
if (CheckDataAddrMode(p)) {
#if WantCycByPriOp
p->Cycles = (12 * kCycleScale + RdAvgXtraCyc);
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindMoveEaCCR;
}
}
break;
case 3:
if (b76(p) != 3) {
/* Not 01000110ssmmmrrr */
FindOpSizeFromb76(p);
if (CheckDataAltAddrMode(p)) {
#if WantCycByPriOp
if (0 != mode(p)) {
p->Cycles = (4 == p->opsize)
? (12 * kCycleScale
+ RdAvgXtraCyc + 2 * WrAvgXtraCyc)
: (8 * kCycleScale
+ RdAvgXtraCyc + WrAvgXtraCyc);
} else {
p->Cycles = (4 == p->opsize)
? (6 * kCycleScale + RdAvgXtraCyc)
: (4 * kCycleScale + RdAvgXtraCyc);
}
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindNot;
}
} else {
/* Move from SR 0100011011mmmrrr */
p->opsize = 2;
if (CheckDataAddrMode(p)) {
#if WantCycByPriOp
if (0 != mode(p)) {
p->Cycles = (8 * kCycleScale
+ RdAvgXtraCyc + WrAvgXtraCyc);
} else {
p->Cycles =
(6 * kCycleScale + RdAvgXtraCyc);
}
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindMoveEaSR;
}
}
break;
case 4:
switch (b76(p)) {
case 0:
#if Use68020
if (mode(p) == 1) {
/* Link.L 0100100000001rrr */
SetDcoArgFields(p, false,
kAMdRegL, reg(p) + 8);
p->MainClass = kIKindLinkL;
} else
#endif
{
/* Nbcd 0100100000mmmrrr */
p->opsize = 1;
if (CheckDataAltAddrMode(p)) {
#if WantCycByPriOp
if (0 != mode(p)) {
p->Cycles = (8 * kCycleScale
+ RdAvgXtraCyc + WrAvgXtraCyc);
} else {
p->Cycles = (6 * kCycleScale
+ RdAvgXtraCyc);
}
p->Cycles +=
OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindNbcd;
}
}
break;
case 1:
if (mode(p) == 0) {
/* Swap 0100100001000rrr */
#if WantCycByPriOp
p->Cycles =
(4 * kCycleScale + RdAvgXtraCyc);
#endif
p->MainClass = kIKindSwap;
SetDcoArgFields(p, false,
kAMdRegL, reg(p));
} else
#if Use68020
if (mode(p) == 1) {
p->MainClass = kIKindBkpt;
} else
#endif
{
/* PEA 0100100001mmmrrr */
if (CheckControlAddrMode(p)) {
#if WantCycByPriOp
p->Cycles = (12 * kCycleScale
+ RdAvgXtraCyc
+ 2 * WrAvgXtraCyc);
p->Cycles +=
LeaPeaEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindPEA;
}
}
break;
case 2:
if (mode(p) == 0) {
/* EXT.W */
#if WantCycByPriOp
p->Cycles =
(4 * kCycleScale + RdAvgXtraCyc);
#endif
SetDcoArgFields(p, false,
kAMdRegW, reg(p));
p->MainClass = kIKindEXTW;
} else {
/* MOVEM reg to mem 01001d001ssmmmrrr */
p->opsize = 2;
if (mode(p) == 4) {
#if WantCycByPriOp
p->Cycles =
MoveMEACalcCyc(p, mode(p), reg(p));
p->Cycles += MoveAvgN * 4 * kCycleScale
+ MoveAvgN * WrAvgXtraCyc;
#endif
SetDcoArgFields(p, false,
kAMdAPreDecL, reg(p) + 8);
p->MainClass = kIKindMOVEMRmMW;
} else {
if (CheckControlAltAddrMode(p)) {
#if WantCycByPriOp
p->Cycles = MoveMEACalcCyc(p,
mode(p), reg(p));
p->Cycles +=
MoveAvgN * 4 * kCycleScale
+ MoveAvgN * WrAvgXtraCyc;
#endif
p->MainClass = kIKindMOVEMrmW;
}
}
}
break;
case 3:
default: /* keep compiler happy */
if (mode(p) == 0) {
/* EXT.L */
#if WantCycByPriOp
p->Cycles =
(4 * kCycleScale + RdAvgXtraCyc);
#endif
SetDcoArgFields(p, false,
kAMdRegL, reg(p));
p->MainClass = kIKindEXTL;
} else {
/* MOVEM reg to mem 01001d001ssmmmrrr */
#if WantCycByPriOp
p->Cycles = MoveMEACalcCyc(p,
mode(p), reg(p));
p->Cycles += MoveAvgN * 8 * kCycleScale
+ MoveAvgN * 2 * WrAvgXtraCyc;
#endif
p->opsize = 4;
if (mode(p) == 4) {
SetDcoArgFields(p, false,
kAMdAPreDecL, reg(p) + 8);
p->MainClass = kIKindMOVEMRmML;
} else {
if (CheckControlAltAddrMode(p)) {
p->MainClass = kIKindMOVEMrmL;
}
}
}
break;
}
break;
case 5:
if (b76(p) == 3) {
if ((mode(p) == 7) && (reg(p) == 4)) {
/* the ILLEGAL instruction */
p->MainClass = kIKindIllegal;
} else {
/* Tas 0100101011mmmrrr */
p->opsize = 1;
if (CheckDataAltAddrMode(p)) {
#if WantCycByPriOp
if (0 != mode(p)) {
p->Cycles = (14 * kCycleScale
+ 2 * RdAvgXtraCyc + WrAvgXtraCyc);
} else {
p->Cycles = (4 * kCycleScale
+ RdAvgXtraCyc);
}
p->Cycles +=
OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindTas;
}
}
} else {
/* Tst 01001010ssmmmrrr */
FindOpSizeFromb76(p);
if (b76(p) == 0) {
if (CheckDataAltAddrMode(p)) {
#if WantCycByPriOp
p->Cycles =
(4 * kCycleScale + RdAvgXtraCyc);
p->Cycles +=
OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindTst;
}
} else {
if (IsValidAddrMode(p)) {
#if WantCycByPriOp
p->Cycles =
(4 * kCycleScale + RdAvgXtraCyc);
p->Cycles +=
OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindTst;
}
}
}
break;
case 6:
if (((p->opcode >> 7) & 1) == 1) {
/* MOVEM mem to reg 0100110011smmmrrr */
p->opsize = 2 * b76(p) - 2;
if (mode(p) == 3) {
#if WantCycByPriOp
p->Cycles = 4 * kCycleScale + RdAvgXtraCyc;
p->Cycles += MoveMEACalcCyc(p, mode(p), reg(p));
if (4 == p->opsize) {
p->Cycles += MoveAvgN * 8 * kCycleScale
+ 2 * MoveAvgN * RdAvgXtraCyc;
} else {
p->Cycles += MoveAvgN * 4 * kCycleScale
+ MoveAvgN * RdAvgXtraCyc;
}
#endif
SetDcoArgFields(p, false,
kAMdAPosIncL, reg(p) + 8);
if (b76(p) == 2) {
p->MainClass = kIKindMOVEMApRW;
} else {
p->MainClass = kIKindMOVEMApRL;
}
} else {
if (CheckControlAddrMode(p)) {
#if WantCycByPriOp
p->Cycles = 4 * kCycleScale + RdAvgXtraCyc;
p->Cycles += MoveMEACalcCyc(p,
mode(p), reg(p));
if (4 == p->opsize) {
p->Cycles += MoveAvgN * 8 * kCycleScale
+ 2 * MoveAvgN * RdAvgXtraCyc;
} else {
p->Cycles += MoveAvgN * 4 * kCycleScale
+ MoveAvgN * RdAvgXtraCyc;
}
#endif
if (4 == p->opsize) {
p->MainClass = kIKindMOVEMmrL;
} else {
p->MainClass = kIKindMOVEMmrW;
}
}
}
} else {
#if Use68020
p->opsize = 4;
if (CheckDataAddrMode(p)) {
if (((p->opcode >> 6) & 1) == 1) {
/* DIVU 0100110001mmmrrr 0rrr0s0000000rrr */
/* DIVS 0100110001mmmrrr 0rrr1s0000000rrr */
p->MainClass = kIKindDivL;
} else {
/* MULU 0100110000mmmrrr 0rrr0s0000000rrr */
/* MULS 0100110000mmmrrr 0rrr1s0000000rrr */
p->MainClass = kIKindMulL;
}
}
#else
p->MainClass = kIKindIllegal;
#endif
}
break;
case 7:
default: /* keep compiler happy */
switch (b76(p)) {
case 0:
p->MainClass = kIKindIllegal;
break;
case 1:
switch (mode(p)) {
case 0:
case 1:
/* Trap 010011100100vvvv */
#if WantCycByPriOp
p->Cycles = (34 * kCycleScale
+ 4 * RdAvgXtraCyc
+ 3 * WrAvgXtraCyc);
#endif
SetDcoArgFields(p, false,
kAMdDat4, (p->opcode & 15) + 32);
p->MainClass = kIKindTrap;
break;
case 2:
/* Link */
#if WantCycByPriOp
p->Cycles = (16 * kCycleScale
+ 2 * RdAvgXtraCyc
+ 2 * WrAvgXtraCyc);
#endif
SetDcoArgFields(p, false,
kAMdRegL, reg(p) + 8);
if (reg(p) == 6) {
p->MainClass = kIKindLinkA6;
} else {
p->MainClass = kIKindLink;
}
break;
case 3:
/* Unlk */
#if WantCycByPriOp
p->Cycles = (12 * kCycleScale
+ 3 * RdAvgXtraCyc);
#endif
SetDcoArgFields(p, false,
kAMdRegL, reg(p) + 8);
if (reg(p) == 6) {
p->MainClass = kIKindUnlkA6;
} else {
p->MainClass = kIKindUnlk;
}
break;
case 4:
/* MOVE USP 0100111001100aaa */
#if WantCycByPriOp
p->Cycles =
(4 * kCycleScale + RdAvgXtraCyc);
#endif
SetDcoArgFields(p, false,
kAMdRegL, reg(p) + 8);
p->MainClass = kIKindMoveRUSP;
break;
case 5:
/* MOVE USP 0100111001101aaa */
#if WantCycByPriOp
p->Cycles =
(4 * kCycleScale + RdAvgXtraCyc);
#endif
SetDcoArgFields(p, false,
kAMdRegL, reg(p) + 8);
p->MainClass = kIKindMoveUSPR;
break;
case 6:
switch (reg(p)) {
case 0:
/* Reset 0100111001100000 */
#if WantCycByPriOp
p->Cycles = (132 * kCycleScale
+ RdAvgXtraCyc);
#endif
p->MainClass = kIKindReset;
break;
case 1:
/* Nop = 0100111001110001 */
#if WantCycByPriOp
p->Cycles = (4 * kCycleScale
+ RdAvgXtraCyc);
#endif
p->MainClass = kIKindNop;
break;
case 2:
/* Stop 0100111001110010 */
#if WantCycByPriOp
p->Cycles = (4 * kCycleScale);
#endif
p->MainClass = kIKindStop;
break;
case 3:
/* Rte 0100111001110011 */
#if WantCycByPriOp
p->Cycles = (20 * kCycleScale
+ 5 * RdAvgXtraCyc);
#endif
p->MainClass = kIKindRte;
break;
case 4:
/* Rtd 0100111001110100 */
#if Use68020
p->MainClass = kIKindRtd;
#else
p->MainClass = kIKindIllegal;
#endif
break;
case 5:
/* Rts 0100111001110101 */
#if WantCycByPriOp
p->Cycles = (16 * kCycleScale
+ 4 * RdAvgXtraCyc);
#endif
p->MainClass = kIKindRts;
break;
case 6:
/* TrapV 0100111001110110 */
#if WantCycByPriOp
p->Cycles = (4 * kCycleScale
+ RdAvgXtraCyc);
#endif
p->MainClass = kIKindTrapV;
break;
case 7:
default: /* keep compiler happy */
/* Rtr 0100111001110111 */
#if WantCycByPriOp
p->Cycles = (20 * kCycleScale
+ 2 * RdAvgXtraCyc);
#endif
p->MainClass = kIKindRtr;
break;
}
break;
case 7:
default: /* keep compiler happy */
#if Use68020
/* MOVEC 010011100111101m */
switch (reg(p)) {
case 2:
p->MainClass = kIKindMoveCEa;
break;
case 3:
p->MainClass = kIKindMoveEaC;
break;
default:
p->MainClass = kIKindIllegal;
break;
}
#else
p->MainClass = kIKindIllegal;
#endif
break;
}
break;
case 2:
/* Jsr 0100111010mmmrrr */
if (CheckControlAddrMode(p)) {
#if WantCycByPriOp
switch (mode(p)) {
case 2:
p->Cycles = (16 * kCycleScale
+ 2 * RdAvgXtraCyc
+ 2 * WrAvgXtraCyc);
break;
case 5:
p->Cycles = (18 * kCycleScale
+ 2 * RdAvgXtraCyc
+ 2 * WrAvgXtraCyc);
break;
case 6:
p->Cycles = (22 * kCycleScale
+ 2 * RdAvgXtraCyc
+ 2 * WrAvgXtraCyc);
break;
case 7:
default: /* keep compiler happy */
switch (reg(p)) {
case 0:
p->Cycles =
(18 * kCycleScale
+ 2 * RdAvgXtraCyc
+ 2 * WrAvgXtraCyc);
break;
case 1:
p->Cycles =
(20 * kCycleScale
+ 3 * RdAvgXtraCyc
+ 2 * WrAvgXtraCyc);
break;
case 2:
p->Cycles =
(18 * kCycleScale
+ 2 * RdAvgXtraCyc
+ 2 * WrAvgXtraCyc);
break;
case 3:
default:
/* keep compiler happy */
p->Cycles =
(22 * kCycleScale
+ 2 * RdAvgXtraCyc
+ 2 * WrAvgXtraCyc);
break;
}
break;
}
#endif
p->MainClass = kIKindJsr;
}
break;
case 3:
default: /* keep compiler happy */
/* JMP 0100111011mmmrrr */
if (CheckControlAddrMode(p)) {
#if WantCycByPriOp
switch (mode(p)) {
case 2:
p->Cycles = (8 * kCycleScale
+ 2 * RdAvgXtraCyc);
break;
case 5:
p->Cycles = (10 * kCycleScale
+ 2 * RdAvgXtraCyc);
break;
case 6:
p->Cycles = (14 * kCycleScale
+ 2 * RdAvgXtraCyc);
break;
case 7:
default: /* keep compiler happy */
switch (reg(p)) {
case 0:
p->Cycles =
(10 * kCycleScale
+ 2 * RdAvgXtraCyc);
break;
case 1:
p->Cycles =
(12 * kCycleScale
+ 3 * RdAvgXtraCyc);
break;
case 2:
p->Cycles =
(10 * kCycleScale
+ 2 * RdAvgXtraCyc);
break;
case 3:
default:
/* keep compiler happy */
p->Cycles =
(14 * kCycleScale
+ 3 * RdAvgXtraCyc);
break;
}
break;
}
#endif
p->MainClass = kIKindJmp;
}
break;
}
break;
}
}
}
LOCALPROCUSEDONCE DeCode5(WorkR *p)
{
if (b76(p) == 3) {
p->DecOp.y.v[0].ArgDat = (p->opcode >> 8) & 15;
if (mode(p) == 1) {
/* DBcc 0101cccc11001ddd */
#if WantCycByPriOp
#if WantCloserCyc
p->Cycles = 0;
#else
p->Cycles = (11 * kCycleScale + 2 * RdAvgXtraCyc);
/*
average of cc true 12(2/0),
cc false taken 10(2/0),
and not 14(3/0)
*/
#endif
#endif
SetDcoArgFields(p, false, kAMdRegW, reg(p));
if (1 == ((p->opcode >> 8) & 15)) {
p->MainClass = kIKindDBF;
} else {
p->MainClass = kIKindDBcc;
}
} else {
#if Use68020
if ((mode(p) == 7) && (reg(p) >= 2)) {
/* TRAPcc 0101cccc11111sss */
p->DecOp.y.v[1].ArgDat = reg(p);
p->MainClass = kIKindTRAPcc;
} else
#endif
{
p->opsize = 1;
/* Scc 0101cccc11mmmrrr */
if (CheckDataAltAddrMode(p)) {
#if WantCycByPriOp
if (0 != mode(p)) {
p->Cycles = (8 * kCycleScale
+ RdAvgXtraCyc + WrAvgXtraCyc);
} else {
#if WantCloserCyc
p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
#else
p->Cycles = (5 * kCycleScale + RdAvgXtraCyc);
/* 4 when false, 6 when true */
#endif
}
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindScc;
}
}
}
} else {
if (mode(p) == 1) {
p->opsize = b8(p) * 2 + 2;
SetDcoArgFields(p, true, kAMdDat4,
octdat(rg9(p)));
SetDcoArgFields(p, false, kAMdRegL,
reg(p) + 8);
/* always long, regardless of opsize */
if (b8(p) == 0) {
#if WantCycByPriOp
p->Cycles = (4 == p->opsize)
? (8 * kCycleScale + RdAvgXtraCyc)
: (4 * kCycleScale + RdAvgXtraCyc);
#endif
p->MainClass = kIKindAddQA; /* AddQA 0101nnn0ss001rrr */
} else {
#if WantCycByPriOp
p->Cycles = (8 * kCycleScale + RdAvgXtraCyc);
#endif
p->MainClass = kIKindSubQA; /* SubQA 0101nnn1ss001rrr */
}
} else {
FindOpSizeFromb76(p);
SetDcoArgFields(p, true, kAMdDat4,
octdat(rg9(p)));
if (CheckValidAddrMode(p,
mode(p), reg(p), kAddrValidDataAlt, false))
{
#if WantCycByPriOp
if (0 != mode(p)) {
p->Cycles = (4 == p->opsize)
? (12 * kCycleScale
+ RdAvgXtraCyc + 2 * WrAvgXtraCyc)
: (8 * kCycleScale
+ RdAvgXtraCyc + WrAvgXtraCyc);
} else {
p->Cycles = (4 == p->opsize)
? (8 * kCycleScale + RdAvgXtraCyc)
: (4 * kCycleScale + RdAvgXtraCyc);
}
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
if (b8(p) == 0) {
/* AddQ 0101nnn0ssmmmrrr */
#if 0
if (CheckDataAltAddrMode(p)) {
p->MainClass = kIKindAddQ;
}
#endif
p->MainClass = kIKindAddB + OpSizeOffset(p);
} else {
/* SubQ 0101nnn1ssmmmrrr */
#if 0
if (CheckDataAltAddrMode(p)) {
p->MainClass = kIKindSubQ;
}
#endif
p->MainClass = kIKindSubB + OpSizeOffset(p);
}
}
}
}
}
LOCALPROCUSEDONCE DeCode6(WorkR *p)
{
uint32_t cond = (p->opcode >> 8) & 15;
if (cond == 1) {
/* Bsr 01100001nnnnnnnn */
#if WantCycByPriOp
p->Cycles = (18 * kCycleScale
+ 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc);
#endif
if (0 == (p->opcode & 255)) {
p->MainClass = kIKindBsrW;
} else
#if Use68020
if (255 == (p->opcode & 255)) {
p->MainClass = kIKindBsrL;
} else
#endif
{
p->MainClass = kIKindBsrB;
p->DecOp.y.v[1].ArgDat = p->opcode & 255;
}
} else if (cond == 0) {
/* Bra 01100000nnnnnnnn */
#if WantCycByPriOp
p->Cycles = (10 * kCycleScale + 2 * RdAvgXtraCyc);
#endif
if (0 == (p->opcode & 255)) {
p->MainClass = kIKindBraW;
} else
#if Use68020
if (255 == (p->opcode & 255)) {
p->MainClass = kIKindBraL;
} else
#endif
{
p->MainClass = kIKindBraB;
p->DecOp.y.v[1].ArgDat = p->opcode & 255;
}
} else {
p->DecOp.y.v[0].ArgDat = cond;
/* Bcc 0110ccccnnnnnnnn */
if (0 == (p->opcode & 255)) {
#if WantCycByPriOp
#if WantCloserCyc
p->Cycles = 0;
#else
p->Cycles = (11 * kCycleScale + 2 * RdAvgXtraCyc);
/* average of branch taken 10(2/0) and not 12(2/0) */
#endif
#endif
p->MainClass = kIKindBccW;
} else
#if Use68020
if (255 == (p->opcode & 255)) {
p->MainClass = kIKindBccL;
} else
#endif
{
#if WantCycByPriOp
#if WantCloserCyc
p->Cycles = 0;
#else
p->Cycles = (9 * kCycleScale
+ RdAvgXtraCyc + (RdAvgXtraCyc / 2));
/* average of branch taken 10(2/0) and not 8(1/0) */
#endif
#endif
p->MainClass = kIKindBccB;
p->DecOp.y.v[1].ArgDat = p->opcode & 255;
}
}
}
LOCALPROCUSEDONCE DeCode7(WorkR *p)
{
if (b8(p) == 0) {
p->opsize = 4;
#if WantCycByPriOp
p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
#endif
p->MainClass = kIKindMoveQ;
p->DecOp.y.v[0].ArgDat = p->opcode & 255;
p->DecOp.y.v[1].ArgDat = rg9(p);
} else {
p->MainClass = kIKindIllegal;
}
}
LOCALPROCUSEDONCE DeCode8(WorkR *p)
{
if (b76(p) == 3) {
p->opsize = 2;
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidData, true))
if (CheckValidAddrMode(p, 0, rg9(p),
kAddrValidAny, false))
{
if (b8(p) == 0) {
/* DivU 1000ddd011mmmrrr */
#if WantCycByPriOp
p->Cycles = RdAvgXtraCyc;
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#if ! WantCloserCyc
p->Cycles += 133 * kCycleScale;
/*
worse case 140, less than ten percent
different from best case
*/
#endif
#endif
p->MainClass = kIKindDivU;
} else {
/* DivS 1000ddd111mmmrrr */
#if WantCycByPriOp
p->Cycles = RdAvgXtraCyc;
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#if ! WantCloserCyc
p->Cycles += 150 * kCycleScale;
/*
worse case 158, less than ten percent different
from best case
*/
#endif
#endif
p->MainClass = kIKindDivS;
}
}
} else {
if (b8(p) == 0) {
/* OR 1000ddd0ssmmmrrr */
#if 0
if (CheckDataAddrMode(p)) {
p->MainClass = kIKindOrEaD;
}
#endif
FindOpSizeFromb76(p);
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidData, true))
if (CheckValidAddrMode(p, 0, rg9(p),
kAddrValidAny, false))
{
#if WantCycByPriOp
if (4 == p->opsize) {
if ((mode(p) < 2)
|| ((7 == mode(p)) && (reg(p) == 4)))
{
p->Cycles = (8 * kCycleScale + RdAvgXtraCyc);
} else {
p->Cycles = (6 * kCycleScale + RdAvgXtraCyc);
}
} else {
p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
}
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindOrEaD;
}
} else {
if (mode(p) < 2) {
switch (b76(p)) {
case 0:
/* SBCD 1000xxx10000mxxx */
#if WantCycByPriOp
if (0 != mode(p)) {
p->Cycles = (18 * kCycleScale
+ 3 * RdAvgXtraCyc + WrAvgXtraCyc);
} else {
p->Cycles = (6 * kCycleScale
+ RdAvgXtraCyc);
}
#endif
p->opsize = 1;
if (mode(p) == 0) {
if (CheckValidAddrMode(p, 0, reg(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, 0, rg9(p),
kAddrValidAny, false))
{
p->MainClass = kIKindSbcd;
}
} else {
if (CheckValidAddrMode(p, 4, reg(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, 4, rg9(p),
kAddrValidAny, false))
{
p->MainClass = kIKindSbcd;
}
}
break;
#if Use68020
case 1:
/* PACK 1000rrr10100mrrr */
if (mode(p) == 0) {
p->opsize = 2;
if (CheckValidAddrMode(p, 0, reg(p),
kAddrValidAny, true))
{
p->opsize = 1;
if (CheckValidAddrMode(p, 0, rg9(p),
kAddrValidAny, false))
{
p->MainClass = kIKindPack;
}
}
} else {
p->opsize = 2;
if (CheckValidAddrMode(p, 4, reg(p),
kAddrValidAny, true))
{
p->opsize = 1;
if (CheckValidAddrMode(p, 4, rg9(p),
kAddrValidAny, false))
{
p->MainClass = kIKindPack;
}
}
}
break;
case 2:
/* UNPK 1000rrr11000mrrr */
if (mode(p) == 0) {
p->opsize = 1;
if (CheckValidAddrMode(p, 0, reg(p),
kAddrValidAny, true))
{
p->opsize = 2;
if (CheckValidAddrMode(p, 0, rg9(p),
kAddrValidAny, false))
{
p->MainClass = kIKindUnpk;
}
}
} else {
p->opsize = 1;
if (CheckValidAddrMode(p, 4, reg(p),
kAddrValidAny, true))
{
p->opsize = 2;
if (CheckValidAddrMode(p, 4, rg9(p),
kAddrValidAny, false))
{
p->MainClass = kIKindUnpk;
}
}
}
break;
#endif
default:
p->MainClass = kIKindIllegal;
break;
}
} else {
/* OR 1000ddd1ssmmmrrr */
#if 0
if (CheckDataAltAddrMode(p)) {
p->MainClass = kIKindOrDEa;
}
#endif
FindOpSizeFromb76(p);
if (CheckValidAddrMode(p, 0, rg9(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidAltMem, false))
{
#if WantCycByPriOp
p->Cycles = (4 == p->opsize)
? (12 * kCycleScale
+ RdAvgXtraCyc + 2 * WrAvgXtraCyc)
: (8 * kCycleScale
+ RdAvgXtraCyc + WrAvgXtraCyc);
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindOrDEa;
}
}
}
}
}
LOCALPROCUSEDONCE DeCode9(WorkR *p)
{
if (b76(p) == 3) {
/* SUBA 1001dddm11mmmrrr */
#if 0
if (IsValidAddrMode(p)) {
p->MainClass = kIKindSubA;
}
#endif
p->opsize = b8(p) * 2 + 2;
SetDcoArgFields(p, false, kAMdRegL, rg9(p) + 8);
/* always long, regardless of opsize */
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidAny, true))
{
#if WantCycByPriOp
if (4 == p->opsize) {
if ((mode(p) < 2) || ((7 == mode(p)) && (reg(p) == 4)))
{
p->Cycles = (8 * kCycleScale + RdAvgXtraCyc);
} else {
p->Cycles = (6 * kCycleScale + RdAvgXtraCyc);
}
} else {
p->Cycles = (8 * kCycleScale + RdAvgXtraCyc);
}
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindSubA;
}
} else {
if (b8(p) == 0) {
/* SUB 1001ddd0ssmmmrrr */
#if 0
if (IsValidAddrMode(p)) {
p->MainClass = kIKindSubEaR;
}
#endif
FindOpSizeFromb76(p);
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, 0, rg9(p),
kAddrValidAny, false))
{
#if WantCycByPriOp
if (4 == p->opsize) {
if ((mode(p) < 2)
|| ((7 == mode(p)) && (reg(p) == 4)))
{
p->Cycles = (8 * kCycleScale + RdAvgXtraCyc);
} else {
p->Cycles = (6 * kCycleScale + RdAvgXtraCyc);
}
} else {
p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
}
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindSubB + OpSizeOffset(p);
}
} else {
if (mode(p) == 0) {
/* SUBX 1001ddd1ss000rrr */
/* p->MainClass = kIKindSubXd; */
FindOpSizeFromb76(p);
if (CheckValidAddrMode(p, 0, reg(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, 0, rg9(p),
kAddrValidAny, false))
{
#if WantCycByPriOp
p->Cycles = (4 == p->opsize)
? (8 * kCycleScale + RdAvgXtraCyc)
: (4 * kCycleScale + RdAvgXtraCyc);
#endif
p->MainClass = kIKindSubXB + OpSizeOffset(p);
}
} else if (mode(p) == 1) {
/* SUBX 1001ddd1ss001rrr */
/* p->MainClass = kIKindSubXm; */
FindOpSizeFromb76(p);
if (CheckValidAddrMode(p, 4, reg(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, 4, rg9(p),
kAddrValidAny, false))
{
#if WantCycByPriOp
p->Cycles = (4 == p->opsize)
? (30 * kCycleScale
+ 5 * RdAvgXtraCyc + 2 * WrAvgXtraCyc)
: (18 * kCycleScale
+ 3 * RdAvgXtraCyc + 1 * WrAvgXtraCyc);
#endif
p->MainClass = kIKindSubXB + OpSizeOffset(p);
}
} else {
/* SUB 1001ddd1ssmmmrrr */
#if 0
if (CheckAltMemAddrMode(p)) {
p->MainClass = kIKindSubREa;
}
#endif
FindOpSizeFromb76(p);
if (CheckValidAddrMode(p, 0, rg9(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, mode(p),
reg(p), kAddrValidAltMem, false))
{
#if WantCycByPriOp
p->Cycles = (4 == p->opsize)
? (12 * kCycleScale
+ RdAvgXtraCyc + 2 * WrAvgXtraCyc)
: (8 * kCycleScale
+ RdAvgXtraCyc + WrAvgXtraCyc);
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindSubB + OpSizeOffset(p);
}
}
}
}
}
LOCALPROCUSEDONCE DeCodeA(WorkR *p)
{
#if WantCycByPriOp
p->Cycles = (34 * kCycleScale
+ 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc);
#endif
p->MainClass = kIKindA;
}
LOCALPROCUSEDONCE DeCodeB(WorkR *p)
{
if (b76(p) == 3) {
/* CMPA 1011ddds11mmmrrr */
#if 0
if (IsValidAddrMode(p)) {
p->MainClass = kIKindCmpA;
}
#endif
p->opsize = b8(p) * 2 + 2;
SetDcoArgFields(p, false, kAMdRegL, rg9(p) + 8);
/* always long, regardless of opsize */
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidAny, true))
{
#if WantCycByPriOp
p->Cycles = (6 * kCycleScale + RdAvgXtraCyc);
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindCmpA;
}
} else if (b8(p) == 1) {
if (mode(p) == 1) {
/* CmpM 1011ddd1ss001rrr */
#if 0
p->MainClass = kIKindCmpM;
#endif
FindOpSizeFromb76(p);
if (CheckValidAddrMode(p, 3, reg(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, 3, rg9(p),
kAddrValidAny, false))
{
#if WantCycByPriOp
p->Cycles = (4 == p->opsize)
? (20 * kCycleScale + 5 * RdAvgXtraCyc)
: (12 * kCycleScale + 3 * RdAvgXtraCyc);
#endif
p->MainClass = kIKindCmpB + OpSizeOffset(p);
}
} else {
#if 0
/* Eor 1011ddd1ssmmmrrr */
if (CheckDataAltAddrMode(p)) {
p->MainClass = kIKindEor;
}
#endif
FindOpSizeFromb76(p);
if (CheckValidAddrMode(p, 0, rg9(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidDataAlt, false))
{
#if WantCycByPriOp
if (0 != mode(p)) {
p->Cycles = (4 == p->opsize)
? (12 * kCycleScale
+ RdAvgXtraCyc + 2 * WrAvgXtraCyc)
: (8 * kCycleScale
+ RdAvgXtraCyc + WrAvgXtraCyc);
} else {
p->Cycles = (4 == p->opsize)
? (8 * kCycleScale + RdAvgXtraCyc)
: (4 * kCycleScale + RdAvgXtraCyc);
}
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindEor;
}
}
} else {
/* Cmp 1011ddd0ssmmmrrr */
#if 0
if (IsValidAddrMode(p)) {
p->MainClass = kIKindCmp;
}
#endif
FindOpSizeFromb76(p);
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, 0, rg9(p),
kAddrValidAny, false))
{
#if WantCycByPriOp
p->Cycles = (4 == p->opsize)
? (6 * kCycleScale + RdAvgXtraCyc)
: (4 * kCycleScale + RdAvgXtraCyc);
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindCmpB + OpSizeOffset(p);
}
}
}
LOCALPROCUSEDONCE DeCodeC(WorkR *p)
{
if (b76(p) == 3) {
p->opsize = 2;
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidData, true))
if (CheckValidAddrMode(p, 0, rg9(p),
kAddrValidAny, false))
{
#if WantCycByPriOp
#if WantCloserCyc
p->Cycles = (38 * kCycleScale + RdAvgXtraCyc);
#else
p->Cycles = (54 * kCycleScale + RdAvgXtraCyc);
/* worst case 70, best case 38 */
#endif
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
if (b8(p) == 0) {
/* MulU 1100ddd011mmmrrr */
p->MainClass = kIKindMulU;
} else {
/* MulS 1100ddd111mmmrrr */
p->MainClass = kIKindMulS;
}
}
} else {
if (b8(p) == 0) {
/* And 1100ddd0ssmmmrrr */
#if 0
if (CheckDataAddrMode(p)) {
p->MainClass = kIKindAndEaD;
}
#endif
FindOpSizeFromb76(p);
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidData, true))
if (CheckValidAddrMode(p, 0, rg9(p),
kAddrValidAny, false))
{
#if WantCycByPriOp
if (4 == p->opsize) {
if ((mode(p) < 2)
|| ((7 == mode(p)) && (reg(p) == 4)))
{
p->Cycles = (8 * kCycleScale + RdAvgXtraCyc);
} else {
p->Cycles = (6 * kCycleScale + RdAvgXtraCyc);
}
} else {
p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
}
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindAndEaD;
}
} else {
if (mode(p) < 2) {
switch (b76(p)) {
case 0:
/* ABCD 1100ddd10000mrrr */
#if WantCycByPriOp
if (0 != mode(p)) {
p->Cycles = (18 * kCycleScale
+ 3 * RdAvgXtraCyc + WrAvgXtraCyc);
} else {
p->Cycles = (6 * kCycleScale
+ RdAvgXtraCyc);
}
#endif
p->opsize = 1;
if (mode(p) == 0) {
if (CheckValidAddrMode(p, 0, reg(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, 0, rg9(p),
kAddrValidAny, false))
{
p->MainClass = kIKindAbcd;
}
} else {
if (CheckValidAddrMode(p, 4, reg(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, 4, rg9(p),
kAddrValidAny, false))
{
p->MainClass = kIKindAbcd;
}
}
break;
case 1:
/* Exg 1100ddd10100trrr */
#if WantCycByPriOp
p->Cycles = (6 * kCycleScale + RdAvgXtraCyc);
#endif
p->opsize = 4;
if (mode(p) == 0) {
if (CheckValidAddrMode(p, 0, rg9(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, 0, reg(p),
kAddrValidAny, false))
{
p->MainClass = kIKindExg;
}
} else {
if (CheckValidAddrMode(p, 1, rg9(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, 1, reg(p),
kAddrValidAny, false))
{
p->MainClass = kIKindExg;
}
}
break;
case 2:
default: /* keep compiler happy */
if (mode(p) == 0) {
p->MainClass = kIKindIllegal;
} else {
/* Exg 1100ddd110001rrr */
#if WantCycByPriOp
p->Cycles = (6 * kCycleScale
+ RdAvgXtraCyc);
#endif
if (CheckValidAddrMode(p, 0, rg9(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, 1, reg(p),
kAddrValidAny, false))
{
p->MainClass = kIKindExg;
}
}
break;
}
} else {
/* And 1100ddd1ssmmmrrr */
#if 0
if (CheckAltMemAddrMode(p)) {
p->MainClass = kIKindAndDEa;
}
#endif
FindOpSizeFromb76(p);
if (CheckValidAddrMode(p, 0, rg9(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidAltMem, false))
{
#if WantCycByPriOp
p->Cycles = (4 == p->opsize)
? (12 * kCycleScale
+ RdAvgXtraCyc + 2 * WrAvgXtraCyc)
: (8 * kCycleScale
+ RdAvgXtraCyc + WrAvgXtraCyc);
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindAndDEa;
}
}
}
}
}
LOCALPROCUSEDONCE DeCodeD(WorkR *p)
{
if (b76(p) == 3) {
/* ADDA 1101dddm11mmmrrr */
p->opsize = b8(p) * 2 + 2;
SetDcoArgFields(p, false, kAMdRegL, rg9(p) + 8);
/* always long, regardless of opsize */
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidAny, true))
{
#if WantCycByPriOp
if (4 == p->opsize) {
if ((mode(p) < 2) || ((7 == mode(p)) && (reg(p) == 4)))
{
p->Cycles = (8 * kCycleScale + RdAvgXtraCyc);
} else {
p->Cycles = (6 * kCycleScale + RdAvgXtraCyc);
}
} else {
p->Cycles = (8 * kCycleScale + RdAvgXtraCyc);
}
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindAddA;
}
} else {
if (b8(p) == 0) {
/* ADD 1101ddd0ssmmmrrr */
FindOpSizeFromb76(p);
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, 0, rg9(p),
kAddrValidAny, false))
{
#if WantCycByPriOp
if (4 == p->opsize) {
if ((mode(p) < 2)
|| ((7 == mode(p)) && (reg(p) == 4)))
{
p->Cycles = (8 * kCycleScale + RdAvgXtraCyc);
} else {
p->Cycles = (6 * kCycleScale + RdAvgXtraCyc);
}
} else {
p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
}
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindAddB + OpSizeOffset(p);
}
} else {
if (mode(p) == 0) {
/* ADDX 1101ddd1ss000rrr */
/* p->MainClass = kIKindAddXd; */
FindOpSizeFromb76(p);
if (CheckValidAddrMode(p, 0, reg(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, 0, rg9(p),
kAddrValidAny, false))
{
#if WantCycByPriOp
p->Cycles = (4 == p->opsize)
? (8 * kCycleScale + RdAvgXtraCyc)
: (4 * kCycleScale + RdAvgXtraCyc);
#endif
p->MainClass = kIKindAddXB + OpSizeOffset(p);
}
} else if (mode(p) == 1) {
/* p->MainClass = kIKindAddXm; */
FindOpSizeFromb76(p);
if (CheckValidAddrMode(p, 4, reg(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, 4, rg9(p),
kAddrValidAny, false))
{
#if WantCycByPriOp
p->Cycles = (4 == p->opsize)
? (30 * kCycleScale
+ 5 * RdAvgXtraCyc + 2 * WrAvgXtraCyc)
: (18 * kCycleScale
+ 3 * RdAvgXtraCyc + 1 * WrAvgXtraCyc);
#endif
p->MainClass = kIKindAddXB + OpSizeOffset(p);
}
} else {
/* ADD 1101ddd1ssmmmrrr */
FindOpSizeFromb76(p);
if (CheckValidAddrMode(p, 0, rg9(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, mode(p), reg(p),
kAddrValidAltMem, false))
{
#if WantCycByPriOp
p->Cycles = (4 == p->opsize)
? (12 * kCycleScale
+ RdAvgXtraCyc + 2 * WrAvgXtraCyc)
: (8 * kCycleScale
+ RdAvgXtraCyc + WrAvgXtraCyc);
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = kIKindAddB + OpSizeOffset(p);
}
}
}
}
}
LOCALFUNC uint32_t rolops(WorkR *p, uint32_t x)
{
uint32_t binop;
binop = (x << 1);
if (! b8(p)) {
binop++; /* 'R' */
} /* else 'L' */
return kIKindAslB + 3 * binop + OpSizeOffset(p);
}
LOCALPROCUSEDONCE DeCodeE(WorkR *p)
{
if (b76(p) == 3) {
if ((p->opcode & 0x0800) != 0) {
#if Use68020
/* 11101???11mmmrrr */
p->DecOp.y.v[0].AMd = mode(p);
p->DecOp.y.v[0].ArgDat = (p->opcode >> 8) & 7;
if (0 == mode(p)) {
SetDcoArgFields(p, false, kAMdRegL, reg(p));
p->MainClass = kIKindBitField;
} else {
switch ((p->opcode >> 8) & 7) {
case 0: /* BFTST */
case 1: /* BFEXTU */
case 3: /* BFEXTS */
case 5: /* BFFFO */
if (CheckControlAddrMode(p)) {
p->MainClass = kIKindBitField;
}
break;
default: /* BFCHG, BFCLR, BFSET, BFINS */
if (CheckControlAltAddrMode(p)) {
p->MainClass = kIKindBitField;
}
break;
}
}
#else
p->MainClass = kIKindIllegal;
#endif
} else {
p->opsize = 2;
/* 11100ttd11mmmddd */
if (CheckAltMemAddrMode(p)) {
#if WantCycByPriOp
p->Cycles = (6 * kCycleScale
#if ! WantCloserCyc
+ 2 * kCycleScale
#endif
+ RdAvgXtraCyc + WrAvgXtraCyc);
p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
#endif
p->MainClass = rolops(p, rg9(p));
SetDcoArgFields(p, true, kAMdDat4, 1);
}
}
} else {
FindOpSizeFromb76(p);
if (mode(p) < 4) {
/* 1110cccdss0ttddd */
if (CheckValidAddrMode(p, 0, reg(p),
kAddrValidAny, false))
{
#if WantCycByPriOp
p->Cycles = ((4 == p->opsize)
? (8 * kCycleScale + RdAvgXtraCyc)
: (6 * kCycleScale + RdAvgXtraCyc))
#if ! WantCloserCyc
+ (octdat(rg9(p)) * (2 * kCycleScale))
#endif
;
#endif
p->MainClass = rolops(p, mode(p) & 3);
SetDcoArgFields(p, true, kAMdDat4, octdat(rg9(p)));
}
} else {
/* 1110rrrdss1ttddd */
if (CheckValidAddrMode(p, 0, rg9(p),
kAddrValidAny, true))
if (CheckValidAddrMode(p, 0, reg(p),
kAddrValidAny, false))
{
#if WantCycByPriOp
#if WantCloserCyc
p->Cycles = ((4 == p->opsize)
? (8 * kCycleScale + RdAvgXtraCyc)
: (6 * kCycleScale + RdAvgXtraCyc));
#else
p->Cycles = (4 == p->opsize)
? ((8 * kCycleScale)
+ RdAvgXtraCyc + (8 * (2 * kCycleScale)))
/* say average shift count of 8 */
: ((6 * kCycleScale)
+ RdAvgXtraCyc + (4 * (2 * kCycleScale)));
/* say average shift count of 4 */
#endif
#endif
p->MainClass = rolops(p, mode(p) & 3);
}
}
}
}
LOCALPROCUSEDONCE DeCodeF(WorkR *p)
{
#if WantCycByPriOp
p->Cycles =
(34 * kCycleScale + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc);
#endif
p->DecOp.y.v[0].AMd = (p->opcode >> 8) & 0xFF;
p->DecOp.y.v[0].ArgDat = (p->opcode ) & 0xFF;
#if EmMMU || EmFPU
switch (rg9(p)) {
#if EmMMU
case 0:
p->MainClass = kIKindMMU;
break;
#endif
#if EmFPU
case 1:
switch (md6(p)) {
case 0:
p->MainClass = kIKindFPUmd60;
break;
case 1:
if (mode(p) == 1) {
p->MainClass = kIKindFPUDBcc;
} else if (mode(p) == 7) {
p->MainClass = kIKindFPUTrapcc;
} else {
p->MainClass = kIKindFPUScc;
}
break;
case 2:
p->MainClass = kIKindFPUFBccW;
break;
case 3:
p->MainClass = kIKindFPUFBccL;
break;
case 4:
p->MainClass = kIKindFPUSave;
break;
case 5:
p->MainClass = kIKindFPURestore;
break;
default:
p->MainClass = kIKindFPUdflt;
break;
}
break;
#endif
default:
p->MainClass = kIKindFdflt;
break;
}
#else
p->MainClass = kIKindFdflt;
#endif
}
LOCALPROC DeCodeOneOp(WorkR *p)
{
switch (p->opcode >> 12) {
case 0x0:
DeCode0(p);
break;
case 0x1:
DeCode1(p);
break;
case 0x2:
DeCode2(p);
break;
case 0x3:
DeCode3(p);
break;
case 0x4:
DeCode4(p);
break;
case 0x5:
DeCode5(p);
break;
case 0x6:
DeCode6(p);
break;
case 0x7:
DeCode7(p);
break;
case 0x8:
DeCode8(p);
break;
case 0x9:
DeCode9(p);
break;
case 0xA:
DeCodeA(p);
break;
case 0xB:
DeCodeB(p);
break;
case 0xC:
DeCodeC(p);
break;
case 0xD:
DeCodeD(p);
break;
case 0xE:
DeCodeE(p);
break;
case 0xF:
default: /* keep compiler happy */
DeCodeF(p);
break;
}
if (kIKindIllegal == p->MainClass) {
#if WantCycByPriOp
p->Cycles = (34 * kCycleScale
+ 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc);
#endif
p->DecOp.y.v[0].AMd = 0;
p->DecOp.y.v[0].ArgDat = 0;
p->DecOp.y.v[1].AMd = 0;
p->DecOp.y.v[1].ArgDat = 0;
}
SetDcoMainClas(&(p->DecOp), p->MainClass);
#if WantCycByPriOp
SetDcoCycles(&(p->DecOp), p->Cycles);
#else
SetDcoCycles(&(p->DecOp), kAvgCycPerInstr);
#endif
}
GLOBALPROC M68KITAB_setup(DecOpR *p)
{
uint32_t i;
WorkR r;
for (i = 0; i < (uint32_t)256 * 256; ++i) {
r.opcode = i;
r.MainClass = kIKindIllegal;
r.DecOp.y.v[0].AMd = 0;
r.DecOp.y.v[0].ArgDat = 0;
r.DecOp.y.v[1].AMd = 0;
r.DecOp.y.v[1].ArgDat = 0;
#if WantCycByPriOp
r.Cycles = kAvgCycPerInstr;
#endif
DeCodeOneOp(&r);
p[i] = r.DecOp;
}
}