Annotation of hatari/src/m68000.c, revision 1.1.1.25

1.1       root        1: /*
1.1.1.6   root        2:   Hatari - m68000.c
1.1       root        3: 
1.1.1.20  root        4:   This file is distributed under the GNU General Public License, version 2
                      5:   or at your option any later version. Read the file gpl.txt for details.
1.1.1.6   root        6: 
                      7:   These routines originally (in WinSTon) handled exceptions as well as some
1.1.1.5   root        8:   few OpCode's such as Line-F and Line-A. In Hatari it has mainly become a
                      9:   wrapper between the WinSTon sources and the UAE CPU code.
1.1       root       10: */
1.1.1.12  root       11: 
                     12: /* 2007/03/xx  [NP]    Possibility to add several wait states for the same instruction in              */
                     13: /*                     M68000_WaitState (e.g. clr.b $fa1b.w in Decade Demo Menu).                      */
                     14: /* 2007/04/14  [NP]    Add support for instruction pairing in M68000_AddCycles, using OpcodeFamily and */
                     15: /*                     LastOpcodeFamily (No Cooper Loader, Oh Crickey ... Hidden Screen).              */
                     16: /* 2007/04/24  [NP]    Add pairing for BCLR/Bcc.                                                       */
                     17: /* 2007/09/29  [NP]    Use the new int.c and INT_CONVERT_TO_INTERNAL.                                  */
                     18: /* 2007/11/26  [NP]    We set BusErrorPC in m68k_run_1 instead of M68000_BusError, else the BusErrorPC */
                     19: /*                     will not point to the opcode that generated the bus error.                      */
                     20: /*                     In M68000_BusError, if we have 'move.l $0,$24', we need to generate a bus error */
                     21: /*                     for the read, not for the write that should occur after (TransBeauce 2 Demo).   */
                     22: /* 2008/01/07  [NP]    Function 'M68000_InitPairing' and 'PairingArray' as a lookup table for fast     */
                     23: /*                     determination of valid pairing combinations (replace lots of 'if' tests in      */
                     24: /*                     m68000.h).                                                                      */
                     25: /* 2008/01/25  [NP]    Add pairing for LSR/MOVE (and all other bit shifting instr) (Anomaly Demo Intro)*/
                     26: /* 2008/02/02  [NP]    Add pairing for CMP/Bcc (Level 16 Fullscreen (1988)).                           */
                     27: /* 2008/02/08  [NP]    Add pairing for LSL/LEA (and all other bit shifting instr) (TVI 2 - The Year    */
                     28: /*                     After Demo).                                                                    */
                     29: /* 2008/02/11  [NP]    Add pairing for MULS/MOVEA (Delirious Demo IV Loader).                          */
                     30: /* 2008/01/25  [NP]    Add pairing for LSR/MOVEA (and all other bit shifting instr) (Decade Demo Reset)*/
1.1.1.13  root       31: /* 2008/02/16  [NP]    Add pairing for MULS/DIVS (fixes e605 demo part 3).                             */
1.1.1.12  root       32: /* 2008/03/08  [NP]    In M68000_Exception, we need to know if the exception was triggered by an MFP   */
                     33: /*                     interrupt or by a video interrupt. In the case MFP vector base was changed in   */
                     34: /*                     fffa17 to an other value than the default $40, testing exceptionNr is not enough*/
                     35: /*                     to correctly process the exception. For example, if vector base is set to $10   */
                     36: /*                     then MFP Timer A will call vector stored at address $74, which would be wrongly */
                     37: /*                     interpreted as a level 5 int (which doesn't exist on Atari and will cause an    */
1.1.1.13  root       38: /*                     assert to fail in intlevel()). We use InterruptSource to correctly recognize the*/
1.1.1.12  root       39: /*                     MFP interrupts (fix 'Toki' end part fullscreen which sets vector base to $10).  */
1.1.1.13  root       40: /* 2008/04/14  [NP]    Add pairing for BTST/Bcc (eg btst #7,d0 + bne.s label  (with branch taken)).    */
                     41: /* 2008/04/15  [NP]    As tested on a real STF :                                                       */
                     42: /*                             - MUL/DIV can pair (but DIV/MUL can't)                                  */
                     43: /*                                     (eg mulu d0,d0 + divs d1,d1 with d0=0 and d1=1)                 */
                     44: /*                             - MUL/MOVE can pair, but not DIV/MOVE                                   */
                     45: /*                             - EXG/MOVE can pair (eg exg d3,d4 + move.l 0(a3,d1.w),a4)               */
                     46: /*                             - MOVE/DBcc can't pair                                                  */
                     47: /* 2008/04/16  [NP]    Functions 'M68000_InitPairing_BitShift' to ease code maintenance.               */
                     48: /*                     Tested on STF : add pairing between bit shift instr and ADD/SUB/OR/AND/EOR/NOT  */
                     49: /*                     CLR/NEG (certainly some more possible, haven't tested everything)               */
                     50: /*                     (fixes lsr.w #4,d4 + add.b $f0(a4,d4),d7 used in Zoolook part of ULM New Year). */
                     51: /* 2008/07/08  [NP]    Add pairing between bit shift instr and ADDX/SUBX/ABCD/SBCD (fixes lsl.l #1,d0  */
                     52: /*                     + abcd d1,d1 used in Dragonnels - Rainbow Wall).                                */
                     53: /* 2008/10/05  [NP]    Pass the 'ExceptionSource' parameter to Exception() in uae-cpu/newcpu.c         */
1.1.1.16  root       54: /* 2010/05/07  [NP]    Add pairing for ADD/MOVE ; such pairing should only be possible when combined   */
                     55: /*                     with d8(an,ix) address mode (eg: add.l (a5,d1.w),d0 + move.b 7(a5,d1.w),d5)     */
                     56: /*                     (fixes Sommarhack 2010 Invitation by DHS).                                      */
1.1.1.17  root       57: /* 2010/11/07  [NP]    Add pairing between bit shift instr and JMP (fixes lsl.w #2,d0 + jmp 2(pc,d0)   */
                     58: /*                     used in Fullparts by Hemoroids).                                                */
1.1.1.18  root       59: /* 2011/12/11  [NP]    Add pairing between MUL and JSR (fixes muls #52,d2 + jsr 0(a1,d2.w) used in     */
1.1.1.21  root       60: /*                     Lemmings Compilation 40's Intro).                                               */
                     61: /* 2014/05/07  [NP]    In M68000_WaitEClock, use CyclesGlobalClockCounter instead of the VBL video     */
                     62: /*                     counter (else for a given position in a VBL we would always get the same value  */
                     63: /*                     for the E clock).                                                               */
1.1.1.22  root       64: /* 2015/02/01  [NP]    When using the new WinUAE's cpu, don't handle MFP/DSP interrupts by calling     */
                     65: /*                     directly Exception(), we must set bit 6 in pendingInterrupts and use the IACK   */
                     66: /*                     sequence to get the exception's vector number.                                  */
                     67: /* 2015/02/05  [NP]    For the new WinUAE's cpu, don't use ExceptionSource anymore when calling        */
                     68: /*                     Exception().                                                                    */
                     69: /* 2015/02/11  [NP]    Replace BusErrorPC by regs.instruction_pc, to get similar code to WinUAE's cpu  */
1.1.1.23  root       70: /* 2015/10/08  [NP]    Add M68000_AddCycles_CE() to handle cycles when running with WinUAE's cpu in    */
                     71: /*                     'cycle exact' mode. In that case, instruction pairing don't have to be handled  */
                     72: /*                     with some tables/heuristics anymore.                                            */
1.1.1.22  root       73: 
1.1.1.12  root       74: 
1.1.1.14  root       75: const char M68000_fileid[] = "Hatari m68000.c : " __DATE__ " " __TIME__;
1.1       root       76: 
                     77: #include "main.h"
1.1.1.12  root       78: #include "configuration.h"
1.1       root       79: #include "gemdos.h"
1.1.1.6   root       80: #include "hatari-glue.h"
1.1.1.16  root       81: #include "cycInt.h"
1.1       root       82: #include "m68000.h"
                     83: #include "memorySnapShot.h"
                     84: #include "mfp.h"
1.1.1.12  root       85: #include "options.h"
                     86: #include "savestate.h"
1.1       root       87: #include "stMemory.h"
                     88: #include "tos.h"
1.1.1.23  root       89: #include "falcon/crossbar.h"
1.1.1.25! root       90: #include "cart.h"
1.1       root       91: 
1.1.1.22  root       92: #if ENABLE_DSP_EMU
                     93: #include "dsp.h"
                     94: #endif
                     95: 
1.1.1.20  root       96: #if ENABLE_WINUAE_CPU
                     97: #include "mmu_common.h"
                     98: #endif
                     99: 
                    100: /* information about current CPU instruction */
                    101: cpu_instruction_t CpuInstruction;
1.1       root      102: 
1.1.1.23  root      103: Uint32 BusErrorAddress;                /* Stores the offending address for bus-/address errors */
                    104: bool bBusErrorReadWrite;       /* 0 for write error, 1 for read error */
                    105: int nCpuFreqShift;             /* Used to emulate higher CPU frequencies: 0=8MHz, 1=16MHz, 2=32Mhz */
                    106: int WaitStateCycles = 0;       /* Used to emulate the wait state cycles of certain IO registers */
1.1.1.14  root      107: int BusMode = BUS_MODE_CPU;    /* Used to tell which part is owning the bus (cpu, blitter, ...) */
1.1.1.20  root      108: bool CPU_IACK = false;         /* Set to true during an exception when getting the interrupt's vector number */
1.1.1.25! root      109: static bool M68000_DebuggerFlag;/* Is debugger enabled or not ? */
1.1.1.12  root      110: 
1.1.1.16  root      111: int LastOpcodeFamily = i_NOP;  /* see the enum in readcpu.h i_XXX */
                    112: int LastInstrCycles = 0;       /* number of cycles for previous instr. (not rounded to 4) */
                    113: int Pairing = 0;               /* set to 1 if the latest 2 intr paired */
1.1.1.12  root      114: char PairingArray[ MAX_OPCODE_FAMILY ][ MAX_OPCODE_FAMILY ];
                    115: 
                    116: 
                    117: /* to convert the enum from OpcodeFamily to a readable value for pairing's debug */
                    118: const char *OpcodeName[] = { "ILLG",
                    119:        "OR","AND","EOR","ORSR","ANDSR","EORSR",
                    120:        "SUB","SUBA","SUBX","SBCD",
                    121:        "ADD","ADDA","ADDX","ABCD",
                    122:        "NEG","NEGX","NBCD","CLR","NOT","TST",
                    123:        "BTST","BCHG","BCLR","BSET",
                    124:        "CMP","CMPM","CMPA",
                    125:        "MVPRM","MVPMR","MOVE","MOVEA","MVSR2","MV2SR",
                    126:        "SWAP","EXG","EXT","MVMEL","MVMLE",
                    127:        "TRAP","MVR2USP","MVUSP2R","RESET","NOP","STOP","RTE","RTD",
                    128:        "LINK","UNLK",
                    129:        "RTS","TRAPV","RTR",
                    130:        "JSR","JMP","BSR","Bcc",
                    131:        "LEA","PEA","DBcc","Scc",
                    132:        "DIVU","DIVS","MULU","MULS",
                    133:        "ASR","ASL","LSR","LSL","ROL","ROR","ROXL","ROXR",
                    134:        "ASRW","ASLW","LSRW","LSLW","ROLW","RORW","ROXLW","ROXRW",
                    135:        "CHK","CHK2",
                    136:        "MOVEC2","MOVE2C","CAS","CAS2","DIVL","MULL",
                    137:        "BFTST","BFEXTU","BFCHG","BFEXTS","BFCLR","BFFFO","BFSET","BFINS",
                    138:        "PACK","UNPK","TAS","BKPT","CALLM","RTM","TRAPcc","MOVES",
                    139:        "FPP","FDBcc","FScc","FTRAPcc","FBcc","FSAVE","FRESTORE",
                    140:        "CINVL","CINVP","CINVA","CPUSHL","CPUSHP","CPUSHA","MOVE16",
                    141:        "MMUOP"
                    142: };
1.1.1.8   root      143: 
1.1.1.12  root      144: 
                    145: /*-----------------------------------------------------------------------*/
                    146: /**
1.1.1.13  root      147:  * Add pairing between all the bit shifting instructions and a given Opcode
                    148:  */
                    149: 
                    150: static void M68000_InitPairing_BitShift ( int OpCode )
                    151: {
                    152:        PairingArray[  i_ASR ][ OpCode ] = 1; 
                    153:        PairingArray[  i_ASL ][ OpCode ] = 1; 
                    154:        PairingArray[  i_LSR ][ OpCode ] = 1; 
                    155:        PairingArray[  i_LSL ][ OpCode ] = 1; 
                    156:        PairingArray[  i_ROL ][ OpCode ] = 1; 
                    157:        PairingArray[  i_ROR ][ OpCode ] = 1; 
                    158:        PairingArray[ i_ROXR ][ OpCode ] = 1; 
                    159:        PairingArray[ i_ROXL ][ OpCode ] = 1; 
                    160: }
                    161: 
                    162: 
                    163: /**
1.1.1.12  root      164:  * Init the pairing matrix
                    165:  * Two instructions can pair if PairingArray[ LastOpcodeFamily ][ OpcodeFamily ] == 1
                    166:  */
1.1.1.16  root      167: static void M68000_InitPairing(void)
1.1.1.12  root      168: {
                    169:        /* First, clear the matrix (pairing is false) */
                    170:        memset(PairingArray , 0 , MAX_OPCODE_FAMILY * MAX_OPCODE_FAMILY);
                    171: 
                    172:        /* Set all valid pairing combinations to 1 */
                    173:        PairingArray[  i_EXG ][ i_DBcc ] = 1;
1.1.1.13  root      174:        PairingArray[  i_EXG ][ i_MOVE ] = 1;
                    175:        PairingArray[  i_EXG ][ i_MOVEA] = 1;
                    176: 
1.1.1.12  root      177:        PairingArray[ i_CMPA ][  i_Bcc ] = 1;
                    178:        PairingArray[  i_CMP ][  i_Bcc ] = 1;
1.1.1.13  root      179: 
                    180:        M68000_InitPairing_BitShift ( i_DBcc );
                    181:        M68000_InitPairing_BitShift ( i_MOVE );
                    182:        M68000_InitPairing_BitShift ( i_MOVEA );
                    183:        M68000_InitPairing_BitShift ( i_LEA );
1.1.1.17  root      184:        M68000_InitPairing_BitShift ( i_JMP );
1.1.1.13  root      185: 
1.1.1.12  root      186:        PairingArray[ i_MULU ][ i_MOVEA] = 1; 
                    187:        PairingArray[ i_MULS ][ i_MOVEA] = 1; 
                    188:        PairingArray[ i_MULU ][ i_MOVE ] = 1; 
                    189:        PairingArray[ i_MULS ][ i_MOVE ] = 1; 
1.1.1.13  root      190: 
                    191:        PairingArray[ i_MULU ][ i_DIVU ] = 1;
                    192:        PairingArray[ i_MULU ][ i_DIVS ] = 1;
                    193:        PairingArray[ i_MULS ][ i_DIVU ] = 1;
                    194:        PairingArray[ i_MULS ][ i_DIVS ] = 1;
                    195: 
1.1.1.18  root      196:        PairingArray[ i_MULU ][ i_JSR ] = 1;
                    197:        PairingArray[ i_MULS ][ i_JSR ] = 1;
                    198: 
1.1.1.13  root      199:        PairingArray[ i_BTST ][  i_Bcc ] = 1;
                    200: 
                    201:        M68000_InitPairing_BitShift ( i_ADD );
                    202:        M68000_InitPairing_BitShift ( i_SUB );
                    203:        M68000_InitPairing_BitShift ( i_OR );
                    204:        M68000_InitPairing_BitShift ( i_AND );
                    205:        M68000_InitPairing_BitShift ( i_EOR );
                    206:        M68000_InitPairing_BitShift ( i_NOT );
                    207:        M68000_InitPairing_BitShift ( i_CLR );
                    208:        M68000_InitPairing_BitShift ( i_NEG );
                    209:        M68000_InitPairing_BitShift ( i_ADDX );
                    210:        M68000_InitPairing_BitShift ( i_SUBX );
                    211:        M68000_InitPairing_BitShift ( i_ABCD );
                    212:        M68000_InitPairing_BitShift ( i_SBCD );
1.1.1.16  root      213: 
                    214:        PairingArray[ i_ADD ][ i_MOVE ] = 1;            /* when using xx(an,dn) addr mode */
                    215:        PairingArray[ i_SUB ][ i_MOVE ] = 1;
1.1.1.22  root      216: 
                    217:        PairingArray[ i_ABCD ][ i_DBcc ] = 1;
                    218:        PairingArray[ i_SBCD ][ i_DBcc ] = 1;
1.1.1.16  root      219: }
                    220: 
                    221: 
                    222: /**
                    223:  * One-time CPU initialization.
                    224:  */
                    225: void M68000_Init(void)
                    226: {
                    227:        /* Init UAE CPU core */
                    228:        Init680x0();
                    229: 
                    230:        /* Init the pairing matrix */
                    231:        M68000_InitPairing();
1.1.1.12  root      232: }
1.1       root      233: 
                    234: 
1.1.1.3   root      235: /*-----------------------------------------------------------------------*/
1.1.1.12  root      236: /**
                    237:  * Reset CPU 68000 variables
                    238:  */
1.1.1.13  root      239: void M68000_Reset(bool bCold)
1.1       root      240: {
1.1.1.25! root      241: //fprintf ( stderr,"M68000_Reset in cold=%d" , bCold );
1.1.1.19  root      242: #if ENABLE_WINUAE_CPU
1.1.1.25! root      243:        UAE_Set_Quit_Reset ( bCold );
        !           244:        set_special(SPCFLAG_MODE_CHANGE);               /* exit m68k_run_xxx() loop and check for cpu changes / reset / quit */
1.1.1.22  root      245: 
1.1.1.19  root      246: #else /* UAE CPU core */
                    247:        if (bCold)
                    248:        {
                    249:                /* Clear registers */
                    250:                memset(&regs, 0, sizeof(regs));
                    251:        }
                    252:        /* Now reset the UAE CPU core */
1.1.1.12  root      253:        m68k_reset();
1.1.1.25! root      254:        Cart_PatchCpuTables();
1.1.1.17  root      255: #endif
1.1.1.25! root      256: 
1.1.1.14  root      257:        BusMode = BUS_MODE_CPU;
1.1.1.20  root      258:        CPU_IACK = false;
1.1.1.25! root      259: //fprintf ( stderr,"M68000_Reset out cold=%d\n" , bCold );
        !           260: }
        !           261: 
        !           262: 
        !           263: /*-----------------------------------------------------------------------*/
        !           264: /**
        !           265:  * Enable/disable breakpoints in the debugger
        !           266:  */
        !           267: void M68000_SetDebugger(bool debug)
        !           268: {
        !           269:        M68000_DebuggerFlag = debug;
        !           270: 
        !           271:        if ( debug )
        !           272:                M68000_SetSpecial(SPCFLAG_DEBUGGER);
        !           273:        else
        !           274:                M68000_UnsetSpecial(SPCFLAG_DEBUGGER);
1.1.1.12  root      275: }
                    276: 
                    277: 
                    278: /*-----------------------------------------------------------------------*/
                    279: /**
1.1.1.25! root      280:  * Restore debugger state (breakpoints)
        !           281:  * This is called from CPU core after a reset, because CPU core clears regs.spcflags
        !           282:  */
        !           283: void M68000_RestoreDebugger(void)
        !           284: {
        !           285:        if ( M68000_DebuggerFlag )
        !           286:                M68000_SetSpecial(SPCFLAG_DEBUGGER);
        !           287:        else
        !           288:                M68000_UnsetSpecial(SPCFLAG_DEBUGGER);
        !           289: }
        !           290: 
        !           291: 
        !           292: 
        !           293: /*-----------------------------------------------------------------------*/
        !           294: /**
1.1.1.16  root      295:  * Start 680x0 emulation
1.1.1.12  root      296:  */
                    297: void M68000_Start(void)
                    298: {
1.1.1.25! root      299: //fprintf (stderr, "M68000_Start\n" );
        !           300: 
1.1.1.12  root      301:        /* Load initial memory snapshot */
                    302:        if (bLoadMemorySave)
                    303:        {
1.1.1.15  root      304:                MemorySnapShot_Restore(ConfigureParams.Memory.szMemoryCaptureFileName, false);
1.1.1.12  root      305:        }
                    306:        else if (bLoadAutoSave)
                    307:        {
1.1.1.15  root      308:                MemorySnapShot_Restore(ConfigureParams.Memory.szAutoSaveFileName, false);
1.1.1.12  root      309:        }
1.1.1.7   root      310: 
1.1.1.25! root      311: #if ENABLE_WINUAE_CPU
        !           312:        UAE_Set_Quit_Reset ( false );
1.1.1.15  root      313:        m68k_go(true);
1.1.1.25! root      314: #else
        !           315:        m68k_go(true);
        !           316: #endif
1.1       root      317: }
                    318: 
1.1.1.3   root      319: 
                    320: /*-----------------------------------------------------------------------*/
1.1.1.12  root      321: /**
1.1.1.17  root      322:  * Check whether CPU settings have been changed.
1.1.1.22  root      323:  * Possible values for WinUAE :
                    324:  *     cpu_model : 68000 , 68010, 68020, 68030, 68040, 68060
                    325:  *     cpu_level : not used anymore
                    326:  *     cpu_compatible : 0/false (no prefetch for 68000/20/30)  1/true (prefetch opcode for 68000/20/30)
                    327:  *     cpu_cycle_exact : 0/false   1/true (most accurate, implies cpu_compatible)
1.1.1.24  root      328:  *     cpu_memory_cycle_exact : 0/false   1/true (less accurate than cpu_cycle_exact)
                    329:  *     cpu_data_cache : 0/false (don't emulate caches)   1/true (emulate instr/data caches for 68020/30/40/60)
1.1.1.22  root      330:  *     address_space_24 : 1 (68000/10 and 68030 LC for Falcon), 0 (68020/30/40/60)
                    331:  *     fpu_model : 0, 68881 (external), 68882 (external), 68040 (cpu) , 68060 (cpu)
                    332:  *     fpu_strict : true/false (more accurate rounding)
1.1.1.25! root      333:  *     fpu_mode :  0  faster but less accurate, use host's cpu/fpu with 64 bit precision)
        !           334:  *                 1  most accurate but slower, use softfloat library)
        !           335:  *                -1  similar to 0 but with extended 80 bit precision, only for x86 CPU)
        !           336:  *                    (TODO [NP] not in Hatari for now, require fpp_native_msvc_80bit.cpp / fpux64_80.asm / fpux86_80.asm)
1.1.1.22  root      337:  *     mmu_model : 0, 68030, 68040, 68060
                    338:  *
                    339:  *     m68k_speed : -1=don't adjust cycle  >=0 use m68k_speed_throttle to precisely adjust cycles
                    340:  *     m68k_speed_throttle : if not 0, used to set cycles_mult. In Hatari, set it to 0
                    341:  *     cpu_frequency : in CE mode, fine control of cpu freq, set it to freq/2. Not used in Hatari, set it to 0.
                    342:  *     cpu_clock_multiplier : used to speed up/slow down clock by multiple of 2 in CE mode. In Hatari
                    343:  *                     we use nCpuFreqShift, so this should always be set to 2<<8 = 512 to get the same
                    344:  *                     cpucycleunit as in non CE mode.
1.1.1.23  root      345:  *     cachesize : size of cache in MB when using JIT. Not used in Hatari at the moment, set it to 0
1.1.1.12  root      346:  */
1.1.1.17  root      347: void M68000_CheckCpuSettings(void)
1.1.1.12  root      348: {
1.1.1.25! root      349: //fprintf ( stderr,"M68000_CheckCpuSettings in\n" );
1.1.1.12  root      350:        changed_prefs.cpu_level = ConfigureParams.System.nCpuLevel;
1.1.1.17  root      351: 
                    352: #if ENABLE_WINUAE_CPU
1.1.1.19  root      353:        /* WinUAE core uses cpu_model instead of cpu_level, so we've got to
                    354:         * convert these values here: */
1.1.1.17  root      355:        switch (changed_prefs.cpu_level) {
                    356:                case 0 : changed_prefs.cpu_model = 68000; break;
                    357:                case 1 : changed_prefs.cpu_model = 68010; break;
                    358:                case 2 : changed_prefs.cpu_model = 68020; break;
                    359:                case 3 : changed_prefs.cpu_model = 68030; break;
                    360:                case 4 : changed_prefs.cpu_model = 68040; break;
                    361:                case 5 : changed_prefs.cpu_model = 68060; break;
1.1.1.25! root      362:                default: fprintf (stderr, "M68000_CheckCpuSettings() : Error, cpu_level unknown\n");
1.1.1.17  root      363:        }
1.1.1.25! root      364:        currprefs.cpu_level = changed_prefs.cpu_level;                  /* TODO remove, not used anymore */
1.1.1.17  root      365: 
1.1.1.24  root      366:        /* Only 68040/60 can have 'internal' FPU */
                    367:        if ( ( ConfigureParams.System.n_FPUType == FPU_CPU ) && ( changed_prefs.cpu_model < 68040 ) )
                    368:                ConfigureParams.System.n_FPUType = FPU_NONE;
                    369: 
                    370:        /* 68000/10 can't have an FPU */
                    371:        if ( ( ConfigureParams.System.n_FPUType != FPU_NONE ) && ( changed_prefs.cpu_model < 68020 ) )
                    372:        {
                    373:                Log_Printf(LOG_WARN, "FPU is not supported in 68000/010 configurations, disabling FPU\n");
                    374:                ConfigureParams.System.n_FPUType = FPU_NONE;
                    375:        }
                    376: 
1.1.1.25! root      377:        changed_prefs.int_no_unimplemented = true;
        !           378:        changed_prefs.fpu_no_unimplemented = true;
        !           379:        changed_prefs.cpu_compatible = ConfigureParams.System.bCompatibleCpu;
1.1.1.17  root      380:        changed_prefs.cpu_cycle_exact = ConfigureParams.System.bCycleExactCpu;
1.1.1.23  root      381:        changed_prefs.cpu_memory_cycle_exact = ConfigureParams.System.bCycleExactCpu;
1.1.1.25! root      382:        changed_prefs.address_space_24 = ConfigureParams.System.bAddressSpace24;
1.1.1.17  root      383:        changed_prefs.fpu_model = ConfigureParams.System.n_FPUType;
                    384:        changed_prefs.fpu_strict = ConfigureParams.System.bCompatibleFPU;
1.1.1.25! root      385:        changed_prefs.fpu_mode = ( ConfigureParams.System.bSoftFloatFPU ? 1 : 0 );
1.1.1.22  root      386: 
                    387:        /* Update the MMU model by taking the same value as CPU model */
                    388:        /* MMU is only supported for CPU >=68030, this is later checked in custom.c fixup_cpu() */
                    389:        if ( !ConfigureParams.System.bMMU )
                    390:                changed_prefs.mmu_model = 0;                            /* MMU disabled */
                    391:        else
                    392:                changed_prefs.mmu_model = changed_prefs.cpu_model;      /* MMU enabled */
                    393: 
1.1.1.25! root      394:        /* Set cpu speed to default values (only used in WinUAE, not in Hatari) */
        !           395:        changed_prefs.m68k_speed = 0;
        !           396:        changed_prefs.cpu_clock_multiplier = 2 << 8;
1.1.1.22  root      397: 
1.1.1.23  root      398:        /* We don't use JIT */
1.1.1.25! root      399:        changed_prefs.cachesize = 0;
1.1.1.24  root      400: 
                    401:        /* Always emulate instr/data caches for cpu >= 68020 */
1.1.1.25! root      402:        /* Cache emulation requires cpu_compatible or cpu_cycle_exact mode */
        !           403:        if ( ( changed_prefs.cpu_model < 68020 ) ||
        !           404:             ( ( changed_prefs.cpu_compatible == false ) && ( changed_prefs.cpu_cycle_exact == false ) ) )
        !           405:                changed_prefs.cpu_data_cache = false;
        !           406:        else
        !           407:                changed_prefs.cpu_data_cache = true;
        !           408: 
        !           409:        /* Update SPCFLAG_MODE_CHANGE flag if needed */
        !           410:        check_prefs_changed_cpu();
        !           411: 
1.1.1.22  root      412: #else
1.1.1.23  root      413:        if (ConfigureParams.System.nCpuLevel > 4)
                    414:                ConfigureParams.System.nCpuLevel = 4;
                    415: 
1.1.1.25! root      416:        changed_prefs.cpu_compatible = ConfigureParams.System.bCompatibleCpu;
1.1.1.22  root      417:        changed_prefs.cpu_cycle_exact = 0;                              /* With old UAE CPU, cycle_exact is always false */
                    418: 
1.1.1.12  root      419:        if (table68k)
                    420:                check_prefs_changed_cpu();
1.1.1.25! root      421: #endif
        !           422: //fprintf ( stderr, "M68000_CheckCpuSettings out\n" );
1.1.1.12  root      423: }
                    424: 
                    425: 
                    426: /*-----------------------------------------------------------------------*/
                    427: /**
                    428:  * Save/Restore snapshot of CPU variables ('MemorySnapShot_Store' handles type)
                    429:  */
1.1.1.13  root      430: void M68000_MemorySnapShot_Capture(bool bSave)
1.1       root      431: {
1.1.1.17  root      432: #if ENABLE_WINUAE_CPU
                    433:        int len;
1.1.1.22  root      434:        uae_u8 chunk[ 1000 ];
                    435: 
1.1.1.25! root      436:        MemorySnapShot_Store(&pendingInterrupts, sizeof(pendingInterrupts));    /* for intlev() */
        !           437: 
1.1.1.22  root      438:        if (bSave)
                    439:        {
                    440:                //m68k_dumpstate_file(stderr, NULL);
                    441:                save_cpu (&len,chunk);
                    442:                //printf ( "save cpu done\n"  );
                    443:                save_cpu_extra (&len,chunk);
                    444:                //printf ( "save cpux done\n" );
                    445:                save_fpu (&len,chunk);
                    446:                //printf ( "save fpu done\n"  );
                    447:                save_mmu (&len,chunk);
                    448:                //printf ( "save mmu done\n"  );
                    449:                //m68k_dumpstate_file(stderr, NULL);
                    450:        }
                    451:        else
                    452:        {
                    453:                //m68k_dumpstate_file(stderr, NULL);
                    454:                restore_cpu (chunk);
                    455:                //printf ( "restore cpu done\n" );
                    456:                restore_cpu_extra (chunk);
                    457:                //printf ( "restore cpux done\n" );
                    458:                restore_fpu (chunk);
                    459:                //printf ( "restore fpu done\n"  );
                    460:                restore_mmu (chunk);
                    461:                //printf ( "restore mmu done\n"  );
                    462:                //m68k_dumpstate_file(stderr, NULL);
                    463:        }
                    464: 
                    465: #else /* UAE CPU core */
                    466:        Uint32 savepc;
1.1       root      467: 
1.1.1.12  root      468:        /* For the UAE CPU core: */
1.1.1.25! root      469:        MemorySnapShot_Store(&pendingInterrupts, sizeof(pendingInterrupts));    /* for intlev() */
        !           470: 
1.1.1.12  root      471:        MemorySnapShot_Store(&currprefs.address_space_24,
                    472:                             sizeof(currprefs.address_space_24));
                    473:        MemorySnapShot_Store(&regs.regs[0], sizeof(regs.regs));       /* D0-D7 A0-A6 */
                    474: 
                    475:        if (bSave)
                    476:        {
                    477:                savepc = M68000_GetPC();
                    478:                MemorySnapShot_Store(&savepc, sizeof(savepc));            /* PC */
                    479:        }
                    480:        else
                    481:        {
                    482:                MemorySnapShot_Store(&savepc, sizeof(savepc));            /* PC */
                    483:                regs.pc = savepc;
                    484:                regs.prefetch_pc = regs.pc + 128;
                    485:        }
1.1.1.8   root      486: 
1.1.1.12  root      487:        MemorySnapShot_Store(&regs.prefetch, sizeof(regs.prefetch));  /* prefetch */
                    488: 
                    489:        if (bSave)
                    490:        {
                    491:                MakeSR();
                    492:                if (regs.s)
                    493:                {
                    494:                        MemorySnapShot_Store(&regs.usp, sizeof(regs.usp));    /* USP */
                    495:                        MemorySnapShot_Store(&regs.regs[15], sizeof(regs.regs[15]));  /* ISP */
                    496:                }
                    497:                else
                    498:                {
                    499:                        MemorySnapShot_Store(&regs.regs[15], sizeof(regs.regs[15]));  /* USP */
                    500:                        MemorySnapShot_Store(&regs.isp, sizeof(regs.isp));    /* ISP */
                    501:                }
                    502:                MemorySnapShot_Store(&regs.sr, sizeof(regs.sr));          /* SR/CCR */
                    503:        }
                    504:        else
                    505:        {
                    506:                MemorySnapShot_Store(&regs.usp, sizeof(regs.usp));
                    507:                MemorySnapShot_Store(&regs.isp, sizeof(regs.isp));
                    508:                MemorySnapShot_Store(&regs.sr, sizeof(regs.sr));
                    509:        }
1.1.1.22  root      510:        MemorySnapShot_Store(&regs.opcode, sizeof(regs.opcode));
                    511:        MemorySnapShot_Store(&regs.instruction_pc, sizeof(regs.instruction_pc));
1.1.1.12  root      512:        MemorySnapShot_Store(&regs.stopped, sizeof(regs.stopped));
                    513:        MemorySnapShot_Store(&regs.dfc, sizeof(regs.dfc));            /* DFC */
                    514:        MemorySnapShot_Store(&regs.sfc, sizeof(regs.sfc));            /* SFC */
                    515:        MemorySnapShot_Store(&regs.vbr, sizeof(regs.vbr));            /* VBR */
1.1.1.25! root      516:        MemorySnapShot_Store(&regs.caar, sizeof(regs.caar));          /* CAAR */
        !           517:        MemorySnapShot_Store(&regs.cacr, sizeof(regs.cacr));          /* CACR */
1.1.1.12  root      518:        MemorySnapShot_Store(&regs.msp, sizeof(regs.msp));            /* MSP */
                    519: 
                    520:        if (!bSave)
                    521:        {
1.1.1.25! root      522:                Cart_PatchCpuTables();
        !           523: 
1.1.1.12  root      524:                M68000_SetPC(regs.pc);
                    525:                /* MakeFromSR() must not swap stack pointer */
                    526:                regs.s = (regs.sr >> 13) & 1;
                    527:                MakeFromSR();
                    528:                /* set stack pointer */
                    529:                if (regs.s)
                    530:                        m68k_areg(regs, 7) = regs.isp;
                    531:                else
                    532:                        m68k_areg(regs, 7) = regs.usp;
                    533:        }
                    534: 
                    535:        if (bSave)
                    536:                save_fpu();
                    537:        else
                    538:                restore_fpu();
1.1.1.17  root      539: #endif
1.1       root      540: }
                    541: 
                    542: 
1.1.1.3   root      543: /*-----------------------------------------------------------------------*/
1.1.1.12  root      544: /**
1.1.1.25! root      545:  * Check whether bus error reporting should be reported or not.
        !           546:  * We do not want to print messages when TOS is testing for available HW
        !           547:  * or when a program just checks for the floating point co-processor.
        !           548:  */
        !           549: bool M68000_IsVerboseBusError(uint32_t pc, uint32_t addr)
        !           550: {
        !           551:        const uint32_t nTosProbeAddrs[] =
        !           552:        {
        !           553:                0xf00039, 0xff8900, 0xff8a00, 0xff8c83,
        !           554:                0xff8e0d, 0xff8e09, 0xfffa40
        !           555:        };
        !           556:        const uint32_t nEmuTosProbeAddrs[] =
        !           557:        {
        !           558:                0xf0001d, 0xf0005d, 0xf0009d, 0xf000dd, 0xff8006, 0xff8282,
        !           559:                0xff8400, 0xff8701, 0xff8901, 0xff8943, 0xff8961, 0xff8c80,
        !           560:                0xff8a3c, 0xff9201, 0xfffa81, 0xfffe00
        !           561:        };
        !           562:        int idx;
        !           563: 
        !           564:        if (ConfigureParams.Log.nTextLogLevel == LOG_DEBUG)
        !           565:                return true;
        !           566: 
        !           567:        if (ConfigureParams.System.bAddressSpace24
        !           568:            || (addr & 0xff000000) == 0xff000000)
        !           569:        {
        !           570:                addr &= 0xffffff;
        !           571:        }
        !           572: 
        !           573:        /* Program just probing for FPU? A lot of C startup code is always
        !           574:         * doing this, so reporting bus errors here would be annoying */
        !           575:        if (addr == 0xfffa42)
        !           576:                return false;
        !           577: 
        !           578:        /* Always report other bus errors from normal programs */
        !           579:        if (pc < TosAddress || pc > TosAddress + TosSize)
        !           580:                return true;
        !           581: 
        !           582:        for (idx = 0; idx < ARRAY_SIZE(nTosProbeAddrs); idx++)
        !           583:        {
        !           584:                if (nTosProbeAddrs[idx] == addr)
        !           585:                        return false;
        !           586:        }
        !           587: 
        !           588:        if (bIsEmuTOS)
        !           589:        {
        !           590:                for (idx = 0; idx < ARRAY_SIZE(nEmuTosProbeAddrs); idx++)
        !           591:                {
        !           592:                        if (nEmuTosProbeAddrs[idx] == addr)
        !           593:                                return false;
        !           594:                }
        !           595:        }
        !           596: 
        !           597:        return true;
        !           598: }
        !           599: 
        !           600: /**
1.1.1.12  root      601:  * BUSERROR - Access outside valid memory range.
1.1.1.17  root      602:  * Use bRead = 0 for write errors and bRead = 1 for read errors!
1.1.1.12  root      603:  */
1.1.1.22  root      604: void M68000_BusError ( Uint32 addr , int ReadWrite , int Size , int AccessType )
1.1       root      605: {
1.1.1.25! root      606:        LOG_TRACE(TRACE_CPU_EXCEPTION, "Bus error %s at address $%x PC=$%x.\n",
        !           607:                  ReadWrite ? "reading" : "writing", addr, M68000_InstrPC);
1.1.1.12  root      608: 
1.1.1.22  root      609: #ifndef ENABLE_WINUAE_CPU
                    610:        if ((regs.spcflags & SPCFLAG_BUSERROR) == 0)            /* [NP] Check that the opcode has not already generated a read bus error */
1.1.1.12  root      611:        {
                    612:                BusErrorAddress = addr;                         /* Store for exception frame */
1.1.1.22  root      613:                bBusErrorReadWrite = ReadWrite;
1.1.1.12  root      614:                M68000_SetSpecial(SPCFLAG_BUSERROR);            /* The exception will be done in newcpu.c */
                    615:        }
1.1.1.22  root      616: #else
                    617:        /* With WinUAE's cpu, on a bus error instruction will be correctly aborted before completing, */
                    618:        /* so we don't need to check if the opcode already generated a bus error or not */
                    619:        exception2 ( addr , ReadWrite , Size , AccessType );
                    620: #endif
1.1       root      621: }
                    622: 
1.1.1.3   root      623: 
                    624: /*-----------------------------------------------------------------------*/
1.1.1.12  root      625: /**
                    626:  * Exception handler
                    627:  */
1.1.1.22  root      628: void M68000_Exception(Uint32 ExceptionNr , int ExceptionSource)
1.1.1.12  root      629: {
1.1.1.22  root      630: #ifndef WINUAE_FOR_HATARI
1.1.1.16  root      631:        if ((ExceptionSource == M68000_EXC_SRC_AUTOVEC)
1.1.1.22  root      632:                && (ExceptionNr>24 && ExceptionNr<32))          /* 68k autovector interrupt? */
1.1.1.12  root      633:        {
                    634:                /* Handle autovector interrupts the UAE's way
                    635:                 * (see intlev() and do_specialties() in UAE CPU core) */
                    636:                /* In our case, this part is only called for HBL and VBL interrupts */
1.1.1.22  root      637:                int intnr = ExceptionNr - 24;
1.1.1.12  root      638:                pendingInterrupts |= (1 << intnr);
                    639:                M68000_SetSpecial(SPCFLAG_INT);
                    640:        }
1.1.1.13  root      641: 
                    642:        else                                                    /* MFP or direct CPU exceptions */
1.1.1.12  root      643:        {
                    644:                Uint16 SR;
                    645: 
                    646:                /* Was the CPU stopped, i.e. by a STOP instruction? */
                    647:                if (regs.spcflags & SPCFLAG_STOP)
                    648:                {
                    649:                        regs.stopped = 0;
                    650:                        M68000_UnsetSpecial(SPCFLAG_STOP);    /* All is go,go,go! */
                    651:                }
                    652: 
                    653:                /* 68k exceptions are handled by Exception() of the UAE CPU core */
1.1.1.22  root      654:                Exception(ExceptionNr, m68k_getpc(), ExceptionSource);
1.1.1.12  root      655: 
                    656:                /* Set Status Register so interrupt can ONLY be stopped by another interrupt
1.1.1.22  root      657:                 * of higher priority */
                    658:                if ( (ExceptionSource == M68000_EXC_SRC_INT_MFP)
                    659:                  || (ExceptionSource == M68000_EXC_SRC_INT_DSP) )
1.1.1.12  root      660:                {
1.1.1.22  root      661:                        SR = M68000_GetSR();
                    662:                        SR = (SR&SR_CLEAR_IPL)|0x0600;          /* MFP or DSP, level 6 */
                    663:                        M68000_SetSR(SR);
1.1.1.16  root      664:                }
1.1.1.22  root      665:        }
                    666: 
                    667: #else
                    668:        if ( ExceptionNr > 24 && ExceptionNr < 32 )             /* Level 1-7 interrupts */
                    669:        {
                    670:                /* In our case, this part is called for HBL, VBL and MFP/DSP interrupts */
1.1.1.23  root      671:                /* For WinUAE CPU, we must call M68000_Update_intlev after changing pendingInterrupts */
                    672:                /* (in order to call doint() and to update regs.ipl with regs.ipl_pin, else */
                    673:                /* the exception might be delayed by one instruction in do_specialties()) */
                    674:                pendingInterrupts |= (1 << ( ExceptionNr - 24 ));
                    675:                M68000_Update_intlev();
1.1.1.22  root      676:        }
1.1.1.12  root      677: 
1.1.1.22  root      678:        else                                                    /* direct CPU exceptions */
                    679:        {
                    680:                Exception(ExceptionNr);
1.1.1.12  root      681:        }
1.1.1.22  root      682: #endif
1.1       root      683: }
                    684: 
1.1.1.8   root      685: 
1.1.1.22  root      686: 
                    687: 
                    688: /*-----------------------------------------------------------------------*/
                    689: /**
                    690:  * Update the list of pending interrupts.
                    691:  * Level 2 (HBL) and 4 (VBL) are only cleared when the interrupt is processed,
                    692:  * but level 6 is shared between MFP and DSP and can be cleared by MFP or DSP
                    693:  * before being processed.
                    694:  * So, we need to check which IRQ are set/cleared at the same time
                    695:  * and update level 6 accordingly : level 6 = MFP_IRQ OR DSP_IRQ
                    696:  *
                    697:  * [NP] NOTE : temporary case for interrupts with WinUAE CPU in cycle exact mode
                    698:  * In CE mode, interrupt state should be updated on each subcycle of every opcode
                    699:  * then ipl_fetch() is called in each opcode.
                    700:  * For now, Hatari with WinUAE CPU in CE mode only evaluates the interrupt state
                    701:  * after the end of each opcode. So we need to call ipl_fetch() ourselves at the moment.
                    702:  */
                    703: void   M68000_Update_intlev ( void )
                    704: {      
                    705: #ifdef WINUAE_FOR_HATARI
                    706:        Uint8   Level6_IRQ;
                    707: 
                    708: #if ENABLE_DSP_EMU
                    709:        Level6_IRQ = MFP_GetIRQ_CPU() | DSP_GetHREQ();
                    710: #else
                    711:        Level6_IRQ = MFP_GetIRQ_CPU();
                    712: #endif
                    713:        if ( Level6_IRQ == 1 )
                    714:                pendingInterrupts |= (1 << 6);
                    715:        else
                    716:                pendingInterrupts &= ~(1 << 6);
                    717: 
                    718:        if ( pendingInterrupts )
                    719:                doint();
                    720:        else
                    721:                M68000_UnsetSpecial ( SPCFLAG_INT | SPCFLAG_DOINT );
                    722: 
                    723:        /* Temporary case for WinUAE CPU in CE mode */
                    724:        /* doint() will update regs.ipl_pin, so copy it into regs.ipl */
                    725:        if ( ConfigureParams.System.bCycleExactCpu )
                    726:                regs.ipl = regs.ipl_pin;                        /* See ipl_fetch() in cpu/cpu_prefetch.h */
                    727: #endif
                    728: }
                    729: 
                    730: 
                    731: 
                    732: 
1.1.1.8   root      733: /*-----------------------------------------------------------------------*/
1.1.1.12  root      734: /**
1.1.1.23  root      735:  * There are some wait states when accessing certain hardware registers on the ST.
                    736:  * This function simulates these wait states and add the corresponding cycles.
                    737:  *
1.1.1.12  root      738:  * [NP] with some instructions like CLR, we have a read then a write at the
                    739:  * same location, so we may have 2 wait states (read and write) to add
1.1.1.23  root      740:  * (WaitStateCycles should be reset to 0 after all the cycles were added
                    741:  * in run_xx() in newcpu.c).
                    742:  *
                    743:  * - When CPU runs in cycle exact mode, wait states are added immediately.
                    744:  * - For other less precise modes, all the wait states are cumulated and added
                    745:  *   after the instruction was processed.
1.1.1.12  root      746:  */
1.1.1.23  root      747: void M68000_WaitState(int WaitCycles)
1.1.1.8   root      748: {
1.1.1.23  root      749: #ifndef WINUAE_FOR_HATARI
                    750:        WaitStateCycles += WaitCycles;                          /* Cumulate all the wait states for this instruction */
1.1.1.11  root      751: 
1.1.1.23  root      752: #else
                    753:        if ( ConfigureParams.System.bCycleExactCpu )
                    754:                currcycle += ( WaitCycles * CYCLE_UNIT / 2 );   /* Add wait states immediately to the CE cycles counter */
                    755:        else
                    756:        {
                    757:                WaitStateCycles += WaitCycles;                  /* Cumulate all the wait states for this instruction */
                    758:        }
                    759: #endif
1.1.1.8   root      760: }
1.1.1.20  root      761: 
                    762: 
                    763: 
                    764: /*-----------------------------------------------------------------------*/
                    765: /**
                    766:  * Some components (HBL/VBL interrupts, access to the ACIA) require an
                    767:  * extra delay to be synchronized with the E Clock.
                    768:  * E Clock's frequency is 1/10th of the CPU, ie 0.8 MHz in an STF/STE
                    769:  * This delay is a multiple of 2 and will follow the pattern [ 0 8 6 4 2 ]
                    770:  */
                    771: int    M68000_WaitEClock ( void )
                    772: {
                    773:        int     CyclesToNextE;
                    774: 
                    775:        /* We must wait for the next multiple of 10 cycles to be synchronised with E Clock */
1.1.1.21  root      776:        CyclesToNextE = 10 - CyclesGlobalClockCounter % 10;
1.1.1.20  root      777:        if ( CyclesToNextE == 10 )              /* we're already synchronised with E Clock */
                    778:                CyclesToNextE = 0;
                    779:        return CyclesToNextE;
                    780: }
                    781: 
                    782: 
                    783: 
1.1.1.22  root      784: 
                    785: /*-----------------------------------------------------------------------*/
                    786: /**
1.1.1.23  root      787:  * Some hardware registers can only be accessed on a 4 cycles boundary
                    788:  * (shifter color regs and shifter res reg).
                    789:  * An extra delay should be added when needed if current cycle
                    790:  * count is not multiple of 4.
                    791:  */
                    792: static void    M68000_SyncCpuBus ( bool read )
                    793: {
                    794:        Uint64  Cycles;
                    795:        int     CyclesToNextBus;
                    796: 
                    797:        if ( read )
                    798:                Cycles = Cycles_GetClockCounterOnReadAccess();
                    799:        else
                    800:                Cycles = Cycles_GetClockCounterOnWriteAccess();
                    801: 
                    802:        CyclesToNextBus = Cycles & 3;
                    803: //fprintf ( stderr , "sync bus %lld %d\n" , Cycles, CyclesToNextBus );
                    804:        if ( CyclesToNextBus != 0 )
                    805:        {
                    806: //fprintf ( stderr , "sync bus wait %lld %d\n" ,Cycles, 4-CyclesToNextBus );
                    807:                M68000_WaitState ( 4 - CyclesToNextBus );
                    808:        }
                    809: }
                    810: 
                    811: 
                    812: void   M68000_SyncCpuBus_OnReadAccess ( void )
                    813: {
                    814:        M68000_SyncCpuBus ( true );
                    815: }
                    816: 
                    817: 
                    818: void   M68000_SyncCpuBus_OnWriteAccess ( void )
                    819: {
                    820:        M68000_SyncCpuBus ( false );
                    821: }
                    822: 
                    823: 
                    824: 
                    825: 
                    826: /*-----------------------------------------------------------------------*/
                    827: /**
1.1.1.22  root      828:  * In case we modified the memory by accessing it directly (and bypassing
                    829:  * the CPU's cache mechanism), we need to flush the instruction and data
                    830:  * caches to force an update of the caches on the next accesses.
                    831:  *
                    832:  * [NP] NOTE : for now, flush_instr_caches and flush_dcache flush
                    833:  * the whole caches, not just 'addr'
                    834:  */
                    835: void   M68000_Flush_All_Caches ( uaecptr addr , int size )
                    836: {
1.1.1.24  root      837: //fprintf ( stderr , "M68000_Flush_All_Caches\n" );
1.1.1.22  root      838: #ifdef WINUAE_FOR_HATARI
1.1.1.24  root      839:        flush_cpu_caches(true);
                    840:        invalidate_cpu_data_caches();
1.1.1.22  root      841: #endif
                    842: }
                    843: 
                    844: 
                    845: void   M68000_Flush_Instr_Cache ( uaecptr addr , int size )
                    846: {
1.1.1.24  root      847: //fprintf ( stderr , "M68000_Flush_Instr_Cache\n" );
1.1.1.22  root      848: #ifdef WINUAE_FOR_HATARI
                    849:        /* Instruction cache for cpu >= 68020 */
1.1.1.24  root      850:        flush_cpu_caches(true);
1.1.1.22  root      851: #endif
                    852: }
                    853: 
                    854: 
                    855: void   M68000_Flush_Data_Cache ( uaecptr addr , int size )
                    856: {
1.1.1.24  root      857: //fprintf ( stderr , "M68000_Flush_Data_Cache\n" );
1.1.1.22  root      858: #ifdef WINUAE_FOR_HATARI
1.1.1.24  root      859:        /* Data cache for cpu >= 68030 */
                    860:        invalidate_cpu_data_caches();
1.1.1.22  root      861: #endif
                    862: }
                    863: 
                    864: 
                    865: 
1.1.1.23  root      866: /*-----------------------------------------------------------------------*/
                    867: /**
1.1.1.24  root      868:  * When running in 68000 CE mode, allow to change the "do_cycles" functions
                    869:  * in the cpu emulation depending on the blitter state.
                    870:  *  - if the blitter is not busy, we keep the 'normal' 68000 CE "do_cycles" functions
                    871:  *  - if the blitter is busy, we use a slightly slower "do_cycles" to accurately
                    872:  *    count bus accesses made by the blitter and the CPU
                    873:  *
                    874:  * This limits the overhead of emulating cycle exact blitter bus accesses when blitter is OFF.
                    875:  */
                    876: void   M68000_SetBlitter_CE ( bool state )
                    877: {
                    878: #ifdef WINUAE_FOR_HATARI
                    879: //fprintf ( stderr , "M68000_SetBlitter_CE state=%s\n" , state ? "on" : "off" );
                    880:        if ( state )
                    881:        {
                    882:                set_x_funcs_hatari_blitter ( 1 );               /* on */
                    883:        }
                    884:        else
                    885:        {
                    886:                set_x_funcs_hatari_blitter ( 0 );               /* off */
                    887:        }
                    888: #endif
                    889: }
                    890: 
                    891: 
                    892: /*-----------------------------------------------------------------------*/
                    893: /**
1.1.1.23  root      894:  * On real STF/STE hardware, DMA accesses are restricted to 4 MB (video addresses,
                    895:  * FDC, STE DMA sound) in the range 0 - $3fffff (22 bits of address)
                    896:  * When STF/STE are expanded beyond 4 MB, some special '_FRB' cookies variables
                    897:  * need to be set in TOS to allocate an intermediate buffer in lower 4 MB
                    898:  * that will be used to transfer data in RAM between 4 MB and 16 MB.
                    899:  * This buffer is needed because real HW can't access RAM beyond 4 MB.
                    900:  *
                    901:  * In Hatari, we allow DMA addresses to use 24 bits when RAM size is set
                    902:  * to 8 or 16 MB. This way any program / TOS version can make use of extra
                    903:  * RAM beyond 4 MB without requiring an intermediate buffer.
                    904:  *
                    905:  * But it should be noted that programs using 24 bits of DMA addresses would
                    906:  * not work on real HW ; this is just to make RAM expansion more transparent
                    907:  * under emulation.
                    908:  *
                    909:  * We return a mask for bits 16-23 :
                    910:  *  - 0x3f for compatibility with real HW and limit of 4 MB
                    911:  *  - 0xff to allow DMA addresses beyond 4 MB (or for Falcon / TT)
                    912:  */
                    913: int    DMA_MaskAddressHigh ( void )
                    914: {
                    915:        if (Config_IsMachineTT() || Config_IsMachineFalcon())
                    916:                return 0xff;                                    /* Falcon / TT can access 24 bits with DMA */
                    917: 
1.1.1.24  root      918:        else if (ConfigureParams.Memory.STRamSize_KB > 4*1024)  /* ST/STE with more than 4 MB */
1.1.1.23  root      919:                return 0xff;                                    /* Allow 'fake' 24 bits for DMA */
                    920: 
                    921:        else                                                    /* ST/STE with <= 4 MB */
                    922:                return 0x3f;                                    /* Limit DMA range to 22 bits (same as real HW) */
                    923: }
                    924: 
                    925: 
                    926: 
                    927: 
                    928: /*-----------------------------------------------------------------------*/
                    929: /**
                    930:  * This function should be called when the cpu freq is changed, to update
                    931:  * other components that depend on it.
                    932:  *
                    933:  * For now, only Falcon mode requires some updates for the crossbar
                    934:  */
                    935: void   M68000_ChangeCpuFreq ( void )
                    936: {
                    937:        if ( Config_IsMachineFalcon() )
                    938:        {
                    939:                Crossbar_Recalculate_Clocks_Cycles();
                    940:        }
                    941: }
1.1.1.24  root      942: 
                    943: 
                    944: 
                    945: 
                    946: /*-----------------------------------------------------------------------*/
                    947: /**
                    948:  * Some CPU registers can't be read or modified directly, some additional
                    949:  * actions are required.
                    950:  */
                    951: Uint16 M68000_GetSR ( void )
                    952: {
                    953:        MakeSR();
                    954:        return regs.sr;
                    955: }
                    956: 
                    957: void   M68000_SetSR ( Uint16 v )
                    958: {
                    959:        regs.sr = v;
                    960:        MakeFromSR();
                    961: }
                    962: 
                    963: void   M68000_SetPC ( uaecptr v )
                    964: {
                    965:        m68k_setpc ( v );
                    966: #ifdef WINUAE_FOR_HATARI
                    967:        fill_prefetch();
                    968: #else
                    969:        refill_prefetch (m68k_getpc(), 0);
                    970: #endif
                    971: }
                    972: 
                    973: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.