ref: d488fabe62aabd0d42421eb3e423a9308ae1fa13
dir: /src/M68KITAB.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 "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #include "M68KITAB.h" struct WorkR { /* expected size : 8 bytes */ ui5b opcode; ui5b opsize; ui4r MainClass; #if WantCycByPriOp ui4r 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 kMyAvgCycPerInstr (10 * kCycleScale + (40 * kCycleScale / 64)) LOCALFUNC ui3r GetAMdRegSz(WorkR *p) { ui3r 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 ui3r GetAMdIndirectSz(WorkR *p) { ui3r 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 ui4r OpEACalcCyc(WorkR *p, ui3r m, ui3r r) { ui4r 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 ui4r OpEADestCalcCyc(WorkR *p, ui3r m, ui3r r) { ui4r 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, blnr src, ui3r CurAMd, ui3r 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 blnr CheckValidAddrMode(WorkR *p, ui3r m, ui3r r, ui3r v, blnr src) { ui3r CurAMd = 0; /* init to keep compiler happy */ ui3r CurArgDat = 0; blnr 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 = falseblnr; break; } break; default: /* keep compiler happy */ IsOk = falseblnr; break; } if (IsOk) { SetDcoArgFields(p, src, CurAMd, CurArgDat); } return IsOk; } #if WantCycByPriOp LOCALFUNC blnr LeaPeaEACalcCyc(WorkR *p, ui3r m, ui3r r) { ui4r 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 blnr IsValidAddrMode(WorkR *p) { return CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, falseblnr); } LOCALFUNC blnr CheckDataAltAddrMode(WorkR *p) { return CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr); } LOCALFUNC blnr CheckDataAddrMode(WorkR *p) { return CheckValidAddrMode(p, mode(p), reg(p), kAddrValidData, falseblnr); } LOCALFUNC blnr CheckControlAddrMode(WorkR *p) { return CheckValidAddrMode(p, mode(p), reg(p), kAddrValidControl, falseblnr); } LOCALFUNC blnr CheckControlAltAddrMode(WorkR *p) { return CheckValidAddrMode(p, mode(p), reg(p), kAddrValidControlAlt, falseblnr); } LOCALFUNC blnr CheckAltMemAddrMode(WorkR *p) { return CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAltMem, falseblnr); } 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 ui3r OpSizeOffset(WorkR *p) { ui3r v; switch (p->opsize) { case 1 : v = 0; break; case 2 : v = 1; break; case 4 : default : v = 2; break; } return v; } LOCALFUNC ui5r octdat(ui5r 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, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { 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, trueblnr, kAMdRegL, rg9(p)); SetDcoArgFields(p, falseblnr, kAMdRegL, reg(p)); } else { p->opsize = 1; p->MainClass = kIKindBTstB + b76(p); SetDcoArgFields(p, trueblnr, 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, trueblnr, kAMdImmedB, 0); SetDcoArgFields(p, falseblnr, kAMdRegL, reg(p)); p->MainClass = kIKindBTstL + b76(p); } else { p->opsize = 1; SetDcoArgFields(p, trueblnr, kAMdImmedB, 0); p->MainClass = kIKindBTstB + b76(p); if (b76(p) == 0) { /* BTst */ if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataNoCn, falseblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataNoCn, falseblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, md6(p), rg9(p), kAddrValidDataAlt, falseblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, 1, rg9(p), kAddrValidAny, falseblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, md6(p), rg9(p), kAddrValidDataAlt, falseblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, 1, rg9(p), kAddrValidAny, falseblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, md6(p), rg9(p), kAddrValidDataAlt, falseblnr)) { #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 ui4r MoveMEACalcCyc(WorkR *p, ui3r m, ui3r r) { ui4r 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, falseblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, trueblnr)) { #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, falseblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, trueblnr)) { #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, falseblnr, 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, falseblnr, 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, falseblnr, 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, falseblnr, 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, falseblnr, 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, falseblnr, 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, falseblnr, 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, falseblnr, 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, falseblnr, 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, falseblnr, 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, falseblnr, 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, falseblnr, kAMdRegL, reg(p) + 8); p->MainClass = kIKindMoveRUSP; break; case 5: /* MOVE USP 0100111001101aaa */ #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); #endif SetDcoArgFields(p, falseblnr, 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, falseblnr, 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, trueblnr, kAMdDat4, octdat(rg9(p))); SetDcoArgFields(p, falseblnr, 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, trueblnr, kAMdDat4, octdat(rg9(p))); if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr)) { #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) { ui5b 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, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { 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, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { p->MainClass = kIKindSbcd; } } else { if (CheckValidAddrMode(p, 4, reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 4, rg9(p), kAddrValidAny, falseblnr)) { p->MainClass = kIKindSbcd; } } break; #if Use68020 case 1: /* PACK 1000rrr10100mrrr */ if (mode(p) == 0) { p->opsize = 2; if (CheckValidAddrMode(p, 0, reg(p), kAddrValidAny, trueblnr)) { p->opsize = 1; if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { p->MainClass = kIKindPack; } } } else { p->opsize = 2; if (CheckValidAddrMode(p, 4, reg(p), kAddrValidAny, trueblnr)) { p->opsize = 1; if (CheckValidAddrMode(p, 4, rg9(p), kAddrValidAny, falseblnr)) { p->MainClass = kIKindPack; } } } break; case 2: /* UNPK 1000rrr11000mrrr */ if (mode(p) == 0) { p->opsize = 1; if (CheckValidAddrMode(p, 0, reg(p), kAddrValidAny, trueblnr)) { p->opsize = 2; if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { p->MainClass = kIKindUnpk; } } } else { p->opsize = 1; if (CheckValidAddrMode(p, 4, reg(p), kAddrValidAny, trueblnr)) { p->opsize = 2; if (CheckValidAddrMode(p, 4, rg9(p), kAddrValidAny, falseblnr)) { 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, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAltMem, falseblnr)) { #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, falseblnr, kAMdRegL, rg9(p) + 8); /* always long, regardless of opsize */ if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, 4, rg9(p), kAddrValidAny, falseblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAltMem, falseblnr)) { #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, falseblnr, kAMdRegL, rg9(p) + 8); /* always long, regardless of opsize */ if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, 3, rg9(p), kAddrValidAny, falseblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { p->MainClass = kIKindAbcd; } } else { if (CheckValidAddrMode(p, 4, reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 4, rg9(p), kAddrValidAny, falseblnr)) { 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, trueblnr)) if (CheckValidAddrMode(p, 0, reg(p), kAddrValidAny, falseblnr)) { p->MainClass = kIKindExg; } } else { if (CheckValidAddrMode(p, 1, rg9(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 1, reg(p), kAddrValidAny, falseblnr)) { 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, trueblnr)) if (CheckValidAddrMode(p, 1, reg(p), kAddrValidAny, falseblnr)) { 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, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAltMem, falseblnr)) { #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, falseblnr, kAMdRegL, rg9(p) + 8); /* always long, regardless of opsize */ if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, 4, rg9(p), kAddrValidAny, falseblnr)) { #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, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAltMem, falseblnr)) { #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 ui5r rolops(WorkR *p, ui5r x) { ui5r 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, falseblnr, 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, trueblnr, kAMdDat4, 1); } } } else { FindOpSizeFromb76(p); if (mode(p) < 4) { /* 1110cccdss0ttddd */ if (CheckValidAddrMode(p, 0, reg(p), kAddrValidAny, falseblnr)) { #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, trueblnr, kAMdDat4, octdat(rg9(p))); } } else { /* 1110rrrdss1ttddd */ if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 0, reg(p), kAddrValidAny, falseblnr)) { #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), kMyAvgCycPerInstr); #endif } GLOBALPROC M68KITAB_setup(DecOpR *p) { ui5b i; WorkR r; for (i = 0; i < (ui5b)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 = kMyAvgCycPerInstr; #endif DeCodeOneOp(&r); p[i] = r.DecOp; } }