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

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       root       90: 
1.1.1.22  root       91: #if ENABLE_DSP_EMU
                     92: #include "dsp.h"
                     93: #endif
                     94: 
1.1.1.20  root       95: #if ENABLE_WINUAE_CPU
                     96: #include "mmu_common.h"
                     97: #endif
                     98: 
                     99: /* information about current CPU instruction */
                    100: cpu_instruction_t CpuInstruction;
1.1       root      101: 
1.1.1.23  root      102: Uint32 BusErrorAddress;                /* Stores the offending address for bus-/address errors */
                    103: bool bBusErrorReadWrite;       /* 0 for write error, 1 for read error */
                    104: int nCpuFreqShift;             /* Used to emulate higher CPU frequencies: 0=8MHz, 1=16MHz, 2=32Mhz */
                    105: int WaitStateCycles = 0;       /* Used to emulate the wait state cycles of certain IO registers */
1.1.1.14  root      106: int BusMode = BUS_MODE_CPU;    /* Used to tell which part is owning the bus (cpu, blitter, ...) */
1.1.1.20  root      107: bool CPU_IACK = false;         /* Set to true during an exception when getting the interrupt's vector number */
1.1.1.12  root      108: 
1.1.1.16  root      109: int LastOpcodeFamily = i_NOP;  /* see the enum in readcpu.h i_XXX */
                    110: int LastInstrCycles = 0;       /* number of cycles for previous instr. (not rounded to 4) */
                    111: int Pairing = 0;               /* set to 1 if the latest 2 intr paired */
1.1.1.12  root      112: char PairingArray[ MAX_OPCODE_FAMILY ][ MAX_OPCODE_FAMILY ];
                    113: 
                    114: 
                    115: /* to convert the enum from OpcodeFamily to a readable value for pairing's debug */
                    116: const char *OpcodeName[] = { "ILLG",
                    117:        "OR","AND","EOR","ORSR","ANDSR","EORSR",
                    118:        "SUB","SUBA","SUBX","SBCD",
                    119:        "ADD","ADDA","ADDX","ABCD",
                    120:        "NEG","NEGX","NBCD","CLR","NOT","TST",
                    121:        "BTST","BCHG","BCLR","BSET",
                    122:        "CMP","CMPM","CMPA",
                    123:        "MVPRM","MVPMR","MOVE","MOVEA","MVSR2","MV2SR",
                    124:        "SWAP","EXG","EXT","MVMEL","MVMLE",
                    125:        "TRAP","MVR2USP","MVUSP2R","RESET","NOP","STOP","RTE","RTD",
                    126:        "LINK","UNLK",
                    127:        "RTS","TRAPV","RTR",
                    128:        "JSR","JMP","BSR","Bcc",
                    129:        "LEA","PEA","DBcc","Scc",
                    130:        "DIVU","DIVS","MULU","MULS",
                    131:        "ASR","ASL","LSR","LSL","ROL","ROR","ROXL","ROXR",
                    132:        "ASRW","ASLW","LSRW","LSLW","ROLW","RORW","ROXLW","ROXRW",
                    133:        "CHK","CHK2",
                    134:        "MOVEC2","MOVE2C","CAS","CAS2","DIVL","MULL",
                    135:        "BFTST","BFEXTU","BFCHG","BFEXTS","BFCLR","BFFFO","BFSET","BFINS",
                    136:        "PACK","UNPK","TAS","BKPT","CALLM","RTM","TRAPcc","MOVES",
                    137:        "FPP","FDBcc","FScc","FTRAPcc","FBcc","FSAVE","FRESTORE",
                    138:        "CINVL","CINVP","CINVA","CPUSHL","CPUSHP","CPUSHA","MOVE16",
                    139:        "MMUOP"
                    140: };
1.1.1.8   root      141: 
1.1.1.12  root      142: 
                    143: /*-----------------------------------------------------------------------*/
                    144: /**
1.1.1.13  root      145:  * Add pairing between all the bit shifting instructions and a given Opcode
                    146:  */
                    147: 
                    148: static void M68000_InitPairing_BitShift ( int OpCode )
                    149: {
                    150:        PairingArray[  i_ASR ][ OpCode ] = 1; 
                    151:        PairingArray[  i_ASL ][ OpCode ] = 1; 
                    152:        PairingArray[  i_LSR ][ OpCode ] = 1; 
                    153:        PairingArray[  i_LSL ][ OpCode ] = 1; 
                    154:        PairingArray[  i_ROL ][ OpCode ] = 1; 
                    155:        PairingArray[  i_ROR ][ OpCode ] = 1; 
                    156:        PairingArray[ i_ROXR ][ OpCode ] = 1; 
                    157:        PairingArray[ i_ROXL ][ OpCode ] = 1; 
                    158: }
                    159: 
                    160: 
                    161: /**
1.1.1.12  root      162:  * Init the pairing matrix
                    163:  * Two instructions can pair if PairingArray[ LastOpcodeFamily ][ OpcodeFamily ] == 1
                    164:  */
1.1.1.16  root      165: static void M68000_InitPairing(void)
1.1.1.12  root      166: {
                    167:        /* First, clear the matrix (pairing is false) */
                    168:        memset(PairingArray , 0 , MAX_OPCODE_FAMILY * MAX_OPCODE_FAMILY);
                    169: 
                    170:        /* Set all valid pairing combinations to 1 */
                    171:        PairingArray[  i_EXG ][ i_DBcc ] = 1;
1.1.1.13  root      172:        PairingArray[  i_EXG ][ i_MOVE ] = 1;
                    173:        PairingArray[  i_EXG ][ i_MOVEA] = 1;
                    174: 
1.1.1.12  root      175:        PairingArray[ i_CMPA ][  i_Bcc ] = 1;
                    176:        PairingArray[  i_CMP ][  i_Bcc ] = 1;
1.1.1.13  root      177: 
                    178:        M68000_InitPairing_BitShift ( i_DBcc );
                    179:        M68000_InitPairing_BitShift ( i_MOVE );
                    180:        M68000_InitPairing_BitShift ( i_MOVEA );
                    181:        M68000_InitPairing_BitShift ( i_LEA );
1.1.1.17  root      182:        M68000_InitPairing_BitShift ( i_JMP );
1.1.1.13  root      183: 
1.1.1.12  root      184:        PairingArray[ i_MULU ][ i_MOVEA] = 1; 
                    185:        PairingArray[ i_MULS ][ i_MOVEA] = 1; 
                    186:        PairingArray[ i_MULU ][ i_MOVE ] = 1; 
                    187:        PairingArray[ i_MULS ][ i_MOVE ] = 1; 
1.1.1.13  root      188: 
                    189:        PairingArray[ i_MULU ][ i_DIVU ] = 1;
                    190:        PairingArray[ i_MULU ][ i_DIVS ] = 1;
                    191:        PairingArray[ i_MULS ][ i_DIVU ] = 1;
                    192:        PairingArray[ i_MULS ][ i_DIVS ] = 1;
                    193: 
1.1.1.18  root      194:        PairingArray[ i_MULU ][ i_JSR ] = 1;
                    195:        PairingArray[ i_MULS ][ i_JSR ] = 1;
                    196: 
1.1.1.13  root      197:        PairingArray[ i_BTST ][  i_Bcc ] = 1;
                    198: 
                    199:        M68000_InitPairing_BitShift ( i_ADD );
                    200:        M68000_InitPairing_BitShift ( i_SUB );
                    201:        M68000_InitPairing_BitShift ( i_OR );
                    202:        M68000_InitPairing_BitShift ( i_AND );
                    203:        M68000_InitPairing_BitShift ( i_EOR );
                    204:        M68000_InitPairing_BitShift ( i_NOT );
                    205:        M68000_InitPairing_BitShift ( i_CLR );
                    206:        M68000_InitPairing_BitShift ( i_NEG );
                    207:        M68000_InitPairing_BitShift ( i_ADDX );
                    208:        M68000_InitPairing_BitShift ( i_SUBX );
                    209:        M68000_InitPairing_BitShift ( i_ABCD );
                    210:        M68000_InitPairing_BitShift ( i_SBCD );
1.1.1.16  root      211: 
                    212:        PairingArray[ i_ADD ][ i_MOVE ] = 1;            /* when using xx(an,dn) addr mode */
                    213:        PairingArray[ i_SUB ][ i_MOVE ] = 1;
1.1.1.22  root      214: 
                    215:        PairingArray[ i_ABCD ][ i_DBcc ] = 1;
                    216:        PairingArray[ i_SBCD ][ i_DBcc ] = 1;
1.1.1.16  root      217: }
                    218: 
                    219: 
                    220: /**
                    221:  * One-time CPU initialization.
                    222:  */
                    223: void M68000_Init(void)
                    224: {
                    225:        /* Init UAE CPU core */
                    226:        Init680x0();
                    227: 
                    228:        /* Init the pairing matrix */
                    229:        M68000_InitPairing();
1.1.1.12  root      230: }
1.1       root      231: 
                    232: 
1.1.1.3   root      233: /*-----------------------------------------------------------------------*/
1.1.1.12  root      234: /**
                    235:  * Reset CPU 68000 variables
                    236:  */
1.1.1.13  root      237: void M68000_Reset(bool bCold)
1.1       root      238: {
1.1.1.19  root      239: #if ENABLE_WINUAE_CPU
1.1.1.22  root      240:        int spcFlags = regs.spcflags & (SPCFLAG_MODE_CHANGE | SPCFLAG_BRK);
1.1.1.12  root      241:        if (bCold)
                    242:        {
1.1.1.16  root      243:                memset(&regs, 0, sizeof(regs));
1.1.1.12  root      244:        }
1.1.1.19  root      245:        /* Now reset the WINUAE CPU core */
1.1.1.22  root      246:        m68k_reset();
                    247: 
                    248:         /* On Hatari, when we change cpu settings, we call m68k_reset() during m68k_run_xx(), */
                    249:        /* so we must keep the value of bits SPCFLAG_MODE_CHANGE and SPCFLAG_BRK to exit m68k_run_xx() */
                    250:        /* and choose a new m68k_run_xx() function */
                    251:        /* [NP] TODO : don't force a reset when changing cpu settings and use common code with WinUAE ? */
                    252:         regs.spcflags |= spcFlags;
                    253: 
1.1.1.19  root      254: #else /* UAE CPU core */
                    255:        if (bCold)
                    256:        {
                    257:                /* Clear registers */
                    258:                memset(&regs, 0, sizeof(regs));
                    259:        }
                    260:        /* Now reset the UAE CPU core */
1.1.1.12  root      261:        m68k_reset();
1.1.1.17  root      262: #endif
1.1.1.14  root      263:        BusMode = BUS_MODE_CPU;
1.1.1.20  root      264:        CPU_IACK = false;
1.1.1.12  root      265: }
                    266: 
                    267: 
                    268: /*-----------------------------------------------------------------------*/
                    269: /**
1.1.1.16  root      270:  * Start 680x0 emulation
1.1.1.12  root      271:  */
                    272: void M68000_Start(void)
                    273: {
                    274:        /* Load initial memory snapshot */
                    275:        if (bLoadMemorySave)
                    276:        {
1.1.1.15  root      277:                MemorySnapShot_Restore(ConfigureParams.Memory.szMemoryCaptureFileName, false);
1.1.1.12  root      278:        }
                    279:        else if (bLoadAutoSave)
                    280:        {
1.1.1.15  root      281:                MemorySnapShot_Restore(ConfigureParams.Memory.szAutoSaveFileName, false);
1.1.1.12  root      282:        }
1.1.1.7   root      283: 
1.1.1.15  root      284:        m68k_go(true);
1.1       root      285: }
                    286: 
1.1.1.3   root      287: 
                    288: /*-----------------------------------------------------------------------*/
1.1.1.12  root      289: /**
1.1.1.17  root      290:  * Check whether CPU settings have been changed.
1.1.1.22  root      291:  * Possible values for WinUAE :
                    292:  *     cpu_model : 68000 , 68010, 68020, 68030, 68040, 68060
                    293:  *     cpu_level : not used anymore
                    294:  *     cpu_compatible : 0/false (no prefetch for 68000/20/30)  1/true (prefetch opcode for 68000/20/30)
                    295:  *     cpu_cycle_exact : 0/false   1/true (most accurate, implies cpu_compatible)
1.1.1.24! root      296:  *     cpu_memory_cycle_exact : 0/false   1/true (less accurate than cpu_cycle_exact)
        !           297:  *     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      298:  *     address_space_24 : 1 (68000/10 and 68030 LC for Falcon), 0 (68020/30/40/60)
                    299:  *     fpu_model : 0, 68881 (external), 68882 (external), 68040 (cpu) , 68060 (cpu)
                    300:  *     fpu_strict : true/false (more accurate rounding)
1.1.1.24! root      301:  *     fpu_softfloat : 0/false (faster but less accurate, use host's cpu/fpu)   1/true (most accurate but slower)
1.1.1.22  root      302:  *     mmu_model : 0, 68030, 68040, 68060
                    303:  *
                    304:  *     m68k_speed : -1=don't adjust cycle  >=0 use m68k_speed_throttle to precisely adjust cycles
                    305:  *     m68k_speed_throttle : if not 0, used to set cycles_mult. In Hatari, set it to 0
                    306:  *     cpu_frequency : in CE mode, fine control of cpu freq, set it to freq/2. Not used in Hatari, set it to 0.
                    307:  *     cpu_clock_multiplier : used to speed up/slow down clock by multiple of 2 in CE mode. In Hatari
                    308:  *                     we use nCpuFreqShift, so this should always be set to 2<<8 = 512 to get the same
                    309:  *                     cpucycleunit as in non CE mode.
1.1.1.23  root      310:  *     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      311:  */
1.1.1.17  root      312: void M68000_CheckCpuSettings(void)
1.1.1.12  root      313: {
                    314:        changed_prefs.cpu_level = ConfigureParams.System.nCpuLevel;
                    315:        changed_prefs.cpu_compatible = ConfigureParams.System.bCompatibleCpu;
1.1.1.17  root      316: 
                    317: #if ENABLE_WINUAE_CPU
1.1.1.19  root      318:        /* WinUAE core uses cpu_model instead of cpu_level, so we've got to
                    319:         * convert these values here: */
1.1.1.17  root      320:        switch (changed_prefs.cpu_level) {
                    321:                case 0 : changed_prefs.cpu_model = 68000; break;
                    322:                case 1 : changed_prefs.cpu_model = 68010; break;
                    323:                case 2 : changed_prefs.cpu_model = 68020; break;
                    324:                case 3 : changed_prefs.cpu_model = 68030; break;
                    325:                case 4 : changed_prefs.cpu_model = 68040; break;
                    326:                case 5 : changed_prefs.cpu_model = 68060; break;
                    327:                default: fprintf (stderr, "Init680x0() : Error, cpu_level unknown\n");
                    328:        }
1.1.1.19  root      329:        currprefs.cpu_level = changed_prefs.cpu_level;
1.1.1.17  root      330: 
1.1.1.24! root      331:        /* Only 68040/60 can have 'internal' FPU */
        !           332:        if ( ( ConfigureParams.System.n_FPUType == FPU_CPU ) && ( changed_prefs.cpu_model < 68040 ) )
        !           333:                ConfigureParams.System.n_FPUType = FPU_NONE;
        !           334: 
        !           335:        /* 68000/10 can't have an FPU */
        !           336:        if ( ( ConfigureParams.System.n_FPUType != FPU_NONE ) && ( changed_prefs.cpu_model < 68020 ) )
        !           337:        {
        !           338:                Log_Printf(LOG_WARN, "FPU is not supported in 68000/010 configurations, disabling FPU\n");
        !           339:                ConfigureParams.System.n_FPUType = FPU_NONE;
        !           340:        }
        !           341: 
1.1.1.17  root      342:        changed_prefs.address_space_24 = ConfigureParams.System.bAddressSpace24;
                    343:        changed_prefs.cpu_cycle_exact = ConfigureParams.System.bCycleExactCpu;
1.1.1.23  root      344:        changed_prefs.cpu_memory_cycle_exact = ConfigureParams.System.bCycleExactCpu;
1.1.1.17  root      345:        changed_prefs.fpu_model = ConfigureParams.System.n_FPUType;
                    346:        changed_prefs.fpu_strict = ConfigureParams.System.bCompatibleFPU;
1.1.1.24! root      347:        changed_prefs.fpu_softfloat = ConfigureParams.System.bSoftFloatFPU;
1.1.1.22  root      348: 
                    349:        /* Update the MMU model by taking the same value as CPU model */
                    350:        /* MMU is only supported for CPU >=68030, this is later checked in custom.c fixup_cpu() */
                    351:        if ( !ConfigureParams.System.bMMU )
                    352:                changed_prefs.mmu_model = 0;                            /* MMU disabled */
                    353:        else
                    354:                changed_prefs.mmu_model = changed_prefs.cpu_model;      /* MMU enabled */
                    355: 
                    356:        /* Set cpu speed to default values (only use in WinUAE, not in Hatari) */
                    357:        currprefs.m68k_speed = changed_prefs.m68k_speed = 0;
                    358:        currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier = 2 << 8;
                    359: 
1.1.1.23  root      360:        /* We don't use JIT */
                    361:        currprefs.cachesize = changed_prefs.cachesize = 0;
1.1.1.24! root      362: 
        !           363:        /* Always emulate instr/data caches for cpu >= 68020 */
        !           364:        changed_prefs.cpu_data_cache = true;
1.1.1.22  root      365: #else
1.1.1.23  root      366:        if (ConfigureParams.System.nCpuLevel > 4)
                    367:                ConfigureParams.System.nCpuLevel = 4;
                    368: 
1.1.1.22  root      369:        changed_prefs.cpu_cycle_exact = 0;                              /* With old UAE CPU, cycle_exact is always false */
1.1.1.12  root      370: #endif
1.1.1.22  root      371: 
1.1.1.12  root      372:        if (table68k)
                    373:                check_prefs_changed_cpu();
                    374: }
                    375: 
                    376: 
                    377: /*-----------------------------------------------------------------------*/
                    378: /**
                    379:  * Save/Restore snapshot of CPU variables ('MemorySnapShot_Store' handles type)
                    380:  */
1.1.1.13  root      381: void M68000_MemorySnapShot_Capture(bool bSave)
1.1       root      382: {
1.1.1.17  root      383: #if ENABLE_WINUAE_CPU
                    384:        int len;
1.1.1.22  root      385:        uae_u8 chunk[ 1000 ];
                    386: 
                    387:        if (bSave)
                    388:        {
                    389:                //m68k_dumpstate_file(stderr, NULL);
                    390:                save_cpu (&len,chunk);
                    391:                //printf ( "save cpu done\n"  );
                    392:                save_cpu_extra (&len,chunk);
                    393:                //printf ( "save cpux done\n" );
                    394:                save_fpu (&len,chunk);
                    395:                //printf ( "save fpu done\n"  );
                    396:                save_mmu (&len,chunk);
                    397:                //printf ( "save mmu done\n"  );
                    398:                //m68k_dumpstate_file(stderr, NULL);
                    399:        }
                    400:        else
                    401:        {
                    402:                //m68k_dumpstate_file(stderr, NULL);
                    403:                restore_cpu (chunk);
                    404:                //printf ( "restore cpu done\n" );
                    405:                restore_cpu_extra (chunk);
                    406:                //printf ( "restore cpux done\n" );
                    407:                restore_fpu (chunk);
                    408:                //printf ( "restore fpu done\n"  );
                    409:                restore_mmu (chunk);
                    410:                //printf ( "restore mmu done\n"  );
                    411: 
                    412:                restore_cpu_finish ();
                    413:                if ( regs.s )   regs.regs[15] = regs.isp;
                    414:                else            regs.regs[15] = regs.usp;
                    415:                //m68k_dumpstate_file(stderr, NULL);
                    416:        }
                    417: 
                    418: #else /* UAE CPU core */
                    419:        Uint32 savepc;
1.1       root      420: 
1.1.1.12  root      421:        /* For the UAE CPU core: */
                    422:        MemorySnapShot_Store(&currprefs.address_space_24,
                    423:                             sizeof(currprefs.address_space_24));
                    424:        MemorySnapShot_Store(&regs.regs[0], sizeof(regs.regs));       /* D0-D7 A0-A6 */
                    425: 
                    426:        if (bSave)
                    427:        {
                    428:                savepc = M68000_GetPC();
                    429:                MemorySnapShot_Store(&savepc, sizeof(savepc));            /* PC */
                    430:        }
                    431:        else
                    432:        {
                    433:                MemorySnapShot_Store(&savepc, sizeof(savepc));            /* PC */
                    434:                regs.pc = savepc;
                    435:                regs.prefetch_pc = regs.pc + 128;
                    436:        }
1.1.1.8   root      437: 
1.1.1.12  root      438:        MemorySnapShot_Store(&regs.prefetch, sizeof(regs.prefetch));  /* prefetch */
                    439: 
                    440:        if (bSave)
                    441:        {
                    442:                MakeSR();
                    443:                if (regs.s)
                    444:                {
                    445:                        MemorySnapShot_Store(&regs.usp, sizeof(regs.usp));    /* USP */
                    446:                        MemorySnapShot_Store(&regs.regs[15], sizeof(regs.regs[15]));  /* ISP */
                    447:                }
                    448:                else
                    449:                {
                    450:                        MemorySnapShot_Store(&regs.regs[15], sizeof(regs.regs[15]));  /* USP */
                    451:                        MemorySnapShot_Store(&regs.isp, sizeof(regs.isp));    /* ISP */
                    452:                }
                    453:                MemorySnapShot_Store(&regs.sr, sizeof(regs.sr));          /* SR/CCR */
                    454:        }
                    455:        else
                    456:        {
                    457:                MemorySnapShot_Store(&regs.usp, sizeof(regs.usp));
                    458:                MemorySnapShot_Store(&regs.isp, sizeof(regs.isp));
                    459:                MemorySnapShot_Store(&regs.sr, sizeof(regs.sr));
                    460:        }
1.1.1.22  root      461:        MemorySnapShot_Store(&regs.opcode, sizeof(regs.opcode));
                    462:        MemorySnapShot_Store(&regs.instruction_pc, sizeof(regs.instruction_pc));
1.1.1.12  root      463:        MemorySnapShot_Store(&regs.stopped, sizeof(regs.stopped));
                    464:        MemorySnapShot_Store(&regs.dfc, sizeof(regs.dfc));            /* DFC */
                    465:        MemorySnapShot_Store(&regs.sfc, sizeof(regs.sfc));            /* SFC */
                    466:        MemorySnapShot_Store(&regs.vbr, sizeof(regs.vbr));            /* VBR */
                    467:        MemorySnapShot_Store(&caar, sizeof(caar));                    /* CAAR */
                    468:        MemorySnapShot_Store(&cacr, sizeof(cacr));                    /* CACR */
                    469:        MemorySnapShot_Store(&regs.msp, sizeof(regs.msp));            /* MSP */
                    470: 
                    471:        if (!bSave)
                    472:        {
                    473:                M68000_SetPC(regs.pc);
                    474:                /* MakeFromSR() must not swap stack pointer */
                    475:                regs.s = (regs.sr >> 13) & 1;
                    476:                MakeFromSR();
                    477:                /* set stack pointer */
                    478:                if (regs.s)
                    479:                        m68k_areg(regs, 7) = regs.isp;
                    480:                else
                    481:                        m68k_areg(regs, 7) = regs.usp;
                    482:        }
                    483: 
                    484:        if (bSave)
                    485:                save_fpu();
                    486:        else
                    487:                restore_fpu();
1.1.1.17  root      488: #endif
1.1       root      489: }
                    490: 
                    491: 
1.1.1.3   root      492: /*-----------------------------------------------------------------------*/
1.1.1.12  root      493: /**
                    494:  * BUSERROR - Access outside valid memory range.
1.1.1.17  root      495:  * Use bRead = 0 for write errors and bRead = 1 for read errors!
1.1.1.12  root      496:  */
1.1.1.22  root      497: void M68000_BusError ( Uint32 addr , int ReadWrite , int Size , int AccessType )
1.1       root      498: {
1.1.1.22  root      499:        Uint32 InstrPC = M68000_InstrPC;
1.1.1.7   root      500: 
1.1.1.15  root      501:        /* Do not print message when TOS is testing for available HW or
                    502:         * when a program just checks for the floating point co-processor. */
1.1.1.22  root      503:        if ((InstrPC < TosAddress || InstrPC > TosAddress + TosSize)
1.1.1.15  root      504:            && addr != 0xfffa42)
1.1.1.12  root      505:        {
1.1.1.15  root      506:                /* Print bus error message */
1.1.1.22  root      507:                fprintf(stderr, "M68000 Bus Error %s at address $%x PC=$%x.\n",
                    508:                        ReadWrite ? "reading" : "writing", addr, InstrPC);
1.1.1.12  root      509:        }
                    510: 
1.1.1.22  root      511: #ifndef ENABLE_WINUAE_CPU
                    512:        if ((regs.spcflags & SPCFLAG_BUSERROR) == 0)            /* [NP] Check that the opcode has not already generated a read bus error */
1.1.1.12  root      513:        {
                    514:                BusErrorAddress = addr;                         /* Store for exception frame */
1.1.1.22  root      515:                bBusErrorReadWrite = ReadWrite;
1.1.1.12  root      516:                M68000_SetSpecial(SPCFLAG_BUSERROR);            /* The exception will be done in newcpu.c */
                    517:        }
1.1.1.22  root      518: 
                    519: #else
                    520:        /* With WinUAE's cpu, on a bus error instruction will be correctly aborted before completing, */
                    521:        /* so we don't need to check if the opcode already generated a bus error or not */
                    522:        exception2 ( addr , ReadWrite , Size , AccessType );
                    523: #endif
1.1       root      524: }
                    525: 
1.1.1.3   root      526: 
                    527: /*-----------------------------------------------------------------------*/
1.1.1.12  root      528: /**
                    529:  * Exception handler
                    530:  */
1.1.1.22  root      531: void M68000_Exception(Uint32 ExceptionNr , int ExceptionSource)
1.1.1.12  root      532: {
1.1.1.22  root      533: #ifndef WINUAE_FOR_HATARI
1.1.1.16  root      534:        if ((ExceptionSource == M68000_EXC_SRC_AUTOVEC)
1.1.1.22  root      535:                && (ExceptionNr>24 && ExceptionNr<32))          /* 68k autovector interrupt? */
1.1.1.12  root      536:        {
                    537:                /* Handle autovector interrupts the UAE's way
                    538:                 * (see intlev() and do_specialties() in UAE CPU core) */
                    539:                /* In our case, this part is only called for HBL and VBL interrupts */
1.1.1.22  root      540:                int intnr = ExceptionNr - 24;
1.1.1.12  root      541:                pendingInterrupts |= (1 << intnr);
                    542:                M68000_SetSpecial(SPCFLAG_INT);
                    543:        }
1.1.1.13  root      544: 
                    545:        else                                                    /* MFP or direct CPU exceptions */
1.1.1.12  root      546:        {
                    547:                Uint16 SR;
                    548: 
                    549:                /* Was the CPU stopped, i.e. by a STOP instruction? */
                    550:                if (regs.spcflags & SPCFLAG_STOP)
                    551:                {
                    552:                        regs.stopped = 0;
                    553:                        M68000_UnsetSpecial(SPCFLAG_STOP);    /* All is go,go,go! */
                    554:                }
                    555: 
                    556:                /* 68k exceptions are handled by Exception() of the UAE CPU core */
1.1.1.22  root      557:                Exception(ExceptionNr, m68k_getpc(), ExceptionSource);
1.1.1.12  root      558: 
                    559:                /* Set Status Register so interrupt can ONLY be stopped by another interrupt
1.1.1.22  root      560:                 * of higher priority */
                    561:                if ( (ExceptionSource == M68000_EXC_SRC_INT_MFP)
                    562:                  || (ExceptionSource == M68000_EXC_SRC_INT_DSP) )
1.1.1.12  root      563:                {
1.1.1.22  root      564:                        SR = M68000_GetSR();
                    565:                        SR = (SR&SR_CLEAR_IPL)|0x0600;          /* MFP or DSP, level 6 */
                    566:                        M68000_SetSR(SR);
1.1.1.16  root      567:                }
1.1.1.22  root      568:        }
                    569: 
                    570: #else
                    571:        if ( ExceptionNr > 24 && ExceptionNr < 32 )             /* Level 1-7 interrupts */
                    572:        {
                    573:                /* In our case, this part is called for HBL, VBL and MFP/DSP interrupts */
1.1.1.23  root      574:                /* For WinUAE CPU, we must call M68000_Update_intlev after changing pendingInterrupts */
                    575:                /* (in order to call doint() and to update regs.ipl with regs.ipl_pin, else */
                    576:                /* the exception might be delayed by one instruction in do_specialties()) */
                    577:                pendingInterrupts |= (1 << ( ExceptionNr - 24 ));
                    578:                M68000_Update_intlev();
1.1.1.22  root      579:        }
1.1.1.12  root      580: 
1.1.1.22  root      581:        else                                                    /* direct CPU exceptions */
                    582:        {
                    583:                Exception(ExceptionNr);
1.1.1.12  root      584:        }
1.1.1.22  root      585: #endif
1.1       root      586: }
                    587: 
1.1.1.8   root      588: 
1.1.1.22  root      589: 
                    590: 
                    591: /*-----------------------------------------------------------------------*/
                    592: /**
                    593:  * Update the list of pending interrupts.
                    594:  * Level 2 (HBL) and 4 (VBL) are only cleared when the interrupt is processed,
                    595:  * but level 6 is shared between MFP and DSP and can be cleared by MFP or DSP
                    596:  * before being processed.
                    597:  * So, we need to check which IRQ are set/cleared at the same time
                    598:  * and update level 6 accordingly : level 6 = MFP_IRQ OR DSP_IRQ
                    599:  *
                    600:  * [NP] NOTE : temporary case for interrupts with WinUAE CPU in cycle exact mode
                    601:  * In CE mode, interrupt state should be updated on each subcycle of every opcode
                    602:  * then ipl_fetch() is called in each opcode.
                    603:  * For now, Hatari with WinUAE CPU in CE mode only evaluates the interrupt state
                    604:  * after the end of each opcode. So we need to call ipl_fetch() ourselves at the moment.
                    605:  */
                    606: void   M68000_Update_intlev ( void )
                    607: {      
                    608: #ifdef WINUAE_FOR_HATARI
                    609:        Uint8   Level6_IRQ;
                    610: 
                    611: #if ENABLE_DSP_EMU
                    612:        Level6_IRQ = MFP_GetIRQ_CPU() | DSP_GetHREQ();
                    613: #else
                    614:        Level6_IRQ = MFP_GetIRQ_CPU();
                    615: #endif
                    616:        if ( Level6_IRQ == 1 )
                    617:                pendingInterrupts |= (1 << 6);
                    618:        else
                    619:                pendingInterrupts &= ~(1 << 6);
                    620: 
                    621:        if ( pendingInterrupts )
                    622:                doint();
                    623:        else
                    624:                M68000_UnsetSpecial ( SPCFLAG_INT | SPCFLAG_DOINT );
                    625: 
                    626:        /* Temporary case for WinUAE CPU in CE mode */
                    627:        /* doint() will update regs.ipl_pin, so copy it into regs.ipl */
                    628:        if ( ConfigureParams.System.bCycleExactCpu )
                    629:                regs.ipl = regs.ipl_pin;                        /* See ipl_fetch() in cpu/cpu_prefetch.h */
                    630: #endif
                    631: }
                    632: 
                    633: 
                    634: 
                    635: 
1.1.1.8   root      636: /*-----------------------------------------------------------------------*/
1.1.1.12  root      637: /**
1.1.1.23  root      638:  * There are some wait states when accessing certain hardware registers on the ST.
                    639:  * This function simulates these wait states and add the corresponding cycles.
                    640:  *
1.1.1.12  root      641:  * [NP] with some instructions like CLR, we have a read then a write at the
                    642:  * same location, so we may have 2 wait states (read and write) to add
1.1.1.23  root      643:  * (WaitStateCycles should be reset to 0 after all the cycles were added
                    644:  * in run_xx() in newcpu.c).
                    645:  *
                    646:  * - When CPU runs in cycle exact mode, wait states are added immediately.
                    647:  * - For other less precise modes, all the wait states are cumulated and added
                    648:  *   after the instruction was processed.
1.1.1.12  root      649:  */
1.1.1.23  root      650: void M68000_WaitState(int WaitCycles)
1.1.1.8   root      651: {
1.1.1.23  root      652: #ifndef WINUAE_FOR_HATARI
                    653:        WaitStateCycles += WaitCycles;                          /* Cumulate all the wait states for this instruction */
1.1.1.11  root      654: 
1.1.1.23  root      655: #else
                    656:        if ( ConfigureParams.System.bCycleExactCpu )
                    657:                currcycle += ( WaitCycles * CYCLE_UNIT / 2 );   /* Add wait states immediately to the CE cycles counter */
                    658:        else
                    659:        {
                    660:                WaitStateCycles += WaitCycles;                  /* Cumulate all the wait states for this instruction */
                    661:        }
                    662: #endif
1.1.1.8   root      663: }
1.1.1.20  root      664: 
                    665: 
                    666: 
                    667: /*-----------------------------------------------------------------------*/
                    668: /**
                    669:  * Some components (HBL/VBL interrupts, access to the ACIA) require an
                    670:  * extra delay to be synchronized with the E Clock.
                    671:  * E Clock's frequency is 1/10th of the CPU, ie 0.8 MHz in an STF/STE
                    672:  * This delay is a multiple of 2 and will follow the pattern [ 0 8 6 4 2 ]
                    673:  */
                    674: int    M68000_WaitEClock ( void )
                    675: {
                    676:        int     CyclesToNextE;
                    677: 
                    678:        /* We must wait for the next multiple of 10 cycles to be synchronised with E Clock */
1.1.1.21  root      679:        CyclesToNextE = 10 - CyclesGlobalClockCounter % 10;
1.1.1.20  root      680:        if ( CyclesToNextE == 10 )              /* we're already synchronised with E Clock */
                    681:                CyclesToNextE = 0;
                    682:        return CyclesToNextE;
                    683: }
                    684: 
                    685: 
                    686: 
1.1.1.22  root      687: 
                    688: /*-----------------------------------------------------------------------*/
                    689: /**
1.1.1.23  root      690:  * Some hardware registers can only be accessed on a 4 cycles boundary
                    691:  * (shifter color regs and shifter res reg).
                    692:  * An extra delay should be added when needed if current cycle
                    693:  * count is not multiple of 4.
                    694:  */
                    695: static void    M68000_SyncCpuBus ( bool read )
                    696: {
                    697:        Uint64  Cycles;
                    698:        int     CyclesToNextBus;
                    699: 
                    700:        if ( read )
                    701:                Cycles = Cycles_GetClockCounterOnReadAccess();
                    702:        else
                    703:                Cycles = Cycles_GetClockCounterOnWriteAccess();
                    704: 
                    705:        CyclesToNextBus = Cycles & 3;
                    706: //fprintf ( stderr , "sync bus %lld %d\n" , Cycles, CyclesToNextBus );
                    707:        if ( CyclesToNextBus != 0 )
                    708:        {
                    709: //fprintf ( stderr , "sync bus wait %lld %d\n" ,Cycles, 4-CyclesToNextBus );
                    710:                M68000_WaitState ( 4 - CyclesToNextBus );
                    711:        }
                    712: }
                    713: 
                    714: 
                    715: void   M68000_SyncCpuBus_OnReadAccess ( void )
                    716: {
                    717:        M68000_SyncCpuBus ( true );
                    718: }
                    719: 
                    720: 
                    721: void   M68000_SyncCpuBus_OnWriteAccess ( void )
                    722: {
                    723:        M68000_SyncCpuBus ( false );
                    724: }
                    725: 
                    726: 
                    727: 
                    728: 
                    729: /*-----------------------------------------------------------------------*/
                    730: /**
1.1.1.22  root      731:  * In case we modified the memory by accessing it directly (and bypassing
                    732:  * the CPU's cache mechanism), we need to flush the instruction and data
                    733:  * caches to force an update of the caches on the next accesses.
                    734:  *
                    735:  * [NP] NOTE : for now, flush_instr_caches and flush_dcache flush
                    736:  * the whole caches, not just 'addr'
                    737:  */
                    738: void   M68000_Flush_All_Caches ( uaecptr addr , int size )
                    739: {
1.1.1.24! root      740: //fprintf ( stderr , "M68000_Flush_All_Caches\n" );
1.1.1.22  root      741: #ifdef WINUAE_FOR_HATARI
1.1.1.24! root      742:        flush_cpu_caches(true);
        !           743:        invalidate_cpu_data_caches();
1.1.1.22  root      744: #endif
                    745: }
                    746: 
                    747: 
                    748: void   M68000_Flush_Instr_Cache ( uaecptr addr , int size )
                    749: {
1.1.1.24! root      750: //fprintf ( stderr , "M68000_Flush_Instr_Cache\n" );
1.1.1.22  root      751: #ifdef WINUAE_FOR_HATARI
                    752:        /* Instruction cache for cpu >= 68020 */
1.1.1.24! root      753:        flush_cpu_caches(true);
1.1.1.22  root      754: #endif
                    755: }
                    756: 
                    757: 
                    758: void   M68000_Flush_Data_Cache ( uaecptr addr , int size )
                    759: {
1.1.1.24! root      760: //fprintf ( stderr , "M68000_Flush_Data_Cache\n" );
1.1.1.22  root      761: #ifdef WINUAE_FOR_HATARI
1.1.1.24! root      762:        /* Data cache for cpu >= 68030 */
        !           763:        invalidate_cpu_data_caches();
1.1.1.22  root      764: #endif
                    765: }
                    766: 
                    767: 
                    768: 
1.1.1.23  root      769: /*-----------------------------------------------------------------------*/
                    770: /**
1.1.1.24! root      771:  * When running in 68000 CE mode, allow to change the "do_cycles" functions
        !           772:  * in the cpu emulation depending on the blitter state.
        !           773:  *  - if the blitter is not busy, we keep the 'normal' 68000 CE "do_cycles" functions
        !           774:  *  - if the blitter is busy, we use a slightly slower "do_cycles" to accurately
        !           775:  *    count bus accesses made by the blitter and the CPU
        !           776:  *
        !           777:  * This limits the overhead of emulating cycle exact blitter bus accesses when blitter is OFF.
        !           778:  */
        !           779: void   M68000_SetBlitter_CE ( bool state )
        !           780: {
        !           781: #ifdef WINUAE_FOR_HATARI
        !           782: //fprintf ( stderr , "M68000_SetBlitter_CE state=%s\n" , state ? "on" : "off" );
        !           783:        if ( state )
        !           784:        {
        !           785:                set_x_funcs_hatari_blitter ( 1 );               /* on */
        !           786:        }
        !           787:        else
        !           788:        {
        !           789:                set_x_funcs_hatari_blitter ( 0 );               /* off */
        !           790:        }
        !           791: #endif
        !           792: }
        !           793: 
        !           794: 
        !           795: /*-----------------------------------------------------------------------*/
        !           796: /**
1.1.1.23  root      797:  * On real STF/STE hardware, DMA accesses are restricted to 4 MB (video addresses,
                    798:  * FDC, STE DMA sound) in the range 0 - $3fffff (22 bits of address)
                    799:  * When STF/STE are expanded beyond 4 MB, some special '_FRB' cookies variables
                    800:  * need to be set in TOS to allocate an intermediate buffer in lower 4 MB
                    801:  * that will be used to transfer data in RAM between 4 MB and 16 MB.
                    802:  * This buffer is needed because real HW can't access RAM beyond 4 MB.
                    803:  *
                    804:  * In Hatari, we allow DMA addresses to use 24 bits when RAM size is set
                    805:  * to 8 or 16 MB. This way any program / TOS version can make use of extra
                    806:  * RAM beyond 4 MB without requiring an intermediate buffer.
                    807:  *
                    808:  * But it should be noted that programs using 24 bits of DMA addresses would
                    809:  * not work on real HW ; this is just to make RAM expansion more transparent
                    810:  * under emulation.
                    811:  *
                    812:  * We return a mask for bits 16-23 :
                    813:  *  - 0x3f for compatibility with real HW and limit of 4 MB
                    814:  *  - 0xff to allow DMA addresses beyond 4 MB (or for Falcon / TT)
                    815:  */
                    816: int    DMA_MaskAddressHigh ( void )
                    817: {
                    818:        if (Config_IsMachineTT() || Config_IsMachineFalcon())
                    819:                return 0xff;                                    /* Falcon / TT can access 24 bits with DMA */
                    820: 
1.1.1.24! root      821:        else if (ConfigureParams.Memory.STRamSize_KB > 4*1024)  /* ST/STE with more than 4 MB */
1.1.1.23  root      822:                return 0xff;                                    /* Allow 'fake' 24 bits for DMA */
                    823: 
                    824:        else                                                    /* ST/STE with <= 4 MB */
                    825:                return 0x3f;                                    /* Limit DMA range to 22 bits (same as real HW) */
                    826: }
                    827: 
                    828: 
                    829: 
                    830: 
                    831: /*-----------------------------------------------------------------------*/
                    832: /**
                    833:  * This function should be called when the cpu freq is changed, to update
                    834:  * other components that depend on it.
                    835:  *
                    836:  * For now, only Falcon mode requires some updates for the crossbar
                    837:  */
                    838: void   M68000_ChangeCpuFreq ( void )
                    839: {
                    840:        if ( Config_IsMachineFalcon() )
                    841:        {
                    842:                Crossbar_Recalculate_Clocks_Cycles();
                    843:        }
                    844: }
1.1.1.24! root      845: 
        !           846: 
        !           847: 
        !           848: 
        !           849: /*-----------------------------------------------------------------------*/
        !           850: /**
        !           851:  * Some CPU registers can't be read or modified directly, some additional
        !           852:  * actions are required.
        !           853:  */
        !           854: Uint16 M68000_GetSR ( void )
        !           855: {
        !           856:        MakeSR();
        !           857:        return regs.sr;
        !           858: }
        !           859: 
        !           860: void   M68000_SetSR ( Uint16 v )
        !           861: {
        !           862:        regs.sr = v;
        !           863:        MakeFromSR();
        !           864: }
        !           865: 
        !           866: void   M68000_SetPC ( uaecptr v )
        !           867: {
        !           868:        m68k_setpc ( v );
        !           869: #ifdef WINUAE_FOR_HATARI
        !           870:        fill_prefetch();
        !           871: #else
        !           872:        refill_prefetch (m68k_getpc(), 0);
        !           873: #endif
        !           874: }
        !           875: 
        !           876: 

unix.superglobalmegacorp.com

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