minivmac4ios/Mini vMac/mnvm_core/MINEM68K.c

1 line
184 KiB
C
Raw Normal View History

/* 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 "MYOSGLUE.h" #include "ENDIANAC.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #include "M68KITAB.h" #if WantDisasm #include "DISAM68K.h" #endif #endif #include "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 { ui5r cmpmask; ui5r cmpvalu; ui5r usemask; ui3p usebase; }; typedef struct MATCr MATCr; typedef MATCr *MATCp; #ifndef USE_PCLIMIT #define USE_PCLIMIT 1 #endif #define AKMemory 0 #define AKRegister 1 union ArgAddrT { ui5r mem; ui5r *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 (my_reg_call *ArgSetDstP)(ui5r 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 { ui5r regs[16]; /* Data and Address registers */ ui3p pc_p; ui3p pc_pHi; si5rr MaxCyclesToGo; #if WantCloserCyc DecOpR *CurDecOp; #endif DecOpYR CurDecOpY; ui3r LazyFlagKind; ui3r LazyXFlagKind; #if UseLazyZ ui3r LazyFlagZSavedKind; #endif ui5r LazyFlagArgSrc; ui5r LazyFlagArgDst; ui5r LazyXFlagArgSrc; ui5r LazyXFlagArgDst; ArgAddrT ArgAddr; ArgSetDstP ArgSetDst; ui5b SrcVal; ui3p pc_pLo; ui5r pc; /* Program Counter */ MATCr MATCrdB; MATCr MATCwrB; MATCr MATCrdW; MATCr MATCwrW; #if FasterAlignedL MATCr MATCrdL; MATCr MATCwrL; #endif ATTep HeadATTel; si5r MoreCyclesToGo; si5r ResidualCycles; ui3b fakeword[2]; /* Status Register */ ui5r 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: eXte