uvmac/src/M68K/MINEM68K.c

8925 lines
189 KiB
C

/*
MINEM68K.c
Copyright (C) 2009 Bernd Schmidt, 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.
*/
/*
EMulator of 68K cpu with GENeric c code (not assembly)
This code descends from a simple 68000 emulator that I
(Paul C. Pratt) wrote long ago. That emulator ran on a 680x0,
and used the cpu it ran on to do some of the work. This
descendent fills in those holes with code from the
Un*x Amiga Emulator by Bernd Schmidt, as found being used in vMac.
This emulator is about 10 times smaller than the UAE,
at the cost of being 2 to 3 times slower.
FPU Emulation added 9/12/2009 by Ross Martin
(this code now located in "FPCPEMDV.h")
*/
#ifndef AllFiles
#include "SYSDEPNS.h"
#include "UI/MYOSGLUE.h"
#include "ENDIANAC.h"
#include "EMCONFIG.h"
#include "GLOBGLUE.h"
#include "M68K/M68KITAB.h"
#if WantDisasm
#include "M68K/DISAM68K.h"
#endif
#endif
#include "M68K/MINEM68K.h"
/*
ReportAbnormalID unused 0x0123 - 0x01FF
*/
#ifndef DisableLazyFlagAll
#define DisableLazyFlagAll 0
#endif
/*
useful for debugging, to tell if an observed bug is
being cause by lazy flag evaluation stuff.
Can also disable parts of it individually:
*/
#ifndef ForceFlagsEval
#if DisableLazyFlagAll
#define ForceFlagsEval 1
#else
#define ForceFlagsEval 0
#endif
#endif
#ifndef UseLazyZ
#if DisableLazyFlagAll || ForceFlagsEval
#define UseLazyZ 0
#else
#define UseLazyZ 1
#endif
#endif
#ifndef UseLazyCC
#if DisableLazyFlagAll
#define UseLazyCC 0
#else
#define UseLazyCC 1
#endif
#endif
typedef unsigned char flagtype; /* must be 0 or 1, not boolean */
/* Memory Address Translation Cache record */
struct MATCr {
uint32_t cmpmask;
uint32_t cmpvalu;
uint32_t usemask;
uint8_t * usebase;
};
typedef struct MATCr MATCr;
typedef MATCr *MATCp;
#ifndef USE_PCLIMIT
#define USE_PCLIMIT 1
#endif
#define AKMemory 0
#define AKRegister 1
union ArgAddrT {
uint32_t mem;
uint32_t *rga;
};
typedef union ArgAddrT ArgAddrT;
enum {
kLazyFlagsDefault,
kLazyFlagsTstB,
kLazyFlagsTstW,
kLazyFlagsTstL,
kLazyFlagsCmpB,
kLazyFlagsCmpW,
kLazyFlagsCmpL,
kLazyFlagsSubB,
kLazyFlagsSubW,
kLazyFlagsSubL,
kLazyFlagsAddB,
kLazyFlagsAddW,
kLazyFlagsAddL,
kLazyFlagsNegB,
kLazyFlagsNegW,
kLazyFlagsNegL,
kLazyFlagsAsrB,
kLazyFlagsAsrW,
kLazyFlagsAsrL,
kLazyFlagsAslB,
kLazyFlagsAslW,
kLazyFlagsAslL,
#if UseLazyZ
kLazyFlagsZSet,
#endif
kNumLazyFlagsKinds
};
typedef void (reg_call *ArgSetDstP)(uint32_t f);
#define FasterAlignedL 0
/*
If most long memory access is long aligned,
this should be faster. But on the Mac, this
doesn't seem to be the case, so an
unpredictable branch slows it down.
*/
#ifndef HaveGlbReg
#define HaveGlbReg 0
#endif
LOCALVAR struct regstruct
{
uint32_t regs[16]; /* Data and Address registers */
uint8_t * pc_p;
uint8_t * pc_pHi;
int32_t MaxCyclesToGo;
#if WantCloserCyc
DecOpR *CurDecOp;
#endif
DecOpYR CurDecOpY;
uint8_t LazyFlagKind;
uint8_t LazyXFlagKind;
#if UseLazyZ
uint8_t LazyFlagZSavedKind;
#endif
uint32_t LazyFlagArgSrc;
uint32_t LazyFlagArgDst;
uint32_t LazyXFlagArgSrc;
uint32_t LazyXFlagArgDst;
ArgAddrT ArgAddr;
ArgSetDstP ArgSetDst;
uint32_t SrcVal;
uint8_t * pc_pLo;
uint32_t pc; /* Program Counter */
MATCr MATCrdB;
MATCr MATCwrB;
MATCr MATCrdW;
MATCr MATCwrW;
#if FasterAlignedL
MATCr MATCrdL;
MATCr MATCwrL;
#endif
ATTep HeadATTel;
int32_t MoreCyclesToGo;
int32_t ResidualCycles;
uint8_t fakeword[2];
/* Status Register */
uint32_t intmask; /* bits 10-8 : interrupt priority mask */
flagtype t1; /* bit 15: Trace mode 1 */
#if Use68020
flagtype t0; /* bit 14: Trace mode 0 */
#endif
flagtype s; /* bit 13: Supervisor or user privilege level */
#if Use68020
flagtype m; /* bit 12: Master or interrupt mode */
#endif
flagtype x; /* bit 4: eXtend */
flagtype n; /* bit 3: Negative */
flagtype z; /* bit 2: Zero */
flagtype v; /* bit 1: oVerflow */
flagtype c; /* bit 0: Carry */
#if EmMMU | EmFPU
uint32_t ArgKind;
#endif
bool TracePending;
bool ExternalInterruptPending;
#if 0
bool ResetPending;
#endif
uint8_t *fIPL;
#ifdef r_regs
struct regstruct *save_regs;
#endif
CPTR usp; /* User Stack Pointer */
CPTR isp; /* Interrupt Stack Pointer */
#if Use68020
CPTR msp; /* Master Stack Pointer */
uint32_t sfc; /* Source Function Code register */
uint32_t dfc; /* Destination Function Code register */
uint32_t vbr; /* Vector Base Register */
uint32_t cacr; /* Cache Control Register */
/*
bit 0 : Enable Cache
bit 1 : Freeze Cache
bit 2 : Clear Entry In Cache (write only)
bit 3 : Clear Cache (write only)
*/
uint32_t caar; /* Cache Address Register */
#endif
#define disp_table_sz (256 * 256)
#if SmallGlobals
DecOpR *disp_table;
#else
DecOpR disp_table[disp_table_sz];
#endif
} regs;
#define uint32_t_MSBisSet(x) (((int32_t)(x)) < 0)
#define Bool2Bit(x) ((x) ? 1 : 0)
#ifdef r_regs
register struct regstruct *g_regs asm (r_regs);
#define V_regs (*g_regs)
#else
#define V_regs regs
#endif
#ifdef r_pc_p
register uint8_t * g_pc_p asm (r_pc_p);
#define V_pc_p g_pc_p
#else
#define V_pc_p V_regs.pc_p
#endif
#ifdef r_MaxCyclesToGo
register int32_t g_MaxCyclesToGo asm (r_MaxCyclesToGo);
#define V_MaxCyclesToGo g_MaxCyclesToGo
#else
#define V_MaxCyclesToGo V_regs.MaxCyclesToGo
#endif
#ifdef r_pc_pHi
register uint8_t * g_pc_pHi asm (r_pc_pHi);
#define V_pc_pHi g_pc_pHi
#else
#define V_pc_pHi V_regs.pc_pHi
#endif
#define ZFLG V_regs.z
#define NFLG V_regs.n
#define CFLG V_regs.c
#define VFLG V_regs.v
#define XFLG V_regs.x
#define m68k_dreg(num) (V_regs.regs[(num)])
#define m68k_areg(num) (V_regs.regs[(num) + 8])
#ifndef WantDumpTable
#define WantDumpTable 0
#endif
#if WantDumpTable
LOCALVAR uint32_t DumpTable[kNumIKinds];
#endif
#if USE_PCLIMIT
FORWARDPROC Recalc_PC_Block(void);
FORWARDFUNC uint32_t reg_call Recalc_PC_BlockReturnUi5r(uint32_t v);
#endif
LOCALINLINEFUNC uint16_t nextiword(void)
/* NOT sign extended */
{
uint16_t r = do_get_mem_word(V_pc_p);
V_pc_p += 2;
#if USE_PCLIMIT
if (cond_rare(V_pc_p >= V_pc_pHi)) {
Recalc_PC_Block();
}
#endif
return r;
}
LOCALINLINEFUNC uint32_t nextiSByte(void)
{
uint32_t r = uint32_t_FromSByte(do_get_mem_byte(V_pc_p + 1));
V_pc_p += 2;
#if USE_PCLIMIT
if (cond_rare(V_pc_p >= V_pc_pHi)) {
return Recalc_PC_BlockReturnUi5r(r);
}
#endif
return r;
}
LOCALINLINEFUNC uint32_t nextiSWord(void)
/* NOT sign extended */
{
uint32_t r = uint32_t_FromSWord(do_get_mem_word(V_pc_p));
V_pc_p += 2;
#if USE_PCLIMIT
if (cond_rare(V_pc_p >= V_pc_pHi)) {
return Recalc_PC_BlockReturnUi5r(r);
}
#endif
return r;
}
FORWARDFUNC uint32_t nextilong_ext(void);
LOCALINLINEFUNC uint32_t nextilong(void)
{
uint32_t r = do_get_mem_long(V_pc_p);
V_pc_p += 4;
#if USE_PCLIMIT
/* could be two words in different blocks */
if (cond_rare(V_pc_p >= V_pc_pHi)) {
r = nextilong_ext();
}
#endif
return r;
}
LOCALINLINEPROC BackupPC(void)
{
V_pc_p -= 2;
#if USE_PCLIMIT
if (cond_rare(V_pc_p < V_regs.pc_pLo)) {
Recalc_PC_Block();
}
#endif
}
LOCALINLINEFUNC CPTR m68k_getpc(void)
{
return V_regs.pc + (V_pc_p - V_regs.pc_pLo);
}
FORWARDPROC DoCodeTst(void);
FORWARDPROC DoCodeCmpB(void);
FORWARDPROC DoCodeCmpW(void);
FORWARDPROC DoCodeCmpL(void);
FORWARDPROC DoCodeBccB(void);
FORWARDPROC DoCodeBccW(void);
FORWARDPROC DoCodeBraB(void);
FORWARDPROC DoCodeBraW(void);
FORWARDPROC DoCodeDBcc(void);
FORWARDPROC DoCodeDBF(void);
FORWARDPROC DoCodeSwap(void);
FORWARDPROC DoCodeMoveL(void);
FORWARDPROC DoCodeMoveW(void);
FORWARDPROC DoCodeMoveB(void);
FORWARDPROC DoCodeMoveA(void);
FORWARDPROC DoCodeMoveQ(void);
FORWARDPROC DoCodeAddB(void);
FORWARDPROC DoCodeAddW(void);
FORWARDPROC DoCodeAddL(void);
FORWARDPROC DoCodeSubB(void);
FORWARDPROC DoCodeSubW(void);
FORWARDPROC DoCodeSubL(void);
FORWARDPROC DoCodeLea(void);
FORWARDPROC DoCodePEA(void);
FORWARDPROC DoCodeA(void);
FORWARDPROC DoCodeBsrB(void);
FORWARDPROC DoCodeBsrW(void);
FORWARDPROC DoCodeJsr(void);
FORWARDPROC DoCodeLinkA6(void);
FORWARDPROC DoCodeMOVEMRmML(void);
FORWARDPROC DoCodeMOVEMApRL(void);
FORWARDPROC DoCodeUnlkA6(void);
FORWARDPROC DoCodeRts(void);
FORWARDPROC DoCodeJmp(void);
FORWARDPROC DoCodeClr(void);
FORWARDPROC DoCodeAddA(void);
FORWARDPROC DoCodeSubA(void);
FORWARDPROC DoCodeCmpA(void);
FORWARDPROC DoCodeAddXB(void);
FORWARDPROC DoCodeAddXW(void);
FORWARDPROC DoCodeAddXL(void);
FORWARDPROC DoCodeSubXB(void);
FORWARDPROC DoCodeSubXW(void);
FORWARDPROC DoCodeSubXL(void);
FORWARDPROC DoCodeAslB(void);
FORWARDPROC DoCodeAslW(void);
FORWARDPROC DoCodeAslL(void);
FORWARDPROC DoCodeAsrB(void);
FORWARDPROC DoCodeAsrW(void);
FORWARDPROC DoCodeAsrL(void);
FORWARDPROC DoCodeLslB(void);
FORWARDPROC DoCodeLslW(void);
FORWARDPROC DoCodeLslL(void);
FORWARDPROC DoCodeLsrB(void);
FORWARDPROC DoCodeLsrW(void);
FORWARDPROC DoCodeLsrL(void);
FORWARDPROC DoCodeRxlB(void);
FORWARDPROC DoCodeRxlW(void);
FORWARDPROC DoCodeRxlL(void);
FORWARDPROC DoCodeRxrB(void);
FORWARDPROC DoCodeRxrW(void);
FORWARDPROC DoCodeRxrL(void);
FORWARDPROC DoCodeRolB(void);
FORWARDPROC DoCodeRolW(void);
FORWARDPROC DoCodeRolL(void);
FORWARDPROC DoCodeRorB(void);
FORWARDPROC DoCodeRorW(void);
FORWARDPROC DoCodeRorL(void);
FORWARDPROC DoCodeBTstB(void);
FORWARDPROC DoCodeBChgB(void);
FORWARDPROC DoCodeBClrB(void);
FORWARDPROC DoCodeBSetB(void);
FORWARDPROC DoCodeBTstL(void);
FORWARDPROC DoCodeBChgL(void);
FORWARDPROC DoCodeBClrL(void);
FORWARDPROC DoCodeBSetL(void);
FORWARDPROC DoCodeAnd(void);
FORWARDPROC DoCodeOr(void);
FORWARDPROC DoCodeEor(void);
FORWARDPROC DoCodeNot(void);
FORWARDPROC DoCodeScc(void);
FORWARDPROC DoCodeNegXB(void);
FORWARDPROC DoCodeNegXW(void);
FORWARDPROC DoCodeNegXL(void);
FORWARDPROC DoCodeNegB(void);
FORWARDPROC DoCodeNegW(void);
FORWARDPROC DoCodeNegL(void);
FORWARDPROC DoCodeEXTW(void);
FORWARDPROC DoCodeEXTL(void);
FORWARDPROC DoCodeMulU(void);
FORWARDPROC DoCodeMulS(void);
FORWARDPROC DoCodeDivU(void);
FORWARDPROC DoCodeDivS(void);
FORWARDPROC DoCodeExg(void);
FORWARDPROC DoCodeMoveEaCR(void);
FORWARDPROC DoCodeMoveSREa(void);
FORWARDPROC DoCodeMoveEaSR(void);
FORWARDPROC DoCodeOrISR(void);
FORWARDPROC DoCodeAndISR(void);
FORWARDPROC DoCodeEorISR(void);
FORWARDPROC DoCodeOrICCR(void);
FORWARDPROC DoCodeAndICCR(void);
FORWARDPROC DoCodeEorICCR(void);
FORWARDPROC DoCodeMOVEMApRW(void);
FORWARDPROC DoCodeMOVEMRmMW(void);
FORWARDPROC DoCodeMOVEMrmW(void);
FORWARDPROC DoCodeMOVEMrmL(void);
FORWARDPROC DoCodeMOVEMmrW(void);
FORWARDPROC DoCodeMOVEMmrL(void);
FORWARDPROC DoCodeAbcd(void);
FORWARDPROC DoCodeSbcd(void);
FORWARDPROC DoCodeNbcd(void);
FORWARDPROC DoCodeRte(void);
FORWARDPROC DoCodeNop(void);
FORWARDPROC DoCodeMoveP0(void);
FORWARDPROC DoCodeMoveP1(void);
FORWARDPROC DoCodeMoveP2(void);
FORWARDPROC DoCodeMoveP3(void);
FORWARDPROC op_illg(void);
FORWARDPROC DoCodeChk(void);
FORWARDPROC DoCodeTrap(void);
FORWARDPROC DoCodeTrapV(void);
FORWARDPROC DoCodeRtr(void);
FORWARDPROC DoCodeLink(void);
FORWARDPROC DoCodeUnlk(void);
FORWARDPROC DoCodeMoveRUSP(void);
FORWARDPROC DoCodeMoveUSPR(void);
FORWARDPROC DoCodeTas(void);
FORWARDPROC DoCodeFdefault(void);
FORWARDPROC DoCodeStop(void);
FORWARDPROC DoCodeReset(void);
#if Use68020
FORWARDPROC DoCodeCallMorRtm(void);
FORWARDPROC DoCodeBraL(void);
FORWARDPROC DoCodeBccL(void);
FORWARDPROC DoCodeBsrL(void);
FORWARDPROC DoCodeEXTBL(void);
FORWARDPROC DoCodeTRAPcc(void);
FORWARDPROC DoCodeBkpt(void);
FORWARDPROC DoCodeDivL(void);
FORWARDPROC DoCodeMulL(void);
FORWARDPROC DoCodeRtd(void);
FORWARDPROC DoCodeMoveCCREa(void);
FORWARDPROC DoMoveFromControl(void);
FORWARDPROC DoMoveToControl(void);
FORWARDPROC DoCodeLinkL(void);
FORWARDPROC DoCodePack(void);
FORWARDPROC DoCodeUnpk(void);
FORWARDPROC DoCHK2orCMP2(void);
FORWARDPROC DoCAS2(void);
FORWARDPROC DoCAS(void);
FORWARDPROC DoMOVES(void);
FORWARDPROC DoBitField(void);
#endif
#if EmMMU
FORWARDPROC DoCodeMMU(void);
#endif
#if EmFPU
FORWARDPROC DoCodeFPU_md60(void);
FORWARDPROC DoCodeFPU_DBcc(void);
FORWARDPROC DoCodeFPU_Trapcc(void);
FORWARDPROC DoCodeFPU_Scc(void);
FORWARDPROC DoCodeFPU_FBccW(void);
FORWARDPROC DoCodeFPU_FBccL(void);
FORWARDPROC DoCodeFPU_Save(void);
FORWARDPROC DoCodeFPU_Restore(void);
FORWARDPROC DoCodeFPU_dflt(void);
#endif
typedef void (*func_pointer_t)(void);
LOCALVAR const func_pointer_t OpDispatch[kNumIKinds + 1] = {
DoCodeTst /* kIKindTst */,
DoCodeCmpB /* kIKindCmpB */,
DoCodeCmpW /* kIKindCmpW */,
DoCodeCmpL /* kIKindCmpL */,
DoCodeBccB /* kIKindBccB */,
DoCodeBccW /* kIKindBccW */,
DoCodeBraB /* kIKindBraB */,
DoCodeBraW /* kIKindBraW */,
DoCodeDBcc /* kIKindDBcc */,
DoCodeDBF /* kIKindDBF */,
DoCodeSwap /* kIKindSwap */,
DoCodeMoveL /* kIKindMoveL */,
DoCodeMoveW /* kIKindMoveW */,
DoCodeMoveB /* kIKindMoveB */,
DoCodeMoveA /* kIKindMoveAL */,
DoCodeMoveA /* kIKindMoveAW */,
DoCodeMoveQ /* kIKindMoveQ */,
DoCodeAddB /* kIKindAddB */,
DoCodeAddW /* kIKindAddW */,
DoCodeAddL /* kIKindAddL */,
DoCodeSubB /* kIKindSubB */,
DoCodeSubW /* kIKindSubW */,
DoCodeSubL /* kIKindSubL */,
DoCodeLea /* kIKindLea */,
DoCodePEA /* kIKindPEA */,
DoCodeA /* kIKindA */,
DoCodeBsrB /* kIKindBsrB */,
DoCodeBsrW /* kIKindBsrW */,
DoCodeJsr /* kIKindJsr */,
DoCodeLinkA6 /* kIKindLinkA6 */,
DoCodeMOVEMRmML /* kIKindMOVEMRmML */,
DoCodeMOVEMApRL /* kIKindMOVEMApRL */,
DoCodeUnlkA6 /* kIKindUnlkA6 */,
DoCodeRts /* kIKindRts */,
DoCodeJmp /* kIKindJmp */,
DoCodeClr /* kIKindClr */,
DoCodeAddA /* kIKindAddA */,
DoCodeAddA /* kIKindAddQA */,
DoCodeSubA /* kIKindSubA */,
DoCodeSubA /* kIKindSubQA */,
DoCodeCmpA /* kIKindCmpA */,
DoCodeAddXB /* kIKindAddXB */,
DoCodeAddXW /* kIKindAddXW */,
DoCodeAddXL /* kIKindAddXL */,
DoCodeSubXB /* kIKindSubXB */,
DoCodeSubXW /* kIKindSubXW */,
DoCodeSubXL /* kIKindSubXL */,
DoCodeAslB /* kIKindAslB */,
DoCodeAslW /* kIKindAslW */,
DoCodeAslL /* kIKindAslL */,
DoCodeAsrB /* kIKindAsrB */,
DoCodeAsrW /* kIKindAsrW */,
DoCodeAsrL /* kIKindAsrL */,
DoCodeLslB /* kIKindLslB */,
DoCodeLslW /* kIKindLslW */,
DoCodeLslL /* kIKindLslL */,
DoCodeLsrB /* kIKindLsrB */,
DoCodeLsrW /* kIKindLsrW */,
DoCodeLsrL /* kIKindLsrL */,
DoCodeRxlB /* kIKindRxlB */,
DoCodeRxlW /* kIKindRxlW */,
DoCodeRxlL /* kIKindRxlL */,
DoCodeRxrB /* kIKindRxrB */,
DoCodeRxrW /* kIKindRxrW */,
DoCodeRxrL /* kIKindRxrL */,
DoCodeRolB /* kIKindRolB */,
DoCodeRolW /* kIKindRolW */,
DoCodeRolL /* kIKindRolL */,
DoCodeRorB /* kIKindRorB */,
DoCodeRorW /* kIKindRorW */,
DoCodeRorL /* kIKindRorL */,
DoCodeBTstB /* kIKindBTstB */,
DoCodeBChgB /* kIKindBChgB */,
DoCodeBClrB /* kIKindBClrB */,
DoCodeBSetB /* kIKindBSetB */,
DoCodeBTstL /* kIKindBTstL */,
DoCodeBChgL /* kIKindBChgL */,
DoCodeBClrL /* kIKindBClrL */,
DoCodeBSetL /* kIKindBSetL */,
DoCodeAnd /* kIKindAndI */,
DoCodeAnd /* kIKindAndEaD */,
DoCodeAnd /* kIKindAndDEa */,
DoCodeOr /* kIKindOrI */,
DoCodeOr /* kIKindOrDEa */,
DoCodeOr /* kIKindOrEaD */,
DoCodeEor /* kIKindEor */,
DoCodeEor /* kIKindEorI */,
DoCodeNot /* kIKindNot */,
DoCodeScc /* kIKindScc */,
DoCodeNegXB /* kIKindNegXB */,
DoCodeNegXW /* kIKindNegXW */,
DoCodeNegXL /* kIKindNegXL */,
DoCodeNegB /* kIKindNegB */,
DoCodeNegW /* kIKindNegW */,
DoCodeNegL /* kIKindNegL */,
DoCodeEXTW /* kIKindEXTW */,
DoCodeEXTL /* kIKindEXTL */,
DoCodeMulU /* kIKindMulU */,
DoCodeMulS /* kIKindMulS */,
DoCodeDivU /* kIKindDivU */,
DoCodeDivS /* kIKindDivS */,
DoCodeExg /* kIKindExg */,
DoCodeMoveEaCR /* kIKindMoveEaCCR */,
DoCodeMoveSREa /* kIKindMoveSREa */,
DoCodeMoveEaSR /* kIKindMoveEaSR */,
DoCodeOrISR /* kIKindOrISR */,
DoCodeAndISR /* kIKindAndISR */,
DoCodeEorISR /* kIKindEorISR */,
DoCodeOrICCR /* kIKindOrICCR */,
DoCodeAndICCR /* kIKindAndICCR */,
DoCodeEorICCR /* kIKindEorICCR */,
DoCodeMOVEMApRW /* kIKindMOVEMApRW */,
DoCodeMOVEMRmMW /* kIKindMOVEMRmMW */,
DoCodeMOVEMrmW /* kIKindMOVEMrmW */,
DoCodeMOVEMrmL /* kIKindMOVEMrmL */,
DoCodeMOVEMmrW /* kIKindMOVEMmrW */,
DoCodeMOVEMmrL /* kIKindMOVEMmrL */,
DoCodeAbcd /* kIKindAbcd */,
DoCodeSbcd /* kIKindSbcd */,
DoCodeNbcd /* kIKindNbcd */,
DoCodeRte /* kIKindRte */,
DoCodeNop /* kIKindNop */,
DoCodeMoveP0 /* kIKindMoveP0 */,
DoCodeMoveP1 /* kIKindMoveP1 */,
DoCodeMoveP2 /* kIKindMoveP2 */,
DoCodeMoveP3 /* kIKindMoveP3 */,
op_illg /* kIKindIllegal */,
DoCodeChk /* kIKindChkW */,
DoCodeTrap /* kIKindTrap */,
DoCodeTrapV /* kIKindTrapV */,
DoCodeRtr /* kIKindRtr */,
DoCodeLink /* kIKindLink */,
DoCodeUnlk /* kIKindUnlk */,
DoCodeMoveRUSP /* kIKindMoveRUSP */,
DoCodeMoveUSPR /* kIKindMoveUSPR */,
DoCodeTas /* kIKindTas */,
DoCodeFdefault /* kIKindFdflt */,
DoCodeStop /* kIKindStop */,
DoCodeReset /* kIKindReset */,
#if Use68020
DoCodeCallMorRtm /* kIKindCallMorRtm */,
DoCodeBraL /* kIKindBraL */,
DoCodeBccL /* kIKindBccL */,
DoCodeBsrL /* kIKindBsrL */,
DoCodeEXTBL /* kIKindEXTBL */,
DoCodeTRAPcc /* kIKindTRAPcc */,
DoCodeChk /* kIKindChkL */,
DoCodeBkpt /* kIKindBkpt */,
DoCodeDivL /* kIKindDivL */,
DoCodeMulL /* kIKindMulL */,
DoCodeRtd /* kIKindRtd */,
DoCodeMoveCCREa /* kIKindMoveCCREa */,
DoMoveFromControl /* kIKindMoveCEa */,
DoMoveToControl /* kIKindMoveEaC */,
DoCodeLinkL /* kIKindLinkL */,
DoCodePack /* kIKindPack */,
DoCodeUnpk /* kIKindUnpk */,
DoCHK2orCMP2 /* kIKindCHK2orCMP2 */,
DoCAS2 /* kIKindCAS2 */,
DoCAS /* kIKindCAS */,
DoMOVES /* kIKindMoveS */,
DoBitField /* kIKindBitField */,
#endif
#if EmMMU
DoCodeMMU /* kIKindMMU */,
#endif
#if EmFPU
DoCodeFPU_md60 /* kIKindFPUmd60 */,
DoCodeFPU_DBcc /* kIKindFPUDBcc */,
DoCodeFPU_Trapcc /* kIKindFPUTrapcc */,
DoCodeFPU_Scc /* kIKindFPUScc */,
DoCodeFPU_FBccW /* kIKindFPUFBccW */,
DoCodeFPU_FBccL /* kIKindFPUFBccL */,
DoCodeFPU_Save /* kIKindFPUSave */,
DoCodeFPU_Restore /* kIKindFPURestore */,
DoCodeFPU_dflt /* kIKindFPUdflt */,
#endif
0
};
#ifndef WantBreakPoint
#define WantBreakPoint 0
#endif
#if WantBreakPoint
#define BreakPointAddress 0xD198
LOCALPROC BreakPointAction(void)
{
dbglog_StartLine();
dbglog_writeCStr("breakpoint A0=");
dbglog_writeHex(m68k_areg(0));
dbglog_writeCStr(" A1=");
dbglog_writeHex(m68k_areg(1));
dbglog_writeReturn();
}
#endif
LOCALINLINEPROC DecodeNextInstruction(func_pointer_t *d, uint16_t *Cycles,
DecOpYR *y)
{
uint32_t opcode;
DecOpR *p;
uint16_t MainClas;
opcode = nextiword();
p = &V_regs.disp_table[opcode];
#if WantCloserCyc
V_regs.CurDecOp = p;
#endif
MainClas = p->x.MainClas;
*Cycles = p->x.Cycles;
*y = p->y;
#if WantDumpTable
DumpTable[MainClas] ++;
#endif
*d = OpDispatch[MainClas];
}
LOCALINLINEPROC UnDecodeNextInstruction(uint16_t Cycles)
{
V_MaxCyclesToGo += Cycles;
BackupPC();
#if WantDumpTable
{
uint32_t opcode = do_get_mem_word(V_pc_p);
DecOpR *p = &V_regs.disp_table[opcode];
uint16_t MainClas = p->x.MainClas;
DumpTable[MainClas] --;
}
#endif
}
LOCALPROC m68k_go_MaxCycles(void)
{
uint16_t Cycles;
DecOpYR y;
func_pointer_t d;
/*
Main loop of emulator.
Always execute at least one instruction,
even if V_regs.MaxInstructionsToGo == 0.
Needed for trace flag to work.
*/
DecodeNextInstruction(&d, &Cycles, &y);
V_MaxCyclesToGo -= Cycles;
do {
V_regs.CurDecOpY = y;
#if WantDisasm || WantBreakPoint
{
CPTR pc = m68k_getpc() - 2;
#if WantDisasm
DisasmOneOrSave(pc);
#endif
#if WantBreakPoint
if (BreakPointAddress == pc) {
BreakPointAction();
}
#endif
}
#endif
d();
DecodeNextInstruction(&d, &Cycles, &y);
} while (((int32_t)(V_MaxCyclesToGo -= Cycles)) > 0);
/* abort instruction that have started to decode */
UnDecodeNextInstruction(Cycles);
}
FORWARDFUNC uint32_t reg_call get_byte_ext(CPTR addr);
LOCALFUNC uint32_t reg_call get_byte(CPTR addr)
{
uint8_t * m = (addr & V_regs.MATCrdB.usemask) + V_regs.MATCrdB.usebase;
if ((addr & V_regs.MATCrdB.cmpmask) == V_regs.MATCrdB.cmpvalu) {
return uint32_t_FromSByte(*m);
} else {
return get_byte_ext(addr);
}
}
FORWARDPROC reg_call put_byte_ext(CPTR addr, uint32_t b);
LOCALPROC reg_call put_byte(CPTR addr, uint32_t b)
{
uint8_t * m = (addr & V_regs.MATCwrB.usemask) + V_regs.MATCwrB.usebase;
if ((addr & V_regs.MATCwrB.cmpmask) == V_regs.MATCwrB.cmpvalu) {
*m = b;
} else {
put_byte_ext(addr, b);
}
}
FORWARDFUNC uint32_t reg_call get_word_ext(CPTR addr);
LOCALFUNC uint32_t reg_call get_word(CPTR addr)
{
uint8_t * m = (addr & V_regs.MATCrdW.usemask) + V_regs.MATCrdW.usebase;
if ((addr & V_regs.MATCrdW.cmpmask) == V_regs.MATCrdW.cmpvalu) {
return uint32_t_FromSWord(do_get_mem_word(m));
} else {
return get_word_ext(addr);
}
}
FORWARDPROC reg_call put_word_ext(CPTR addr, uint32_t w);
LOCALPROC reg_call put_word(CPTR addr, uint32_t w)
{
uint8_t * m = (addr & V_regs.MATCwrW.usemask) + V_regs.MATCwrW.usebase;
if ((addr & V_regs.MATCwrW.cmpmask) == V_regs.MATCwrW.cmpvalu) {
do_put_mem_word(m, w);
} else {
put_word_ext(addr, w);
}
}
FORWARDFUNC uint32_t reg_call get_long_misaligned_ext(CPTR addr);
LOCALFUNC uint32_t reg_call get_long_misaligned(CPTR addr)
{
CPTR addr2 = addr + 2;
uint8_t * m = (addr & V_regs.MATCrdW.usemask) + V_regs.MATCrdW.usebase;
uint8_t * m2 = (addr2 & V_regs.MATCrdW.usemask) + V_regs.MATCrdW.usebase;
if (((addr & V_regs.MATCrdW.cmpmask) == V_regs.MATCrdW.cmpvalu)
&& ((addr2 & V_regs.MATCrdW.cmpmask) == V_regs.MATCrdW.cmpvalu))
{
uint32_t hi = do_get_mem_word(m);
uint32_t lo = do_get_mem_word(m2);
uint32_t Data = ((hi << 16) & 0xFFFF0000)
| (lo & 0x0000FFFF);
return uint32_t_FromSLong(Data);
} else {
return get_long_misaligned_ext(addr);
}
}
#if FasterAlignedL
FORWARDFUNC uint32_t reg_call get_long_ext(CPTR addr);
#endif
#if FasterAlignedL
LOCALFUNC uint32_t reg_call get_long(CPTR addr)
{
if (0 == (addr & 0x03)) {
uint8_t * m = (addr & V_regs.MATCrdL.usemask)
+ V_regs.MATCrdL.usebase;
if ((addr & V_regs.MATCrdL.cmpmask) == V_regs.MATCrdL.cmpvalu) {
return uint32_t_FromSLong(do_get_mem_long(m));
} else {
return get_long_ext(addr);
}
} else {
return get_long_misaligned(addr);
}
}
#else
#define get_long get_long_misaligned
#endif
FORWARDPROC reg_call put_long_misaligned_ext(CPTR addr, uint32_t l);
LOCALPROC reg_call put_long_misaligned(CPTR addr, uint32_t l)
{
CPTR addr2 = addr + 2;
uint8_t * m = (addr & V_regs.MATCwrW.usemask) + V_regs.MATCwrW.usebase;
uint8_t * m2 = (addr2 & V_regs.MATCwrW.usemask) + V_regs.MATCwrW.usebase;
if (((addr & V_regs.MATCwrW.cmpmask) == V_regs.MATCwrW.cmpvalu)
&& ((addr2 & V_regs.MATCwrW.cmpmask) == V_regs.MATCwrW.cmpvalu))
{
do_put_mem_word(m, l >> 16);
do_put_mem_word(m2, l);
} else {
put_long_misaligned_ext(addr, l);
}
}
#if FasterAlignedL
FORWARDPROC reg_call put_long_ext(CPTR addr, uint32_t l);
#endif
#if FasterAlignedL
LOCALPROC reg_call put_long(CPTR addr, uint32_t l)
{
if (0 == (addr & 0x03)) {
uint8_t * m = (addr & V_regs.MATCwrL.usemask)
+ V_regs.MATCwrL.usebase;
if ((addr & V_regs.MATCwrL.cmpmask) == V_regs.MATCwrL.cmpvalu) {
do_put_mem_long(m, l);
} else {
put_long_ext(addr, l);
}
} else {
put_long_misaligned(addr, l);
}
}
#else
#define put_long put_long_misaligned
#endif
LOCALFUNC uint32_t reg_call get_disp_ea(uint32_t base)
{
uint16_t dp = nextiword();
int regno = (dp >> 12) & 0x0F;
int32_t regd = V_regs.regs[regno];
if ((dp & 0x0800) == 0) {
regd = (int32_t)(int16_t)regd;
}
#if Use68020
regd <<= (dp >> 9) & 3;
#if ExtraAbnormalReports
if (((dp >> 9) & 3) != 0) {
/* ReportAbnormal("Have scale in Extension Word"); */
/* apparently can happen in Sys 7.5.5 boot on 68000 */
}
#endif
if (dp & 0x0100) {
if ((dp & 0x80) != 0) {
base = 0;
/* ReportAbnormal("Extension Word: suppress base"); */
/* used by Sys 7.5.5 boot */
}
if ((dp & 0x40) != 0) {
regd = 0;
/* ReportAbnormal("Extension Word: suppress regd"); */
/* used by Mac II boot */
}
switch ((dp >> 4) & 0x03) {
case 0:
/* reserved */
ReportAbnormalID(0x0101, "Extension Word: dp reserved");
break;
case 1:
/* no displacement */
/* ReportAbnormal("Extension Word: no displacement"); */
/* used by Sys 7.5.5 boot */
break;
case 2:
base += nextiSWord();
/*
ReportAbnormal("Extension Word: word displacement");
*/
/* used by Sys 7.5.5 boot */
break;
case 3:
base += nextilong();
/*
ReportAbnormal("Extension Word: long displacement");
*/
/* used by Mac II boot from system 6.0.8? */
break;
}
if ((dp & 0x03) == 0) {
base += regd;
if ((dp & 0x04) != 0) {
ReportAbnormalID(0x0102,
"Extension Word: reserved dp form");
}
/* ReportAbnormal("Extension Word: noindex"); */
/* used by Sys 7.5.5 boot */
} else {
if ((dp & 0x04) != 0) {
base = get_long(base);
base += regd;
/* ReportAbnormal("Extension Word: postindex"); */
/* used by Sys 7.5.5 boot */
} else {
base += regd;
base = get_long(base);
/* ReportAbnormal("Extension Word: preindex"); */
/* used by Sys 7.5.5 boot */
}
switch (dp & 0x03) {
case 1:
/* null outer displacement */
/*
ReportAbnormal(
"Extension Word: null outer displacement");
*/
/* used by Sys 7.5.5 boot */
break;
case 2:
base += nextiSWord();
/*
ReportAbnormal(
"Extension Word: word outer displacement");
*/
/* used by Mac II boot from system 6.0.8? */
break;
case 3:
base += nextilong();
/*
ReportAbnormal(
"Extension Word: long outer displacement");
*/
/* used by Mac II boot from system 6.0.8? */
break;
}
}
return base;
} else
#endif
{
return base + (int8_t)(dp) + regd;
}
}
LOCALFUNC uint32_t reg_call DecodeAddr_Indirect(uint8_t ArgDat)
{
return V_regs.regs[ArgDat];
}
LOCALFUNC uint32_t reg_call DecodeAddr_APosIncB(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p;
*p = a + 1;
return a;
}
LOCALFUNC uint32_t reg_call DecodeAddr_APosIncW(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p;
*p = a + 2;
return a;
}
LOCALFUNC uint32_t reg_call DecodeAddr_APosIncL(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p;
*p = a + 4;
return a;
}
LOCALFUNC uint32_t reg_call DecodeAddr_APreDecB(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p - 1;
*p = a;
return a;
}
LOCALFUNC uint32_t reg_call DecodeAddr_APreDecW(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p - 2;
*p = a;
return a;
}
LOCALFUNC uint32_t reg_call DecodeAddr_APreDecL(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p - 4;
*p = a;
return a;
}
LOCALFUNC uint32_t reg_call DecodeAddr_ADisp(uint8_t ArgDat)
{
return V_regs.regs[ArgDat] + nextiSWord();
}
LOCALFUNC uint32_t reg_call DecodeAddr_AIndex(uint8_t ArgDat)
{
return get_disp_ea(V_regs.regs[ArgDat]);
}
LOCALFUNC uint32_t reg_call DecodeAddr_AbsW(uint8_t ArgDat)
{
UnusedParam(ArgDat);
return nextiSWord();
}
LOCALFUNC uint32_t reg_call DecodeAddr_AbsL(uint8_t ArgDat)
{
UnusedParam(ArgDat);
return nextilong();
}
LOCALFUNC uint32_t reg_call DecodeAddr_PCDisp(uint8_t ArgDat)
{
CPTR pc = m68k_getpc();
UnusedParam(ArgDat);
return pc + nextiSWord();
}
LOCALFUNC uint32_t reg_call DecodeAddr_PCIndex(uint8_t ArgDat)
{
UnusedParam(ArgDat);
return get_disp_ea(m68k_getpc());
}
typedef uint32_t (reg_call *DecodeAddrP)(uint8_t ArgDat);
LOCALVAR const DecodeAddrP DecodeAddrDispatch[kNumAMds] = {
(DecodeAddrP)nullpr /* kAMdRegB */,
(DecodeAddrP)nullpr /* kAMdRegW */,
(DecodeAddrP)nullpr /* kAMdRegL */,
DecodeAddr_Indirect /* kAMdIndirectB */,
DecodeAddr_Indirect /* kAMdIndirectW */,
DecodeAddr_Indirect /* kAMdIndirectL */,
DecodeAddr_APosIncB /* kAMdAPosIncB */,
DecodeAddr_APosIncW /* kAMdAPosIncW */,
DecodeAddr_APosIncL /* kAMdAPosIncL */,
DecodeAddr_APosIncW /* kAMdAPosInc7B */,
DecodeAddr_APreDecB /* kAMdAPreDecB */,
DecodeAddr_APreDecW /* kAMdAPreDecW */,
DecodeAddr_APreDecL /* kAMdAPreDecL */,
DecodeAddr_APreDecW /* kAMdAPreDec7B */,
DecodeAddr_ADisp /* kAMdADispB */,
DecodeAddr_ADisp /* kAMdADispW */,
DecodeAddr_ADisp /* kAMdADispL */,
DecodeAddr_AIndex /* kAMdAIndexB */,
DecodeAddr_AIndex /* kAMdAIndexW */,
DecodeAddr_AIndex /* kAMdAIndexL */,
DecodeAddr_AbsW /* kAMdAbsWB */,
DecodeAddr_AbsW /* kAMdAbsWW */,
DecodeAddr_AbsW /* kAMdAbsWL */,
DecodeAddr_AbsL /* kAMdAbsLB */,
DecodeAddr_AbsL /* kAMdAbsLW */,
DecodeAddr_AbsL /* kAMdAbsLL */,
DecodeAddr_PCDisp /* kAMdPCDispB */,
DecodeAddr_PCDisp /* kAMdPCDispW */,
DecodeAddr_PCDisp /* kAMdPCDispL */,
DecodeAddr_PCIndex /* kAMdPCIndexB */,
DecodeAddr_PCIndex /* kAMdPCIndexW */,
DecodeAddr_PCIndex /* kAMdPCIndexL */,
(DecodeAddrP)nullpr /* kAMdImmedB */,
(DecodeAddrP)nullpr /* kAMdImmedW */,
(DecodeAddrP)nullpr /* kAMdImmedL */,
(DecodeAddrP)nullpr /* kAMdDat4 */
};
LOCALINLINEFUNC uint32_t DecodeAddrSrcDst(DecArgR *f)
{
return (DecodeAddrDispatch[f->AMd])(f->ArgDat);
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_RegB(uint8_t ArgDat)
{
return uint32_t_FromSByte(V_regs.regs[ArgDat]);
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_RegW(uint8_t ArgDat)
{
return uint32_t_FromSWord(V_regs.regs[ArgDat]);
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_RegL(uint8_t ArgDat)
{
return uint32_t_FromSLong(V_regs.regs[ArgDat]);
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_IndirectB(uint8_t ArgDat)
{
return get_byte(V_regs.regs[ArgDat]);
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_IndirectW(uint8_t ArgDat)
{
return get_word(V_regs.regs[ArgDat]);
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_IndirectL(uint8_t ArgDat)
{
return get_long(V_regs.regs[ArgDat]);
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_APosIncB(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p;
*p = a + 1;
return get_byte(a);
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_APosIncW(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p;
*p = a + 2;
return get_word(a);
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_APosIncL(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p;
*p = a + 4;
return get_long(a);
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_APosInc7B(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p;
*p = a + 2;
return get_byte(a);
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_APreDecB(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p - 1;
*p = a;
return get_byte(a);
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_APreDecW(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p - 2;
*p = a;
return get_word(a);
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_APreDecL(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p - 4;
*p = a;
return get_long(a);
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_APreDec7B(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p - 2;
*p = a;
return get_byte(a);
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_ADispB(uint8_t ArgDat)
{
return get_byte(DecodeAddr_ADisp(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_ADispW(uint8_t ArgDat)
{
return get_word(DecodeAddr_ADisp(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_ADispL(uint8_t ArgDat)
{
return get_long(DecodeAddr_ADisp(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_AIndexB(uint8_t ArgDat)
{
return get_byte(get_disp_ea(V_regs.regs[ArgDat]));
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_AIndexW(uint8_t ArgDat)
{
return get_word(get_disp_ea(V_regs.regs[ArgDat]));
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_AIndexL(uint8_t ArgDat)
{
return get_long(get_disp_ea(V_regs.regs[ArgDat]));
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_AbsWB(uint8_t ArgDat)
{
return get_byte(DecodeAddr_AbsW(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_AbsWW(uint8_t ArgDat)
{
return get_word(DecodeAddr_AbsW(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_AbsWL(uint8_t ArgDat)
{
return get_long(DecodeAddr_AbsW(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_AbsLB(uint8_t ArgDat)
{
return get_byte(DecodeAddr_AbsL(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_AbsLW(uint8_t ArgDat)
{
return get_word(DecodeAddr_AbsL(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_AbsLL(uint8_t ArgDat)
{
return get_long(DecodeAddr_AbsL(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_PCDispB(uint8_t ArgDat)
{
return get_byte(DecodeAddr_PCDisp(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_PCDispW(uint8_t ArgDat)
{
return get_word(DecodeAddr_PCDisp(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_PCDispL(uint8_t ArgDat)
{
return get_long(DecodeAddr_PCDisp(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_PCIndexB(uint8_t ArgDat)
{
return get_byte(DecodeAddr_PCIndex(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_PCIndexW(uint8_t ArgDat)
{
return get_word(DecodeAddr_PCIndex(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_PCIndexL(uint8_t ArgDat)
{
return get_long(DecodeAddr_PCIndex(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_ImmedB(uint8_t ArgDat)
{
UnusedParam(ArgDat);
return nextiSByte();
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_ImmedW(uint8_t ArgDat)
{
UnusedParam(ArgDat);
return nextiSWord();
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_ImmedL(uint8_t ArgDat)
{
UnusedParam(ArgDat);
return uint32_t_FromSLong(nextilong());
}
LOCALFUNC uint32_t reg_call DecodeGetSrcDst_Dat4(uint8_t ArgDat)
{
return ArgDat;
}
typedef uint32_t (reg_call *DecodeGetSrcDstP)(uint8_t ArgDat);
LOCALVAR const DecodeGetSrcDstP DecodeGetSrcDstDispatch[kNumAMds] = {
DecodeGetSrcDst_RegB /* kAMdRegB */,
DecodeGetSrcDst_RegW /* kAMdRegW */,
DecodeGetSrcDst_RegL /* kAMdRegL */,
DecodeGetSrcDst_IndirectB /* kAMdIndirectB */,
DecodeGetSrcDst_IndirectW /* kAMdIndirectW */,
DecodeGetSrcDst_IndirectL /* kAMdIndirectL */,
DecodeGetSrcDst_APosIncB /* kAMdAPosIncB */,
DecodeGetSrcDst_APosIncW /* kAMdAPosIncW */,
DecodeGetSrcDst_APosIncL /* kAMdAPosIncL */,
DecodeGetSrcDst_APosInc7B /* kAMdAPosInc7B */,
DecodeGetSrcDst_APreDecB /* kAMdAPreDecB */,
DecodeGetSrcDst_APreDecW /* kAMdAPreDecW */,
DecodeGetSrcDst_APreDecL /* kAMdAPreDecL */,
DecodeGetSrcDst_APreDec7B /* kAMdAPreDec7B */,
DecodeGetSrcDst_ADispB /* kAMdADispB */,
DecodeGetSrcDst_ADispW /* kAMdADispW */,
DecodeGetSrcDst_ADispL /* kAMdADispL */,
DecodeGetSrcDst_AIndexB /* kAMdAIndexB */,
DecodeGetSrcDst_AIndexW /* kAMdAIndexW */,
DecodeGetSrcDst_AIndexL /* kAMdAIndexL */,
DecodeGetSrcDst_AbsWB /* kAMdAbsWB */,
DecodeGetSrcDst_AbsWW /* kAMdAbsWW */,
DecodeGetSrcDst_AbsWL /* kAMdAbsWL */,
DecodeGetSrcDst_AbsLB /* kAMdAbsLB */,
DecodeGetSrcDst_AbsLW /* kAMdAbsLW */,
DecodeGetSrcDst_AbsLL /* kAMdAbsLL */,
DecodeGetSrcDst_PCDispB /* kAMdPCDispB */,
DecodeGetSrcDst_PCDispW /* kAMdPCDispW */,
DecodeGetSrcDst_PCDispL /* kAMdPCDispL */,
DecodeGetSrcDst_PCIndexB /* kAMdPCIndexB */,
DecodeGetSrcDst_PCIndexW /* kAMdPCIndexW */,
DecodeGetSrcDst_PCIndexL /* kAMdPCIndexL */,
DecodeGetSrcDst_ImmedB /* kAMdImmedB */,
DecodeGetSrcDst_ImmedW /* kAMdImmedW */,
DecodeGetSrcDst_ImmedL /* kAMdImmedL */,
DecodeGetSrcDst_Dat4 /* kAMdDat4 */
};
LOCALINLINEFUNC uint32_t DecodeGetSrcDst(DecArgR *f)
{
return (DecodeGetSrcDstDispatch[f->AMd])(f->ArgDat);
}
LOCALPROC reg_call DecodeSetSrcDst_RegB(uint32_t v, uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
#if LittleEndianUnaligned
*(uint8_t *)p = v;
#else
*p = (*p & ~ 0xff) | ((v) & 0xff);
#endif
}
LOCALPROC reg_call DecodeSetSrcDst_RegW(uint32_t v, uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
#if LittleEndianUnaligned
*(uint16_t *)p = v;
#else
*p = (*p & ~ 0xffff) | ((v) & 0xffff);
#endif
}
LOCALPROC reg_call DecodeSetSrcDst_RegL(uint32_t v, uint8_t ArgDat)
{
V_regs.regs[ArgDat] = v;
}
LOCALPROC reg_call DecodeSetSrcDst_IndirectB(uint32_t v, uint8_t ArgDat)
{
put_byte(V_regs.regs[ArgDat], v);
}
LOCALPROC reg_call DecodeSetSrcDst_IndirectW(uint32_t v, uint8_t ArgDat)
{
put_word(V_regs.regs[ArgDat], v);
}
LOCALPROC reg_call DecodeSetSrcDst_IndirectL(uint32_t v, uint8_t ArgDat)
{
put_long(V_regs.regs[ArgDat], v);
}
LOCALPROC reg_call DecodeSetSrcDst_APosIncB(uint32_t v, uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p;
*p = a + 1;
put_byte(a, v);
}
LOCALPROC reg_call DecodeSetSrcDst_APosIncW(uint32_t v, uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p;
*p = a + 2;
put_word(a, v);
}
LOCALPROC reg_call DecodeSetSrcDst_APosIncL(uint32_t v, uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p;
*p = a + 4;
put_long(a, v);
}
LOCALPROC reg_call DecodeSetSrcDst_APosInc7B(uint32_t v, uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p;
*p = a + 2;
put_byte(a, v);
}
LOCALPROC reg_call DecodeSetSrcDst_APreDecB(uint32_t v, uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p - 1;
*p = a;
put_byte(a, v);
}
LOCALPROC reg_call DecodeSetSrcDst_APreDecW(uint32_t v, uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p - 2;
*p = a;
put_word(a, v);
}
LOCALPROC reg_call DecodeSetSrcDst_APreDecL(uint32_t v, uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p - 4;
*p = a;
put_long(a, v);
}
LOCALPROC reg_call DecodeSetSrcDst_APreDec7B(uint32_t v, uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p - 2;
*p = a;
put_byte(a, v);
}
LOCALPROC reg_call DecodeSetSrcDst_ADispB(uint32_t v, uint8_t ArgDat)
{
put_byte(V_regs.regs[ArgDat]
+ nextiSWord(), v);
}
LOCALPROC reg_call DecodeSetSrcDst_ADispW(uint32_t v, uint8_t ArgDat)
{
put_word(V_regs.regs[ArgDat]
+ nextiSWord(), v);
}
LOCALPROC reg_call DecodeSetSrcDst_ADispL(uint32_t v, uint8_t ArgDat)
{
put_long(V_regs.regs[ArgDat]
+ nextiSWord(), v);
}
LOCALPROC reg_call DecodeSetSrcDst_AIndexB(uint32_t v, uint8_t ArgDat)
{
put_byte(get_disp_ea(V_regs.regs[ArgDat]), v);
}
LOCALPROC reg_call DecodeSetSrcDst_AIndexW(uint32_t v, uint8_t ArgDat)
{
put_word(get_disp_ea(V_regs.regs[ArgDat]), v);
}
LOCALPROC reg_call DecodeSetSrcDst_AIndexL(uint32_t v, uint8_t ArgDat)
{
put_long(get_disp_ea(V_regs.regs[ArgDat]), v);
}
LOCALPROC reg_call DecodeSetSrcDst_AbsWB(uint32_t v, uint8_t ArgDat)
{
put_byte(DecodeAddr_AbsW(ArgDat), v);
}
LOCALPROC reg_call DecodeSetSrcDst_AbsWW(uint32_t v, uint8_t ArgDat)
{
put_word(DecodeAddr_AbsW(ArgDat), v);
}
LOCALPROC reg_call DecodeSetSrcDst_AbsWL(uint32_t v, uint8_t ArgDat)
{
put_long(DecodeAddr_AbsW(ArgDat), v);
}
LOCALPROC reg_call DecodeSetSrcDst_AbsLB(uint32_t v, uint8_t ArgDat)
{
put_byte(DecodeAddr_AbsL(ArgDat), v);
}
LOCALPROC reg_call DecodeSetSrcDst_AbsLW(uint32_t v, uint8_t ArgDat)
{
put_word(DecodeAddr_AbsL(ArgDat), v);
}
LOCALPROC reg_call DecodeSetSrcDst_AbsLL(uint32_t v, uint8_t ArgDat)
{
put_long(DecodeAddr_AbsL(ArgDat), v);
}
LOCALPROC reg_call DecodeSetSrcDst_PCDispB(uint32_t v, uint8_t ArgDat)
{
put_byte(DecodeAddr_PCDisp(ArgDat), v);
}
LOCALPROC reg_call DecodeSetSrcDst_PCDispW(uint32_t v, uint8_t ArgDat)
{
put_word(DecodeAddr_PCDisp(ArgDat), v);
}
LOCALPROC reg_call DecodeSetSrcDst_PCDispL(uint32_t v, uint8_t ArgDat)
{
put_long(DecodeAddr_PCDisp(ArgDat), v);
}
LOCALPROC reg_call DecodeSetSrcDst_PCIndexB(uint32_t v, uint8_t ArgDat)
{
put_byte(DecodeAddr_PCIndex(ArgDat), v);
}
LOCALPROC reg_call DecodeSetSrcDst_PCIndexW(uint32_t v, uint8_t ArgDat)
{
put_word(DecodeAddr_PCIndex(ArgDat), v);
}
LOCALPROC reg_call DecodeSetSrcDst_PCIndexL(uint32_t v, uint8_t ArgDat)
{
put_long(DecodeAddr_PCIndex(ArgDat), v);
}
typedef void (reg_call *DecodeSetSrcDstP)(uint32_t v, uint8_t ArgDat);
LOCALVAR const DecodeSetSrcDstP DecodeSetSrcDstDispatch[kNumAMds] = {
DecodeSetSrcDst_RegB /* kAMdRegB */,
DecodeSetSrcDst_RegW /* kAMdRegW */,
DecodeSetSrcDst_RegL /* kAMdRegL */,
DecodeSetSrcDst_IndirectB /* kAMdIndirectB */,
DecodeSetSrcDst_IndirectW /* kAMdIndirectW */,
DecodeSetSrcDst_IndirectL /* kAMdIndirectL*/,
DecodeSetSrcDst_APosIncB /* kAMdAPosIncB */,
DecodeSetSrcDst_APosIncW /* kAMdAPosIncW */,
DecodeSetSrcDst_APosIncL /* kAMdAPosIncL */,
DecodeSetSrcDst_APosInc7B /* kAMdAPosInc7B */,
DecodeSetSrcDst_APreDecB /* kAMdAPreDecB */,
DecodeSetSrcDst_APreDecW /* kAMdAPreDecW */,
DecodeSetSrcDst_APreDecL /* kAMdAPreDecL */,
DecodeSetSrcDst_APreDec7B /* kAMdAPreDec7B */,
DecodeSetSrcDst_ADispB /* kAMdADispB */,
DecodeSetSrcDst_ADispW /* kAMdADispW */,
DecodeSetSrcDst_ADispL /* kAMdADispL */,
DecodeSetSrcDst_AIndexB /* kAMdAIndexB */,
DecodeSetSrcDst_AIndexW /* kAMdAIndexW */,
DecodeSetSrcDst_AIndexL /* kAMdAIndexL */,
DecodeSetSrcDst_AbsWB /* kAMdAbsWB */,
DecodeSetSrcDst_AbsWW /* kAMdAbsWW */,
DecodeSetSrcDst_AbsWL /* kAMdAbsWL */,
DecodeSetSrcDst_AbsLB /* kAMdAbsLB */,
DecodeSetSrcDst_AbsLW /* kAMdAbsLW */,
DecodeSetSrcDst_AbsLL /* kAMdAbsLL */,
DecodeSetSrcDst_PCDispB /* kAMdPCDispB */,
DecodeSetSrcDst_PCDispW /* kAMdPCDispW */,
DecodeSetSrcDst_PCDispL /* kAMdPCDispL */,
DecodeSetSrcDst_PCIndexB /* kAMdPCIndexB */,
DecodeSetSrcDst_PCIndexW /* kAMdPCIndexW */,
DecodeSetSrcDst_PCIndexL /* kAMdPCIndexL */,
(DecodeSetSrcDstP)nullpr /* kAMdImmedB */,
(DecodeSetSrcDstP)nullpr /* kAMdImmedW */,
(DecodeSetSrcDstP)nullpr /* kAMdImmedL */,
(DecodeSetSrcDstP)nullpr /* kAMdDat4 */
};
LOCALINLINEPROC DecodeSetSrcDst(uint32_t v, DecArgR *f)
{
(DecodeSetSrcDstDispatch[f->AMd])(v, f->ArgDat);
}
LOCALPROC reg_call ArgSetDstRegBValue(uint32_t v)
{
uint32_t *p = V_regs.ArgAddr.rga;
#if LittleEndianUnaligned
*(uint8_t *)p = v;
#else
*p = (*p & ~ 0xff) | ((v) & 0xff);
#endif
}
LOCALPROC reg_call ArgSetDstRegWValue(uint32_t v)
{
uint32_t *p = V_regs.ArgAddr.rga;
#if LittleEndianUnaligned
*(uint16_t *)p = v;
#else
*p = (*p & ~ 0xffff) | ((v) & 0xffff);
#endif
}
LOCALPROC reg_call ArgSetDstRegLValue(uint32_t v)
{
uint32_t *p = V_regs.ArgAddr.rga;
*p = v;
}
LOCALPROC reg_call ArgSetDstMemBValue(uint32_t v)
{
put_byte(V_regs.ArgAddr.mem, v);
}
LOCALPROC reg_call ArgSetDstMemWValue(uint32_t v)
{
put_word(V_regs.ArgAddr.mem, v);
}
LOCALPROC reg_call ArgSetDstMemLValue(uint32_t v)
{
put_long(V_regs.ArgAddr.mem, v);
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_RegB(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
V_regs.ArgAddr.rga = p;
V_regs.ArgSetDst = ArgSetDstRegBValue;
return uint32_t_FromSByte(*p);
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_RegW(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
V_regs.ArgAddr.rga = p;
V_regs.ArgSetDst = ArgSetDstRegWValue;
return uint32_t_FromSWord(*p);
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_RegL(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
V_regs.ArgAddr.rga = p;
V_regs.ArgSetDst = ArgSetDstRegLValue;
return uint32_t_FromSLong(*p);
}
LOCALFUNC uint32_t reg_call getarg_byte(uint32_t a)
{
V_regs.ArgAddr.mem = a;
V_regs.ArgSetDst = ArgSetDstMemBValue;
return get_byte(a);
}
LOCALFUNC uint32_t reg_call getarg_word(uint32_t a)
{
V_regs.ArgAddr.mem = a;
V_regs.ArgSetDst = ArgSetDstMemWValue;
return get_word(a);
}
LOCALFUNC uint32_t reg_call getarg_long(uint32_t a)
{
V_regs.ArgAddr.mem = a;
V_regs.ArgSetDst = ArgSetDstMemLValue;
return get_long(a);
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_IndirectB(uint8_t ArgDat)
{
return getarg_byte(V_regs.regs[ArgDat]);
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_IndirectW(uint8_t ArgDat)
{
return getarg_word(V_regs.regs[ArgDat]);
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_IndirectL(uint8_t ArgDat)
{
return getarg_long(V_regs.regs[ArgDat]);
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_APosIncB(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p;
*p = a + 1;
return getarg_byte(a);
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_APosIncW(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p;
*p = a + 2;
return getarg_word(a);
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_APosIncL(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p;
*p = a + 4;
return getarg_long(a);
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_APosInc7B(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p;
*p = a + 2;
return getarg_byte(a);
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_APreDecB(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p - 1;
*p = a;
return getarg_byte(a);
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_APreDecW(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p - 2;
*p = a;
return getarg_word(a);
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_APreDecL(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p - 4;
*p = a;
return getarg_long(a);
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_APreDec7B(uint8_t ArgDat)
{
uint32_t *p = &V_regs.regs[ArgDat];
uint32_t a = *p - 2;
*p = a;
return getarg_byte(a);
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_ADispB(uint8_t ArgDat)
{
return getarg_byte(V_regs.regs[ArgDat]
+ nextiSWord());
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_ADispW(uint8_t ArgDat)
{
return getarg_word(V_regs.regs[ArgDat]
+ nextiSWord());
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_ADispL(uint8_t ArgDat)
{
return getarg_long(V_regs.regs[ArgDat]
+ nextiSWord());
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_AIndexB(uint8_t ArgDat)
{
return getarg_byte(get_disp_ea(V_regs.regs[ArgDat]));
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_AIndexW(uint8_t ArgDat)
{
return getarg_word(get_disp_ea(V_regs.regs[ArgDat]));
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_AIndexL(uint8_t ArgDat)
{
return getarg_long(get_disp_ea(V_regs.regs[ArgDat]));
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_AbsWB(uint8_t ArgDat)
{
return getarg_byte(DecodeAddr_AbsW(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_AbsWW(uint8_t ArgDat)
{
return getarg_word(DecodeAddr_AbsW(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_AbsWL(uint8_t ArgDat)
{
return getarg_long(DecodeAddr_AbsW(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_AbsLB(uint8_t ArgDat)
{
return getarg_byte(DecodeAddr_AbsL(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_AbsLW(uint8_t ArgDat)
{
return getarg_word(DecodeAddr_AbsL(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_AbsLL(uint8_t ArgDat)
{
return getarg_long(DecodeAddr_AbsL(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_PCDispB(uint8_t ArgDat)
{
return getarg_byte(DecodeAddr_PCDisp(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_PCDispW(uint8_t ArgDat)
{
return getarg_word(DecodeAddr_PCDisp(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_PCDispL(uint8_t ArgDat)
{
return getarg_long(DecodeAddr_PCDisp(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_PCIndexB(uint8_t ArgDat)
{
return getarg_byte(DecodeAddr_PCIndex(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_PCIndexW(uint8_t ArgDat)
{
return getarg_word(DecodeAddr_PCIndex(ArgDat));
}
LOCALFUNC uint32_t reg_call DecodeGetSetSrcDst_PCIndexL(uint8_t ArgDat)
{
return getarg_long(DecodeAddr_PCIndex(ArgDat));
}
typedef uint32_t (reg_call *DecodeGetSetSrcDstP)(uint8_t ArgDat);
LOCALVAR const DecodeGetSetSrcDstP
DecodeGetSetSrcDstDispatch[kNumAMds] =
{
DecodeGetSetSrcDst_RegB /* kAMdRegB */,
DecodeGetSetSrcDst_RegW /* kAMdRegW */,
DecodeGetSetSrcDst_RegL /* kAMdRegL */,
DecodeGetSetSrcDst_IndirectB /* kAMdIndirectB */,
DecodeGetSetSrcDst_IndirectW /* kAMdIndirectW */,
DecodeGetSetSrcDst_IndirectL /* kAMdIndirectL*/,
DecodeGetSetSrcDst_APosIncB /* kAMdAPosIncB */,
DecodeGetSetSrcDst_APosIncW /* kAMdAPosIncW */,
DecodeGetSetSrcDst_APosIncL /* kAMdAPosIncL */,
DecodeGetSetSrcDst_APosInc7B /* kAMdAPosInc7B */,
DecodeGetSetSrcDst_APreDecB /* kAMdAPreDecB */,
DecodeGetSetSrcDst_APreDecW /* kAMdAPreDecW */,
DecodeGetSetSrcDst_APreDecL /* kAMdAPreDecL */,
DecodeGetSetSrcDst_APreDec7B /* kAMdAPreDec7B */,
DecodeGetSetSrcDst_ADispB /* kAMdADispB */,
DecodeGetSetSrcDst_ADispW /* kAMdADispW */,
DecodeGetSetSrcDst_ADispL /* kAMdADispL */,
DecodeGetSetSrcDst_AIndexB /* kAMdAIndexB */,
DecodeGetSetSrcDst_AIndexW /* kAMdAIndexW */,
DecodeGetSetSrcDst_AIndexL /* kAMdAIndexL */,
DecodeGetSetSrcDst_AbsWB /* kAMdAbsWB */,
DecodeGetSetSrcDst_AbsWW /* kAMdAbsWW */,
DecodeGetSetSrcDst_AbsWL /* kAMdAbsWL */,
DecodeGetSetSrcDst_AbsLB /* kAMdAbsLB */,
DecodeGetSetSrcDst_AbsLW /* kAMdAbsLW */,
DecodeGetSetSrcDst_AbsLL /* kAMdAbsLL */,
DecodeGetSetSrcDst_PCDispB /* kAMdPCDispB */,
DecodeGetSetSrcDst_PCDispW /* kAMdPCDispW */,
DecodeGetSetSrcDst_PCDispL /* kAMdPCDispL */,
DecodeGetSetSrcDst_PCIndexB /* kAMdPCIndexB */,
DecodeGetSetSrcDst_PCIndexW /* kAMdPCIndexW */,
DecodeGetSetSrcDst_PCIndexL /* kAMdPCIndexL */,
(DecodeGetSetSrcDstP)nullpr /* kAMdImmedB */,
(DecodeGetSetSrcDstP)nullpr /* kAMdImmedW */,
(DecodeGetSetSrcDstP)nullpr /* kAMdImmedL */,
(DecodeGetSetSrcDstP)nullpr /* kAMdDat4 */
};
LOCALINLINEFUNC uint32_t DecodeGetSetSrcDst(DecArgR *f)
{
return (DecodeGetSetSrcDstDispatch[f->AMd])(f->ArgDat);
}
LOCALINLINEFUNC uint32_t DecodeDst(void)
{
return DecodeAddrSrcDst(&V_regs.CurDecOpY.v[1]);
}
LOCALINLINEFUNC uint32_t DecodeGetSetDstValue(void)
{
return DecodeGetSetSrcDst(&V_regs.CurDecOpY.v[1]);
}
LOCALINLINEPROC ArgSetDstValue(uint32_t v)
{
V_regs.ArgSetDst(v);
}
LOCALINLINEPROC DecodeSetDstValue(uint32_t v)
{
DecodeSetSrcDst(v, &V_regs.CurDecOpY.v[1]);
}
LOCALINLINEFUNC uint32_t DecodeGetSrcValue(void)
{
return DecodeGetSrcDst(&V_regs.CurDecOpY.v[0]);
}
LOCALINLINEFUNC uint32_t DecodeGetDstValue(void)
{
return DecodeGetSrcDst(&V_regs.CurDecOpY.v[1]);
}
LOCALINLINEFUNC uint32_t DecodeGetSrcSetDstValue(void)
{
V_regs.SrcVal = DecodeGetSrcValue();
return DecodeGetSetDstValue();
}
LOCALINLINEFUNC uint32_t DecodeGetSrcGetDstValue(void)
{
V_regs.SrcVal = DecodeGetSrcValue();
return DecodeGetDstValue();
}
typedef void (*cond_actP)(void);
LOCALPROC reg_call cctrue_T(cond_actP t_act, cond_actP f_act)
{
UnusedParam(f_act);
t_act();
}
LOCALPROC reg_call cctrue_F(cond_actP t_act, cond_actP f_act)
{
UnusedParam(t_act);
f_act();
}
LOCALPROC reg_call cctrue_HI(cond_actP t_act, cond_actP f_act)
{
if (0 == (CFLG | ZFLG)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_LS(cond_actP t_act, cond_actP f_act)
{
if (0 != (CFLG | ZFLG)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CC(cond_actP t_act, cond_actP f_act)
{
if (0 == (CFLG)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CS(cond_actP t_act, cond_actP f_act)
{
if (0 != (CFLG)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_NE(cond_actP t_act, cond_actP f_act)
{
if (0 == (ZFLG)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_EQ(cond_actP t_act, cond_actP f_act)
{
if (0 != (ZFLG)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_VC(cond_actP t_act, cond_actP f_act)
{
if (0 == (VFLG)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_VS(cond_actP t_act, cond_actP f_act)
{
if (0 != (VFLG)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_PL(cond_actP t_act, cond_actP f_act)
{
if (0 == (NFLG)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_MI(cond_actP t_act, cond_actP f_act)
{
if (0 != (NFLG)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_GE(cond_actP t_act, cond_actP f_act)
{
if (0 == (NFLG ^ VFLG)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_LT(cond_actP t_act, cond_actP f_act)
{
if (0 != (NFLG ^ VFLG)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_GT(cond_actP t_act, cond_actP f_act)
{
if (0 == (ZFLG | (NFLG ^ VFLG))) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_LE(cond_actP t_act, cond_actP f_act)
{
if (0 != (ZFLG | (NFLG ^ VFLG))) {
t_act();
} else {
f_act();
}
}
#if Have_ASR
#define Ui5rASR(x, s) ((uint32_t)(((int32_t)(x)) >> (s)))
#else
LOCALFUNC uint32_t Ui5rASR(uint32_t x, uint32_t s)
{
uint32_t v;
if (uint32_t_MSBisSet(x)) {
v = ~ ((~ x) >> s);
} else {
v = x >> s;
}
return v;
}
#endif
#if UseLazyCC
LOCALPROC reg_call cctrue_TstL_HI(cond_actP t_act, cond_actP f_act)
{
if (((uint32_t)V_regs.LazyFlagArgDst) > ((uint32_t)0)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_TstL_LS(cond_actP t_act, cond_actP f_act)
{
if (((uint32_t)V_regs.LazyFlagArgDst) <= ((uint32_t)0)) {
t_act();
} else {
f_act();
}
}
#if 0 /* always true */
LOCALPROC reg_call cctrue_TstL_CC(cond_actP t_act, cond_actP f_act)
{
if (((uint32_t)V_regs.LazyFlagArgDst) >= ((uint32_t)0)) {
t_act();
} else {
f_act();
}
}
#endif
#if 0 /* always false */
LOCALPROC reg_call cctrue_TstL_CS(cond_actP t_act, cond_actP f_act)
{
if (((uint32_t)V_regs.LazyFlagArgDst) < ((uint32_t)0)) {
t_act();
} else {
f_act();
}
}
#endif
LOCALPROC reg_call cctrue_TstL_NE(cond_actP t_act, cond_actP f_act)
{
if (V_regs.LazyFlagArgDst != 0) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_TstL_EQ(cond_actP t_act, cond_actP f_act)
{
if (V_regs.LazyFlagArgDst == 0) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_TstL_PL(cond_actP t_act, cond_actP f_act)
{
if (((int32_t)(V_regs.LazyFlagArgDst)) >= 0) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_TstL_MI(cond_actP t_act, cond_actP f_act)
{
if (((int32_t)(V_regs.LazyFlagArgDst)) < 0) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_TstL_GE(cond_actP t_act, cond_actP f_act)
{
if (((int32_t)V_regs.LazyFlagArgDst) >= ((int32_t)0)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_TstL_LT(cond_actP t_act, cond_actP f_act)
{
if (((int32_t)V_regs.LazyFlagArgDst) < ((int32_t)0)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_TstL_GT(cond_actP t_act, cond_actP f_act)
{
if (((int32_t)V_regs.LazyFlagArgDst) > ((int32_t)0)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_TstL_LE(cond_actP t_act, cond_actP f_act)
{
if (((int32_t)V_regs.LazyFlagArgDst) <= ((int32_t)0)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpB_HI(cond_actP t_act, cond_actP f_act)
{
if (((uint8_t)V_regs.LazyFlagArgDst) > ((uint8_t)V_regs.LazyFlagArgSrc)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpB_LS(cond_actP t_act, cond_actP f_act)
{
if (((uint8_t)V_regs.LazyFlagArgDst) <= ((uint8_t)V_regs.LazyFlagArgSrc))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpB_CC(cond_actP t_act, cond_actP f_act)
{
if (((uint8_t)V_regs.LazyFlagArgDst) >= ((uint8_t)V_regs.LazyFlagArgSrc))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpB_CS(cond_actP t_act, cond_actP f_act)
{
if (((uint8_t)V_regs.LazyFlagArgDst) < ((uint8_t)V_regs.LazyFlagArgSrc))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpB_NE(cond_actP t_act, cond_actP f_act)
{
if (((uint8_t)V_regs.LazyFlagArgDst) != ((uint8_t)V_regs.LazyFlagArgSrc))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpB_EQ(cond_actP t_act, cond_actP f_act)
{
if (((uint8_t)V_regs.LazyFlagArgDst) == ((uint8_t)V_regs.LazyFlagArgSrc))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpB_PL(cond_actP t_act, cond_actP f_act)
{
if (((int8_t)(V_regs.LazyFlagArgDst - V_regs.LazyFlagArgSrc)) >= 0) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpB_MI(cond_actP t_act, cond_actP f_act)
{
if (((int8_t)(V_regs.LazyFlagArgDst - V_regs.LazyFlagArgSrc)) < 0) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpB_GE(cond_actP t_act, cond_actP f_act)
{
if (((int8_t)V_regs.LazyFlagArgDst) >= ((int8_t)V_regs.LazyFlagArgSrc))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpB_LT(cond_actP t_act, cond_actP f_act)
{
if (((int8_t)V_regs.LazyFlagArgDst) < ((int8_t)V_regs.LazyFlagArgSrc)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpB_GT(cond_actP t_act, cond_actP f_act)
{
if (((int8_t)V_regs.LazyFlagArgDst) > ((int8_t)V_regs.LazyFlagArgSrc)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpB_LE(cond_actP t_act, cond_actP f_act)
{
if (((int8_t)V_regs.LazyFlagArgDst) <= ((int8_t)V_regs.LazyFlagArgSrc))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpW_HI(cond_actP t_act, cond_actP f_act)
{
if (((uint16_t)V_regs.LazyFlagArgDst) > ((uint16_t)V_regs.LazyFlagArgSrc))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpW_LS(cond_actP t_act, cond_actP f_act)
{
if (((uint16_t)V_regs.LazyFlagArgDst) <= ((uint16_t)V_regs.LazyFlagArgSrc))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpW_CC(cond_actP t_act, cond_actP f_act)
{
if (((uint16_t)V_regs.LazyFlagArgDst) >= ((uint16_t)V_regs.LazyFlagArgSrc))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpW_CS(cond_actP t_act, cond_actP f_act)
{
if (((uint16_t)V_regs.LazyFlagArgDst) < ((uint16_t)V_regs.LazyFlagArgSrc)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpW_NE(cond_actP t_act, cond_actP f_act)
{
if (((uint16_t)V_regs.LazyFlagArgDst) != ((uint16_t)V_regs.LazyFlagArgSrc))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpW_EQ(cond_actP t_act, cond_actP f_act)
{
if (((uint16_t)V_regs.LazyFlagArgDst) == ((uint16_t)V_regs.LazyFlagArgSrc))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpW_PL(cond_actP t_act, cond_actP f_act)
{
if (((int16_t)(V_regs.LazyFlagArgDst - V_regs.LazyFlagArgSrc)) >= 0) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpW_MI(cond_actP t_act, cond_actP f_act)
{
if (((int16_t)(V_regs.LazyFlagArgDst - V_regs.LazyFlagArgSrc)) < 0) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpW_GE(cond_actP t_act, cond_actP f_act)
{
if (((int16_t)V_regs.LazyFlagArgDst) >= ((int16_t)V_regs.LazyFlagArgSrc))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpW_LT(cond_actP t_act, cond_actP f_act)
{
if (((int16_t)V_regs.LazyFlagArgDst) < ((int16_t)V_regs.LazyFlagArgSrc)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpW_GT(cond_actP t_act, cond_actP f_act)
{
if (((int16_t)V_regs.LazyFlagArgDst) > ((int16_t)V_regs.LazyFlagArgSrc)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpW_LE(cond_actP t_act, cond_actP f_act)
{
if (((int16_t)V_regs.LazyFlagArgDst) <= ((int16_t)V_regs.LazyFlagArgSrc))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpL_HI(cond_actP t_act, cond_actP f_act)
{
if (((uint32_t)V_regs.LazyFlagArgDst) > ((uint32_t)V_regs.LazyFlagArgSrc)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpL_LS(cond_actP t_act, cond_actP f_act)
{
if (((uint32_t)V_regs.LazyFlagArgDst) <= ((uint32_t)V_regs.LazyFlagArgSrc))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpL_CC(cond_actP t_act, cond_actP f_act)
{
if (((uint32_t)V_regs.LazyFlagArgDst) >= ((uint32_t)V_regs.LazyFlagArgSrc))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpL_CS(cond_actP t_act, cond_actP f_act)
{
if (((uint32_t)V_regs.LazyFlagArgDst) < ((uint32_t)V_regs.LazyFlagArgSrc)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpL_NE(cond_actP t_act, cond_actP f_act)
{
if (V_regs.LazyFlagArgDst != V_regs.LazyFlagArgSrc) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpL_EQ(cond_actP t_act, cond_actP f_act)
{
if (V_regs.LazyFlagArgDst == V_regs.LazyFlagArgSrc) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpL_PL(cond_actP t_act, cond_actP f_act)
{
if ((((int32_t)(V_regs.LazyFlagArgDst - V_regs.LazyFlagArgSrc)) >= 0))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpL_MI(cond_actP t_act, cond_actP f_act)
{
if ((((int32_t)(V_regs.LazyFlagArgDst - V_regs.LazyFlagArgSrc)) < 0)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpL_GE(cond_actP t_act, cond_actP f_act)
{
if (((int32_t)V_regs.LazyFlagArgDst) >= ((int32_t)V_regs.LazyFlagArgSrc))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpL_LT(cond_actP t_act, cond_actP f_act)
{
if (((int32_t)V_regs.LazyFlagArgDst) < ((int32_t)V_regs.LazyFlagArgSrc)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpL_GT(cond_actP t_act, cond_actP f_act)
{
if (((int32_t)V_regs.LazyFlagArgDst) > ((int32_t)V_regs.LazyFlagArgSrc)) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_CmpL_LE(cond_actP t_act, cond_actP f_act)
{
if (((int32_t)V_regs.LazyFlagArgDst) <= ((int32_t)V_regs.LazyFlagArgSrc))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_Asr_CC(cond_actP t_act, cond_actP f_act)
{
if (0 ==
((V_regs.LazyFlagArgDst >> (V_regs.LazyFlagArgSrc - 1)) & 1))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_Asr_CS(cond_actP t_act, cond_actP f_act)
{
if (0 !=
((V_regs.LazyFlagArgDst >> (V_regs.LazyFlagArgSrc - 1)) & 1))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_AslB_CC(cond_actP t_act, cond_actP f_act)
{
if (0 ==
((V_regs.LazyFlagArgDst >> (8 - V_regs.LazyFlagArgSrc)) & 1))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_AslB_CS(cond_actP t_act, cond_actP f_act)
{
if (0 !=
((V_regs.LazyFlagArgDst >> (8 - V_regs.LazyFlagArgSrc)) & 1))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_AslB_VC(cond_actP t_act, cond_actP f_act)
{
uint32_t cnt = V_regs.LazyFlagArgSrc;
uint32_t dst = uint32_t_FromSByte(V_regs.LazyFlagArgDst << cnt);
if (Ui5rASR(dst, cnt) == V_regs.LazyFlagArgDst) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_AslB_VS(cond_actP t_act, cond_actP f_act)
{
uint32_t cnt = V_regs.LazyFlagArgSrc;
uint32_t dst = uint32_t_FromSByte(V_regs.LazyFlagArgDst << cnt);
if (Ui5rASR(dst, cnt) != V_regs.LazyFlagArgDst) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_AslW_CC(cond_actP t_act, cond_actP f_act)
{
if (0 ==
((V_regs.LazyFlagArgDst >> (16 - V_regs.LazyFlagArgSrc)) & 1))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_AslW_CS(cond_actP t_act, cond_actP f_act)
{
if (0 !=
((V_regs.LazyFlagArgDst >> (16 - V_regs.LazyFlagArgSrc)) & 1))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_AslW_VC(cond_actP t_act, cond_actP f_act)
{
uint32_t cnt = V_regs.LazyFlagArgSrc;
uint32_t dst = uint32_t_FromSWord(V_regs.LazyFlagArgDst << cnt);
if (Ui5rASR(dst, cnt) == V_regs.LazyFlagArgDst) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_AslW_VS(cond_actP t_act, cond_actP f_act)
{
uint32_t cnt = V_regs.LazyFlagArgSrc;
uint32_t dst = uint32_t_FromSWord(V_regs.LazyFlagArgDst << cnt);
if (Ui5rASR(dst, cnt) != V_regs.LazyFlagArgDst) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_AslL_CC(cond_actP t_act, cond_actP f_act)
{
if (0 ==
((V_regs.LazyFlagArgDst >> (32 - V_regs.LazyFlagArgSrc)) & 1))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_AslL_CS(cond_actP t_act, cond_actP f_act)
{
if (0 !=
((V_regs.LazyFlagArgDst >> (32 - V_regs.LazyFlagArgSrc)) & 1))
{
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_AslL_VC(cond_actP t_act, cond_actP f_act)
{
uint32_t cnt = V_regs.LazyFlagArgSrc;
uint32_t dst = uint32_t_FromSLong(V_regs.LazyFlagArgDst << cnt);
if (Ui5rASR(dst, cnt) == V_regs.LazyFlagArgDst) {
t_act();
} else {
f_act();
}
}
LOCALPROC reg_call cctrue_AslL_VS(cond_actP t_act, cond_actP f_act)
{
uint32_t cnt = V_regs.LazyFlagArgSrc;
uint32_t dst = uint32_t_FromSLong(V_regs.LazyFlagArgDst << cnt);
if (Ui5rASR(dst, cnt) != V_regs.LazyFlagArgDst) {
t_act();
} else {
f_act();
}
}
FORWARDPROC reg_call cctrue_Dflt(cond_actP t_act, cond_actP f_act);
#endif /* UseLazyCC */
#if UseLazyCC
#define CCdispSz (16 * kNumLazyFlagsKinds)
#else
#define CCdispSz kNumLazyFlagsKinds
#endif
typedef void (reg_call *cctrueP)(cond_actP t_act, cond_actP f_act);
LOCALVAR const cctrueP cctrueDispatch[CCdispSz + 1] = {
cctrue_T /* kLazyFlagsDefault T */,
cctrue_F /* kLazyFlagsDefault F */,
cctrue_HI /* kLazyFlagsDefault HI */,
cctrue_LS /* kLazyFlagsDefault LS */,
cctrue_CC /* kLazyFlagsDefault CC */,
cctrue_CS /* kLazyFlagsDefault CS */,
cctrue_NE /* kLazyFlagsDefault NE */,
cctrue_EQ /* kLazyFlagsDefault EQ */,
cctrue_VC /* kLazyFlagsDefault VC */,
cctrue_VS /* kLazyFlagsDefault VS */,
cctrue_PL /* kLazyFlagsDefault PL */,
cctrue_MI /* kLazyFlagsDefault MI */,
cctrue_GE /* kLazyFlagsDefault GE */,
cctrue_LT /* kLazyFlagsDefault LT */,
cctrue_GT /* kLazyFlagsDefault GT */,
cctrue_LE /* kLazyFlagsDefault LE */,
#if UseLazyCC
cctrue_T /* kLazyFlagsTstB T */,
cctrue_F /* kLazyFlagsTstB F */,
cctrue_Dflt /* kLazyFlagsTstB HI */,
cctrue_Dflt /* kLazyFlagsTstB LS */,
cctrue_Dflt /* kLazyFlagsTstB CC */,
cctrue_Dflt /* kLazyFlagsTstB CS */,
cctrue_Dflt /* kLazyFlagsTstB NE */,
cctrue_Dflt /* kLazyFlagsTstB EQ */,
cctrue_Dflt /* kLazyFlagsTstB VC */,
cctrue_Dflt /* kLazyFlagsTstB VS */,
cctrue_Dflt /* kLazyFlagsTstB PL */,
cctrue_Dflt /* kLazyFlagsTstB MI */,
cctrue_Dflt /* kLazyFlagsTstB GE */,
cctrue_Dflt /* kLazyFlagsTstB LT */,
cctrue_Dflt /* kLazyFlagsTstB GT */,
cctrue_Dflt /* kLazyFlagsTstB LE */,
cctrue_T /* kLazyFlagsTstW T */,
cctrue_F /* kLazyFlagsTstW F */,
cctrue_Dflt /* kLazyFlagsTstW HI */,
cctrue_Dflt /* kLazyFlagsTstW LS */,
cctrue_Dflt /* kLazyFlagsTstW CC */,
cctrue_Dflt /* kLazyFlagsTstW CS */,
cctrue_Dflt /* kLazyFlagsTstW NE */,
cctrue_Dflt /* kLazyFlagsTstW EQ */,
cctrue_Dflt /* kLazyFlagsTstW VC */,
cctrue_Dflt /* kLazyFlagsTstW VS */,
cctrue_Dflt /* kLazyFlagsTstW PL */,
cctrue_Dflt /* kLazyFlagsTstW MI */,
cctrue_Dflt /* kLazyFlagsTstW GE */,
cctrue_Dflt /* kLazyFlagsTstW LT */,
cctrue_Dflt /* kLazyFlagsTstW GT */,
cctrue_Dflt /* kLazyFlagsTstW LE */,
cctrue_T /* kLazyFlagsTstL T */,
cctrue_F /* kLazyFlagsTstL F */,
cctrue_TstL_HI /* kLazyFlagsTstL HI */,
cctrue_TstL_LS /* kLazyFlagsTstL LS */,
cctrue_T /* cctrue_TstL_CC */ /* kLazyFlagsTstL CC */,
cctrue_F /* cctrue_TstL_CS */ /* kLazyFlagsTstL CS */,
cctrue_TstL_NE /* kLazyFlagsTstL NE */,
cctrue_TstL_EQ /* kLazyFlagsTstL EQ */,
cctrue_T /* cctrue_Dflt */ /* kLazyFlagsTstL VC */,
cctrue_F /* cctrue_Dflt */ /* kLazyFlagsTstL VS */,
cctrue_TstL_PL /* kLazyFlagsTstL PL */,
cctrue_TstL_MI /* kLazyFlagsTstL MI */,
cctrue_TstL_GE /* kLazyFlagsTstL GE */,
cctrue_TstL_LT /* kLazyFlagsTstL LT */,
cctrue_TstL_GT /* kLazyFlagsTstL GT */,
cctrue_TstL_LE /* kLazyFlagsTstL LE */,
cctrue_T /* kLazyFlagsCmpB T */,
cctrue_F /* kLazyFlagsCmpB F */,
cctrue_CmpB_HI /* kLazyFlagsCmpB HI */,
cctrue_CmpB_LS /* kLazyFlagsCmpB LS */,
cctrue_CmpB_CC /* kLazyFlagsCmpB CC */,
cctrue_CmpB_CS /* kLazyFlagsCmpB CS */,
cctrue_CmpB_NE /* kLazyFlagsCmpB NE */,
cctrue_CmpB_EQ /* kLazyFlagsCmpB EQ */,
cctrue_Dflt /* kLazyFlagsCmpB VC */,
cctrue_Dflt /* kLazyFlagsCmpB VS */,
cctrue_CmpB_PL /* kLazyFlagsCmpB PL */,
cctrue_CmpB_MI /* kLazyFlagsCmpB MI */,
cctrue_CmpB_GE /* kLazyFlagsCmpB GE */,
cctrue_CmpB_LT /* kLazyFlagsCmpB LT */,
cctrue_CmpB_GT /* kLazyFlagsCmpB GT */,
cctrue_CmpB_LE /* kLazyFlagsCmpB LE */,
cctrue_T /* kLazyFlagsCmpW T */,
cctrue_F /* kLazyFlagsCmpW F */,
cctrue_CmpW_HI /* kLazyFlagsCmpW HI */,
cctrue_CmpW_LS /* kLazyFlagsCmpW LS */,
cctrue_CmpW_CC /* kLazyFlagsCmpW CC */,
cctrue_CmpW_CS /* kLazyFlagsCmpW CS */,
cctrue_CmpW_NE /* kLazyFlagsCmpW NE */,
cctrue_CmpW_EQ /* kLazyFlagsCmpW EQ */,
cctrue_Dflt /* kLazyFlagsCmpW VC */,
cctrue_Dflt /* kLazyFlagsCmpW VS */,
cctrue_CmpW_PL /* kLazyFlagsCmpW PL */,
cctrue_CmpW_MI /* kLazyFlagsCmpW MI */,
cctrue_CmpW_GE /* kLazyFlagsCmpW GE */,
cctrue_CmpW_LT /* kLazyFlagsCmpW LT */,
cctrue_CmpW_GT /* kLazyFlagsCmpW GT */,
cctrue_CmpW_LE /* kLazyFlagsCmpW LE */,
cctrue_T /* kLazyFlagsCmpL T */,
cctrue_F /* kLazyFlagsCmpL F */,
cctrue_CmpL_HI /* kLazyFlagsCmpL HI */,
cctrue_CmpL_LS /* kLazyFlagsCmpL LS */,
cctrue_CmpL_CC /* kLazyFlagsCmpL CC */,
cctrue_CmpL_CS /* kLazyFlagsCmpL CS */,
cctrue_CmpL_NE /* kLazyFlagsCmpL NE */,
cctrue_CmpL_EQ /* kLazyFlagsCmpL EQ */,
cctrue_Dflt /* kLazyFlagsCmpL VC */,
cctrue_Dflt /* kLazyFlagsCmpL VS */,
cctrue_CmpL_PL /* kLazyFlagsCmpL PL */,
cctrue_CmpL_MI /* kLazyFlagsCmpL MI */,
cctrue_CmpL_GE /* kLazyFlagsCmpL GE */,
cctrue_CmpL_LT /* kLazyFlagsCmpL LT */,
cctrue_CmpL_GT /* kLazyFlagsCmpL GT */,
cctrue_CmpL_LE /* kLazyFlagsCmpL LE */,
cctrue_T /* kLazyFlagsSubB T */,
cctrue_F /* kLazyFlagsSubB F */,
cctrue_CmpB_HI /* kLazyFlagsSubB HI */,
cctrue_CmpB_LS /* kLazyFlagsSubB LS */,
cctrue_CmpB_CC /* kLazyFlagsSubB CC */,
cctrue_CmpB_CS /* kLazyFlagsSubB CS */,
cctrue_CmpB_NE /* kLazyFlagsSubB NE */,
cctrue_CmpB_EQ /* kLazyFlagsSubB EQ */,
cctrue_Dflt /* kLazyFlagsSubB VC */,
cctrue_Dflt /* kLazyFlagsSubB VS */,
cctrue_CmpB_PL /* kLazyFlagsSubB PL */,
cctrue_CmpB_MI /* kLazyFlagsSubB MI */,
cctrue_CmpB_GE /* kLazyFlagsSubB GE */,
cctrue_CmpB_LT /* kLazyFlagsSubB LT */,
cctrue_CmpB_GT /* kLazyFlagsSubB GT */,
cctrue_CmpB_LE /* kLazyFlagsSubB LE */,
cctrue_T /* kLazyFlagsSubW T */,
cctrue_F /* kLazyFlagsSubW F */,
cctrue_CmpW_HI /* kLazyFlagsSubW HI */,
cctrue_CmpW_LS /* kLazyFlagsSubW LS */,
cctrue_CmpW_CC /* kLazyFlagsSubW CC */,
cctrue_CmpW_CS /* kLazyFlagsSubW CS */,
cctrue_CmpW_NE /* kLazyFlagsSubW NE */,
cctrue_CmpW_EQ /* kLazyFlagsSubW EQ */,
cctrue_Dflt /* kLazyFlagsSubW VC */,
cctrue_Dflt /* kLazyFlagsSubW VS */,
cctrue_CmpW_PL /* kLazyFlagsSubW PL */,
cctrue_CmpW_MI /* kLazyFlagsSubW MI */,
cctrue_CmpW_GE /* kLazyFlagsSubW GE */,
cctrue_CmpW_LT /* kLazyFlagsSubW LT */,
cctrue_CmpW_GT /* kLazyFlagsSubW GT */,
cctrue_CmpW_LE /* kLazyFlagsSubW LE */,
cctrue_T /* kLazyFlagsSubL T */,
cctrue_F /* kLazyFlagsSubL F */,
cctrue_CmpL_HI /* kLazyFlagsSubL HI */,
cctrue_CmpL_LS /* kLazyFlagsSubL LS */,
cctrue_CmpL_CC /* kLazyFlagsSubL CC */,
cctrue_CmpL_CS /* kLazyFlagsSubL CS */,
cctrue_CmpL_NE /* kLazyFlagsSubL NE */,
cctrue_CmpL_EQ /* kLazyFlagsSubL EQ */,
cctrue_Dflt /* kLazyFlagsSubL VC */,
cctrue_Dflt /* kLazyFlagsSubL VS */,
cctrue_CmpL_PL /* kLazyFlagsSubL PL */,
cctrue_CmpL_MI /* kLazyFlagsSubL MI */,
cctrue_CmpL_GE /* kLazyFlagsSubL GE */,
cctrue_CmpL_LT /* kLazyFlagsSubL LT */,
cctrue_CmpL_GT /* kLazyFlagsSubL GT */,
cctrue_CmpL_LE /* kLazyFlagsSubL LE */,
cctrue_T /* kLazyFlagsAddB T */,
cctrue_F /* kLazyFlagsAddB F */,
cctrue_Dflt /* kLazyFlagsAddB HI */,
cctrue_Dflt /* kLazyFlagsAddB LS */,
cctrue_Dflt /* kLazyFlagsAddB CC */,
cctrue_Dflt /* kLazyFlagsAddB CS */,
cctrue_Dflt /* kLazyFlagsAddB NE */,
cctrue_Dflt /* kLazyFlagsAddB EQ */,
cctrue_Dflt /* kLazyFlagsAddB VC */,
cctrue_Dflt /* kLazyFlagsAddB VS */,
cctrue_Dflt /* kLazyFlagsAddB PL */,
cctrue_Dflt /* kLazyFlagsAddB MI */,
cctrue_Dflt /* kLazyFlagsAddB GE */,
cctrue_Dflt /* kLazyFlagsAddB LT */,
cctrue_Dflt /* kLazyFlagsAddB GT */,
cctrue_Dflt /* kLazyFlagsAddB LE */,
cctrue_T /* kLazyFlagsAddW T */,
cctrue_F /* kLazyFlagsAddW F */,
cctrue_Dflt /* kLazyFlagsAddW HI */,
cctrue_Dflt /* kLazyFlagsAddW LS */,
cctrue_Dflt /* kLazyFlagsAddW CC */,
cctrue_Dflt /* kLazyFlagsAddW CS */,
cctrue_Dflt /* kLazyFlagsAddW NE */,
cctrue_Dflt /* kLazyFlagsAddW EQ */,
cctrue_Dflt /* kLazyFlagsAddW VC */,
cctrue_Dflt /* kLazyFlagsAddW VS */,
cctrue_Dflt /* kLazyFlagsAddW PL */,
cctrue_Dflt /* kLazyFlagsAddW MI */,
cctrue_Dflt /* kLazyFlagsAddW GE */,
cctrue_Dflt /* kLazyFlagsAddW LT */,
cctrue_Dflt /* kLazyFlagsAddW GT */,
cctrue_Dflt /* kLazyFlagsAddW LE */,
cctrue_T /* kLazyFlagsAddL T */,
cctrue_F /* kLazyFlagsAddL F */,
cctrue_Dflt /* kLazyFlagsAddL HI */,
cctrue_Dflt /* kLazyFlagsAddL LS */,
cctrue_Dflt /* kLazyFlagsAddL CC */,
cctrue_Dflt /* kLazyFlagsAddL CS */,
cctrue_Dflt /* kLazyFlagsAddL NE */,
cctrue_Dflt /* kLazyFlagsAddL EQ */,
cctrue_Dflt /* kLazyFlagsAddL VC */,
cctrue_Dflt /* kLazyFlagsAddL VS */,
cctrue_Dflt /* kLazyFlagsAddL PL */,
cctrue_Dflt /* kLazyFlagsAddL MI */,
cctrue_Dflt /* kLazyFlagsAddL GE */,
cctrue_Dflt /* kLazyFlagsAddL LT */,
cctrue_Dflt /* kLazyFlagsAddL GT */,
cctrue_Dflt /* kLazyFlagsAddL LE */,
cctrue_T /* kLazyFlagsNegB T */,
cctrue_F /* kLazyFlagsNegB F */,
cctrue_Dflt /* kLazyFlagsNegB HI */,
cctrue_Dflt /* kLazyFlagsNegB LS */,
cctrue_Dflt /* kLazyFlagsNegB CC */,
cctrue_Dflt /* kLazyFlagsNegB CS */,
cctrue_Dflt /* kLazyFlagsNegB NE */,
cctrue_Dflt /* kLazyFlagsNegB EQ */,
cctrue_Dflt /* kLazyFlagsNegB VC */,
cctrue_Dflt /* kLazyFlagsNegB VS */,
cctrue_Dflt /* kLazyFlagsNegB PL */,
cctrue_Dflt /* kLazyFlagsNegB MI */,
cctrue_Dflt /* kLazyFlagsNegB GE */,
cctrue_Dflt /* kLazyFlagsNegB LT */,
cctrue_Dflt /* kLazyFlagsNegB GT */,
cctrue_Dflt /* kLazyFlagsNegB LE */,
cctrue_T /* kLazyFlagsNegW T */,
cctrue_F /* kLazyFlagsNegW F */,
cctrue_Dflt /* kLazyFlagsNegW HI */,
cctrue_Dflt /* kLazyFlagsNegW LS */,
cctrue_Dflt /* kLazyFlagsNegW CC */,
cctrue_Dflt /* kLazyFlagsNegW CS */,
cctrue_Dflt /* kLazyFlagsNegW NE */,
cctrue_Dflt /* kLazyFlagsNegW EQ */,
cctrue_Dflt /* kLazyFlagsNegW VC */,
cctrue_Dflt /* kLazyFlagsNegW VS */,
cctrue_Dflt /* kLazyFlagsNegW PL */,
cctrue_Dflt /* kLazyFlagsNegW MI */,
cctrue_Dflt /* kLazyFlagsNegW GE */,
cctrue_Dflt /* kLazyFlagsNegW LT */,
cctrue_Dflt /* kLazyFlagsNegW GT */,
cctrue_Dflt /* kLazyFlagsNegW LE */,
cctrue_T /* kLazyFlagsNegL T */,
cctrue_F /* kLazyFlagsNegL F */,
cctrue_Dflt /* kLazyFlagsNegL HI */,
cctrue_Dflt /* kLazyFlagsNegL LS */,
cctrue_Dflt /* kLazyFlagsNegL CC */,
cctrue_Dflt /* kLazyFlagsNegL CS */,
cctrue_Dflt /* kLazyFlagsNegL NE */,
cctrue_Dflt /* kLazyFlagsNegL EQ */,
cctrue_Dflt /* kLazyFlagsNegL VC */,
cctrue_Dflt /* kLazyFlagsNegL VS */,
cctrue_Dflt /* kLazyFlagsNegL PL */,
cctrue_Dflt /* kLazyFlagsNegL MI */,
cctrue_Dflt /* kLazyFlagsNegL GE */,
cctrue_Dflt /* kLazyFlagsNegL LT */,
cctrue_Dflt /* kLazyFlagsNegL GT */,
cctrue_Dflt /* kLazyFlagsNegL LE */,
cctrue_T /* kLazyFlagsAsrB T */,
cctrue_F /* kLazyFlagsAsrB F */,
cctrue_Dflt /* kLazyFlagsAsrB HI */,
cctrue_Dflt /* kLazyFlagsAsrB LS */,
cctrue_Asr_CC /* kLazyFlagsAsrB CC */,
cctrue_Asr_CS /* kLazyFlagsAsrB CS */,
cctrue_Dflt /* kLazyFlagsAsrB NE */,
cctrue_Dflt /* kLazyFlagsAsrB EQ */,
cctrue_Dflt /* kLazyFlagsAsrB VC */,
cctrue_Dflt /* kLazyFlagsAsrB VS */,
cctrue_Dflt /* kLazyFlagsAsrB PL */,
cctrue_Dflt /* kLazyFlagsAsrB MI */,
cctrue_Dflt /* kLazyFlagsAsrB GE */,
cctrue_Dflt /* kLazyFlagsAsrB LT */,
cctrue_Dflt /* kLazyFlagsAsrB GT */,
cctrue_Dflt /* kLazyFlagsAsrB LE */,
cctrue_T /* kLazyFlagsAsrW T */,
cctrue_F /* kLazyFlagsAsrW F */,
cctrue_Dflt /* kLazyFlagsAsrW HI */,
cctrue_Dflt /* kLazyFlagsAsrW LS */,
cctrue_Asr_CC /* kLazyFlagsAsrW CC */,
cctrue_Asr_CS /* kLazyFlagsAsrW CS */,
cctrue_Dflt /* kLazyFlagsAsrW NE */,
cctrue_Dflt /* kLazyFlagsAsrW EQ */,
cctrue_Dflt /* kLazyFlagsAsrW VC */,
cctrue_Dflt /* kLazyFlagsAsrW VS */,
cctrue_Dflt /* kLazyFlagsAsrW PL */,
cctrue_Dflt /* kLazyFlagsAsrW MI */,
cctrue_Dflt /* kLazyFlagsAsrW GE */,
cctrue_Dflt /* kLazyFlagsAsrW LT */,
cctrue_Dflt /* kLazyFlagsAsrW GT */,
cctrue_Dflt /* kLazyFlagsAsrW LE */,
cctrue_T /* kLazyFlagsAsrL T */,
cctrue_F /* kLazyFlagsAsrL F */,
cctrue_Dflt /* kLazyFlagsAsrL HI */,
cctrue_Dflt /* kLazyFlagsAsrL LS */,
cctrue_Asr_CC /* kLazyFlagsAsrL CC */,
cctrue_Asr_CS /* kLazyFlagsAsrL CS */,
cctrue_Dflt /* kLazyFlagsAsrL NE */,
cctrue_Dflt /* kLazyFlagsAsrL EQ */,
cctrue_Dflt /* kLazyFlagsAsrL VC */,
cctrue_Dflt /* kLazyFlagsAsrL VS */,
cctrue_Dflt /* kLazyFlagsAsrL PL */,
cctrue_Dflt /* kLazyFlagsAsrL MI */,
cctrue_Dflt /* kLazyFlagsAsrL GE */,
cctrue_Dflt /* kLazyFlagsAsrL LT */,
cctrue_Dflt /* kLazyFlagsAsrL GT */,
cctrue_Dflt /* kLazyFlagsAsrL LE */,
cctrue_T /* kLazyFlagsAslB T */,
cctrue_F /* kLazyFlagsAslB F */,
cctrue_Dflt /* kLazyFlagsAslB HI */,
cctrue_Dflt /* kLazyFlagsAslB LS */,
cctrue_AslB_CC /* kLazyFlagsAslB CC */,
cctrue_AslB_CS /* kLazyFlagsAslB CS */,
cctrue_Dflt /* kLazyFlagsAslB NE */,
cctrue_Dflt /* kLazyFlagsAslB EQ */,
cctrue_AslB_VC /* kLazyFlagsAslB VC */,
cctrue_AslB_VS /* kLazyFlagsAslB VS */,
cctrue_Dflt /* kLazyFlagsAslB PL */,
cctrue_Dflt /* kLazyFlagsAslB MI */,
cctrue_Dflt /* kLazyFlagsAslB GE */,
cctrue_Dflt /* kLazyFlagsAslB LT */,
cctrue_Dflt /* kLazyFlagsAslB GT */,
cctrue_Dflt /* kLazyFlagsAslB LE */,
cctrue_T /* kLazyFlagsAslW T */,
cctrue_F /* kLazyFlagsAslW F */,
cctrue_Dflt /* kLazyFlagsAslW HI */,
cctrue_Dflt /* kLazyFlagsAslW LS */,
cctrue_AslW_CC /* kLazyFlagsAslW CC */,
cctrue_AslW_CS /* kLazyFlagsAslW CS */,
cctrue_Dflt /* kLazyFlagsAslW NE */,
cctrue_Dflt /* kLazyFlagsAslW EQ */,
cctrue_AslW_VC /* kLazyFlagsAslW VC */,
cctrue_AslW_VS /* kLazyFlagsAslW VS */,
cctrue_Dflt /* kLazyFlagsAslW PL */,
cctrue_Dflt /* kLazyFlagsAslW MI */,
cctrue_Dflt /* kLazyFlagsAslW GE */,
cctrue_Dflt /* kLazyFlagsAslW LT */,
cctrue_Dflt /* kLazyFlagsAslW GT */,
cctrue_Dflt /* kLazyFlagsAslW LE */,
cctrue_T /* kLazyFlagsAslL T */,
cctrue_F /* kLazyFlagsAslL F */,
cctrue_Dflt /* kLazyFlagsAslL HI */,
cctrue_Dflt /* kLazyFlagsAslL LS */,
cctrue_AslL_CC /* kLazyFlagsAslL CC */,
cctrue_AslL_CS /* kLazyFlagsAslL CS */,
cctrue_Dflt /* kLazyFlagsAslL NE */,
cctrue_Dflt /* kLazyFlagsAslL EQ */,
cctrue_AslL_VC /* kLazyFlagsAslL VC */,
cctrue_AslL_VS /* kLazyFlagsAslL VS */,
cctrue_Dflt /* kLazyFlagsAslL PL */,
cctrue_Dflt /* kLazyFlagsAslL MI */,
cctrue_Dflt /* kLazyFlagsAslL GE */,
cctrue_Dflt /* kLazyFlagsAslL LT */,
cctrue_Dflt /* kLazyFlagsAslL GT */,
cctrue_Dflt /* kLazyFlagsAslL LE */,
#if UseLazyZ
cctrue_T /* kLazyFlagsZSet T */,
cctrue_F /* kLazyFlagsZSet F */,
cctrue_Dflt /* kLazyFlagsZSet HI */,
cctrue_Dflt /* kLazyFlagsZSet LS */,
cctrue_Dflt /* kLazyFlagsZSet CC */,
cctrue_Dflt /* kLazyFlagsZSet CS */,
cctrue_NE /* kLazyFlagsZSet NE */,
cctrue_EQ /* kLazyFlagsZSet EQ */,
cctrue_Dflt /* kLazyFlagsZSet VC */,
cctrue_Dflt /* kLazyFlagsZSet VS */,
cctrue_Dflt /* kLazyFlagsZSet PL */,
cctrue_Dflt /* kLazyFlagsZSet MI */,
cctrue_Dflt /* kLazyFlagsZSet GE */,
cctrue_Dflt /* kLazyFlagsZSet LT */,
cctrue_Dflt /* kLazyFlagsZSet GT */,
cctrue_Dflt /* kLazyFlagsZSet LE */,
#endif
#endif /* UseLazyCC */
0
};
#if UseLazyCC
LOCALINLINEPROC cctrue(cond_actP t_act, cond_actP f_act)
{
(cctrueDispatch[V_regs.LazyFlagKind * 16
+ V_regs.CurDecOpY.v[0].ArgDat])(t_act, f_act);
}
#endif
LOCALPROC NeedDefaultLazyXFlagSubB(void)
{
XFLG = Bool2Bit(((uint8_t)V_regs.LazyXFlagArgDst)
< ((uint8_t)V_regs.LazyXFlagArgSrc));
V_regs.LazyXFlagKind = kLazyFlagsDefault;
}
LOCALPROC NeedDefaultLazyXFlagSubW(void)
{
XFLG = Bool2Bit(((uint16_t)V_regs.LazyXFlagArgDst)
< ((uint16_t)V_regs.LazyXFlagArgSrc));
V_regs.LazyXFlagKind = kLazyFlagsDefault;
}
LOCALPROC NeedDefaultLazyXFlagSubL(void)
{
XFLG = Bool2Bit(((uint32_t)V_regs.LazyXFlagArgDst)
< ((uint32_t)V_regs.LazyXFlagArgSrc));
V_regs.LazyXFlagKind = kLazyFlagsDefault;
}
LOCALPROC NeedDefaultLazyXFlagAddB(void)
{
uint8_t src = (uint8_t)V_regs.LazyXFlagArgSrc;
uint8_t dst = (uint8_t)V_regs.LazyXFlagArgDst;
uint8_t result = dst + src;
XFLG = Bool2Bit(result < src);
V_regs.LazyXFlagKind = kLazyFlagsDefault;
}
LOCALPROC NeedDefaultLazyXFlagAddW(void)
{
uint16_t src = (uint16_t)V_regs.LazyXFlagArgSrc;
uint16_t dst = (uint16_t)V_regs.LazyXFlagArgDst;
uint16_t result = dst + src;
XFLG = Bool2Bit(result < src);
V_regs.LazyXFlagKind = kLazyFlagsDefault;
}
LOCALPROC NeedDefaultLazyXFlagAddL(void)
{
uint32_t src = (uint32_t)V_regs.LazyXFlagArgSrc;
uint32_t dst = (uint32_t)V_regs.LazyXFlagArgDst;
uint32_t result = dst + src;
XFLG = Bool2Bit(result < src);
V_regs.LazyXFlagKind = kLazyFlagsDefault;
}
LOCALPROC NeedDefaultLazyXFlagNegB(void)
{
XFLG = Bool2Bit(((uint8_t)0)
< ((uint8_t)V_regs.LazyXFlagArgDst));
V_regs.LazyXFlagKind = kLazyFlagsDefault;
}
LOCALPROC NeedDefaultLazyXFlagNegW(void)
{
XFLG = Bool2Bit(((uint16_t)0)
< ((uint16_t)V_regs.LazyXFlagArgDst));
V_regs.LazyXFlagKind = kLazyFlagsDefault;
}
LOCALPROC NeedDefaultLazyXFlagNegL(void)
{
XFLG = Bool2Bit(((uint32_t)0)
< ((uint32_t)V_regs.LazyXFlagArgDst));
V_regs.LazyXFlagKind = kLazyFlagsDefault;
}
LOCALPROC NeedDefaultLazyXFlagAsr(void)
{
uint32_t cnt = V_regs.LazyFlagArgSrc;
uint32_t dst = V_regs.LazyFlagArgDst;
XFLG = ((dst >> (cnt - 1)) & 1);
V_regs.LazyXFlagKind = kLazyFlagsDefault;
}
LOCALPROC NeedDefaultLazyXFlagAslB(void)
{
XFLG = (V_regs.LazyFlagArgDst >> (8 - V_regs.LazyFlagArgSrc)) & 1;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
}
LOCALPROC NeedDefaultLazyXFlagAslW(void)
{
XFLG = (V_regs.LazyFlagArgDst >> (16 - V_regs.LazyFlagArgSrc)) & 1;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
}
LOCALPROC NeedDefaultLazyXFlagAslL(void)
{
XFLG = (V_regs.LazyFlagArgDst >> (32 - V_regs.LazyFlagArgSrc)) & 1;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
}
LOCALPROC NeedDefaultLazyXFlagDefault(void)
{
}
typedef void (*NeedLazyFlagP)(void);
LOCALVAR const NeedLazyFlagP
NeedLazyXFlagDispatch[kNumLazyFlagsKinds + 1] =
{
NeedDefaultLazyXFlagDefault /* kLazyFlagsDefault */,
0 /* kLazyFlagsTstB */,
0 /* kLazyFlagsTstW */,
0 /* kLazyFlagsTstL */,
0 /* kLazyFlagsCmpB */,
0 /* kLazyFlagsCmpW */,
0 /* kLazyFlagsCmpL */,
NeedDefaultLazyXFlagSubB /* kLazyFlagsSubB */,
NeedDefaultLazyXFlagSubW /* kLazyFlagsSubW */,
NeedDefaultLazyXFlagSubL /* kLazyFlagsSubL */,
NeedDefaultLazyXFlagAddB /* kLazyFlagsAddB */,
NeedDefaultLazyXFlagAddW /* kLazyFlagsAddW */,
NeedDefaultLazyXFlagAddL /* kLazyFlagsAddL */,
NeedDefaultLazyXFlagNegB /* kLazyFlagsNegB */,
NeedDefaultLazyXFlagNegW /* kLazyFlagsNegW */,
NeedDefaultLazyXFlagNegL /* kLazyFlagsNegL */,
NeedDefaultLazyXFlagAsr /* kLazyFlagsAsrB */,
NeedDefaultLazyXFlagAsr /* kLazyFlagsAsrW */,
NeedDefaultLazyXFlagAsr /* kLazyFlagsAsrL */,
NeedDefaultLazyXFlagAslB /* kLazyFlagsAslB */,
NeedDefaultLazyXFlagAslW /* kLazyFlagsAslW */,
NeedDefaultLazyXFlagAslL /* kLazyFlagsAslL */,
#if UseLazyZ
0 /* kLazyFlagsZSet */,
#endif
0
};
LOCALPROC NeedDefaultLazyXFlag(void)
{
#if ForceFlagsEval
if (kLazyFlagsDefault != V_regs.LazyXFlagKind) {
ReportAbnormalID(0x0103,
"not kLazyFlagsDefault in NeedDefaultLazyXFlag");
}
#else
(NeedLazyXFlagDispatch[V_regs.LazyXFlagKind])();
#endif
}
LOCALPROC NeedDefaultLazyFlagsTstL(void)
{
uint32_t dst = V_regs.LazyFlagArgDst;
VFLG = CFLG = 0;
ZFLG = Bool2Bit(dst == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(dst));
V_regs.LazyFlagKind = kLazyFlagsDefault;
NeedDefaultLazyXFlag();
}
LOCALPROC NeedDefaultLazyFlagsCmpB(void)
{
uint32_t src = V_regs.LazyFlagArgSrc;
uint32_t dst = V_regs.LazyFlagArgDst;
uint32_t result0 = dst - src;
uint32_t result1 = uint32_t_FromUByte(dst)
- uint32_t_FromUByte(src);
uint32_t result = uint32_t_FromSByte(result0);
ZFLG = Bool2Bit(result == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(result));
VFLG = (((result0 >> 1) ^ result0) >> 7) & 1;
CFLG = (result1 >> 8) & 1;
V_regs.LazyFlagKind = kLazyFlagsDefault;
NeedDefaultLazyXFlag();
}
LOCALPROC NeedDefaultLazyFlagsCmpW(void)
{
uint32_t result0 = V_regs.LazyFlagArgDst - V_regs.LazyFlagArgSrc;
uint32_t result = uint32_t_FromSWord(result0);
ZFLG = Bool2Bit(result == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(result));
VFLG = (((result0 >> 1) ^ result0) >> 15) & 1;
{
uint32_t result1 = uint32_t_FromUWord(V_regs.LazyFlagArgDst)
- uint32_t_FromUWord(V_regs.LazyFlagArgSrc);
CFLG = (result1 >> 16) & 1;
}
V_regs.LazyFlagKind = kLazyFlagsDefault;
NeedDefaultLazyXFlag();
}
LOCALPROC NeedDefaultLazyFlagsCmpL(void)
{
uint32_t src = V_regs.LazyFlagArgSrc;
uint32_t dst = V_regs.LazyFlagArgDst;
uint32_t result = uint32_t_FromSLong(dst - src);
ZFLG = Bool2Bit(result == 0);
{
flagtype flgn = Bool2Bit(uint32_t_MSBisSet(result));
flagtype flgs = Bool2Bit(uint32_t_MSBisSet(src));
flagtype flgo = Bool2Bit(uint32_t_MSBisSet(dst)) ^ 1;
flagtype flgsando = flgs & flgo;
flagtype flgsoro = flgs | flgo;
NFLG = flgn;
VFLG = ((flgn | flgsoro) ^ 1) | (flgn & flgsando);
CFLG = flgsando | (flgn & flgsoro);
}
V_regs.LazyFlagKind = kLazyFlagsDefault;
NeedDefaultLazyXFlag();
}
LOCALPROC NeedDefaultLazyFlagsSubB(void)
{
uint32_t src = V_regs.LazyFlagArgSrc;
uint32_t dst = V_regs.LazyFlagArgDst;
uint32_t result0 = dst - src;
uint32_t result1 = uint32_t_FromUByte(dst)
- uint32_t_FromUByte(src);
uint32_t result = uint32_t_FromSByte(result0);
ZFLG = Bool2Bit(result == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(result));
VFLG = (((result0 >> 1) ^ result0) >> 7) & 1;
CFLG = (result1 >> 8) & 1;
XFLG = CFLG;
V_regs.LazyFlagKind = kLazyFlagsDefault;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
}
LOCALPROC NeedDefaultLazyFlagsSubW(void)
{
uint32_t result0 = V_regs.LazyFlagArgDst - V_regs.LazyFlagArgSrc;
uint32_t result = uint32_t_FromSWord(result0);
ZFLG = Bool2Bit(result == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(result));
VFLG = (((result0 >> 1) ^ result0) >> 15) & 1;
{
uint32_t result1 = uint32_t_FromUWord(V_regs.LazyFlagArgDst)
- uint32_t_FromUWord(V_regs.LazyFlagArgSrc);
CFLG = (result1 >> 16) & 1;
}
XFLG = CFLG;
V_regs.LazyFlagKind = kLazyFlagsDefault;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
}
LOCALPROC NeedDefaultLazyFlagsSubL(void)
{
uint32_t src = V_regs.LazyFlagArgSrc;
uint32_t dst = V_regs.LazyFlagArgDst;
uint32_t result = uint32_t_FromSLong(dst - src);
ZFLG = Bool2Bit(result == 0);
{
flagtype flgn = Bool2Bit(uint32_t_MSBisSet(result));
flagtype flgs = Bool2Bit(uint32_t_MSBisSet(src));
flagtype flgo = Bool2Bit(uint32_t_MSBisSet(dst)) ^ 1;
flagtype flgsando = flgs & flgo;
flagtype flgsoro = flgs | flgo;
NFLG = flgn;
VFLG = ((flgn | flgsoro) ^ 1) | (flgn & flgsando);
CFLG = flgsando | (flgn & flgsoro);
}
XFLG = CFLG;
V_regs.LazyFlagKind = kLazyFlagsDefault;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
}
LOCALPROC NeedDefaultLazyFlagsAddB(void)
{
uint32_t src = V_regs.LazyFlagArgSrc;
uint32_t dst = V_regs.LazyFlagArgDst;
uint32_t result0 = dst + src;
uint32_t result1 = uint32_t_FromUByte(dst)
+ uint32_t_FromUByte(src);
uint32_t result = uint32_t_FromSByte(result0);
ZFLG = Bool2Bit(result == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(result));
VFLG = (((result0 >> 1) ^ result0) >> 7) & 1;
CFLG = (result1 >> 8);
XFLG = CFLG;
V_regs.LazyFlagKind = kLazyFlagsDefault;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
}
LOCALPROC NeedDefaultLazyFlagsAddW(void)
{
uint32_t src = V_regs.LazyFlagArgSrc;
uint32_t dst = V_regs.LazyFlagArgDst;
uint32_t result0 = dst + src;
uint32_t result1 = uint32_t_FromUWord(dst)
+ uint32_t_FromUWord(src);
uint32_t result = uint32_t_FromSWord(result0);
ZFLG = Bool2Bit(result == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(result));
VFLG = (((result0 >> 1) ^ result0) >> 15) & 1;
CFLG = (result1 >> 16);
XFLG = CFLG;
V_regs.LazyFlagKind = kLazyFlagsDefault;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
}
#if 0
LOCALPROC NeedDefaultLazyFlagsAddCommon(uint32_t result)
{
ZFLG = Bool2Bit(result == 0);
{
flagtype flgn = Bool2Bit(uint32_t_MSBisSet(result));
flagtype flgs = Bool2Bit(uint32_t_MSBisSet(V_regs.LazyFlagArgSrc));
flagtype flgo = Bool2Bit(uint32_t_MSBisSet(V_regs.LazyFlagArgDst));
flagtype flgsando = flgs & flgo;
flagtype flgsoro = flgs | flgo;
NFLG = flgn;
flgn ^= 1;
VFLG = ((flgn | flgsoro) ^ 1) | (flgn & flgsando);
CFLG = flgsando | (flgn & flgsoro);
}
XFLG = CFLG;
V_regs.LazyFlagKind = kLazyFlagsDefault;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
}
#endif
LOCALPROC NeedDefaultLazyFlagsAddL(void)
{
#if 1
uint32_t src = V_regs.LazyFlagArgSrc;
uint32_t dst = V_regs.LazyFlagArgDst;
uint32_t result = uint32_t_FromSLong(dst + src);
ZFLG = Bool2Bit(result == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(result));
{
uint32_t result1;
uint32_t result0;
uint32_t MidCarry = (uint32_t_FromUWord(dst)
+ uint32_t_FromUWord(src)) >> 16;
dst >>= 16;
src >>= 16;
result1 = uint32_t_FromUWord(dst)
+ uint32_t_FromUWord(src)
+ MidCarry;
CFLG = (result1 >> 16);
result0 = uint32_t_FromSWord(dst)
+ uint32_t_FromSWord(src)
+ MidCarry;
VFLG = (((result0 >> 1) ^ result0) >> 15) & 1;
}
XFLG = CFLG;
V_regs.LazyFlagKind = kLazyFlagsDefault;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
#else
uint32_t result = uint32_t_FromSLong(V_regs.LazyFlagArgDst
+ V_regs.LazyFlagArgSrc);
NeedDefaultLazyFlagsAddCommon(result);
#endif
}
LOCALPROC NeedDefaultLazyFlagsNegCommon(uint32_t dstvalue, uint32_t result)
{
flagtype flgs = Bool2Bit(uint32_t_MSBisSet(dstvalue));
flagtype flgn = Bool2Bit(uint32_t_MSBisSet(result));
ZFLG = Bool2Bit(result == 0);
NFLG = flgn;
VFLG = flgs & flgn;
CFLG = flgs | flgn;
XFLG = CFLG;
V_regs.LazyFlagKind = kLazyFlagsDefault;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
}
LOCALPROC NeedDefaultLazyFlagsNegB(void)
{
uint32_t dstvalue = V_regs.LazyFlagArgDst;
uint32_t result = uint32_t_FromSByte(0 - dstvalue);
NeedDefaultLazyFlagsNegCommon(dstvalue, result);
}
LOCALPROC NeedDefaultLazyFlagsNegW(void)
{
uint32_t dstvalue = V_regs.LazyFlagArgDst;
uint32_t result = uint32_t_FromSWord(0 - dstvalue);
NeedDefaultLazyFlagsNegCommon(dstvalue, result);
}
LOCALPROC NeedDefaultLazyFlagsNegL(void)
{
uint32_t dstvalue = V_regs.LazyFlagArgDst;
uint32_t result = uint32_t_FromSLong(0 - dstvalue);
NeedDefaultLazyFlagsNegCommon(dstvalue, result);
}
LOCALPROC NeedDefaultLazyFlagsAsr(void)
{
uint32_t cnt = V_regs.LazyFlagArgSrc;
uint32_t dst = V_regs.LazyFlagArgDst;
NFLG = Bool2Bit(uint32_t_MSBisSet(dst));
VFLG = 0;
CFLG = ((dst >> (cnt - 1)) & 1);
dst = Ui5rASR(dst, cnt);
ZFLG = Bool2Bit(dst == 0);
XFLG = CFLG;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
V_regs.LazyFlagKind = kLazyFlagsDefault;
}
LOCALPROC NeedDefaultLazyFlagsAslB(void)
{
uint32_t cnt = V_regs.LazyFlagArgSrc;
uint32_t dst = V_regs.LazyFlagArgDst;
uint32_t dstvalue0 = dst;
uint32_t comparevalue;
dst = dst << (cnt - 1);
dst = uint32_t_FromSByte(dst);
CFLG = Bool2Bit(uint32_t_MSBisSet(dst));
dst = dst << 1;
dst = uint32_t_FromSByte(dst);
comparevalue = Ui5rASR(dst, cnt);
VFLG = Bool2Bit(comparevalue != dstvalue0);
ZFLG = Bool2Bit(dst == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(dst));
XFLG = CFLG;
V_regs.LazyFlagKind = kLazyFlagsDefault;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
}
LOCALPROC NeedDefaultLazyFlagsAslW(void)
{
uint32_t cnt = V_regs.LazyFlagArgSrc;
uint32_t dst = V_regs.LazyFlagArgDst;
uint32_t dstvalue0 = dst;
uint32_t comparevalue;
dst = dst << (cnt - 1);
dst = uint32_t_FromSWord(dst);
CFLG = Bool2Bit(uint32_t_MSBisSet(dst));
dst = dst << 1;
dst = uint32_t_FromSWord(dst);
comparevalue = Ui5rASR(dst, cnt);
VFLG = Bool2Bit(comparevalue != dstvalue0);
ZFLG = Bool2Bit(dst == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(dst));
XFLG = CFLG;
V_regs.LazyFlagKind = kLazyFlagsDefault;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
}
LOCALPROC NeedDefaultLazyFlagsAslL(void)
{
uint32_t cnt = V_regs.LazyFlagArgSrc;
uint32_t dst = V_regs.LazyFlagArgDst;
uint32_t dstvalue0 = dst;
uint32_t comparevalue;
dst = dst << (cnt - 1);
dst = uint32_t_FromSLong(dst);
CFLG = Bool2Bit(uint32_t_MSBisSet(dst));
dst = dst << 1;
dst = uint32_t_FromSLong(dst);
comparevalue = Ui5rASR(dst, cnt);
VFLG = Bool2Bit(comparevalue != dstvalue0);
ZFLG = Bool2Bit(dst == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(dst));
XFLG = CFLG;
V_regs.LazyFlagKind = kLazyFlagsDefault;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
}
#if UseLazyZ
FORWARDPROC NeedDefaultLazyFlagsZSet(void);
#endif
LOCALVAR const NeedLazyFlagP
NeedLazyFlagDispatch[kNumLazyFlagsKinds + 1] =
{
NeedDefaultLazyXFlag /* kLazyFlagsDefault */,
0 /* kLazyFlagsTstB */,
0 /* kLazyFlagsTstW */,
NeedDefaultLazyFlagsTstL /* kLazyFlagsTstL */,
NeedDefaultLazyFlagsCmpB /* kLazyFlagsCmpB */,
NeedDefaultLazyFlagsCmpW /* kLazyFlagsCmpW */,
NeedDefaultLazyFlagsCmpL /* kLazyFlagsCmpL */,
NeedDefaultLazyFlagsSubB /* kLazyFlagsSubB */,
NeedDefaultLazyFlagsSubW /* kLazyFlagsSubW */,
NeedDefaultLazyFlagsSubL /* kLazyFlagsSubL */,
NeedDefaultLazyFlagsAddB /* kLazyFlagsAddB */,
NeedDefaultLazyFlagsAddW /* kLazyFlagsAddW */,
NeedDefaultLazyFlagsAddL /* kLazyFlagsAddL */,
NeedDefaultLazyFlagsNegB /* kLazyFlagsNegB */,
NeedDefaultLazyFlagsNegW /* kLazyFlagsNegW */,
NeedDefaultLazyFlagsNegL /* kLazyFlagsNegL */,
NeedDefaultLazyFlagsAsr /* kLazyFlagsAsrB */,
NeedDefaultLazyFlagsAsr /* kLazyFlagsAsrW */,
NeedDefaultLazyFlagsAsr /* kLazyFlagsAsrL */,
NeedDefaultLazyFlagsAslB /* kLazyFlagsAslB */,
NeedDefaultLazyFlagsAslW /* kLazyFlagsAslW */,
NeedDefaultLazyFlagsAslL /* kLazyFlagsAslL */,
#if UseLazyZ
NeedDefaultLazyFlagsZSet /* kLazyFlagsZSet */,
#endif
0
};
LOCALPROC NeedDefaultLazyAllFlags0(void)
{
(NeedLazyFlagDispatch[V_regs.LazyFlagKind])();
}
#if ForceFlagsEval
LOCALPROC NeedDefaultLazyAllFlags(void)
{
if (kLazyFlagsDefault != V_regs.LazyFlagKind) {
ReportAbnormalID(0x0104,
"not kLazyFlagsDefault in NeedDefaultLazyAllFlags");
#if dbglog_HAVE
dbglog_writelnNum("LazyFlagKind", V_regs.LazyFlagKind);
#endif
}
}
#else
#define NeedDefaultLazyAllFlags NeedDefaultLazyAllFlags0
#endif
#if ForceFlagsEval
#define HaveSetUpFlags NeedDefaultLazyAllFlags0
#else
#define HaveSetUpFlags()
#endif
#if UseLazyZ
LOCALPROC NeedDefaultLazyFlagsZSet(void)
{
flagtype SaveZFLG = ZFLG;
V_regs.LazyFlagKind = V_regs.LazyFlagZSavedKind;
NeedDefaultLazyAllFlags();
ZFLG = SaveZFLG;
}
#endif
#if UseLazyCC
LOCALPROC reg_call cctrue_Dflt(cond_actP t_act, cond_actP f_act)
{
NeedDefaultLazyAllFlags();
cctrue(t_act, f_act);
}
#endif
#if ! UseLazyCC
LOCALINLINEPROC cctrue(cond_actP t_act, cond_actP f_act)
{
NeedDefaultLazyAllFlags();
(cctrueDispatch[V_regs.CurDecOpY.v[0].ArgDat])(t_act, f_act);
}
#endif
#define LOCALIPROC LOCALPROC /* LOCALPROCUSEDONCE */
LOCALIPROC DoCodeCmpB(void)
{
uint32_t dstvalue = DecodeGetSrcGetDstValue();
V_regs.LazyFlagKind = kLazyFlagsCmpB;
V_regs.LazyFlagArgSrc = V_regs.SrcVal;
V_regs.LazyFlagArgDst = dstvalue;
HaveSetUpFlags();
}
LOCALIPROC DoCodeCmpW(void)
{
uint32_t dstvalue = DecodeGetSrcGetDstValue();
V_regs.LazyFlagKind = kLazyFlagsCmpW;
V_regs.LazyFlagArgSrc = V_regs.SrcVal;
V_regs.LazyFlagArgDst = dstvalue;
HaveSetUpFlags();
}
LOCALIPROC DoCodeCmpL(void)
{
uint32_t dstvalue = DecodeGetSrcGetDstValue();
V_regs.LazyFlagKind = kLazyFlagsCmpL;
V_regs.LazyFlagArgSrc = V_regs.SrcVal;
V_regs.LazyFlagArgDst = dstvalue;
HaveSetUpFlags();
}
LOCALIPROC DoCodeMoveL(void)
{
uint32_t src = DecodeGetSrcValue();
V_regs.LazyFlagKind = kLazyFlagsTstL;
V_regs.LazyFlagArgDst = src;
HaveSetUpFlags();
DecodeSetDstValue(src);
}
LOCALIPROC DoCodeMoveW(void)
{
uint32_t src = DecodeGetSrcValue();
V_regs.LazyFlagKind = kLazyFlagsTstL;
V_regs.LazyFlagArgDst = src;
HaveSetUpFlags();
DecodeSetDstValue(src);
}
LOCALIPROC DoCodeMoveB(void)
{
uint32_t src = DecodeGetSrcValue();
V_regs.LazyFlagKind = kLazyFlagsTstL;
V_regs.LazyFlagArgDst = src;
HaveSetUpFlags();
DecodeSetDstValue(src);
}
LOCALIPROC DoCodeTst(void)
{
/* Tst 01001010ssmmmrrr */
uint32_t srcvalue = DecodeGetDstValue();
V_regs.LazyFlagKind = kLazyFlagsTstL;
V_regs.LazyFlagArgDst = srcvalue;
HaveSetUpFlags();
}
LOCALIPROC DoCodeBraB(void)
{
int32_t offset = (int32_t)(int8_t)(uint8_t)(V_regs.CurDecOpY.v[1].ArgDat);
uint8_t * s = V_pc_p + offset;
V_pc_p = s;
#if USE_PCLIMIT
if (cond_rare(s >= V_pc_pHi)
|| cond_rare(s < V_regs.pc_pLo))
{
Recalc_PC_Block();
}
#endif
}
LOCALIPROC DoCodeBraW(void)
{
int32_t offset = (int32_t)(int16_t)(uint16_t)do_get_mem_word(V_pc_p);
/* note that pc not incremented here */
uint8_t * s = V_pc_p + offset;
V_pc_p = s;
#if USE_PCLIMIT
if (cond_rare(s >= V_pc_pHi)
|| cond_rare(s < V_regs.pc_pLo))
{
Recalc_PC_Block();
}
#endif
}
#if WantCloserCyc
LOCALPROC DoCodeBccB_t(void)
{
V_MaxCyclesToGo -= (10 * kCycleScale + 2 * RdAvgXtraCyc);
DoCodeBraB();
}
#else
#define DoCodeBccB_t DoCodeBraB
#endif
LOCALPROC DoCodeBccB_f(void)
{
#if WantCloserCyc
V_MaxCyclesToGo -= (8 * kCycleScale + RdAvgXtraCyc);
#endif
/* do nothing */
}
LOCALIPROC DoCodeBccB(void)
{
/* Bcc 0110ccccnnnnnnnn */
cctrue(DoCodeBccB_t, DoCodeBccB_f);
}
LOCALPROC SkipiWord(void)
{
V_pc_p += 2;
#if USE_PCLIMIT
if (cond_rare(V_pc_p >= V_pc_pHi)) {
Recalc_PC_Block();
}
#endif
}
#if WantCloserCyc
LOCALPROC DoCodeBccW_t(void)
{
V_MaxCyclesToGo -= (10 * kCycleScale + 2 * RdAvgXtraCyc);
DoCodeBraW();
}
#else
#define DoCodeBccW_t DoCodeBraW
#endif
#if WantCloserCyc
LOCALPROC DoCodeBccW_f(void)
{
V_MaxCyclesToGo -= (12 * kCycleScale + 2 * RdAvgXtraCyc);
SkipiWord();
}
#else
#define DoCodeBccW_f SkipiWord
#endif
LOCALIPROC DoCodeBccW(void)
{
/* Bcc 0110ccccnnnnnnnn */
cctrue(DoCodeBccW_t, DoCodeBccW_f);
}
LOCALIPROC DoCodeDBF(void)
{
/* DBcc 0101cccc11001ddd */
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
uint32_t *dstp = &V_regs.regs[dstreg];
uint32_t dstvalue = uint32_t_FromSWord(*dstp);
--dstvalue;
#if LittleEndianUnaligned
*(uint16_t *)dstp = dstvalue;
#else
*dstp = (*dstp & ~ 0xffff) | ((dstvalue) & 0xffff);
#endif
if ((int32_t)dstvalue == -1) {
#if WantCloserCyc
V_MaxCyclesToGo -= (14 * kCycleScale + 3 * RdAvgXtraCyc);
#endif
SkipiWord();
} else {
#if WantCloserCyc
V_MaxCyclesToGo -= (10 * kCycleScale + 2 * RdAvgXtraCyc);
#endif
DoCodeBraW();
}
}
#if WantCloserCyc
LOCALPROC DoCodeDBcc_t(void)
{
V_MaxCyclesToGo -= (12 * kCycleScale + 2 * RdAvgXtraCyc);
SkipiWord();
}
#else
#define DoCodeDBcc_t SkipiWord
#endif
LOCALIPROC DoCodeDBcc(void)
{
/* DBcc 0101cccc11001ddd */
cctrue(DoCodeDBcc_t, DoCodeDBF);
}
LOCALIPROC DoCodeSwap(void)
{
/* Swap 0100100001000rrr */
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
uint32_t *dstp = &V_regs.regs[dstreg];
uint32_t src = *dstp;
uint32_t dst = uint32_t_FromSLong(((src >> 16) & 0xFFFF)
| ((src & 0xFFFF) << 16));
V_regs.LazyFlagKind = kLazyFlagsTstL;
V_regs.LazyFlagArgDst = dst;
HaveSetUpFlags();
*dstp = dst;
}
LOCALIPROC DoCodeMoveA(void) /* MOVE */
{
uint32_t src = DecodeGetSrcValue();
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
m68k_areg(dstreg) = src;
}
LOCALIPROC DoCodeMoveQ(void)
{
/* MoveQ 0111ddd0nnnnnnnn */
uint32_t src = uint32_t_FromSByte(V_regs.CurDecOpY.v[0].ArgDat);
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
V_regs.LazyFlagKind = kLazyFlagsTstL;
V_regs.LazyFlagArgDst = src;
HaveSetUpFlags();
m68k_dreg(dstreg) = src;
}
LOCALIPROC DoCodeAddB(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t srcvalue = V_regs.SrcVal;
uint32_t result = uint32_t_FromSByte(dstvalue + srcvalue);
V_regs.LazyFlagKind = kLazyFlagsAddB;
V_regs.LazyFlagArgSrc = srcvalue;
V_regs.LazyFlagArgDst = dstvalue;
V_regs.LazyXFlagKind = kLazyFlagsAddB;
V_regs.LazyXFlagArgSrc = srcvalue;
V_regs.LazyXFlagArgDst = dstvalue;
HaveSetUpFlags();
ArgSetDstValue(result);
}
LOCALIPROC DoCodeAddW(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t srcvalue = V_regs.SrcVal;
uint32_t result = uint32_t_FromSWord(dstvalue + srcvalue);
V_regs.LazyFlagKind = kLazyFlagsAddW;
V_regs.LazyFlagArgSrc = srcvalue;
V_regs.LazyFlagArgDst = dstvalue;
V_regs.LazyXFlagKind = kLazyFlagsAddW;
V_regs.LazyXFlagArgSrc = srcvalue;
V_regs.LazyXFlagArgDst = dstvalue;
HaveSetUpFlags();
ArgSetDstValue(result);
}
LOCALIPROC DoCodeAddL(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t srcvalue = V_regs.SrcVal;
uint32_t result = uint32_t_FromSLong(dstvalue + srcvalue);
V_regs.LazyFlagKind = kLazyFlagsAddL;
V_regs.LazyFlagArgSrc = srcvalue;
V_regs.LazyFlagArgDst = dstvalue;
V_regs.LazyXFlagKind = kLazyFlagsAddL;
V_regs.LazyXFlagArgSrc = srcvalue;
V_regs.LazyXFlagArgDst = dstvalue;
HaveSetUpFlags();
ArgSetDstValue(result);
}
LOCALIPROC DoCodeSubB(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t srcvalue = V_regs.SrcVal;
uint32_t result = uint32_t_FromSByte(dstvalue - srcvalue);
V_regs.LazyFlagKind = kLazyFlagsSubB;
V_regs.LazyFlagArgSrc = srcvalue;
V_regs.LazyFlagArgDst = dstvalue;
V_regs.LazyXFlagKind = kLazyFlagsSubB;
V_regs.LazyXFlagArgSrc = srcvalue;
V_regs.LazyXFlagArgDst = dstvalue;
HaveSetUpFlags();
ArgSetDstValue(result);
}
LOCALIPROC DoCodeSubW(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t srcvalue = V_regs.SrcVal;
uint32_t result = uint32_t_FromSWord(dstvalue - srcvalue);
V_regs.LazyFlagKind = kLazyFlagsSubW;
V_regs.LazyFlagArgSrc = srcvalue;
V_regs.LazyFlagArgDst = dstvalue;
V_regs.LazyXFlagKind = kLazyFlagsSubW;
V_regs.LazyXFlagArgSrc = srcvalue;
V_regs.LazyXFlagArgDst = dstvalue;
HaveSetUpFlags();
ArgSetDstValue(result);
}
LOCALIPROC DoCodeSubL(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t srcvalue = V_regs.SrcVal;
uint32_t result = uint32_t_FromSLong(dstvalue - srcvalue);
V_regs.LazyFlagKind = kLazyFlagsSubL;
V_regs.LazyFlagArgSrc = srcvalue;
V_regs.LazyFlagArgDst = dstvalue;
V_regs.LazyXFlagKind = kLazyFlagsSubL;
V_regs.LazyXFlagArgSrc = srcvalue;
V_regs.LazyXFlagArgDst = dstvalue;
HaveSetUpFlags();
ArgSetDstValue(result);
}
LOCALIPROC DoCodeLea(void)
{
/* Lea 0100aaa111mmmrrr */
uint32_t DstAddr = DecodeDst();
uint32_t dstreg = V_regs.CurDecOpY.v[0].ArgDat;
m68k_areg(dstreg) = DstAddr;
}
LOCALIPROC DoCodePEA(void)
{
/* PEA 0100100001mmmrrr */
uint32_t DstAddr = DecodeDst();
m68k_areg(7) -= 4;
put_long(m68k_areg(7), DstAddr);
}
LOCALIPROC DoCodeBsrB(void)
{
m68k_areg(7) -= 4;
put_long(m68k_areg(7), m68k_getpc());
DoCodeBraB();
}
LOCALIPROC DoCodeBsrW(void)
{
m68k_areg(7) -= 4;
put_long(m68k_areg(7), m68k_getpc() + 2);
DoCodeBraW();
}
#define m68k_logExceptions (dbglog_HAVE && 0)
#ifndef WantDumpAJump
#define WantDumpAJump 0
#endif
#if WantDumpAJump
LOCALPROCUSEDONCE DumpAJump(CPTR toaddr)
{
CPTR fromaddr = m68k_getpc();
if ((toaddr > fromaddr) || (toaddr < V_regs.pc))
{
dbglog_writeHex(fromaddr);
dbglog_writeCStr(",");
dbglog_writeHex(toaddr);
dbglog_writeReturn();
}
}
#endif
LOCALPROC reg_call m68k_setpc(CPTR newpc)
{
#if WantDumpAJump
DumpAJump(newpc);
#endif
#if 0
if (newpc == 0xBD50 /* 401AB4 */) {
/* Debugger(); */
/* Exception(5); */ /* try and get macsbug */
}
#endif
V_pc_p = V_regs.pc_pLo + (newpc - V_regs.pc);
if (cond_rare(V_pc_p >= V_pc_pHi)
|| cond_rare(V_pc_p < V_regs.pc_pLo))
{
Recalc_PC_Block();
}
}
LOCALIPROC DoCodeJsr(void)
{
/* Jsr 0100111010mmmrrr */
uint32_t DstAddr = DecodeDst();
m68k_areg(7) -= 4;
put_long(m68k_areg(7), m68k_getpc());
m68k_setpc(DstAddr);
}
LOCALIPROC DoCodeLinkA6(void)
{
CPTR stackp = m68k_areg(7);
stackp -= 4;
put_long(stackp, m68k_areg(6));
m68k_areg(6) = stackp;
m68k_areg(7) = stackp + nextiSWord();
}
LOCALIPROC DoCodeUnlkA6(void)
{
uint32_t src = m68k_areg(6);
m68k_areg(6) = get_long(src);
m68k_areg(7) = src + 4;
}
LOCALIPROC DoCodeRts(void)
{
/* Rts 0100111001110101 */
uint32_t NewPC = get_long(m68k_areg(7));
m68k_areg(7) += 4;
m68k_setpc(NewPC);
}
LOCALIPROC DoCodeJmp(void)
{
/* JMP 0100111011mmmrrr */
uint32_t DstAddr = DecodeDst();
m68k_setpc(DstAddr);
}
LOCALIPROC DoCodeClr(void)
{
/* Clr 01000010ssmmmrrr */
V_regs.LazyFlagKind = kLazyFlagsTstL;
V_regs.LazyFlagArgDst = 0;
HaveSetUpFlags();
DecodeSetDstValue(0);
}
LOCALIPROC DoCodeAddA(void)
{
/* ADDA 1101dddm11mmmrrr */
uint32_t dstvalue = DecodeGetSrcSetDstValue();
ArgSetDstValue(dstvalue + V_regs.SrcVal);
}
LOCALIPROC DoCodeSubA(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
ArgSetDstValue(dstvalue - V_regs.SrcVal);
}
LOCALIPROC DoCodeCmpA(void)
{
uint32_t dstvalue = DecodeGetSrcGetDstValue();
V_regs.LazyFlagKind = kLazyFlagsCmpL;
V_regs.LazyFlagArgSrc = V_regs.SrcVal;
V_regs.LazyFlagArgDst = dstvalue;
HaveSetUpFlags();
}
LOCALFUNC uint16_t m68k_getCR(void)
{
NeedDefaultLazyAllFlags();
return (XFLG << 4) | (NFLG << 3) | (ZFLG << 2)
| (VFLG << 1) | CFLG;
}
LOCALPROC reg_call m68k_setCR(uint16_t newcr)
{
XFLG = (newcr >> 4) & 1;
NFLG = (newcr >> 3) & 1;
ZFLG = (newcr >> 2) & 1;
VFLG = (newcr >> 1) & 1;
CFLG = newcr & 1;
V_regs.LazyFlagKind = kLazyFlagsDefault;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
}
LOCALFUNC uint16_t m68k_getSR(void)
{
return m68k_getCR()
| (V_regs.t1 << 15)
#if Use68020
| (V_regs.t0 << 14)
#endif
| (V_regs.s << 13)
#if Use68020
| (V_regs.m << 12)
#endif
| (V_regs.intmask << 8);
}
LOCALPROC NeedToGetOut(void)
{
if (V_MaxCyclesToGo <= 0) {
/*
already have gotten out, and exception processing has
caused another exception, such as because a bad
stack pointer pointing to a memory mapped device.
*/
} else {
V_regs.MoreCyclesToGo += V_MaxCyclesToGo;
/* not counting the current instruction */
V_MaxCyclesToGo = 0;
}
}
LOCALPROC SetExternalInterruptPending(void)
{
V_regs.ExternalInterruptPending = true;
NeedToGetOut();
}
LOCALPROC reg_call m68k_setSR(uint16_t newsr)
{
CPTR *pnewstk;
CPTR *poldstk = (V_regs.s != 0) ? (
#if Use68020
(V_regs.m != 0) ? &V_regs.msp :
#endif
&V_regs.isp) : &V_regs.usp;
uint32_t oldintmask = V_regs.intmask;
V_regs.t1 = (newsr >> 15) & 1;
#if Use68020
V_regs.t0 = (newsr >> 14) & 1;
if (V_regs.t0 != 0) {
ReportAbnormalID(0x0105, "t0 flag set in m68k_setSR");
}
#endif
V_regs.s = (newsr >> 13) & 1;
#if Use68020
V_regs.m = (newsr >> 12) & 1;
if (V_regs.m != 0) {
ReportAbnormalID(0x0106, "m flag set in m68k_setSR");
}
#endif
V_regs.intmask = (newsr >> 8) & 7;
pnewstk = (V_regs.s != 0) ? (
#if Use68020
(V_regs.m != 0) ? &V_regs.msp :
#endif
&V_regs.isp) : &V_regs.usp;
if (poldstk != pnewstk) {
*poldstk = m68k_areg(7);
m68k_areg(7) = *pnewstk;
}
if (V_regs.intmask != oldintmask) {
SetExternalInterruptPending();
}
if (V_regs.t1 != 0) {
NeedToGetOut();
} else {
/* V_regs.TracePending = false; */
}
m68k_setCR(newsr);
}
LOCALPROC reg_call ExceptionTo(CPTR newpc
#if Use68020
, int nr
#endif
)
{
uint16_t saveSR = m68k_getSR();
if (0 == V_regs.s) {
V_regs.usp = m68k_areg(7);
m68k_areg(7) =
#if Use68020
(V_regs.m != 0) ? V_regs.msp :
#endif
V_regs.isp;
V_regs.s = 1;
}
#if Use68020
switch (nr) {
case 5: /* Zero Divide */
case 6: /* CHK, CHK2 */
case 7: /* cpTRAPcc, TRAPCcc, TRAPv */
case 9: /* Trace */
m68k_areg(7) -= 4;
put_long(m68k_areg(7), m68k_getpc());
m68k_areg(7) -= 2;
put_word(m68k_areg(7), 0x2000 + nr * 4);
break;
default:
m68k_areg(7) -= 2;
put_word(m68k_areg(7), nr * 4);
break;
}
/* if V_regs.m should make throw away stack frame */
#endif
m68k_areg(7) -= 4;
put_long(m68k_areg(7), m68k_getpc());
m68k_areg(7) -= 2;
put_word(m68k_areg(7), saveSR);
m68k_setpc(newpc);
V_regs.t1 = 0;
#if Use68020
V_regs.t0 = 0;
V_regs.m = 0;
#endif
V_regs.TracePending = false;
}
LOCALPROC reg_call Exception(int nr)
{
ExceptionTo(get_long(4 * nr
#if Use68020
+ V_regs.vbr
#endif
)
#if Use68020
, nr
#endif
);
}
LOCALIPROC DoCodeA(void)
{
BackupPC();
Exception(0xA);
}
LOCALFUNC uint16_t nextiword_nm(void)
/* NOT sign extended */
{
return nextiword();
}
LOCALIPROC DoCodeMOVEMRmML(void)
{
/* MOVEM reg to mem 01001000111100rrr */
int16_t z;
uint32_t regmask = nextiword_nm();
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
uint32_t *dstp = &V_regs.regs[dstreg];
uint32_t p = *dstp;
#if Use68020
{
int n = 0;
for (z = 0; z < 16; ++z) {
if ((regmask & (1 << z)) != 0) {
n++;
}
}
*dstp = p - n * 4;
}
#endif
for (z = 16; --z >= 0; ) {
if ((regmask & (1 << (15 - z))) != 0) {
#if WantCloserCyc
V_MaxCyclesToGo -= (8 * kCycleScale + 2 * WrAvgXtraCyc);
#endif
p -= 4;
put_long(p, V_regs.regs[z]);
}
}
#if ! Use68020
*dstp = p;
#endif
}
LOCALIPROC DoCodeMOVEMApRL(void)
{
/* MOVEM mem to reg 01001100111011rrr */
int16_t z;
uint32_t regmask = nextiword_nm();
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
uint32_t *dstp = &V_regs.regs[dstreg];
uint32_t p = *dstp;
for (z = 0; z < 16; ++z) {
if ((regmask & (1 << z)) != 0) {
#if WantCloserCyc
V_MaxCyclesToGo -= (8 * kCycleScale + 2 * RdAvgXtraCyc);
#endif
V_regs.regs[z] = get_long(p);
p += 4;
}
}
*dstp = p;
}
LOCALPROC reg_call SetCCRforAddX(uint32_t dstvalue, uint32_t srcvalue,
uint32_t result)
{
ZFLG &= Bool2Bit(result == 0);
{
flagtype flgs = Bool2Bit(uint32_t_MSBisSet(srcvalue));
flagtype flgo = Bool2Bit(uint32_t_MSBisSet(dstvalue));
flagtype flgsando = flgs & flgo;
flagtype flgsoro = flgs | flgo;
flagtype flgn = Bool2Bit(uint32_t_MSBisSet(result));
NFLG = flgn;
flgn ^= 1;
VFLG = ((flgn | flgsoro) ^ 1) | (flgn & flgsando);
XFLG = CFLG = flgsando | (flgn & flgsoro);
}
ArgSetDstValue(result);
}
LOCALIPROC DoCodeAddXB(void)
{
NeedDefaultLazyAllFlags();
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t srcvalue = V_regs.SrcVal;
uint32_t result = uint32_t_FromSByte(XFLG + dstvalue + srcvalue);
SetCCRforAddX(dstvalue, srcvalue, result);
}
}
LOCALIPROC DoCodeAddXW(void)
{
if ((kLazyFlagsDefault != V_regs.LazyFlagKind)
|| (kLazyFlagsDefault != V_regs.LazyXFlagKind))
{
NeedDefaultLazyAllFlags();
}
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t srcvalue = V_regs.SrcVal;
uint32_t result = uint32_t_FromSWord(XFLG + dstvalue + srcvalue);
SetCCRforAddX(dstvalue, srcvalue, result);
}
}
LOCALIPROC DoCodeAddXL(void)
{
if (kLazyFlagsAddL == V_regs.LazyFlagKind) {
uint32_t src = V_regs.LazyFlagArgSrc;
uint32_t dst = V_regs.LazyFlagArgDst;
uint32_t result = uint32_t_FromULong(dst + src);
ZFLG = Bool2Bit(result == 0);
XFLG = Bool2Bit(result < src);
V_regs.LazyFlagKind = kLazyFlagsDefault;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
} else
if ((kLazyFlagsDefault == V_regs.LazyFlagKind)
&& (kLazyFlagsDefault == V_regs.LazyXFlagKind))
{
/* ok */
} else
{
NeedDefaultLazyAllFlags();
}
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t srcvalue = V_regs.SrcVal;
uint32_t result = uint32_t_FromSLong(XFLG + dstvalue + srcvalue);
SetCCRforAddX(dstvalue, srcvalue, result);
}
}
LOCALPROC reg_call SetCCRforSubX(uint32_t dstvalue, uint32_t srcvalue,
uint32_t result)
{
ZFLG &= Bool2Bit(result == 0);
{
flagtype flgs = Bool2Bit(uint32_t_MSBisSet(srcvalue));
flagtype flgo = Bool2Bit(uint32_t_MSBisSet(dstvalue)) ^ 1;
flagtype flgsando = flgs & flgo;
flagtype flgsoro = flgs | flgo;
flagtype flgn = Bool2Bit(uint32_t_MSBisSet(result));
NFLG = flgn;
VFLG = ((flgn | flgsoro) ^ 1) | (flgn & flgsando);
XFLG = CFLG = flgsando | (flgn & flgsoro);
}
ArgSetDstValue(result);
}
LOCALIPROC DoCodeSubXB(void)
{
NeedDefaultLazyAllFlags();
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t srcvalue = V_regs.SrcVal;
uint32_t result = uint32_t_FromSByte(dstvalue - srcvalue - XFLG);
SetCCRforSubX(dstvalue, srcvalue, result);
}
}
LOCALIPROC DoCodeSubXW(void)
{
if ((kLazyFlagsDefault != V_regs.LazyFlagKind)
|| (kLazyFlagsDefault != V_regs.LazyXFlagKind))
{
NeedDefaultLazyAllFlags();
}
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t srcvalue = V_regs.SrcVal;
uint32_t result = uint32_t_FromSWord(dstvalue - srcvalue - XFLG);
SetCCRforSubX(dstvalue, srcvalue, result);
}
}
LOCALIPROC DoCodeSubXL(void)
{
if (kLazyFlagsSubL == V_regs.LazyFlagKind) {
uint32_t src = V_regs.LazyFlagArgSrc;
uint32_t dst = V_regs.LazyFlagArgDst;
uint32_t result = uint32_t_FromSLong(dst - src);
ZFLG = Bool2Bit(result == 0);
XFLG = Bool2Bit(((uint32_t)dst) < ((uint32_t)src));
V_regs.LazyFlagKind = kLazyFlagsDefault;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
} else
if ((kLazyFlagsDefault == V_regs.LazyFlagKind)
&& (kLazyFlagsDefault == V_regs.LazyXFlagKind))
{
/* ok */
} else
{
NeedDefaultLazyAllFlags();
}
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t srcvalue = V_regs.SrcVal;
uint32_t result = uint32_t_FromSLong(dstvalue - srcvalue - XFLG);
SetCCRforSubX(dstvalue, srcvalue, result);
}
}
LOCALPROC reg_call DoCodeNullShift(uint32_t dstvalue)
{
V_regs.LazyFlagKind = kLazyFlagsTstL;
V_regs.LazyFlagArgDst = dstvalue;
HaveSetUpFlags();
ArgSetDstValue(dstvalue);
}
LOCALPROC DoCodeOverAsl(uint32_t dstvalue)
{
XFLG = CFLG = 0;
VFLG = Bool2Bit(0 != dstvalue);
ZFLG = 1;
NFLG = 0;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
V_regs.LazyFlagKind = kLazyFlagsDefault;
ArgSetDstValue(0);
}
LOCALPROC reg_call DoCodeMaxAsr(uint32_t dstvalue)
{
XFLG = CFLG = dstvalue & 1;
VFLG = Bool2Bit(0 != dstvalue);
ZFLG = 1;
NFLG = 0;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
V_regs.LazyFlagKind = kLazyFlagsDefault;
ArgSetDstValue(0);
}
LOCALIPROC DoCodeAslB(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t cnt = V_regs.SrcVal & 63;
if (0 == cnt) {
DoCodeNullShift(dstvalue);
} else {
#if WantCloserCyc
V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
#endif
if (cnt >= 8) {
if (cnt == 8) {
DoCodeMaxAsr(dstvalue);
} else {
DoCodeOverAsl(dstvalue);
}
} else {
uint32_t result = uint32_t_FromSByte(dstvalue << cnt);
V_regs.LazyFlagKind = kLazyFlagsAslB;
V_regs.LazyFlagArgSrc = cnt;
V_regs.LazyFlagArgDst = dstvalue;
V_regs.LazyXFlagKind = kLazyFlagsAslB;
V_regs.LazyXFlagArgSrc = cnt;
V_regs.LazyXFlagArgDst = dstvalue;
HaveSetUpFlags();
ArgSetDstValue(result);
}
}
}
LOCALIPROC DoCodeAslW(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t cnt = V_regs.SrcVal & 63;
if (0 == cnt) {
DoCodeNullShift(dstvalue);
} else {
#if WantCloserCyc
V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
#endif
if (cnt >= 16) {
if (cnt == 16) {
DoCodeMaxAsr(dstvalue);
} else {
DoCodeOverAsl(dstvalue);
}
} else {
uint32_t result = uint32_t_FromSWord(dstvalue << cnt);
V_regs.LazyFlagKind = kLazyFlagsAslW;
V_regs.LazyFlagArgSrc = cnt;
V_regs.LazyFlagArgDst = dstvalue;
V_regs.LazyXFlagKind = kLazyFlagsAslW;
V_regs.LazyXFlagArgSrc = cnt;
V_regs.LazyXFlagArgDst = dstvalue;
HaveSetUpFlags();
ArgSetDstValue(result);
}
}
}
LOCALIPROC DoCodeAslL(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t cnt = V_regs.SrcVal & 63;
if (0 == cnt) {
DoCodeNullShift(dstvalue);
} else {
#if WantCloserCyc
V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
#endif
if (cnt >= 32) {
if (cnt == 32) {
DoCodeMaxAsr(dstvalue);
} else {
DoCodeOverAsl(dstvalue);
}
} else {
uint32_t result = uint32_t_FromSLong(dstvalue << cnt);
V_regs.LazyFlagKind = kLazyFlagsAslL;
V_regs.LazyFlagArgSrc = cnt;
V_regs.LazyFlagArgDst = dstvalue;
V_regs.LazyXFlagKind = kLazyFlagsAslL;
V_regs.LazyXFlagArgSrc = cnt;
V_regs.LazyXFlagArgDst = dstvalue;
HaveSetUpFlags();
ArgSetDstValue(result);
}
}
}
LOCALPROC DoCodeOverShift(void)
{
XFLG = CFLG = 0;
ZFLG = 1;
NFLG = 0;
VFLG = 0;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
V_regs.LazyFlagKind = kLazyFlagsDefault;
ArgSetDstValue(0);
}
LOCALPROC DoCodeOverShiftN(void)
{
NFLG = 1;
VFLG = 0;
CFLG = 1;
XFLG = CFLG;
ZFLG = 0;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
V_regs.LazyFlagKind = kLazyFlagsDefault;
ArgSetDstValue(~ 0);
}
LOCALPROC DoCodeOverAShift(uint32_t dstvalue)
{
if (uint32_t_MSBisSet(dstvalue)) {
DoCodeOverShiftN();
} else {
DoCodeOverShift();
}
}
LOCALIPROC DoCodeAsrB(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t cnt = V_regs.SrcVal & 63;
if (0 == cnt) {
DoCodeNullShift(dstvalue);
} else {
#if WantCloserCyc
V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
#endif
if (cnt >= 8) {
DoCodeOverAShift(dstvalue);
} else {
uint32_t result = Ui5rASR(dstvalue, cnt);
V_regs.LazyFlagKind = kLazyFlagsAsrB;
V_regs.LazyFlagArgSrc = cnt;
V_regs.LazyFlagArgDst = dstvalue;
V_regs.LazyXFlagKind = kLazyFlagsAsrB;
V_regs.LazyXFlagArgSrc = cnt;
V_regs.LazyXFlagArgDst = dstvalue;
HaveSetUpFlags();
ArgSetDstValue(result);
}
}
}
LOCALIPROC DoCodeAsrW(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t cnt = V_regs.SrcVal & 63;
if (0 == cnt) {
DoCodeNullShift(dstvalue);
} else {
#if WantCloserCyc
V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
#endif
if (cnt >= 16) {
DoCodeOverAShift(dstvalue);
} else {
uint32_t result = Ui5rASR(dstvalue, cnt);
V_regs.LazyFlagKind = kLazyFlagsAsrW;
V_regs.LazyFlagArgSrc = cnt;
V_regs.LazyFlagArgDst = dstvalue;
V_regs.LazyXFlagKind = kLazyFlagsAsrW;
V_regs.LazyXFlagArgSrc = cnt;
V_regs.LazyXFlagArgDst = dstvalue;
HaveSetUpFlags();
ArgSetDstValue(result);
}
}
}
LOCALIPROC DoCodeAsrL(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t cnt = V_regs.SrcVal & 63;
if (0 == cnt) {
DoCodeNullShift(dstvalue);
} else {
#if WantCloserCyc
V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
#endif
if (cnt >= 32) {
DoCodeOverAShift(dstvalue);
} else {
uint32_t result = Ui5rASR(dstvalue, cnt);
V_regs.LazyFlagKind = kLazyFlagsAsrL;
V_regs.LazyFlagArgSrc = cnt;
V_regs.LazyFlagArgDst = dstvalue;
V_regs.LazyXFlagKind = kLazyFlagsAsrL;
V_regs.LazyXFlagArgSrc = cnt;
V_regs.LazyXFlagArgDst = dstvalue;
HaveSetUpFlags();
ArgSetDstValue(result);
}
}
}
LOCALPROC reg_call DoCodeMaxLslShift(uint32_t dstvalue)
{
XFLG = CFLG = dstvalue & 1;
ZFLG = 1;
NFLG = 0;
VFLG = 0;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
V_regs.LazyFlagKind = kLazyFlagsDefault;
ArgSetDstValue(0);
}
LOCALIPROC DoCodeLslB(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t cnt = V_regs.SrcVal & 63;
if (0 == cnt) {
DoCodeNullShift(dstvalue);
} else {
#if WantCloserCyc
V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
#endif
if (cnt >= 8) {
if (cnt == 8) {
DoCodeMaxLslShift(dstvalue);
} else {
DoCodeOverShift();
}
} else {
CFLG = (dstvalue >> (8 - cnt)) & 1;
dstvalue = dstvalue << cnt;
dstvalue = uint32_t_FromSByte(dstvalue);
ZFLG = Bool2Bit(dstvalue == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(dstvalue));
VFLG = 0;
XFLG = CFLG;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
V_regs.LazyFlagKind = kLazyFlagsDefault;
ArgSetDstValue(dstvalue);
}
}
}
LOCALIPROC DoCodeLslW(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t cnt = V_regs.SrcVal & 63;
if (0 == cnt) {
DoCodeNullShift(dstvalue);
} else {
#if WantCloserCyc
V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
#endif
if (cnt >= 16) {
if (cnt == 16) {
DoCodeMaxLslShift(dstvalue);
} else {
DoCodeOverShift();
}
} else {
CFLG = (dstvalue >> (16 - cnt)) & 1;
dstvalue = dstvalue << cnt;
dstvalue = uint32_t_FromSWord(dstvalue);
ZFLG = Bool2Bit(dstvalue == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(dstvalue));
VFLG = 0;
XFLG = CFLG;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
V_regs.LazyFlagKind = kLazyFlagsDefault;
ArgSetDstValue(dstvalue);
}
}
}
LOCALIPROC DoCodeLslL(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t cnt = V_regs.SrcVal & 63;
if (0 == cnt) {
DoCodeNullShift(dstvalue);
} else {
#if WantCloserCyc
V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
#endif
if (cnt >= 32) {
if (cnt == 32) {
DoCodeMaxLslShift(dstvalue);
} else {
DoCodeOverShift();
}
} else {
CFLG = (dstvalue >> (32 - cnt)) & 1;
dstvalue = dstvalue << cnt;
dstvalue = uint32_t_FromSLong(dstvalue);
ZFLG = Bool2Bit(dstvalue == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(dstvalue));
VFLG = 0;
XFLG = CFLG;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
V_regs.LazyFlagKind = kLazyFlagsDefault;
ArgSetDstValue(dstvalue);
}
}
}
LOCALIPROC DoCodeLsrB(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t cnt = V_regs.SrcVal & 63;
#if WantCloserCyc
V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
#endif
if (0 == cnt) {
DoCodeNullShift(dstvalue);
} else if (cnt > 32) {
DoCodeOverShift();
} else {
dstvalue = uint32_t_FromUByte(dstvalue);
dstvalue = dstvalue >> (cnt - 1);
CFLG = XFLG = (dstvalue & 1);
dstvalue = dstvalue >> 1;
ZFLG = Bool2Bit(dstvalue == 0);
NFLG = 0 /* Bool2Bit(uint32_t_MSBisSet(dstvalue)) */;
/* if cnt != 0, always false */
VFLG = 0;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
V_regs.LazyFlagKind = kLazyFlagsDefault;
ArgSetDstValue(dstvalue);
}
}
LOCALIPROC DoCodeLsrW(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t cnt = V_regs.SrcVal & 63;
#if WantCloserCyc
V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
#endif
if (0 == cnt) {
DoCodeNullShift(dstvalue);
} else if (cnt > 32) {
DoCodeOverShift();
} else {
dstvalue = uint32_t_FromUWord(dstvalue);
dstvalue = dstvalue >> (cnt - 1);
CFLG = XFLG = (dstvalue & 1);
dstvalue = dstvalue >> 1;
ZFLG = Bool2Bit(dstvalue == 0);
NFLG = 0 /* Bool2Bit(uint32_t_MSBisSet(dstvalue)) */;
/* if cnt != 0, always false */
VFLG = 0;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
V_regs.LazyFlagKind = kLazyFlagsDefault;
ArgSetDstValue(dstvalue);
}
}
LOCALIPROC DoCodeLsrL(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t cnt = V_regs.SrcVal & 63;
#if WantCloserCyc
V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
#endif
if (0 == cnt) {
DoCodeNullShift(dstvalue);
} else if (cnt > 32) {
DoCodeOverShift();
} else {
dstvalue = uint32_t_FromULong(dstvalue);
dstvalue = dstvalue >> (cnt - 1);
CFLG = XFLG = (dstvalue & 1);
dstvalue = dstvalue >> 1;
ZFLG = Bool2Bit(dstvalue == 0);
NFLG = 0 /* Bool2Bit(uint32_t_MSBisSet(dstvalue)) */;
/* if cnt != 0, always false */
VFLG = 0;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
V_regs.LazyFlagKind = kLazyFlagsDefault;
ArgSetDstValue(dstvalue);
}
}
LOCALFUNC uint32_t DecodeGetSrcSetDstValueDfltFlags_nm(void)
{
NeedDefaultLazyAllFlags();
return DecodeGetSrcSetDstValue();
}
LOCALPROC reg_call DoCodeNullXShift(uint32_t dstvalue)
{
CFLG = XFLG;
ZFLG = Bool2Bit(dstvalue == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(dstvalue));
VFLG = 0;
ArgSetDstValue(dstvalue);
}
LOCALIPROC DoCodeRxlB(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValueDfltFlags_nm();
uint32_t cnt = V_regs.SrcVal & 63;
if (0 == cnt) {
DoCodeNullXShift(dstvalue);
} else {
#if WantCloserCyc
V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
#endif
for (; cnt; --cnt) {
CFLG = Bool2Bit(uint32_t_MSBisSet(dstvalue));
dstvalue = (dstvalue << 1) | XFLG;
dstvalue = uint32_t_FromSByte(dstvalue);
XFLG = CFLG;
}
ZFLG = Bool2Bit(dstvalue == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(dstvalue));
VFLG = 0;
ArgSetDstValue(dstvalue);
}
}
LOCALIPROC DoCodeRxlW(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValueDfltFlags_nm();
uint32_t cnt = V_regs.SrcVal & 63;
if (0 == cnt) {
DoCodeNullXShift(dstvalue);
} else {
#if WantCloserCyc
V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
#endif
for (; cnt; --cnt) {
CFLG = Bool2Bit(uint32_t_MSBisSet(dstvalue));
dstvalue = (dstvalue << 1) | XFLG;
dstvalue = uint32_t_FromSWord(dstvalue);
XFLG = CFLG;
}
ZFLG = Bool2Bit(dstvalue == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(dstvalue));
VFLG = 0;
ArgSetDstValue(dstvalue);
}
}
LOCALIPROC DoCodeRxlL(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValueDfltFlags_nm();
uint32_t cnt = V_regs.SrcVal & 63;
if (0 == cnt) {
DoCodeNullXShift(dstvalue);
} else {
#if WantCloserCyc
V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
#endif
for (; cnt; --cnt) {
CFLG = Bool2Bit(uint32_t_MSBisSet(dstvalue));
dstvalue = (dstvalue << 1) | XFLG;
dstvalue = uint32_t_FromSLong(dstvalue);
XFLG = CFLG;
}
ZFLG = Bool2Bit(dstvalue == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(dstvalue));
VFLG = 0;
ArgSetDstValue(dstvalue);
}
}
LOCALIPROC DoCodeRxrB(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValueDfltFlags_nm();
uint32_t cnt = V_regs.SrcVal & 63;
if (0 == cnt) {
DoCodeNullXShift(dstvalue);
} else {
#if WantCloserCyc
V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
#endif
dstvalue = uint32_t_FromUByte(dstvalue);
for (; cnt; --cnt) {
CFLG = dstvalue & 1;
dstvalue = (dstvalue >> 1) | (((uint32_t)XFLG) << 7);
XFLG = CFLG;
}
dstvalue = uint32_t_FromSByte(dstvalue);
ZFLG = Bool2Bit(dstvalue == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(dstvalue));
VFLG = 0;
ArgSetDstValue(dstvalue);
}
}
LOCALIPROC DoCodeRxrW(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValueDfltFlags_nm();
uint32_t cnt = V_regs.SrcVal & 63;
if (0 == cnt) {
DoCodeNullXShift(dstvalue);
} else {
#if WantCloserCyc
V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
#endif
dstvalue = uint32_t_FromUWord(dstvalue);
for (; cnt; --cnt) {
CFLG = dstvalue & 1;
dstvalue = (dstvalue >> 1) | (((uint32_t)XFLG) << 15);
XFLG = CFLG;
}
dstvalue = uint32_t_FromSWord(dstvalue);
ZFLG = Bool2Bit(dstvalue == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(dstvalue));
VFLG = 0;
ArgSetDstValue(dstvalue);
}
}
LOCALIPROC DoCodeRxrL(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValueDfltFlags_nm();
uint32_t cnt = V_regs.SrcVal & 63;
if (0 == cnt) {
DoCodeNullXShift(dstvalue);
} else {
#if WantCloserCyc
V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
#endif
dstvalue = uint32_t_FromULong(dstvalue);
for (; cnt; --cnt) {
CFLG = dstvalue & 1;
dstvalue = (dstvalue >> 1) | (((uint32_t)XFLG) << 31);
XFLG = CFLG;
}
dstvalue = uint32_t_FromSLong(dstvalue);
ZFLG = Bool2Bit(dstvalue == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(dstvalue));
VFLG = 0;
ArgSetDstValue(dstvalue);
}
}
LOCALIPROC DoCodeRolB(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t cnt = V_regs.SrcVal & 63;
#if WantCloserCyc
V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
#endif
if (0 == cnt) {
DoCodeNullShift(dstvalue);
} else {
cnt &= 7;
if (0 != cnt) {
uint8_t dst = (uint8_t)dstvalue;
dst = (dst >> (8 - cnt))
| ((dst & ((1 << (8 - cnt)) - 1))
<< cnt);
dstvalue = (uint32_t)(int32_t)(int8_t)dst;
}
ZFLG = Bool2Bit(dstvalue == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(dstvalue));
VFLG = 0;
CFLG = (dstvalue & 1);
V_regs.LazyFlagKind = kLazyFlagsDefault;
ArgSetDstValue(dstvalue);
}
}
LOCALIPROC DoCodeRolW(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t cnt = V_regs.SrcVal & 63;
#if WantCloserCyc
V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
#endif
if (0 == cnt) {
DoCodeNullShift(dstvalue);
} else {
cnt &= 15;
if (0 != cnt) {
uint16_t dst = (uint16_t)dstvalue;
dst = (dst >> (16 - cnt))
| ((dst & ((1 << (16 - cnt)) - 1))
<< cnt);
dstvalue = (uint32_t)(int32_t)(int16_t)dst;
}
ZFLG = Bool2Bit(dstvalue == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(dstvalue));
VFLG = 0;
CFLG = (dstvalue & 1);
V_regs.LazyFlagKind = kLazyFlagsDefault;
ArgSetDstValue(dstvalue);
}
}
LOCALIPROC DoCodeRolL(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t cnt = V_regs.SrcVal & 63;
#if WantCloserCyc
V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
#endif
if (0 == cnt) {
DoCodeNullShift(dstvalue);
} else {
cnt &= 31;
if (0 != cnt) {
uint32_t dst = (uint32_t)dstvalue;
dst = (dst >> (32 - cnt))
| ((dst & ((1 << (32 - cnt)) - 1))
<< cnt);
dstvalue = (uint32_t)(int32_t)(int32_t)dst;
}
ZFLG = Bool2Bit(dstvalue == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(dstvalue));
VFLG = 0;
CFLG = (dstvalue & 1);
V_regs.LazyFlagKind = kLazyFlagsDefault;
ArgSetDstValue(dstvalue);
}
}
LOCALIPROC DoCodeRorB(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t cnt = V_regs.SrcVal & 63;
#if WantCloserCyc
V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
#endif
if (0 == cnt) {
DoCodeNullShift(dstvalue);
} else {
cnt &= 7;
if (0 != cnt) {
uint8_t dst = (uint8_t)dstvalue;
dst = (dst >> cnt)
| ((dst & ((1 << cnt) - 1))
<< (8 - cnt));
dstvalue = (uint32_t)(int32_t)(int8_t)dst;
}
ZFLG = Bool2Bit(dstvalue == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(dstvalue));
VFLG = 0;
CFLG = NFLG;
V_regs.LazyFlagKind = kLazyFlagsDefault;
ArgSetDstValue(dstvalue);
}
}
LOCALIPROC DoCodeRorW(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t cnt = V_regs.SrcVal & 63;
#if WantCloserCyc
V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
#endif
if (0 == cnt) {
DoCodeNullShift(dstvalue);
} else {
cnt &= 15;
if (0 != cnt) {
uint16_t dst = (uint16_t)dstvalue;
dst = (dst >> cnt)
| ((dst & ((1 << cnt) - 1))
<< (16 - cnt));
dstvalue = (uint32_t)(int32_t)(int16_t)dst;
}
ZFLG = Bool2Bit(dstvalue == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(dstvalue));
VFLG = 0;
CFLG = NFLG;
V_regs.LazyFlagKind = kLazyFlagsDefault;
ArgSetDstValue(dstvalue);
}
}
LOCALIPROC DoCodeRorL(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValue();
uint32_t cnt = V_regs.SrcVal & 63;
#if WantCloserCyc
V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
#endif
if (0 == cnt) {
DoCodeNullShift(dstvalue);
} else {
cnt &= 31;
if (0 != cnt) {
uint32_t dst = (uint32_t)dstvalue;
dst = (dst >> cnt)
| ((dst & ((1 << cnt) - 1))
<< (32 - cnt));
dstvalue = (uint32_t)(int32_t)(int32_t)dst;
}
ZFLG = Bool2Bit(dstvalue == 0);
NFLG = Bool2Bit(uint32_t_MSBisSet(dstvalue));
VFLG = 0;
CFLG = NFLG;
V_regs.LazyFlagKind = kLazyFlagsDefault;
ArgSetDstValue(dstvalue);
}
}
#if UseLazyZ
LOCALPROC WillSetZFLG(void)
{
if (kLazyFlagsZSet == V_regs.LazyFlagKind) {
/* ok */
} else if (kLazyFlagsDefault == V_regs.LazyFlagKind) {
/* also ok */
} else {
V_regs.LazyFlagZSavedKind = V_regs.LazyFlagKind;
V_regs.LazyFlagKind = kLazyFlagsZSet;
}
}
#else
#define WillSetZFLG NeedDefaultLazyAllFlags
#endif
LOCALINLINEFUNC uint32_t DecodeGetSrcGetDstValueSetZ(void)
{
WillSetZFLG();
return DecodeGetSrcSetDstValue();
}
LOCALIPROC DoCodeBTstB(void)
{
uint32_t dstvalue = DecodeGetSrcGetDstValueSetZ();
uint32_t srcvalue = V_regs.SrcVal & 7;
ZFLG = ((dstvalue >> srcvalue) ^ 1) & 1;
}
LOCALIPROC DoCodeBTstL(void)
{
uint32_t dstvalue = DecodeGetSrcGetDstValueSetZ();
uint32_t srcvalue = V_regs.SrcVal & 31;
ZFLG = ((dstvalue >> srcvalue) ^ 1) & 1;
}
LOCALINLINEFUNC uint32_t DecodeGetSrcSetDstValueSetZ(void)
{
WillSetZFLG();
return DecodeGetSrcSetDstValue();
}
LOCALIPROC DoCodeBChgB(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValueSetZ();
uint32_t srcvalue = V_regs.SrcVal & 7;
ZFLG = ((dstvalue >> srcvalue) ^ 1) & 1;
dstvalue ^= (1 << srcvalue);
ArgSetDstValue(dstvalue);
}
LOCALIPROC DoCodeBChgL(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValueSetZ();
uint32_t srcvalue = V_regs.SrcVal & 31;
ZFLG = ((dstvalue >> srcvalue) ^ 1) & 1;
dstvalue ^= (1 << srcvalue);
ArgSetDstValue(dstvalue);
}
LOCALIPROC DoCodeBClrB(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValueSetZ();
uint32_t srcvalue = V_regs.SrcVal & 7;
ZFLG = ((dstvalue >> srcvalue) ^ 1) & 1;
dstvalue &= ~ (1 << srcvalue);
ArgSetDstValue(dstvalue);
}
LOCALIPROC DoCodeBClrL(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValueSetZ();
uint32_t srcvalue = V_regs.SrcVal & 31;
ZFLG = ((dstvalue >> srcvalue) ^ 1) & 1;
dstvalue &= ~ (1 << srcvalue);
ArgSetDstValue(dstvalue);
}
LOCALIPROC DoCodeBSetB(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValueSetZ();
uint32_t srcvalue = V_regs.SrcVal & 7;
ZFLG = ((dstvalue >> srcvalue) ^ 1) & 1;
dstvalue |= (1 << srcvalue);
ArgSetDstValue(dstvalue);
}
LOCALIPROC DoCodeBSetL(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValueSetZ();
uint32_t srcvalue = V_regs.SrcVal & 31;
ZFLG = ((dstvalue >> srcvalue) ^ 1) & 1;
dstvalue |= (1 << srcvalue);
ArgSetDstValue(dstvalue);
}
LOCALIPROC DoCodeAnd(void)
{
/* DoBinOpAnd(DecodeI_xxxxxxxxssmmmrrr()); */
uint32_t dstvalue = DecodeGetSrcSetDstValue();
dstvalue &= V_regs.SrcVal;
/*
don't need to extend, since excess high
bits all the same as desired high bit.
*/
V_regs.LazyFlagKind = kLazyFlagsTstL;
V_regs.LazyFlagArgDst = dstvalue;
HaveSetUpFlags();
ArgSetDstValue(dstvalue);
}
LOCALIPROC DoCodeOr(void)
{
/* DoBinOr(DecodeI_xxxxxxxxssmmmrrr()); */
uint32_t dstvalue = DecodeGetSrcSetDstValue();
dstvalue |= V_regs.SrcVal;
/*
don't need to extend, since excess high
bits all the same as desired high bit.
*/
V_regs.LazyFlagKind = kLazyFlagsTstL;
V_regs.LazyFlagArgDst = dstvalue;
HaveSetUpFlags();
ArgSetDstValue(dstvalue);
}
LOCALIPROC DoCodeEor(void)
{
/* Eor 1011ddd1ssmmmrrr */
/* DoBinOpEor(DecodeDEa_xxxxdddxssmmmrrr()); */
uint32_t dstvalue = DecodeGetSrcSetDstValue();
dstvalue ^= V_regs.SrcVal;
/*
don't need to extend, since excess high
bits all the same as desired high bit.
*/
V_regs.LazyFlagKind = kLazyFlagsTstL;
V_regs.LazyFlagArgDst = dstvalue;
HaveSetUpFlags();
ArgSetDstValue(dstvalue);
}
LOCALIPROC DoCodeNot(void)
{
/* Not 01000110ssmmmrrr */
uint32_t dstvalue = DecodeGetSetDstValue();
dstvalue = ~ dstvalue;
V_regs.LazyFlagKind = kLazyFlagsTstL;
V_regs.LazyFlagArgDst = dstvalue;
HaveSetUpFlags();
ArgSetDstValue(dstvalue);
}
LOCALPROC DoCodeScc_t(void)
{
#if WantCloserCyc
if (kAMdRegB == V_regs.CurDecOpY.v[1].AMd) {
V_MaxCyclesToGo -= (2 * kCycleScale);
}
#endif
DecodeSetDstValue(0xff);
}
LOCALPROC DoCodeScc_f(void)
{
DecodeSetDstValue(0);
}
LOCALIPROC DoCodeScc(void)
{
/* Scc 0101cccc11mmmrrr */
cctrue(DoCodeScc_t, DoCodeScc_f);
}
LOCALIPROC DoCodeEXTL(void)
{
/* EXT.L */
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
uint32_t *dstp = &V_regs.regs[dstreg];
uint32_t dstvalue = uint32_t_FromSWord(*dstp);
V_regs.LazyFlagKind = kLazyFlagsTstL;
V_regs.LazyFlagArgDst = dstvalue;
HaveSetUpFlags();
*dstp = dstvalue;
}
LOCALIPROC DoCodeEXTW(void)
{
/* EXT.W */
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
uint32_t *dstp = &V_regs.regs[dstreg];
uint32_t dstvalue = uint32_t_FromSByte(*dstp);
V_regs.LazyFlagKind = kLazyFlagsTstL;
V_regs.LazyFlagArgDst = dstvalue;
HaveSetUpFlags();
#if LittleEndianUnaligned
*(uint16_t *)dstp = dstvalue;
#else
*dstp = (*dstp & ~ 0xffff) | (dstvalue & 0xffff);
#endif
}
LOCALIPROC DoCodeNegB(void)
{
uint32_t dstvalue = DecodeGetSetDstValue();
uint32_t result = uint32_t_FromSByte(0 - dstvalue);
V_regs.LazyFlagKind = kLazyFlagsNegB;
V_regs.LazyFlagArgDst = dstvalue;
V_regs.LazyXFlagKind = kLazyFlagsNegB;
V_regs.LazyXFlagArgDst = dstvalue;
HaveSetUpFlags();
ArgSetDstValue(result);
}
LOCALIPROC DoCodeNegW(void)
{
uint32_t dstvalue = DecodeGetSetDstValue();
uint32_t result = uint32_t_FromSWord(0 - dstvalue);
V_regs.LazyFlagKind = kLazyFlagsNegW;
V_regs.LazyFlagArgDst = dstvalue;
V_regs.LazyXFlagKind = kLazyFlagsNegW;
V_regs.LazyXFlagArgDst = dstvalue;
HaveSetUpFlags();
ArgSetDstValue(result);
}
LOCALIPROC DoCodeNegL(void)
{
uint32_t dstvalue = DecodeGetSetDstValue();
uint32_t result = uint32_t_FromSLong(0 - dstvalue);
V_regs.LazyFlagKind = kLazyFlagsNegL;
V_regs.LazyFlagArgDst = dstvalue;
V_regs.LazyXFlagKind = kLazyFlagsNegL;
V_regs.LazyXFlagArgDst = dstvalue;
HaveSetUpFlags();
ArgSetDstValue(result);
}
LOCALPROC reg_call SetCCRforNegX(uint32_t dstvalue, uint32_t result)
{
ZFLG &= Bool2Bit(result == 0);
{
flagtype flgs = Bool2Bit(uint32_t_MSBisSet(dstvalue));
flagtype flgn = Bool2Bit(uint32_t_MSBisSet(result));
NFLG = flgn;
VFLG = flgs & flgn;
XFLG = CFLG = flgs | flgn;
}
ArgSetDstValue(result);
}
LOCALIPROC DoCodeNegXB(void)
{
NeedDefaultLazyAllFlags();
{
uint32_t dstvalue = DecodeGetSetDstValue();
uint32_t result = uint32_t_FromSByte(0 - (XFLG + dstvalue));
SetCCRforNegX(dstvalue, result);
}
}
LOCALIPROC DoCodeNegXW(void)
{
if ((kLazyFlagsDefault != V_regs.LazyFlagKind)
|| (kLazyFlagsDefault != V_regs.LazyXFlagKind))
{
NeedDefaultLazyAllFlags();
}
{
uint32_t dstvalue = DecodeGetSetDstValue();
uint32_t result = uint32_t_FromSWord(0 - (XFLG + dstvalue));
SetCCRforNegX(dstvalue, result);
}
}
LOCALIPROC DoCodeNegXL(void)
{
if (kLazyFlagsNegL == V_regs.LazyFlagKind) {
NeedDefaultLazyFlagsNegL();
} else
if ((kLazyFlagsDefault == V_regs.LazyFlagKind)
&& (kLazyFlagsDefault == V_regs.LazyXFlagKind))
{
/* ok */
} else
{
NeedDefaultLazyAllFlags();
}
{
uint32_t dstvalue = DecodeGetSetDstValue();
uint32_t result = uint32_t_FromSLong(0 - (XFLG + dstvalue));
SetCCRforNegX(dstvalue, result);
}
}
LOCALIPROC DoCodeMulU(void)
{
/* MulU 1100ddd011mmmrrr */
uint32_t srcvalue = DecodeGetSrcValue();
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
uint32_t *dstp = &V_regs.regs[dstreg];
uint32_t dstvalue = *dstp;
dstvalue = uint32_t_FromSLong(uint32_t_FromUWord(dstvalue)
* uint32_t_FromUWord(srcvalue));
#if WantCloserCyc
{
uint32_t v = srcvalue;
while (v != 0) {
if ((v & 1) != 0) {
V_MaxCyclesToGo -= (2 * kCycleScale);
}
v >>= 1;
}
}
#endif
V_regs.LazyFlagKind = kLazyFlagsTstL;
V_regs.LazyFlagArgDst = dstvalue;
HaveSetUpFlags();
*dstp = dstvalue;
}
LOCALIPROC DoCodeMulS(void)
{
/* MulS 1100ddd111mmmrrr */
uint32_t srcvalue = DecodeGetSrcValue();
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
uint32_t *dstp = &V_regs.regs[dstreg];
uint32_t dstvalue = *dstp;
dstvalue = uint32_t_FromSLong((int32_t)(int16_t)dstvalue
* (int32_t)(int16_t)srcvalue);
#if WantCloserCyc
{
uint32_t v = (srcvalue << 1);
while (v != 0) {
if ((v & 1) != ((v >> 1) & 1)) {
V_MaxCyclesToGo -= (2 * kCycleScale);
}
v >>= 1;
}
}
#endif
V_regs.LazyFlagKind = kLazyFlagsTstL;
V_regs.LazyFlagArgDst = dstvalue;
HaveSetUpFlags();
*dstp = dstvalue;
}
LOCALIPROC DoCodeDivU(void)
{
/* DivU 1000ddd011mmmrrr */
uint32_t srcvalue = DecodeGetSrcValue();
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
uint32_t *dstp = &V_regs.regs[dstreg];
uint32_t dstvalue = *dstp;
if (srcvalue == 0) {
#if WantCloserCyc
V_MaxCyclesToGo -=
(38 * kCycleScale + 3 * RdAvgXtraCyc + 3 * WrAvgXtraCyc);
#endif
Exception(5);
#if m68k_logExceptions
dbglog_WriteNote("*** zero devide exception");
#endif
} else {
uint32_t newv = (uint32_t)dstvalue / (uint32_t)(uint16_t)srcvalue;
uint32_t rem = (uint32_t)dstvalue % (uint32_t)(uint16_t)srcvalue;
#if WantCloserCyc
V_MaxCyclesToGo -= (133 * kCycleScale);
#endif
if (newv > 0xffff) {
NeedDefaultLazyAllFlags();
VFLG = NFLG = 1;
CFLG = 0;
} else {
VFLG = CFLG = 0;
ZFLG = Bool2Bit(((int16_t)(newv)) == 0);
NFLG = Bool2Bit(((int16_t)(newv)) < 0);
V_regs.LazyFlagKind = kLazyFlagsDefault;
newv = (newv & 0xffff) | ((uint32_t)rem << 16);
dstvalue = newv;
}
}
*dstp = dstvalue;
}
LOCALIPROC DoCodeDivS(void)
{
/* DivS 1000ddd111mmmrrr */
uint32_t srcvalue = DecodeGetSrcValue();
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
uint32_t *dstp = &V_regs.regs[dstreg];
uint32_t dstvalue = *dstp;
if (srcvalue == 0) {
#if WantCloserCyc
V_MaxCyclesToGo -=
(38 * kCycleScale + 3 * RdAvgXtraCyc + 3 * WrAvgXtraCyc);
#endif
Exception(5);
#if m68k_logExceptions
dbglog_WriteNote("*** zero devide exception");
#endif
} else {
int32_t newv = (int32_t)dstvalue / (int32_t)(int16_t)srcvalue;
uint16_t rem = (int32_t)dstvalue % (int32_t)(int16_t)srcvalue;
#if WantCloserCyc
V_MaxCyclesToGo -= (150 * kCycleScale);
#endif
if (((newv & 0xffff8000) != 0) &&
((newv & 0xffff8000) != 0xffff8000))
{
NeedDefaultLazyAllFlags();
VFLG = NFLG = 1;
CFLG = 0;
} else {
if (((int16_t)rem < 0) != ((int32_t)dstvalue < 0)) {
rem = - rem;
}
VFLG = CFLG = 0;
ZFLG = Bool2Bit(((int16_t)(newv)) == 0);
NFLG = Bool2Bit(((int16_t)(newv)) < 0);
V_regs.LazyFlagKind = kLazyFlagsDefault;
newv = (newv & 0xffff) | ((uint32_t)rem << 16);
dstvalue = newv;
}
}
*dstp = dstvalue;
}
LOCALIPROC DoCodeExg(void)
{
/* Exg dd 1100ddd101000rrr, opsize = 4 */
/* Exg aa 1100ddd101001rrr, opsize = 4 */
/* Exg da 1100ddd110001rrr, opsize = 4 */
uint32_t srcreg = V_regs.CurDecOpY.v[0].ArgDat;
uint32_t *srcp = &V_regs.regs[srcreg];
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
uint32_t *dstp = &V_regs.regs[dstreg];
uint32_t srcvalue = *srcp;
*srcp = *dstp;
*dstp = srcvalue;
}
LOCALIPROC DoCodeMoveEaCR(void)
{
/* 0100010011mmmrrr */
m68k_setCR(DecodeGetDstValue());
}
LOCALPROC DoPrivilegeViolation(void)
{
#if WantCloserCyc
V_MaxCyclesToGo += GetDcoCycles(V_regs.CurDecOp);
V_MaxCyclesToGo -=
(34 * kCycleScale + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc);
#endif
BackupPC();
Exception(8);
#if m68k_logExceptions
dbglog_WriteNote("*** Privilege Violation exception");
#endif
}
LOCALIPROC DoCodeMoveSREa(void)
{
/* Move from SR 0100000011mmmrrr */
#if Use68020
if (0 == V_regs.s) {
DoPrivilegeViolation();
} else
#endif
{
DecodeSetDstValue(m68k_getSR());
}
}
LOCALIPROC DoCodeMoveEaSR(void)
{
/* 0100011011mmmrrr */
if (0 == V_regs.s) {
DoPrivilegeViolation();
} else {
m68k_setSR(DecodeGetDstValue());
}
}
LOCALIPROC DoCodeOrISR(void)
{
if (0 == V_regs.s) {
DoPrivilegeViolation();
} else {
V_regs.SrcVal = nextiword_nm();
m68k_setSR(m68k_getSR() | V_regs.SrcVal);
}
}
LOCALIPROC DoCodeAndISR(void)
{
if (0 == V_regs.s) {
DoPrivilegeViolation();
} else {
V_regs.SrcVal = nextiword_nm();
m68k_setSR(m68k_getSR() & V_regs.SrcVal);
}
}
LOCALIPROC DoCodeEorISR(void)
{
if (0 == V_regs.s) {
DoPrivilegeViolation();
} else {
V_regs.SrcVal = nextiword_nm();
m68k_setSR(m68k_getSR() ^ V_regs.SrcVal);
}
}
LOCALIPROC DoCodeOrICCR(void)
{
V_regs.SrcVal = nextiword_nm();
m68k_setCR(m68k_getCR() | V_regs.SrcVal);
}
LOCALIPROC DoCodeAndICCR(void)
{
V_regs.SrcVal = nextiword_nm();
m68k_setCR(m68k_getCR() & V_regs.SrcVal);
}
LOCALIPROC DoCodeEorICCR(void)
{
V_regs.SrcVal = nextiword_nm();
m68k_setCR(m68k_getCR() ^ V_regs.SrcVal);
}
LOCALIPROC DoCodeMOVEMApRW(void)
{
/* MOVEM mem to reg 01001100110011rrr */
int16_t z;
uint32_t regmask = nextiword_nm();
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
uint32_t *dstp = &V_regs.regs[dstreg];
uint32_t p = *dstp;
for (z = 0; z < 16; ++z) {
if ((regmask & (1 << z)) != 0) {
#if WantCloserCyc
V_MaxCyclesToGo -= (4 * kCycleScale + RdAvgXtraCyc);
#endif
V_regs.regs[z] = get_word(p);
p += 2;
}
}
*dstp = p;
}
LOCALIPROC DoCodeMOVEMRmMW(void)
{
/* MOVEM reg to mem 01001000110100rrr */
int16_t z;
uint32_t regmask = nextiword_nm();
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
uint32_t *dstp = &V_regs.regs[dstreg];
uint32_t p = *dstp;
#if Use68020
{
int n = 0;
for (z = 0; z < 16; ++z) {
if ((regmask & (1 << z)) != 0) {
n++;
}
}
*dstp = p - n * 2;
}
#endif
for (z = 16; --z >= 0; ) {
if ((regmask & (1 << (15 - z))) != 0) {
#if WantCloserCyc
V_MaxCyclesToGo -= (4 * kCycleScale + WrAvgXtraCyc);
#endif
p -= 2;
put_word(p, V_regs.regs[z]);
}
}
#if ! Use68020
*dstp = p;
#endif
}
LOCALIPROC DoCodeMOVEMrmW(void)
{
/* MOVEM reg to mem 010010001ssmmmrrr */
int16_t z;
uint32_t regmask = nextiword_nm();
uint32_t p = DecodeDst();
for (z = 0; z < 16; ++z) {
if ((regmask & (1 << z)) != 0) {
#if WantCloserCyc
V_MaxCyclesToGo -=
(4 * kCycleScale + WrAvgXtraCyc);
#endif
put_word(p, V_regs.regs[z]);
p += 2;
}
}
}
LOCALIPROC DoCodeMOVEMrmL(void)
{
/* MOVEM reg to mem 010010001ssmmmrrr */
int16_t z;
uint32_t regmask = nextiword_nm();
uint32_t p = DecodeDst();
for (z = 0; z < 16; ++z) {
if ((regmask & (1 << z)) != 0) {
#if WantCloserCyc
V_MaxCyclesToGo -=
(8 * kCycleScale + 2 * WrAvgXtraCyc);
#endif
put_long(p, V_regs.regs[z]);
p += 4;
}
}
}
LOCALIPROC DoCodeMOVEMmrW(void)
{
/* MOVEM mem to reg 0100110011smmmrrr */
int16_t z;
uint32_t regmask = nextiword_nm();
uint32_t p = DecodeDst();
for (z = 0; z < 16; ++z) {
if ((regmask & (1 << z)) != 0) {
#if WantCloserCyc
V_MaxCyclesToGo -=
(4 * kCycleScale + RdAvgXtraCyc);
#endif
V_regs.regs[z] = get_word(p);
p += 2;
}
}
}
LOCALIPROC DoCodeMOVEMmrL(void)
{
/* MOVEM mem to reg 0100110011smmmrrr */
int16_t z;
uint32_t regmask = nextiword_nm();
uint32_t p = DecodeDst();
for (z = 0; z < 16; ++z) {
if ((regmask & (1 << z)) != 0) {
#if WantCloserCyc
V_MaxCyclesToGo -=
(8 * kCycleScale + 2 * RdAvgXtraCyc);
#endif
V_regs.regs[z] = get_long(p);
p += 4;
}
}
}
LOCALIPROC DoCodeAbcd(void)
{
/* ABCD r 1100ddd100000rrr */
/* ABCD m 1100ddd100001rrr */
uint32_t dstvalue = DecodeGetSrcSetDstValueDfltFlags_nm();
uint32_t srcvalue = V_regs.SrcVal;
{
/* if (V_regs.opsize != 1) a bug */
int flgs = uint32_t_MSBisSet(srcvalue);
int flgo = uint32_t_MSBisSet(dstvalue);
uint16_t newv_lo =
(srcvalue & 0xF) + (dstvalue & 0xF) + XFLG;
uint16_t newv_hi = (srcvalue & 0xF0) + (dstvalue & 0xF0);
uint16_t newv;
if (newv_lo > 9) {
newv_lo += 6;
}
newv = newv_hi + newv_lo;
CFLG = XFLG = Bool2Bit((newv & 0x1F0) > 0x90);
if (CFLG != 0) {
newv += 0x60;
}
dstvalue = uint32_t_FromSByte(newv);
if (dstvalue != 0) {
ZFLG = 0;
}
NFLG = Bool2Bit(uint32_t_MSBisSet(dstvalue));
VFLG = Bool2Bit((flgs != flgo) && ((NFLG != 0) != flgo));
/*
but according to my reference book,
VFLG is Undefined for ABCD
*/
}
ArgSetDstValue(dstvalue);
}
LOCALIPROC DoCodeSbcd(void)
{
uint32_t dstvalue = DecodeGetSrcSetDstValueDfltFlags_nm();
uint32_t srcvalue = V_regs.SrcVal;
{
int flgs = uint32_t_MSBisSet(srcvalue);
int flgo = uint32_t_MSBisSet(dstvalue);
uint16_t newv_lo =
(dstvalue & 0xF) - (srcvalue & 0xF) - XFLG;
uint16_t newv_hi = (dstvalue & 0xF0) - (srcvalue & 0xF0);
uint16_t newv;
if (newv_lo > 9) {
newv_lo -= 6;
newv_hi -= 0x10;
}
newv = newv_hi + (newv_lo & 0xF);
CFLG = XFLG = Bool2Bit((newv_hi & 0x1F0) > 0x90);
if (CFLG != 0) {
newv -= 0x60;
}
dstvalue = uint32_t_FromSByte(newv);
if (dstvalue != 0) {
ZFLG = 0;
}
NFLG = Bool2Bit(uint32_t_MSBisSet(dstvalue));
VFLG = Bool2Bit((flgs != flgo) && ((NFLG != 0) != flgo));
/*
but according to my reference book,
VFLG is Undefined for SBCD
*/
}
ArgSetDstValue(dstvalue);
}
LOCALIPROC DoCodeNbcd(void)
{
/* Nbcd 0100100000mmmrrr */
uint32_t dstvalue = DecodeGetSetDstValue();
NeedDefaultLazyAllFlags();
{
uint16_t newv_lo = - (dstvalue & 0xF) - XFLG;
uint16_t newv_hi = - (dstvalue & 0xF0);
uint16_t newv;
if (newv_lo > 9) {
newv_lo -= 6;
newv_hi -= 0x10;
}
newv = newv_hi + (newv_lo & 0xF);
CFLG = XFLG = Bool2Bit((newv_hi & 0x1F0) > 0x90);
if (CFLG != 0) {
newv -= 0x60;
}
dstvalue = uint32_t_FromSByte(newv);
NFLG = Bool2Bit(uint32_t_MSBisSet(dstvalue));
if (dstvalue != 0) {
ZFLG = 0;
}
}
ArgSetDstValue(dstvalue);
}
LOCALIPROC DoCodeRte(void)
{
/* Rte 0100111001110011 */
if (0 == V_regs.s) {
DoPrivilegeViolation();
} else {
uint32_t NewPC;
CPTR stackp = m68k_areg(7);
uint32_t NewSR = get_word(stackp);
stackp += 2;
NewPC = get_long(stackp);
stackp += 4;
#if Use68020
{
uint16_t format = get_word(stackp);
stackp += 2;
switch ((format >> 12) & 0x0F) {
case 0:
/* ReportAbnormal("rte stack frame format 0"); */
break;
case 1:
ReportAbnormalID(0x0107,
"rte stack frame format 1");
NewPC = m68k_getpc() - 2;
/* rerun instruction */
break;
case 2:
ReportAbnormalID(0x0108,
"rte stack frame format 2");
stackp += 4;
break;
case 9:
ReportAbnormalID(0x0109,
"rte stack frame format 9");
stackp += 12;
break;
case 10:
ReportAbnormalID(0x010A,
"rte stack frame format 10");
stackp += 24;
break;
case 11:
ReportAbnormalID(0x010B,
"rte stack frame format 11");
stackp += 84;
break;
default:
ReportAbnormalID(0x010C,
"unknown rte stack frame format");
Exception(14);
return;
break;
}
}
#endif
m68k_areg(7) = stackp;
m68k_setSR(NewSR);
m68k_setpc(NewPC);
}
}
LOCALIPROC DoCodeNop(void)
{
/* Nop 0100111001110001 */
}
LOCALIPROC DoCodeMoveP0(void)
{
/* MoveP 0000ddd1mm001aaa */
uint32_t srcreg = V_regs.CurDecOpY.v[0].ArgDat;
uint32_t *srcp = &V_regs.regs[srcreg];
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
uint32_t *dstp = &V_regs.regs[dstreg];
uint32_t Displacement = nextiword_nm();
/* shouldn't this sign extend ? */
CPTR memp = *srcp + Displacement;
uint16_t val = ((get_byte(memp) & 0x00FF) << 8)
| (get_byte(memp + 2) & 0x00FF);
*dstp =
(*dstp & ~ 0xffff) | (val & 0xffff);
#if 0
if ((Displacement & 0x00008000) != 0) {
/* **** for testing only **** */
BackupPC();
op_illg();
}
#endif
}
LOCALIPROC DoCodeMoveP1(void)
{
/* MoveP 0000ddd1mm001aaa */
uint32_t srcreg = V_regs.CurDecOpY.v[0].ArgDat;
uint32_t *srcp = &V_regs.regs[srcreg];
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
uint32_t *dstp = &V_regs.regs[dstreg];
uint32_t Displacement = nextiword_nm();
/* shouldn't this sign extend ? */
CPTR memp = *srcp + Displacement;
uint32_t val = ((get_byte(memp) & 0x00FF) << 24)
| ((get_byte(memp + 2) & 0x00FF) << 16)
| ((get_byte(memp + 4) & 0x00FF) << 8)
| (get_byte(memp + 6) & 0x00FF);
*dstp = val;
}
LOCALIPROC DoCodeMoveP2(void)
{
/* MoveP 0000ddd1mm001aaa */
uint32_t srcreg = V_regs.CurDecOpY.v[0].ArgDat;
uint32_t *srcp = &V_regs.regs[srcreg];
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
uint32_t *dstp = &V_regs.regs[dstreg];
uint32_t Displacement = nextiword_nm();
/* shouldn't this sign extend ? */
CPTR memp = *srcp + Displacement;
int16_t val = *dstp;
put_byte(memp, val >> 8);
put_byte(memp + 2, val);
}
LOCALIPROC DoCodeMoveP3(void)
{
/* MoveP 0000ddd1mm001aaa */
uint32_t srcreg = V_regs.CurDecOpY.v[0].ArgDat;
uint32_t *srcp = &V_regs.regs[srcreg];
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
uint32_t *dstp = &V_regs.regs[dstreg];
uint32_t Displacement = nextiword_nm();
/* shouldn't this sign extend ? */
CPTR memp = *srcp + Displacement;
int32_t val = *dstp;
put_byte(memp, val >> 24);
put_byte(memp + 2, val >> 16);
put_byte(memp + 4, val >> 8);
put_byte(memp + 6, val);
}
LOCALPROC op_illg(void)
{
BackupPC();
Exception(4);
#if m68k_logExceptions
dbglog_WriteNote("*** illegal instruction exception");
#endif
}
LOCALIPROC DoCodeChk(void)
{
uint32_t dstvalue = DecodeGetSrcGetDstValue();
uint32_t srcvalue = V_regs.SrcVal;
if (uint32_t_MSBisSet(srcvalue)) {
NeedDefaultLazyAllFlags();
#if WantCloserCyc
V_MaxCyclesToGo -=
(30 * kCycleScale + 3 * RdAvgXtraCyc + 3 * WrAvgXtraCyc);
#endif
NFLG = 1;
Exception(6);
} else if (((int32_t)srcvalue) > ((int32_t)dstvalue)) {
NeedDefaultLazyAllFlags();
#if WantCloserCyc
V_MaxCyclesToGo -=
(30 * kCycleScale + 3 * RdAvgXtraCyc + 3 * WrAvgXtraCyc);
#endif
NFLG = 0;
Exception(6);
}
}
LOCALIPROC DoCodeTrap(void)
{
/* Trap 010011100100vvvv */
Exception(V_regs.CurDecOpY.v[1].ArgDat);
}
LOCALIPROC DoCodeTrapV(void)
{
/* TrapV 0100111001110110 */
NeedDefaultLazyAllFlags();
if (VFLG != 0) {
#if WantCloserCyc
V_MaxCyclesToGo += GetDcoCycles(V_regs.CurDecOp);
V_MaxCyclesToGo -=
(34 * kCycleScale + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc);
#endif
Exception(7);
}
}
LOCALIPROC DoCodeRtr(void)
{
/* Rtr 0100111001110111 */
uint32_t NewPC;
CPTR stackp = m68k_areg(7);
uint32_t NewCR = get_word(stackp);
stackp += 2;
NewPC = get_long(stackp);
stackp += 4;
m68k_areg(7) = stackp;
m68k_setCR(NewCR);
m68k_setpc(NewPC);
}
LOCALIPROC DoCodeLink(void)
{
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
uint32_t *dstp = &V_regs.regs[dstreg];
CPTR stackp = m68k_areg(7);
stackp -= 4;
m68k_areg(7) = stackp; /* only matters if dstreg == 7 + 8 */
put_long(stackp, *dstp);
*dstp = stackp;
m68k_areg(7) += uint32_t_FromSWord(nextiword_nm());
}
LOCALIPROC DoCodeUnlk(void)
{
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
uint32_t *dstp = &V_regs.regs[dstreg];
if (dstreg != 7 + 8) {
uint32_t src = *dstp;
*dstp = get_long(src);
m68k_areg(7) = src + 4;
} else {
/* wouldn't expect this to happen */
m68k_areg(7) = get_long(m68k_areg(7)) + 4;
}
}
LOCALIPROC DoCodeMoveRUSP(void)
{
/* MOVE USP 0100111001100aaa */
if (0 == V_regs.s) {
DoPrivilegeViolation();
} else {
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
uint32_t *dstp = &V_regs.regs[dstreg];
V_regs.usp = *dstp;
}
}
LOCALIPROC DoCodeMoveUSPR(void)
{
/* MOVE USP 0100111001101aaa */
if (0 == V_regs.s) {
DoPrivilegeViolation();
} else {
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
uint32_t *dstp = &V_regs.regs[dstreg];
*dstp = V_regs.usp;
}
}
LOCALIPROC DoCodeTas(void)
{
/* Tas 0100101011mmmrrr */
uint32_t dstvalue = DecodeGetSetDstValue();
V_regs.LazyFlagKind = kLazyFlagsTstL;
V_regs.LazyFlagArgDst = dstvalue;
HaveSetUpFlags();
dstvalue |= 0x80;
ArgSetDstValue(dstvalue);
}
LOCALIPROC DoCodeFdefault(void)
{
BackupPC();
Exception(0xB);
}
LOCALPROC m68k_setstopped(void)
{
/* not implemented. doesn't seemed to be used on Mac Plus */
Exception(4); /* fake an illegal instruction */
#if m68k_logExceptions
dbglog_WriteNote("*** set stopped");
#endif
}
LOCALIPROC DoCodeStop(void)
{
/* Stop 0100111001110010 */
if (0 == V_regs.s) {
DoPrivilegeViolation();
} else {
m68k_setSR(nextiword_nm());
m68k_setstopped();
}
}
FORWARDPROC local_customreset(void);
LOCALIPROC DoCodeReset(void)
{
/* Reset 0100111001100000 */
if (0 == V_regs.s) {
DoPrivilegeViolation();
} else {
local_customreset();
}
}
#if Use68020
LOCALIPROC DoCodeCallMorRtm(void)
{
/* CALLM or RTM 0000011011mmmrrr */
ReportAbnormalID(0x010D, "CALLM or RTM instruction");
}
#endif
#if Use68020
LOCALIPROC DoCodeMoveCCREa(void)
{
/* Move from CCR 0100001011mmmrrr */
DecodeSetDstValue(m68k_getCR());
}
#endif
#if Use68020
LOCALIPROC DoCodeBraL(void)
{
/* Bra 0110ccccnnnnnnnn */
int32_t offset = ((int32_t)(uint32_t)nextilong()) - 4;
uint8_t * s = V_pc_p + offset;
V_pc_p = s;
#if USE_PCLIMIT
if (cond_rare(s >= V_pc_pHi)
|| cond_rare(s < V_regs.pc_pLo))
{
Recalc_PC_Block();
}
#endif
}
#endif
#if Use68020
LOCALPROC SkipiLong(void)
{
V_pc_p += 4;
#if USE_PCLIMIT
if (cond_rare(V_pc_p >= V_pc_pHi)) {
Recalc_PC_Block();
}
#endif
}
#endif
#if Use68020
LOCALIPROC DoCodeBccL(void)
{
/* Bcc 0110ccccnnnnnnnn */
cctrue(DoCodeBraL, SkipiLong);
}
#endif
#if Use68020
LOCALIPROC DoCodeBsrL(void)
{
int32_t offset = ((int32_t)(uint32_t)nextilong()) - 4;
uint8_t * s = V_pc_p + offset;
m68k_areg(7) -= 4;
put_long(m68k_areg(7), m68k_getpc());
V_pc_p = s;
#if USE_PCLIMIT
if (cond_rare(s >= V_pc_pHi)
|| cond_rare(s < V_regs.pc_pLo))
{
Recalc_PC_Block();
}
#endif
/* ReportAbnormal("long branch in DoCode6"); */
/* Used by various Apps */
}
#endif
#if Use68020
LOCALIPROC DoCodeEXTBL(void)
{
/* EXTB.L */
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
uint32_t *dstp = &V_regs.regs[dstreg];
uint32_t dstvalue = uint32_t_FromSByte(*dstp);
V_regs.LazyFlagKind = kLazyFlagsTstL;
V_regs.LazyFlagArgDst = dstvalue;
HaveSetUpFlags();
*dstp = dstvalue;
}
#endif
#if Use68020
LOCALPROC DoCHK2orCMP2(void)
{
/* CHK2 or CMP2 00000ss011mmmrrr */
uint32_t regv;
uint32_t lower;
uint32_t upper;
uint32_t extra = nextiword_nm();
uint32_t DstAddr = DecodeDst();
uint32_t srcreg = (extra >> 12) & 0x0F;
uint32_t *srcp = &V_regs.regs[srcreg];
/* ReportAbnormal("CHK2 or CMP2 instruction"); */
switch (V_regs.CurDecOpY.v[0].ArgDat) {
case 1:
if ((extra & 0x8000) == 0) {
regv = uint32_t_FromSByte(*srcp);
} else {
regv = uint32_t_FromSLong(*srcp);
}
lower = get_byte(DstAddr);
upper = get_byte(DstAddr + 1);
break;
case 2:
if ((extra & 0x8000) == 0) {
regv = uint32_t_FromSWord(*srcp);
} else {
regv = uint32_t_FromSLong(*srcp);
}
lower = get_word(DstAddr);
upper = get_word(DstAddr + 2);
break;
default:
#if ExtraAbnormalReports
if (4 != V_regs.CurDecOpY.v[0].ArgDat) {
ReportAbnormalID(0x010E,
"illegal opsize in CHK2 or CMP2");
}
#endif
if ((extra & 0x8000) == 0) {
regv = uint32_t_FromSLong(*srcp);
} else {
regv = uint32_t_FromSLong(*srcp);
}
lower = get_long(DstAddr);
upper = get_long(DstAddr + 4);
break;
}
NeedDefaultLazyAllFlags();
ZFLG = Bool2Bit((upper == regv) || (lower == regv));
CFLG = Bool2Bit((((int32_t)lower) <= ((int32_t)upper))
? (((int32_t)regv) < ((int32_t)lower)
|| ((int32_t)regv) > ((int32_t)upper))
: (((int32_t)regv) > ((int32_t)upper)
|| ((int32_t)regv) < ((int32_t)lower)));
if ((extra & 0x800) && (CFLG != 0)) {
Exception(6);
}
}
#endif
#if Use68020
LOCALPROC DoCAS(void)
{
/* CAS 00001ss011mmmrrr */
uint32_t srcvalue;
uint32_t dstvalue;
uint16_t src = nextiword_nm();
int ru = (src >> 6) & 7;
int rc = src & 7;
ReportAbnormalID(0x010F, "CAS instruction");
switch (V_regs.CurDecOpY.v[0].ArgDat) {
case 1:
srcvalue = uint32_t_FromSByte(V_regs.regs[rc]);
break;
case 2:
srcvalue = uint32_t_FromSWord(V_regs.regs[rc]);
break;
default:
#if ExtraAbnormalReports
if (4 != V_regs.CurDecOpY.v[0].ArgDat) {
ReportAbnormalID(0x0110, "illegal opsize in DoCAS");
}
#endif
srcvalue = uint32_t_FromSLong(V_regs.regs[rc]);
break;
}
dstvalue = DecodeGetSetDstValue();
{
int flgs = ((int32_t)srcvalue) < 0;
int flgo = ((int32_t)dstvalue) < 0;
uint32_t newv = dstvalue - srcvalue;
if (V_regs.CurDecOpY.v[0].ArgDat == 1) {
newv = uint32_t_FromSByte(newv);
} else if (V_regs.CurDecOpY.v[0].ArgDat == 2) {
newv = uint32_t_FromSWord(newv);
} else {
newv = uint32_t_FromSLong(newv);
}
ZFLG = Bool2Bit(((int32_t)newv) == 0);
NFLG = Bool2Bit(((int32_t)newv) < 0);
VFLG = Bool2Bit((flgs != flgo) && ((NFLG != 0) != flgo));
CFLG = Bool2Bit(
(flgs && ! flgo) || ((NFLG != 0) && ((! flgo) || flgs)));
V_regs.LazyFlagKind = kLazyFlagsDefault;
if (ZFLG != 0) {
ArgSetDstValue(m68k_dreg(ru));
} else {
V_regs.ArgAddr.rga = &V_regs.regs[rc];
if (V_regs.CurDecOpY.v[0].ArgDat == 2) {
*V_regs.ArgAddr.rga =
(*V_regs.ArgAddr.rga & ~ 0xffff)
| ((dstvalue) & 0xffff);
} else if (V_regs.CurDecOpY.v[0].ArgDat < 2) {
*V_regs.ArgAddr.rga =
(*V_regs.ArgAddr.rga & ~ 0xff)
| ((dstvalue) & 0xff);
} else {
*V_regs.ArgAddr.rga = dstvalue;
}
}
}
}
#endif
#if Use68020
LOCALPROC DoCAS2(void)
{
/* CAS2 00001ss011111100 */
uint32_t extra = nextilong();
int dc2 = extra & 7;
int du2 = (extra >> 6) & 7;
int dc1 = (extra >> 16) & 7;
int du1 = (extra >> 22) & 7;
CPTR rn1 = V_regs.regs[(extra >> 28) & 0x0F];
CPTR rn2 = V_regs.regs[(extra >> 12) & 0x0F];
int32_t src = m68k_dreg(dc1);
int32_t dst1;
int32_t dst2;
ReportAbnormalID(0x0111, "DoCAS2 instruction");
if (V_regs.CurDecOpY.v[0].ArgDat == 2) {
dst1 = get_word(rn1);
dst2 = get_word(rn2);
src = (int32_t)(int16_t)src;
} else {
dst1 = get_long(rn1);
dst2 = get_long(rn2);
}
{
int flgs = src < 0;
int flgo = dst1 < 0;
int32_t newv = dst1 - src;
if (V_regs.CurDecOpY.v[0].ArgDat == 2) {
newv = (uint16_t)newv;
}
ZFLG = Bool2Bit(newv == 0);
NFLG = Bool2Bit(newv < 0);
VFLG = Bool2Bit((flgs != flgo) && ((NFLG != 0) != flgo));
CFLG = Bool2Bit(
(flgs && ! flgo) || ((NFLG != 0) && ((! flgo) || flgs)));
V_regs.LazyFlagKind = kLazyFlagsDefault;
if (ZFLG != 0) {
src = m68k_dreg(dc2);
if (V_regs.CurDecOpY.v[0].ArgDat == 2) {
src = (int32_t)(int16_t)src;
}
flgs = src < 0;
flgo = dst2 < 0;
newv = dst2 - src;
if (V_regs.CurDecOpY.v[0].ArgDat == 2) {
newv = (uint16_t)newv;
}
ZFLG = Bool2Bit(newv == 0);
NFLG = Bool2Bit(newv < 0);
VFLG = Bool2Bit((flgs != flgo) && ((NFLG != 0) != flgo));
CFLG = Bool2Bit((flgs && ! flgo)
|| ((NFLG != 0) && ((! flgo) || flgs)));
V_regs.LazyFlagKind = kLazyFlagsDefault;
if (ZFLG != 0) {
if (V_regs.CurDecOpY.v[0].ArgDat == 2) {
put_word(rn1, m68k_dreg(du1));
put_word(rn2, m68k_dreg(du2));
} else {
put_word(rn1, m68k_dreg(du1));
put_word(rn2, m68k_dreg(du2));
}
}
}
}
if (ZFLG == 0) {
if (V_regs.CurDecOpY.v[0].ArgDat == 2) {
m68k_dreg(du1) =
(m68k_dreg(du1) & ~ 0xffff) | ((uint32_t)dst1 & 0xffff);
m68k_dreg(du2) =
(m68k_dreg(du2) & ~ 0xffff) | ((uint32_t)dst2 & 0xffff);
} else {
m68k_dreg(du1) = dst1;
m68k_dreg(du2) = dst2;
}
}
}
#endif
#if Use68020
LOCALPROC DoMOVES(void)
{
/* MoveS 00001110ssmmmrrr */
ReportAbnormalID(0x0112, "MoveS instruction");
if (0 == V_regs.s) {
DoPrivilegeViolation();
} else {
uint16_t extra = nextiword_nm();
if (extra & 0x0800) {
uint32_t src = V_regs.regs[(extra >> 12) & 0x0F];
DecodeSetDstValue(src);
} else {
uint32_t srcvalue = DecodeGetDstValue();
uint32_t rr = (extra >> 12) & 7;
if (extra & 0x8000) {
m68k_areg(rr) = srcvalue;
} else {
V_regs.ArgAddr.rga = &V_regs.regs[rr];
if (V_regs.CurDecOpY.v[0].ArgDat == 2) {
*V_regs.ArgAddr.rga =
(*V_regs.ArgAddr.rga & ~ 0xffff)
| ((srcvalue) & 0xffff);
} else if (V_regs.CurDecOpY.v[0].ArgDat < 2) {
*V_regs.ArgAddr.rga =
(*V_regs.ArgAddr.rga & ~ 0xff)
| ((srcvalue) & 0xff);
} else {
*V_regs.ArgAddr.rga = srcvalue;
}
}
}
}
}
#endif
#define uint32_t_lo(x) ((x) & 0x0000FFFF)
#define uint32_t_hi(x) (((x) >> 16) & 0x0000FFFF)
#if Use68020
struct uint64_t0 {
uint32_t hi;
uint32_t lo;
};
typedef struct uint64_t0 uint64_t0;
#endif
#if Use68020
LOCALPROC Ui6r_Negate(uint64_t0 *v)
{
v->hi = ~ v->hi;
v->lo = - v->lo;
if (v->lo == 0) {
v->hi++;
}
}
#endif
#if Use68020
LOCALFUNC bool reg_call Ui6r_IsZero(uint64_t0 *v)
{
return (v->hi == 0) && (v->lo == 0);
}
#endif
#if Use68020
LOCALFUNC bool reg_call Ui6r_IsNeg(uint64_t0 *v)
{
return ((int32_t)v->hi) < 0;
}
#endif
#if Use68020
LOCALPROC mul_unsigned(uint32_t src1, uint32_t src2, uint64_t0 *dst)
{
uint32_t src1_lo = uint32_t_lo(src1);
uint32_t src2_lo = uint32_t_lo(src2);
uint32_t src1_hi = uint32_t_hi(src1);
uint32_t src2_hi = uint32_t_hi(src2);
uint32_t r0 = src1_lo * src2_lo;
uint32_t r1 = src1_hi * src2_lo;
uint32_t r2 = src1_lo * src2_hi;
uint32_t r3 = src1_hi * src2_hi;
uint32_t ra1 = uint32_t_hi(r0) + uint32_t_lo(r1) + uint32_t_lo(r2);
dst->lo = (uint32_t_lo(ra1) << 16) | uint32_t_lo(r0);
dst->hi = uint32_t_hi(ra1) + uint32_t_hi(r1) + uint32_t_hi(r2) + r3;
}
#endif
#if Use68020
LOCALFUNC bool div_unsigned(uint64_t0 *src, uint32_t div,
uint32_t *quot, uint32_t *rem)
{
int i;
uint32_t q = 0;
uint32_t cbit = 0;
uint32_t src_hi = src->hi;
uint32_t src_lo = src->lo;
if (div <= src_hi) {
return true;
}
for (i = 0 ; i < 32 ; i++) {
cbit = src_hi & 0x80000000ul;
src_hi <<= 1;
if (src_lo & 0x80000000ul) {
src_hi++;
}
src_lo <<= 1;
q = q << 1;
if (cbit || div <= src_hi) {
q |= 1;
src_hi -= div;
}
}
*quot = q;
*rem = src_hi;
return false;
}
#endif
#if Use68020
LOCALIPROC DoCodeMulL(void)
{
/* MULU 0100110000mmmrrr 0rrr0s0000000rrr */
/* MULS 0100110000mmmrrr 0rrr1s0000000rrr */
uint64_t0 dst;
uint16_t extra = nextiword();
uint32_t r2 = (extra >> 12) & 7;
uint32_t dstvalue = m68k_dreg(r2);
uint32_t srcvalue = DecodeGetDstValue();
if (extra & 0x800) {
/* MULS.L - signed */
int32_t src1 = (int32_t)srcvalue;
int32_t src2 = (int32_t)dstvalue;
bool s1 = src1 < 0;
bool s2 = src2 < 0;
bool sr = s1 != s2;
/* ReportAbnormal("MULS.L"); */
/* used by Sys 7.5.5 boot extensions */
if (s1) {
src1 = - src1;
}
if (s2) {
src2 = - src2;
}
mul_unsigned((uint32_t)src1, (uint32_t)src2, &dst);
if (sr) {
Ui6r_Negate(&dst);
}
VFLG = CFLG = 0;
ZFLG = Bool2Bit(Ui6r_IsZero(&dst));
NFLG = Bool2Bit(Ui6r_IsNeg(&dst));
V_regs.LazyFlagKind = kLazyFlagsDefault;
if (extra & 0x400) {
m68k_dreg(extra & 7) = dst.hi;
} else {
if ((dst.lo & 0x80000000) != 0) {
if ((dst.hi & 0xffffffff) != 0xffffffff) {
VFLG = 1;
}
} else {
if (dst.hi != 0) {
VFLG = 1;
}
}
}
} else {
/* MULU.L - unsigned */
/* ReportAbnormal("MULU.U"); */
/* Used by various Apps */
mul_unsigned(srcvalue, dstvalue, &dst);
VFLG = CFLG = 0;
ZFLG = Bool2Bit(Ui6r_IsZero(&dst));
NFLG = Bool2Bit(Ui6r_IsNeg(&dst));
V_regs.LazyFlagKind = kLazyFlagsDefault;
if (extra & 0x400) {
m68k_dreg(extra & 7) = dst.hi;
} else {
if (dst.hi != 0) {
VFLG = 1;
}
}
}
m68k_dreg(r2) = dst.lo;
}
#endif
#if Use68020
LOCALIPROC DoCodeDivL(void)
{
/* DIVU 0100110001mmmrrr 0rrr0s0000000rrr */
/* DIVS 0100110001mmmrrr 0rrr1s0000000rrr */
/* ReportAbnormal("DIVS/DIVU long"); */
uint64_t0 v2;
uint32_t quot;
uint32_t rem;
uint16_t extra = nextiword();
uint32_t rDr = extra & 7;
uint32_t rDq = (extra >> 12) & 7;
uint32_t src = (uint32_t)(int32_t)DecodeGetDstValue();
if (src == 0) {
Exception(5);
#if m68k_logExceptions
dbglog_WriteNote("*** zero devide exception");
#endif
return;
}
if (0 != (extra & 0x0800)) {
/* signed variant */
bool sr;
bool s2;
bool s1 = ((int32_t)src < 0);
v2.lo = (int32_t)m68k_dreg(rDq);
if (extra & 0x0400) {
v2.hi = (int32_t)m68k_dreg(rDr);
} else {
v2.hi = ((int32_t)v2.lo) < 0 ? -1 : 0;
}
s2 = Ui6r_IsNeg(&v2);
sr = (s1 != s2);
if (s2) {
Ui6r_Negate(&v2);
}
if (s1) {
src = - src;
}
if (div_unsigned(&v2, src, &quot, &rem)
|| (sr ? quot > 0x80000000 : quot > 0x7fffffff))
{
NeedDefaultLazyAllFlags();
VFLG = NFLG = 1;
CFLG = 0;
} else {
if (sr) {
quot = - quot;
}
if (((int32_t)rem < 0) != s2) {
rem = - rem;
}
VFLG = CFLG = 0;
ZFLG = Bool2Bit(((int32_t)quot) == 0);
NFLG = Bool2Bit(((int32_t)quot) < 0);
V_regs.LazyFlagKind = kLazyFlagsDefault;
m68k_dreg(rDr) = rem;
m68k_dreg(rDq) = quot;
}
} else {
/* unsigned */
v2.lo = (uint32_t)m68k_dreg(rDq);
if (extra & 0x400) {
v2.hi = (uint32_t)m68k_dreg(rDr);
} else {
v2.hi = 0;
}
if (div_unsigned(&v2, src, &quot, &rem)) {
NeedDefaultLazyAllFlags();
VFLG = NFLG = 1;
CFLG = 0;
} else {
VFLG = CFLG = 0;
ZFLG = Bool2Bit(((int32_t)quot) == 0);
NFLG = Bool2Bit(((int32_t)quot) < 0);
V_regs.LazyFlagKind = kLazyFlagsDefault;
m68k_dreg(rDr) = rem;
m68k_dreg(rDq) = quot;
}
}
}
#endif
#if Use68020
LOCALIPROC DoMoveToControl(void)
{
if (0 == V_regs.s) {
DoPrivilegeViolation();
} else {
uint16_t src = nextiword_nm();
int regno = (src >> 12) & 0x0F;
uint32_t v = V_regs.regs[regno];
switch (src & 0x0FFF) {
case 0x0000:
V_regs.sfc = v & 7;
/* ReportAbnormal("DoMoveToControl: sfc"); */
/* happens on entering macsbug */
break;
case 0x0001:
V_regs.dfc = v & 7;
/* ReportAbnormal("DoMoveToControl: dfc"); */
break;
case 0x0002:
V_regs.cacr = v & 0x3;
/* ReportAbnormal("DoMoveToControl: cacr"); */
/* used by Sys 7.5.5 boot */
break;
case 0x0800:
V_regs.usp = v;
ReportAbnormalID(0x0113, "DoMoveToControl: usp");
break;
case 0x0801:
V_regs.vbr = v;
/* ReportAbnormal("DoMoveToControl: vbr"); */
/* happens on entering macsbug */
break;
case 0x0802:
V_regs.caar = v &0xfc;
/* ReportAbnormal("DoMoveToControl: caar"); */
/* happens on entering macsbug */
break;
case 0x0803:
V_regs.msp = v;
if (V_regs.m == 1) {
m68k_areg(7) = V_regs.msp;
}
/* ReportAbnormal("DoMoveToControl: msp"); */
/* happens on entering macsbug */
break;
case 0x0804:
V_regs.isp = v;
if (V_regs.m == 0) {
m68k_areg(7) = V_regs.isp;
}
ReportAbnormalID(0x0114, "DoMoveToControl: isp");
break;
default:
op_illg();
ReportAbnormalID(0x0115,
"DoMoveToControl: unknown reg");
break;
}
}
}
#endif
#if Use68020
LOCALIPROC DoMoveFromControl(void)
{
if (0 == V_regs.s) {
DoPrivilegeViolation();
} else {
uint32_t v;
uint16_t src = nextiword_nm();
int regno = (src >> 12) & 0x0F;
switch (src & 0x0FFF) {
case 0x0000:
v = V_regs.sfc;
/* ReportAbnormal("DoMoveFromControl: sfc"); */
/* happens on entering macsbug */
break;
case 0x0001:
v = V_regs.dfc;
/* ReportAbnormal("DoMoveFromControl: dfc"); */
/* happens on entering macsbug */
break;
case 0x0002:
v = V_regs.cacr;
/* ReportAbnormal("DoMoveFromControl: cacr"); */
/* used by Sys 7.5.5 boot */
break;
case 0x0800:
v = V_regs.usp;
ReportAbnormalID(0x0116, "DoMoveFromControl: usp");
break;
case 0x0801:
v = V_regs.vbr;
/* ReportAbnormal("DoMoveFromControl: vbr"); */
/* happens on entering macsbug */
break;
case 0x0802:
v = V_regs.caar;
/* ReportAbnormal("DoMoveFromControl: caar"); */
/* happens on entering macsbug */
break;
case 0x0803:
v = (V_regs.m == 1)
? m68k_areg(7)
: V_regs.msp;
/* ReportAbnormal("DoMoveFromControl: msp"); */
/* happens on entering macsbug */
break;
case 0x0804:
v = (V_regs.m == 0)
? m68k_areg(7)
: V_regs.isp;
ReportAbnormalID(0x0117, "DoMoveFromControl: isp");
break;
default:
v = 0;
ReportAbnormalID(0x0118,
"DoMoveFromControl: unknown reg");
op_illg();
break;
}
V_regs.regs[regno] = v;
}
}
#endif
#if Use68020
LOCALIPROC DoCodeBkpt(void)
{
/* BKPT 0100100001001rrr */
ReportAbnormalID(0x0119, "BKPT instruction");
op_illg();
}
#endif
#if Use68020
LOCALIPROC DoCodeRtd(void)
{
/* Rtd 0100111001110100 */
uint32_t NewPC = get_long(m68k_areg(7));
int32_t offs = nextiSWord();
/* ReportAbnormal("RTD"); */
/* used by Sys 7.5.5 boot */
m68k_areg(7) += (4 + offs);
m68k_setpc(NewPC);
}
#endif
#if Use68020
LOCALIPROC DoCodeLinkL(void)
{
/* Link.L 0100100000001rrr */
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
uint32_t *dstp = &V_regs.regs[dstreg];
CPTR stackp = m68k_areg(7);
ReportAbnormalID(0x011A, "Link.L");
stackp -= 4;
m68k_areg(7) = stackp; /* only matters if dstreg == 7 + 8 */
put_long(stackp, *dstp);
*dstp = stackp;
m68k_areg(7) += (int32_t)nextilong();
}
#endif
#if Use68020
LOCALPROC DoCodeTRAPcc_t(void)
{
ReportAbnormalID(0x011B, "TRAPcc trapping");
Exception(7);
/* pc pushed onto stack wrong */
}
#endif
#if Use68020
LOCALPROC DoCodeTRAPcc_f(void)
{
}
#endif
#if Use68020
LOCALIPROC DoCodeTRAPcc(void)
{
/* TRAPcc 0101cccc11111sss */
/* ReportAbnormal("TRAPcc"); */
switch (V_regs.CurDecOpY.v[1].ArgDat) {
case 2:
ReportAbnormalID(0x011C, "TRAPcc word data");
SkipiWord();
break;
case 3:
ReportAbnormalID(0x011D, "TRAPcc long data");
SkipiLong();
break;
case 4:
/* ReportAbnormal("TRAPcc no data"); */
/* no optional data */
break;
default:
ReportAbnormalID(0x011E, "TRAPcc illegal format");
op_illg();
break;
}
cctrue(DoCodeTRAPcc_t, DoCodeTRAPcc_f);
}
#endif
#if Use68020
LOCALIPROC DoCodePack(void)
{
uint32_t offs = nextiSWord();
uint32_t val = DecodeGetSrcValue();
ReportAbnormalID(0x011F, "PACK");
val += offs;
val = ((val >> 4) & 0xf0) | (val & 0xf);
DecodeSetDstValue(val);
}
#endif
#if Use68020
LOCALIPROC DoCodeUnpk(void)
{
uint32_t offs = nextiSWord();
uint32_t val = DecodeGetSrcValue();
ReportAbnormalID(0x0120, "UNPK");
val = (((val & 0xF0) << 4) | (val & 0x0F)) + offs;
DecodeSetDstValue(val);
}
#endif
#if Use68020
LOCALIPROC DoBitField(void)
{
uint32_t tmp;
uint32_t newtmp;
CPTR dsta;
uint32_t bf0;
uint8_t bf1;
uint32_t dstreg = V_regs.CurDecOpY.v[1].ArgDat;
uint16_t extra = nextiword();
uint32_t offset = ((extra & 0x0800) != 0)
? m68k_dreg((extra >> 6) & 7)
: ((extra >> 6) & 0x1f);
uint32_t width = ((extra & 0x0020) != 0)
? m68k_dreg(extra & 7)
: extra;
uint8_t bfa[5];
uint32_t offwid;
/* ReportAbnormal("Bit Field operator"); */
/* width = ((width - 1) & 0x1f) + 1; */ /* 0 -> 32 */
width &= 0x001F; /* except width == 0 really means 32 */
if (V_regs.CurDecOpY.v[0].AMd == 0) {
bf0 = m68k_dreg(dstreg);
offset &= 0x1f;
tmp = bf0;
if (0 != offset) {
tmp = (tmp << offset) | (tmp >> (32 - offset));
}
} else {
/*
V_regs.ArgKind == AKMemory,
otherwise illegal and don't get here
*/
dsta = DecodeDst();
dsta += Ui5rASR(offset, 3);
offset &= 7;
offwid = offset + ((width == 0) ? 32 : width);
/* if (offwid > 0) */ {
bf1 = get_byte(dsta);
bfa[0] = bf1;
tmp = ((uint32_t)bf1) << (24 + offset);
}
if (offwid > 8) {
bf1 = get_byte(dsta + 1);
bfa[1] = bf1;
tmp |= ((uint32_t)bf1) << (16 + offset);
}
if (offwid > 16) {
bf1 = get_byte(dsta + 2);
bfa[2] = bf1;
tmp |= ((uint32_t)bf1) << (8 + offset);
}
if (offwid > 24) {
bf1 = get_byte(dsta + 3);
bfa[3] = bf1;
tmp |= ((uint32_t)bf1) << (offset);
}
if (offwid > 32) {
bf1 = get_byte(dsta + 4);
bfa[4] = bf1;
tmp |= ((uint32_t)bf1) >> (8 - offset);
}
}
NFLG = Bool2Bit(((int32_t)tmp) < 0);
if (width != 0) {
tmp >>= (32 - width);
}
ZFLG = tmp == 0;
VFLG = 0;
CFLG = 0;
V_regs.LazyFlagKind = kLazyFlagsDefault;
newtmp = tmp;
switch (V_regs.CurDecOpY.v[0].ArgDat) {
case 0: /* BFTST */
/* do nothing */
break;
case 1: /* BFEXTU */
m68k_dreg((extra >> 12) & 7) = tmp;
break;
case 2: /* BFCHG */
newtmp = ~ newtmp;
if (width != 0) {
newtmp &= ((1 << width) - 1);
}
break;
case 3: /* BFEXTS */
if (NFLG != 0) {
m68k_dreg((extra >> 12) & 7) = tmp
| ((width == 0) ? 0 : (-1 << width));
} else {
m68k_dreg((extra >> 12) & 7) = tmp;
}
break;
case 4: /* BFCLR */
newtmp = 0;
break;
case 5: /* BFFFO */
{
uint32_t mask = 1 << ((width == 0) ? 31 : (width - 1));
uint32_t i = offset;
while ((0 != mask) && (0 == (tmp & mask))) {
mask >>= 1;
i++;
}
m68k_dreg((extra >> 12) & 7) = i;
}
break;
case 6: /* BFSET */
newtmp = (width == 0) ? ~ 0 : ((1 << width) - 1);
break;
case 7: /* BFINS */
newtmp = m68k_dreg((extra >> 12) & 7);
if (width != 0) {
newtmp &= ((1 << width) - 1);
}
break;
}
if (newtmp != tmp) {
if (width != 0) {
newtmp <<= (32 - width);
}
if (V_regs.CurDecOpY.v[0].AMd == 0) {
uint32_t mask = ~ 0;
if (width != 0) {
mask <<= (32 - width);
}
if (0 != offset) {
newtmp = (newtmp >> offset) | (newtmp << (32 - offset));
mask = (mask >> offset) | (mask << (32 - offset));
}
bf0 = (bf0 & ~ mask) | (newtmp);
m68k_dreg(dstreg) = bf0;
} else {
/* if (offwid > 0) */ {
uint8_t mask = ~ (0xFF >> offset);
bf1 = newtmp >> (24 + offset);
if (offwid < 8) {
mask |= (0xFF >> offwid);
}
if (mask != 0) {
bf1 |= bfa[0] & mask;
}
put_byte(dsta + 0, bf1);
}
if (offwid > 8) {
bf1 = newtmp >> (16 + offset);
if (offwid < 16) {
bf1 |= (bfa[1] & (0xFF >> (offwid - 8)));
}
put_byte(dsta + 1, bf1);
}
if (offwid > 16) {
bf1 = newtmp >> (8 + offset);
if (offwid < 24) {
bf1 |= (bfa[2] & (0xFF >> (offwid - 16)));
}
put_byte(dsta + 2, bf1);
}
if (offwid > 24) {
bf1 = newtmp >> (offset);
if (offwid < 32) {
bf1 |= (bfa[3] & (0xFF >> (offwid - 24)));
}
put_byte(dsta + 3, bf1);
}
if (offwid > 32) {
bf1 = newtmp << (8 - offset);
bf1 |= (bfa[4] & (0xFF >> (offwid - 32)));
put_byte(dsta + 4, bf1);
}
}
}
}
#endif
#if EmMMU | EmFPU
LOCALFUNC bool DecodeModeRegister(uint32_t sz)
{
bool IsOk;
uint16_t Dat = V_regs.CurDecOpY.v[0].ArgDat;
uint16_t themode = (Dat >> 3) & 7;
uint16_t thereg = Dat & 7;
switch (themode) {
case 0 :
V_regs.ArgKind = AKRegister;
V_regs.ArgAddr.rga = &V_regs.regs[thereg];
IsOk = true;
break;
case 1 :
V_regs.ArgKind = AKRegister;
V_regs.ArgAddr.rga = &V_regs.regs[thereg + 8];
IsOk = true;
break;
case 2 :
V_regs.ArgKind = AKMemory;
V_regs.ArgAddr.mem = m68k_areg(thereg);
IsOk = true;
break;
case 3 :
V_regs.ArgKind = AKMemory;
V_regs.ArgAddr.mem = m68k_areg(thereg);
if ((thereg == 7) && (sz == 1)) {
m68k_areg(thereg) += 2;
} else {
m68k_areg(thereg) += sz;
}
IsOk = true;
break;
case 4 :
V_regs.ArgKind = AKMemory;
if ((thereg == 7) && (sz == 1)) {
m68k_areg(thereg) -= 2;
} else {
m68k_areg(thereg) -= sz;
}
V_regs.ArgAddr.mem = m68k_areg(thereg);
IsOk = true;
break;
case 5 :
V_regs.ArgKind = AKMemory;
V_regs.ArgAddr.mem = m68k_areg(thereg)
+ nextiSWord();
IsOk = true;
break;
case 6 :
V_regs.ArgKind = AKMemory;
V_regs.ArgAddr.mem = get_disp_ea(m68k_areg(thereg));
IsOk = true;
break;
case 7 :
switch (thereg) {
case 0 :
V_regs.ArgKind = AKMemory;
V_regs.ArgAddr.mem = nextiSWord();
IsOk = true;
break;
case 1 :
V_regs.ArgKind = AKMemory;
V_regs.ArgAddr.mem = nextilong();
IsOk = true;
break;
case 2 :
V_regs.ArgKind = AKMemory;
V_regs.ArgAddr.mem = m68k_getpc();
V_regs.ArgAddr.mem += nextiSWord();
IsOk = true;
break;
case 3 :
V_regs.ArgKind = AKMemory;
V_regs.ArgAddr.mem = get_disp_ea(m68k_getpc());
IsOk = true;
break;
case 4 :
V_regs.ArgKind = AKMemory;
V_regs.ArgAddr.mem = m68k_getpc();
if (sz == 1) {
++V_regs.ArgAddr.mem;
}
m68k_setpc(V_regs.ArgAddr.mem + sz);
IsOk = true;
break;
default:
IsOk = false;
break;
}
break;
default:
IsOk = false;
break;
}
return IsOk;
}
#endif
#if EmMMU | EmFPU
LOCALFUNC uint32_t GetArgValueL(void)
{
uint32_t v;
if (AKMemory == V_regs.ArgKind) {
v = get_long(V_regs.ArgAddr.mem);
} else {
/* must be AKRegister */
v = uint32_t_FromSLong(*V_regs.ArgAddr.rga);
}
return v;
}
#endif
#if EmMMU | EmFPU
LOCALFUNC uint32_t GetArgValueW(void)
{
uint32_t v;
if (AKMemory == V_regs.ArgKind) {
v = get_word(V_regs.ArgAddr.mem);
} else {
/* must be AKRegister */
v = uint32_t_FromSWord(*V_regs.ArgAddr.rga);
}
return v;
}
#endif
#if EmMMU | EmFPU
LOCALFUNC uint32_t GetArgValueB(void)
{
uint32_t v;
if (AKMemory == V_regs.ArgKind) {
v = get_byte(V_regs.ArgAddr.mem);
} else {
/* must be AKRegister */
v = uint32_t_FromSByte(*V_regs.ArgAddr.rga);
}
return v;
}
#endif
#if EmMMU | EmFPU
LOCALPROC SetArgValueL(uint32_t v)
{
if (AKMemory == V_regs.ArgKind) {
put_long(V_regs.ArgAddr.mem, v);
} else {
/* must be AKRegister */
*V_regs.ArgAddr.rga = v;
}
}
#endif
#if EmMMU | EmFPU
LOCALPROC SetArgValueW(uint32_t v)
{
if (AKMemory == V_regs.ArgKind) {
put_word(V_regs.ArgAddr.mem, v);
} else {
/* must be AKRegister */
*V_regs.ArgAddr.rga =
(*V_regs.ArgAddr.rga & ~ 0xffff) | ((v) & 0xffff);
}
}
#endif
#if EmMMU | EmFPU
LOCALPROC SetArgValueB(uint32_t v)
{
if (AKMemory == V_regs.ArgKind) {
put_byte(V_regs.ArgAddr.mem, v);
} else {
/* must be AKRegister */
*V_regs.ArgAddr.rga =
(*V_regs.ArgAddr.rga & ~ 0xff) | ((v) & 0xff);
}
}
#endif
#if EmMMU
LOCALIPROC DoCodeMMU(void)
{
/*
Emulate enough of MMU for System 7.5.5 universal
to boot on Mac Plus 68020. There is one
spurious "PMOVE TC, (A0)".
And implement a few more PMOVE operations seen
when running Disk Copy 6.3.3 and MacsBug.
*/
uint16_t opcode = ((uint16_t)(V_regs.CurDecOpY.v[0].AMd) << 8)
| V_regs.CurDecOpY.v[0].ArgDat;
if (opcode == 0xF010) {
uint16_t ew = (int)nextiword_nm();
if (ew == 0x4200) {
/* PMOVE TC, (A0) */
/* fprintf(stderr, "0xF010 0x4200\n"); */
if (DecodeModeRegister(4)) {
SetArgValueL(0);
return;
}
} else if ((ew == 0x4E00) || (ew == 0x4A00)) {
/* PMOVE CRP, (A0) and PMOVE SRP, (A0) */
/* fprintf(stderr, "0xF010 %x\n", ew); */
if (DecodeModeRegister(4)) {
SetArgValueL(0x7FFF0001);
V_regs.ArgAddr.mem += 4;
SetArgValueL(0);
return;
}
} else if (ew == 0x6200) {
/* PMOVE MMUSR, (A0) */
/* fprintf(stderr, "0xF010 %x\n", ew); */
if (DecodeModeRegister(2)) {
SetArgValueW(0);
return;
}
}
/* fprintf(stderr, "extensions %x\n", ew); */
BackupPC();
}
/* fprintf(stderr, "opcode %x\n", (int)opcode); */
ReportAbnormalID(0x0121, "MMU op");
DoCodeFdefault();
}
#endif
#if EmFPU
#include "FPMATHEM.h"
#include "FPCPEMDV.h"
#endif
#if HaveGlbReg
LOCALPROC Em_Swap(void)
{
#ifdef r_pc_p
{
uint8_t * t = g_pc_p;
g_pc_p = regs.pc_p;
regs.pc_p = t;
}
#endif
#ifdef r_MaxCyclesToGo
{
int32_t t = g_MaxCyclesToGo;
g_MaxCyclesToGo = regs.MaxCyclesToGo;
regs.MaxCyclesToGo = t;
}
#endif
#ifdef r_pc_pHi
{
uint8_t * t = g_pc_pHi;
g_pc_pHi = regs.pc_pHi;
regs.pc_pHi = t;
}
#endif
#ifdef r_regs
{
struct regstruct *t = g_regs;
g_regs = regs.save_regs;
regs.save_regs = t;
}
#endif
}
#endif
#if HaveGlbReg
#define Em_Enter Em_Swap
#else
#define Em_Enter()
#endif
#if HaveGlbReg
#define Em_Exit Em_Swap
#else
#define Em_Exit()
#endif
#if HaveGlbReg
LOCALFUNC bool LocalMemAccessNtfy(ATTep pT)
{
bool v;
Em_Exit();
v = MemAccessNtfy(pT);
Em_Enter();
return v;
}
#else
#define LocalMemAccessNtfy MemAccessNtfy
#endif
#if HaveGlbReg
LOCALFUNC uint32_t LocalMMDV_Access(ATTep p, uint32_t Data,
bool WriteMem, bool ByteSize, CPTR addr)
{
uint32_t v;
Em_Exit();
v = MMDV_Access(p, Data, WriteMem, ByteSize, addr);
Em_Enter();
return v;
}
#else
#define LocalMMDV_Access MMDV_Access
#endif
LOCALPROC local_customreset(void)
{
Em_Exit();
customreset();
Em_Enter();
}
LOCALFUNC ATTep LocalFindATTel(CPTR addr)
{
ATTep prev;
ATTep p;
p = V_regs.HeadATTel;
if ((addr & p->cmpmask) != p->cmpvalu) {
do {
prev = p;
p = p->Next;
} while ((addr & p->cmpmask) != p->cmpvalu);
{
ATTep next = p->Next;
if (nullpr == next) {
/* don't move the end guard */
} else {
/* move to first */
prev->Next = next;
p->Next = V_regs.HeadATTel;
V_regs.HeadATTel = p;
}
}
}
return p;
}
LOCALPROC SetUpMATC(
MATCp CurMATC,
ATTep p)
{
CurMATC->cmpmask = p->cmpmask;
CurMATC->usemask = p->usemask;
CurMATC->cmpvalu = p->cmpvalu;
CurMATC->usebase = p->usebase;
}
LOCALFUNC uint32_t reg_call get_byte_ext(CPTR addr)
{
ATTep p;
uint8_t * m;
uint32_t AccFlags;
uint32_t Data;
Label_Retry:
p = LocalFindATTel(addr);
AccFlags = p->Access;
if (0 != (AccFlags & kATTA_readreadymask)) {
SetUpMATC(&V_regs.MATCrdB, p);
m = p->usebase + (addr & p->usemask);
Data = *m;
} else if (0 != (AccFlags & kATTA_mmdvmask)) {
Data = LocalMMDV_Access(p, 0, false, true, addr);
} else if (0 != (AccFlags & kATTA_ntfymask)) {
if (LocalMemAccessNtfy(p)) {
goto Label_Retry;
} else {
Data = 0; /* fail */
}
} else {
Data = 0; /* fail */
}
return uint32_t_FromSByte(Data);
}
LOCALPROC reg_call put_byte_ext(CPTR addr, uint32_t b)
{
ATTep p;
uint8_t * m;
uint32_t AccFlags;
Label_Retry:
p = LocalFindATTel(addr);
AccFlags = p->Access;
if (0 != (AccFlags & kATTA_writereadymask)) {
SetUpMATC(&V_regs.MATCwrB, p);
m = p->usebase + (addr & p->usemask);
*m = b;
} else if (0 != (AccFlags & kATTA_mmdvmask)) {
(void) LocalMMDV_Access(p, b & 0x00FF,
true, true, addr);
} else if (0 != (AccFlags & kATTA_ntfymask)) {
if (LocalMemAccessNtfy(p)) {
goto Label_Retry;
} else {
/* fail */
}
} else {
/* fail */
}
}
LOCALFUNC uint32_t reg_call get_word_ext(CPTR addr)
{
uint32_t Data;
if (0 != (addr & 0x01)) {
uint32_t hi = get_byte(addr);
uint32_t lo = get_byte(addr + 1);
Data = ((hi << 8) & 0x0000FF00)
| (lo & 0x000000FF);
} else {
ATTep p;
uint8_t * m;
uint32_t AccFlags;
Label_Retry:
p = LocalFindATTel(addr);
AccFlags = p->Access;
if (0 != (AccFlags & kATTA_readreadymask)) {
SetUpMATC(&V_regs.MATCrdW, p);
V_regs.MATCrdW.cmpmask |= 0x01;
m = p->usebase + (addr & p->usemask);
Data = do_get_mem_word(m);
} else if (0 != (AccFlags & kATTA_mmdvmask)) {
Data = LocalMMDV_Access(p, 0, false, false, addr);
} else if (0 != (AccFlags & kATTA_ntfymask)) {
if (LocalMemAccessNtfy(p)) {
goto Label_Retry;
} else {
Data = 0; /* fail */
}
} else {
Data = 0; /* fail */
}
}
return uint32_t_FromSWord(Data);
}
LOCALPROC reg_call put_word_ext(CPTR addr, uint32_t w)
{
if (0 != (addr & 0x01)) {
put_byte(addr, w >> 8);
put_byte(addr + 1, w);
} else {
ATTep p;
uint8_t * m;
uint32_t AccFlags;
Label_Retry:
p = LocalFindATTel(addr);
AccFlags = p->Access;
if (0 != (AccFlags & kATTA_writereadymask)) {
SetUpMATC(&V_regs.MATCwrW, p);
V_regs.MATCwrW.cmpmask |= 0x01;
m = p->usebase + (addr & p->usemask);
do_put_mem_word(m, w);
} else if (0 != (AccFlags & kATTA_mmdvmask)) {
(void) LocalMMDV_Access(p, w & 0x0000FFFF,
true, false, addr);
} else if (0 != (AccFlags & kATTA_ntfymask)) {
if (LocalMemAccessNtfy(p)) {
goto Label_Retry;
} else {
/* fail */
}
} else {
/* fail */
}
}
}
LOCALFUNC uint32_t reg_call get_long_misaligned_ext(CPTR addr)
{
uint32_t hi = get_word(addr);
uint32_t lo = get_word(addr + 2);
uint32_t Data = ((hi << 16) & 0xFFFF0000)
| (lo & 0x0000FFFF);
return uint32_t_FromSLong(Data);
}
LOCALPROC reg_call put_long_misaligned_ext(CPTR addr, uint32_t l)
{
put_word(addr, l >> 16);
put_word(addr + 2, l);
}
#if FasterAlignedL
LOCALFUNC uint32_t reg_call get_long_ext(CPTR addr)
{
uint32_t Data;
if (0 != (addr & 0x03)) {
uint32_t hi = get_word(addr);
uint32_t lo = get_word(addr + 2);
Data = ((hi << 16) & 0xFFFF0000)
| (lo & 0x0000FFFF);
} else {
ATTep p;
uint8_t * m;
uint32_t AccFlags;
Label_Retry:
p = LocalFindATTel(addr);
AccFlags = p->Access;
if (0 != (AccFlags & kATTA_readreadymask)) {
SetUpMATC(&V_regs.MATCrdL, p);
V_regs.MATCrdL.cmpmask |= 0x03;
m = p->usebase + (addr & p->usemask);
Data = do_get_mem_long(m);
} else if (0 != (AccFlags & kATTA_mmdvmask)) {
uint32_t hi = LocalMMDV_Access(p, 0,
false, false, addr);
uint32_t lo = LocalMMDV_Access(p, 0,
false, false, addr + 2);
Data = ((hi << 16) & 0xFFFF0000)
| (lo & 0x0000FFFF);
} else if (0 != (AccFlags & kATTA_ntfymask)) {
if (LocalMemAccessNtfy(p)) {
goto Label_Retry;
} else {
Data = 0; /* fail */
}
} else {
Data = 0; /* fail */
}
}
return uint32_t_FromSLong(Data);
}
#endif
#if FasterAlignedL
LOCALPROC reg_call put_long_ext(CPTR addr, uint32_t l)
{
if (0 != (addr & 0x03)) {
put_word(addr, l >> 16);
put_word(addr + 2, l);
} else {
ATTep p;
uint8_t * m;
uint32_t AccFlags;
Label_Retry:
p = LocalFindATTel(addr);
AccFlags = p->Access;
if (0 != (AccFlags & kATTA_writereadymask)) {
SetUpMATC(&V_regs.MATCwrL, p);
V_regs.MATCwrL.cmpmask |= 0x03;
m = p->usebase + (addr & p->usemask);
do_put_mem_long(m, l);
} else if (0 != (AccFlags & kATTA_mmdvmask)) {
(void) LocalMMDV_Access(p, (l >> 16) & 0x0000FFFF,
true, false, addr);
(void) LocalMMDV_Access(p, l & 0x0000FFFF,
true, false, addr + 2);
} else if (0 != (AccFlags & kATTA_ntfymask)) {
if (LocalMemAccessNtfy(p)) {
goto Label_Retry;
} else {
/* fail */
}
} else {
/* fail */
}
}
}
#endif
LOCALPROC Recalc_PC_Block(void)
{
ATTep p;
CPTR curpc = m68k_getpc();
Label_Retry:
p = LocalFindATTel(curpc);
if (cond_rare(0 == (p->Access & kATTA_readreadymask))) {
if (0 != (p->Access & kATTA_ntfymask)) {
if (LocalMemAccessNtfy(p)) {
goto Label_Retry;
}
}
/* in trouble if get here */
#if ExtraAbnormalReports
ReportAbnormalID(0x0122, "Recalc_PC_Block fails");
/* happens on Restart */
#endif
V_regs.pc_pLo = V_regs.fakeword;
V_pc_p = V_regs.pc_pLo;
V_pc_pHi = V_regs.pc_pLo + 2;
V_regs.pc = curpc;
} else {
uint32_t m2 = p->usemask & ~ p->cmpmask;
m2 = m2 & ~ (m2 + 1);
V_pc_p = p->usebase + (curpc & p->usemask);
V_regs.pc_pLo = V_pc_p - (curpc & m2);
V_pc_pHi = V_regs.pc_pLo + m2 + 1;
V_regs.pc = curpc - (V_pc_p - V_regs.pc_pLo);
}
}
LOCALFUNC uint32_t reg_call Recalc_PC_BlockReturnUi5r(uint32_t v)
{
/*
Used to prevent compiler from saving
register on the stack in calling
functions, when Recalc_PC_Block isn't being called.
*/
Recalc_PC_Block();
return v;
}
LOCALFUNC uint32_t nextilong_ext(void)
{
uint32_t r;
V_pc_p -= 4;
{
uint32_t hi = nextiword();
uint32_t lo = nextiword();
r = ((hi << 16) & 0xFFFF0000)
| (lo & 0x0000FFFF);
}
return r;
}
LOCALPROC DoCheckExternalInterruptPending(void)
{
uint8_t level = *V_regs.fIPL;
if ((level > V_regs.intmask) || (level == 7)) {
#if WantCloserCyc
V_MaxCyclesToGo -=
(44 * kCycleScale + 5 * RdAvgXtraCyc + 3 * WrAvgXtraCyc);
#endif
Exception(24 + level);
V_regs.intmask = level;
}
}
LOCALPROC do_trace(void)
{
V_regs.TracePending = true;
NeedToGetOut();
}
GLOBALPROC m68k_go_nCycles(uint32_t n)
{
Em_Enter();
V_MaxCyclesToGo += (n + V_regs.ResidualCycles);
while (V_MaxCyclesToGo > 0) {
#if 0
if (V_regs.ResetPending) {
m68k_DoReset();
}
#endif
if (V_regs.TracePending) {
#if WantCloserCyc
V_MaxCyclesToGo -= (34 * kCycleScale
+ 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc);
#endif
Exception(9);
}
if (V_regs.ExternalInterruptPending) {
V_regs.ExternalInterruptPending = false;
DoCheckExternalInterruptPending();
}
if (V_regs.t1 != 0) {
do_trace();
}
m68k_go_MaxCycles();
V_MaxCyclesToGo += V_regs.MoreCyclesToGo;
V_regs.MoreCyclesToGo = 0;
}
V_regs.ResidualCycles = V_MaxCyclesToGo;
V_MaxCyclesToGo = 0;
Em_Exit();
}
GLOBALFUNC int32_t GetCyclesRemaining(void)
{
int32_t v;
Em_Enter();
v = V_regs.MoreCyclesToGo + V_MaxCyclesToGo;
Em_Exit();
return v;
}
GLOBALPROC SetCyclesRemaining(int32_t n)
{
Em_Enter();
if (V_MaxCyclesToGo >= n) {
V_regs.MoreCyclesToGo = 0;
V_MaxCyclesToGo = n;
} else {
V_regs.MoreCyclesToGo = n - V_MaxCyclesToGo;
}
Em_Exit();
}
GLOBALFUNC ATTep FindATTel(CPTR addr)
{
ATTep v;
Em_Enter();
v = LocalFindATTel(addr);
Em_Exit();
return v;
}
GLOBALFUNC uint8_t get_vm_byte(CPTR addr)
{
uint8_t v;
Em_Enter();
v = (uint8_t) get_byte(addr);
Em_Exit();
return v;
}
GLOBALFUNC uint16_t get_vm_word(CPTR addr)
{
uint16_t v;
Em_Enter();
v = (uint16_t) get_word(addr);
Em_Exit();
return v;
}
GLOBALFUNC uint32_t get_vm_long(CPTR addr)
{
uint32_t v;
Em_Enter();
v = (uint32_t) get_long(addr);
Em_Exit();
return v;
}
GLOBALPROC put_vm_byte(CPTR addr, uint8_t b)
{
Em_Enter();
put_byte(addr, uint32_t_FromSByte(b));
Em_Exit();
}
GLOBALPROC put_vm_word(CPTR addr, uint16_t w)
{
Em_Enter();
put_word(addr, uint32_t_FromSWord(w));
Em_Exit();
}
GLOBALPROC put_vm_long(CPTR addr, uint32_t l)
{
Em_Enter();
put_long(addr, uint32_t_FromSLong(l));
Em_Exit();
}
GLOBALPROC SetHeadATTel(ATTep p)
{
Em_Enter();
V_regs.MATCrdB.cmpmask = 0;
V_regs.MATCrdB.cmpvalu = 0xFFFFFFFF;
V_regs.MATCwrB.cmpmask = 0;
V_regs.MATCwrB.cmpvalu = 0xFFFFFFFF;
V_regs.MATCrdW.cmpmask = 0;
V_regs.MATCrdW.cmpvalu = 0xFFFFFFFF;
V_regs.MATCwrW.cmpmask = 0;
V_regs.MATCwrW.cmpvalu = 0xFFFFFFFF;
#if FasterAlignedL
V_regs.MATCrdL.cmpmask = 0;
V_regs.MATCrdL.cmpvalu = 0xFFFFFFFF;
V_regs.MATCwrL.cmpmask = 0;
V_regs.MATCwrL.cmpvalu = 0xFFFFFFFF;
#endif
/* force Recalc_PC_Block soon */
V_regs.pc = m68k_getpc();
V_regs.pc_pLo = V_pc_p;
V_pc_pHi = V_regs.pc_pLo + 2;
V_regs.HeadATTel = p;
Em_Exit();
}
GLOBALPROC DiskInsertedPsuedoException(CPTR newpc, uint32_t data)
{
Em_Enter();
ExceptionTo(newpc
#if Use68020
, 0
#endif
);
m68k_areg(7) -= 4;
put_long(m68k_areg(7), data);
Em_Exit();
}
GLOBALPROC m68k_IPLchangeNtfy(void)
{
Em_Enter();
{
uint8_t level = *V_regs.fIPL;
if ((level > V_regs.intmask) || (level == 7)) {
SetExternalInterruptPending();
}
}
Em_Exit();
}
#if WantDumpTable
LOCALPROC InitDumpTable(void)
{
int32_t i;
for (i = 0; i < kNumIKinds; ++i) {
DumpTable[i] = 0;
}
}
LOCALPROC DumpATable(uint32_t *p, uint32_t n)
{
int32_t i;
for (i = 0; i < n; ++i) {
dbglog_writeNum(p[i]);
dbglog_writeReturn();
}
}
EXPORTPROC DoDumpTable(void);
GLOBALPROC DoDumpTable(void)
{
DumpATable(DumpTable, kNumIKinds);
}
#endif
GLOBALPROC m68k_reset(void)
{
Em_Enter();
#if WantDumpTable
InitDumpTable();
#endif
V_MaxCyclesToGo = 0;
V_regs.MoreCyclesToGo = 0;
V_regs.ResidualCycles = 0;
V_pc_p = (uint8_t *)nullpr;
V_pc_pHi = (uint8_t *)nullpr;
V_regs.pc_pLo = (uint8_t *)nullpr;
do_put_mem_word(V_regs.fakeword, 0x4AFC);
/* illegal instruction opcode */
#if 0
V_regs.ResetPending = true;
NeedToGetOut();
#else
/* Sets the MC68000 reset jump vector... */
m68k_setpc(get_long(0x00000004));
/* Sets the initial stack vector... */
m68k_areg(7) = get_long(0x00000000);
V_regs.s = 1;
#if Use68020
V_regs.m = 0;
V_regs.t0 = 0;
#endif
V_regs.t1 = 0;
ZFLG = CFLG = NFLG = VFLG = 0;
V_regs.LazyFlagKind = kLazyFlagsDefault;
V_regs.LazyXFlagKind = kLazyFlagsDefault;
V_regs.ExternalInterruptPending = false;
V_regs.TracePending = false;
V_regs.intmask = 7;
#if Use68020
V_regs.sfc = 0;
V_regs.dfc = 0;
V_regs.vbr = 0;
V_regs.cacr = 0;
V_regs.caar = 0;
#endif
#endif
Em_Exit();
}
#if SmallGlobals
GLOBALPROC MINEM68K_ReserveAlloc(void)
{
ReserveAllocOneBlock((uint8_t * *)&regs.disp_table,
disp_table_sz * 8, 6, false);
}
#endif
GLOBALPROC MINEM68K_Init(
uint8_t *fIPL)
{
regs.fIPL = fIPL;
#ifdef r_regs
regs.save_regs = &regs;
#endif
M68KITAB_setup(regs.disp_table);
}