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

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.12  root       64: 
1.1.1.14  root       65: const char M68000_fileid[] = "Hatari m68000.c : " __DATE__ " " __TIME__;
1.1       root       66: 
                     67: #include "main.h"
1.1.1.12  root       68: #include "configuration.h"
1.1       root       69: #include "gemdos.h"
1.1.1.6   root       70: #include "hatari-glue.h"
1.1.1.16  root       71: #include "cycInt.h"
1.1       root       72: #include "m68000.h"
                     73: #include "memorySnapShot.h"
                     74: #include "mfp.h"
1.1.1.12  root       75: #include "options.h"
                     76: #include "savestate.h"
1.1       root       77: #include "stMemory.h"
                     78: #include "tos.h"
                     79: 
1.1.1.20  root       80: #if ENABLE_WINUAE_CPU
                     81: #include "mmu_common.h"
                     82: #endif
                     83: 
                     84: /* information about current CPU instruction */
                     85: cpu_instruction_t CpuInstruction;
1.1       root       86: 
1.1.1.12  root       87: Uint32 BusErrorAddress;         /* Stores the offending address for bus-/address errors */
                     88: Uint32 BusErrorPC;              /* Value of the PC when bus error occurs */
1.1.1.13  root       89: bool bBusErrorReadWrite;        /* 0 for write error, 1 for read error */
1.1.1.12  root       90: int nCpuFreqShift;              /* Used to emulate higher CPU frequencies: 0=8MHz, 1=16MHz, 2=32Mhz */
                     91: int nWaitStateCycles;           /* Used to emulate the wait state cycles of certain IO registers */
1.1.1.14  root       92: int BusMode = BUS_MODE_CPU;    /* Used to tell which part is owning the bus (cpu, blitter, ...) */
1.1.1.20  root       93: bool CPU_IACK = false;         /* Set to true during an exception when getting the interrupt's vector number */
1.1.1.12  root       94: 
1.1.1.16  root       95: int LastOpcodeFamily = i_NOP;  /* see the enum in readcpu.h i_XXX */
                     96: int LastInstrCycles = 0;       /* number of cycles for previous instr. (not rounded to 4) */
                     97: int Pairing = 0;               /* set to 1 if the latest 2 intr paired */
1.1.1.12  root       98: char PairingArray[ MAX_OPCODE_FAMILY ][ MAX_OPCODE_FAMILY ];
                     99: 
                    100: 
                    101: /* to convert the enum from OpcodeFamily to a readable value for pairing's debug */
                    102: const char *OpcodeName[] = { "ILLG",
                    103:        "OR","AND","EOR","ORSR","ANDSR","EORSR",
                    104:        "SUB","SUBA","SUBX","SBCD",
                    105:        "ADD","ADDA","ADDX","ABCD",
                    106:        "NEG","NEGX","NBCD","CLR","NOT","TST",
                    107:        "BTST","BCHG","BCLR","BSET",
                    108:        "CMP","CMPM","CMPA",
                    109:        "MVPRM","MVPMR","MOVE","MOVEA","MVSR2","MV2SR",
                    110:        "SWAP","EXG","EXT","MVMEL","MVMLE",
                    111:        "TRAP","MVR2USP","MVUSP2R","RESET","NOP","STOP","RTE","RTD",
                    112:        "LINK","UNLK",
                    113:        "RTS","TRAPV","RTR",
                    114:        "JSR","JMP","BSR","Bcc",
                    115:        "LEA","PEA","DBcc","Scc",
                    116:        "DIVU","DIVS","MULU","MULS",
                    117:        "ASR","ASL","LSR","LSL","ROL","ROR","ROXL","ROXR",
                    118:        "ASRW","ASLW","LSRW","LSLW","ROLW","RORW","ROXLW","ROXRW",
                    119:        "CHK","CHK2",
                    120:        "MOVEC2","MOVE2C","CAS","CAS2","DIVL","MULL",
                    121:        "BFTST","BFEXTU","BFCHG","BFEXTS","BFCLR","BFFFO","BFSET","BFINS",
                    122:        "PACK","UNPK","TAS","BKPT","CALLM","RTM","TRAPcc","MOVES",
                    123:        "FPP","FDBcc","FScc","FTRAPcc","FBcc","FSAVE","FRESTORE",
                    124:        "CINVL","CINVP","CINVA","CPUSHL","CPUSHP","CPUSHA","MOVE16",
                    125:        "MMUOP"
                    126: };
1.1.1.8   root      127: 
1.1.1.12  root      128: 
                    129: /*-----------------------------------------------------------------------*/
                    130: /**
1.1.1.13  root      131:  * Add pairing between all the bit shifting instructions and a given Opcode
                    132:  */
                    133: 
                    134: static void M68000_InitPairing_BitShift ( int OpCode )
                    135: {
                    136:        PairingArray[  i_ASR ][ OpCode ] = 1; 
                    137:        PairingArray[  i_ASL ][ OpCode ] = 1; 
                    138:        PairingArray[  i_LSR ][ OpCode ] = 1; 
                    139:        PairingArray[  i_LSL ][ OpCode ] = 1; 
                    140:        PairingArray[  i_ROL ][ OpCode ] = 1; 
                    141:        PairingArray[  i_ROR ][ OpCode ] = 1; 
                    142:        PairingArray[ i_ROXR ][ OpCode ] = 1; 
                    143:        PairingArray[ i_ROXL ][ OpCode ] = 1; 
                    144: }
                    145: 
                    146: 
                    147: /**
1.1.1.12  root      148:  * Init the pairing matrix
                    149:  * Two instructions can pair if PairingArray[ LastOpcodeFamily ][ OpcodeFamily ] == 1
                    150:  */
1.1.1.16  root      151: static void M68000_InitPairing(void)
1.1.1.12  root      152: {
                    153:        /* First, clear the matrix (pairing is false) */
                    154:        memset(PairingArray , 0 , MAX_OPCODE_FAMILY * MAX_OPCODE_FAMILY);
                    155: 
                    156:        /* Set all valid pairing combinations to 1 */
                    157:        PairingArray[  i_EXG ][ i_DBcc ] = 1;
1.1.1.13  root      158:        PairingArray[  i_EXG ][ i_MOVE ] = 1;
                    159:        PairingArray[  i_EXG ][ i_MOVEA] = 1;
                    160: 
1.1.1.12  root      161:        PairingArray[ i_CMPA ][  i_Bcc ] = 1;
                    162:        PairingArray[  i_CMP ][  i_Bcc ] = 1;
1.1.1.13  root      163: 
                    164:        M68000_InitPairing_BitShift ( i_DBcc );
                    165:        M68000_InitPairing_BitShift ( i_MOVE );
                    166:        M68000_InitPairing_BitShift ( i_MOVEA );
                    167:        M68000_InitPairing_BitShift ( i_LEA );
1.1.1.17  root      168:        M68000_InitPairing_BitShift ( i_JMP );
1.1.1.13  root      169: 
1.1.1.12  root      170:        PairingArray[ i_MULU ][ i_MOVEA] = 1; 
                    171:        PairingArray[ i_MULS ][ i_MOVEA] = 1; 
                    172:        PairingArray[ i_MULU ][ i_MOVE ] = 1; 
                    173:        PairingArray[ i_MULS ][ i_MOVE ] = 1; 
1.1.1.13  root      174: 
                    175:        PairingArray[ i_MULU ][ i_DIVU ] = 1;
                    176:        PairingArray[ i_MULU ][ i_DIVS ] = 1;
                    177:        PairingArray[ i_MULS ][ i_DIVU ] = 1;
                    178:        PairingArray[ i_MULS ][ i_DIVS ] = 1;
                    179: 
1.1.1.18  root      180:        PairingArray[ i_MULU ][ i_JSR ] = 1;
                    181:        PairingArray[ i_MULS ][ i_JSR ] = 1;
                    182: 
1.1.1.13  root      183:        PairingArray[ i_BTST ][  i_Bcc ] = 1;
                    184: 
                    185:        M68000_InitPairing_BitShift ( i_ADD );
                    186:        M68000_InitPairing_BitShift ( i_SUB );
                    187:        M68000_InitPairing_BitShift ( i_OR );
                    188:        M68000_InitPairing_BitShift ( i_AND );
                    189:        M68000_InitPairing_BitShift ( i_EOR );
                    190:        M68000_InitPairing_BitShift ( i_NOT );
                    191:        M68000_InitPairing_BitShift ( i_CLR );
                    192:        M68000_InitPairing_BitShift ( i_NEG );
                    193:        M68000_InitPairing_BitShift ( i_ADDX );
                    194:        M68000_InitPairing_BitShift ( i_SUBX );
                    195:        M68000_InitPairing_BitShift ( i_ABCD );
                    196:        M68000_InitPairing_BitShift ( i_SBCD );
1.1.1.16  root      197: 
                    198:        PairingArray[ i_ADD ][ i_MOVE ] = 1;            /* when using xx(an,dn) addr mode */
                    199:        PairingArray[ i_SUB ][ i_MOVE ] = 1;
                    200: }
                    201: 
                    202: 
                    203: /**
                    204:  * One-time CPU initialization.
                    205:  */
                    206: void M68000_Init(void)
                    207: {
                    208:        /* Init UAE CPU core */
                    209:        Init680x0();
                    210: 
                    211:        /* Init the pairing matrix */
                    212:        M68000_InitPairing();
1.1.1.12  root      213: }
1.1       root      214: 
                    215: 
1.1.1.3   root      216: /*-----------------------------------------------------------------------*/
1.1.1.12  root      217: /**
                    218:  * Reset CPU 68000 variables
                    219:  */
1.1.1.13  root      220: void M68000_Reset(bool bCold)
1.1       root      221: {
1.1.1.19  root      222: #if ENABLE_WINUAE_CPU
1.1.1.12  root      223:        if (bCold)
                    224:        {
1.1.1.19  root      225:                /* Clear registers, but we need to keep SPCFLAG_MODE_CHANGE and SPCFLAG_BRK unchanged */
                    226:                int spcFlags = regs.spcflags & (SPCFLAG_MODE_CHANGE | SPCFLAG_BRK);
1.1.1.16  root      227:                memset(&regs, 0, sizeof(regs));
1.1.1.19  root      228:                regs.spcflags = spcFlags;
1.1.1.12  root      229:        }
1.1.1.19  root      230:        /* Now reset the WINUAE CPU core */
1.1.1.20  root      231:        m68k_reset(bCold);
1.1.1.19  root      232: #else /* UAE CPU core */
                    233:        if (bCold)
                    234:        {
                    235:                /* Clear registers */
                    236:                memset(&regs, 0, sizeof(regs));
                    237:        }
                    238:        /* Now reset the UAE CPU core */
1.1.1.12  root      239:        m68k_reset();
1.1.1.17  root      240: #endif
1.1.1.14  root      241:        BusMode = BUS_MODE_CPU;
1.1.1.20  root      242:        CPU_IACK = false;
1.1.1.12  root      243: }
                    244: 
                    245: 
                    246: /*-----------------------------------------------------------------------*/
                    247: /**
1.1.1.16  root      248:  * Start 680x0 emulation
1.1.1.12  root      249:  */
                    250: void M68000_Start(void)
                    251: {
                    252:        /* Load initial memory snapshot */
                    253:        if (bLoadMemorySave)
                    254:        {
1.1.1.15  root      255:                MemorySnapShot_Restore(ConfigureParams.Memory.szMemoryCaptureFileName, false);
1.1.1.12  root      256:        }
                    257:        else if (bLoadAutoSave)
                    258:        {
1.1.1.15  root      259:                MemorySnapShot_Restore(ConfigureParams.Memory.szAutoSaveFileName, false);
1.1.1.12  root      260:        }
1.1.1.7   root      261: 
1.1.1.15  root      262:        m68k_go(true);
1.1       root      263: }
                    264: 
1.1.1.3   root      265: 
                    266: /*-----------------------------------------------------------------------*/
1.1.1.12  root      267: /**
1.1.1.17  root      268:  * Check whether CPU settings have been changed.
1.1.1.12  root      269:  */
1.1.1.17  root      270: void M68000_CheckCpuSettings(void)
1.1.1.12  root      271: {
1.1.1.17  root      272:        if (ConfigureParams.System.nCpuFreq < 12)
                    273:        {
                    274:                ConfigureParams.System.nCpuFreq = 8;
                    275:                nCpuFreqShift = 0;
                    276:        }
                    277:        else if (ConfigureParams.System.nCpuFreq > 26)
                    278:        {
                    279:                ConfigureParams.System.nCpuFreq = 32;
                    280:                nCpuFreqShift = 2;
                    281:        }
                    282:        else
                    283:        {
                    284:                ConfigureParams.System.nCpuFreq = 16;
                    285:                nCpuFreqShift = 1;
                    286:        }
1.1.1.12  root      287:        changed_prefs.cpu_level = ConfigureParams.System.nCpuLevel;
                    288:        changed_prefs.cpu_compatible = ConfigureParams.System.bCompatibleCpu;
1.1.1.17  root      289: 
                    290: #if ENABLE_WINUAE_CPU
1.1.1.19  root      291:        /* WinUAE core uses cpu_model instead of cpu_level, so we've got to
                    292:         * convert these values here: */
1.1.1.17  root      293:        switch (changed_prefs.cpu_level) {
                    294:                case 0 : changed_prefs.cpu_model = 68000; break;
                    295:                case 1 : changed_prefs.cpu_model = 68010; break;
                    296:                case 2 : changed_prefs.cpu_model = 68020; break;
                    297:                case 3 : changed_prefs.cpu_model = 68030; break;
                    298:                case 4 : changed_prefs.cpu_model = 68040; break;
                    299:                case 5 : changed_prefs.cpu_model = 68060; break;
                    300:                default: fprintf (stderr, "Init680x0() : Error, cpu_level unknown\n");
                    301:        }
1.1.1.19  root      302:        currprefs.cpu_level = changed_prefs.cpu_level;
1.1.1.17  root      303: 
                    304:        changed_prefs.address_space_24 = ConfigureParams.System.bAddressSpace24;
                    305:        changed_prefs.cpu_cycle_exact = ConfigureParams.System.bCycleExactCpu;
                    306:        changed_prefs.fpu_model = ConfigureParams.System.n_FPUType;
                    307:        changed_prefs.fpu_strict = ConfigureParams.System.bCompatibleFPU;
                    308:        changed_prefs.mmu_model = ConfigureParams.System.bMMU;
1.1.1.12  root      309: #endif
                    310:        if (table68k)
                    311:                check_prefs_changed_cpu();
                    312: }
                    313: 
                    314: 
                    315: /*-----------------------------------------------------------------------*/
                    316: /**
                    317:  * Save/Restore snapshot of CPU variables ('MemorySnapShot_Store' handles type)
                    318:  */
1.1.1.13  root      319: void M68000_MemorySnapShot_Capture(bool bSave)
1.1       root      320: {
1.1.1.12  root      321:        Uint32 savepc;
1.1.1.17  root      322: #if ENABLE_WINUAE_CPU
                    323:        int len;
                    324:        uae_u8 *chunk = 0;
                    325: #endif
1.1       root      326: 
1.1.1.12  root      327:        /* For the UAE CPU core: */
                    328:        MemorySnapShot_Store(&currprefs.address_space_24,
                    329:                             sizeof(currprefs.address_space_24));
                    330:        MemorySnapShot_Store(&regs.regs[0], sizeof(regs.regs));       /* D0-D7 A0-A6 */
                    331: 
                    332:        if (bSave)
                    333:        {
                    334:                savepc = M68000_GetPC();
                    335:                MemorySnapShot_Store(&savepc, sizeof(savepc));            /* PC */
                    336:        }
                    337:        else
                    338:        {
                    339:                MemorySnapShot_Store(&savepc, sizeof(savepc));            /* PC */
                    340:                regs.pc = savepc;
                    341: #ifdef UAE_NEWCPU_H
                    342:                regs.prefetch_pc = regs.pc + 128;
                    343: #endif
                    344:        }
1.1.1.8   root      345: 
1.1.1.12  root      346: #ifdef UAE_NEWCPU_H
                    347:        MemorySnapShot_Store(&regs.prefetch, sizeof(regs.prefetch));  /* prefetch */
                    348: #else
                    349:        uae_u32 prefetch_dummy;
                    350:        MemorySnapShot_Store(&prefetch_dummy, sizeof(prefetch_dummy));
                    351: #endif
                    352: 
                    353:        if (bSave)
                    354:        {
                    355:                MakeSR();
                    356:                if (regs.s)
                    357:                {
                    358:                        MemorySnapShot_Store(&regs.usp, sizeof(regs.usp));    /* USP */
                    359:                        MemorySnapShot_Store(&regs.regs[15], sizeof(regs.regs[15]));  /* ISP */
                    360:                }
                    361:                else
                    362:                {
                    363:                        MemorySnapShot_Store(&regs.regs[15], sizeof(regs.regs[15]));  /* USP */
                    364:                        MemorySnapShot_Store(&regs.isp, sizeof(regs.isp));    /* ISP */
                    365:                }
                    366:                MemorySnapShot_Store(&regs.sr, sizeof(regs.sr));          /* SR/CCR */
                    367:        }
                    368:        else
                    369:        {
                    370:                MemorySnapShot_Store(&regs.usp, sizeof(regs.usp));
                    371:                MemorySnapShot_Store(&regs.isp, sizeof(regs.isp));
                    372:                MemorySnapShot_Store(&regs.sr, sizeof(regs.sr));
                    373:        }
                    374:        MemorySnapShot_Store(&regs.stopped, sizeof(regs.stopped));
                    375:        MemorySnapShot_Store(&regs.dfc, sizeof(regs.dfc));            /* DFC */
                    376:        MemorySnapShot_Store(&regs.sfc, sizeof(regs.sfc));            /* SFC */
                    377:        MemorySnapShot_Store(&regs.vbr, sizeof(regs.vbr));            /* VBR */
1.1.1.17  root      378: #if ENABLE_WINUAE_CPU
                    379:        MemorySnapShot_Store(&regs.caar, sizeof(regs.caar));          /* CAAR */
                    380:        MemorySnapShot_Store(&regs.cacr, sizeof(regs.cacr));          /* CACR */
                    381: #else
1.1.1.12  root      382:        MemorySnapShot_Store(&caar, sizeof(caar));                    /* CAAR */
                    383:        MemorySnapShot_Store(&cacr, sizeof(cacr));                    /* CACR */
1.1.1.17  root      384: #endif
1.1.1.12  root      385:        MemorySnapShot_Store(&regs.msp, sizeof(regs.msp));            /* MSP */
                    386: 
                    387:        if (!bSave)
                    388:        {
                    389:                M68000_SetPC(regs.pc);
                    390:                /* MakeFromSR() must not swap stack pointer */
                    391:                regs.s = (regs.sr >> 13) & 1;
                    392:                MakeFromSR();
                    393:                /* set stack pointer */
                    394:                if (regs.s)
                    395:                        m68k_areg(regs, 7) = regs.isp;
                    396:                else
                    397:                        m68k_areg(regs, 7) = regs.usp;
                    398:        }
                    399: 
1.1.1.17  root      400: #if ENABLE_WINUAE_CPU
                    401:        if (bSave)
                    402:                save_fpu(&len,0);
                    403:        else
                    404:                restore_fpu(chunk);
                    405: #else
1.1.1.12  root      406:        if (bSave)
                    407:                save_fpu();
                    408:        else
                    409:                restore_fpu();
1.1.1.17  root      410: #endif
1.1       root      411: }
                    412: 
                    413: 
1.1.1.3   root      414: /*-----------------------------------------------------------------------*/
1.1.1.12  root      415: /**
                    416:  * BUSERROR - Access outside valid memory range.
1.1.1.17  root      417:  * Use bRead = 0 for write errors and bRead = 1 for read errors!
1.1.1.12  root      418:  */
1.1.1.17  root      419: void M68000_BusError(Uint32 addr, bool bRead)
1.1       root      420: {
1.1.1.12  root      421:        /* FIXME: In prefetch mode, m68k_getpc() seems already to point to the next instruction */
                    422:        // BusErrorPC = M68000_GetPC();         /* [NP] We set BusErrorPC in m68k_run_1 */
1.1.1.7   root      423: 
1.1.1.15  root      424:        /* Do not print message when TOS is testing for available HW or
                    425:         * when a program just checks for the floating point co-processor. */
                    426:        if ((BusErrorPC < TosAddress || BusErrorPC > TosAddress + TosSize)
                    427:            && addr != 0xfffa42)
1.1.1.12  root      428:        {
1.1.1.15  root      429:                /* Print bus error message */
1.1.1.17  root      430:                fprintf(stderr, "M68000 Bus Error %s at address $%x.\n",
                    431:                        bRead ? "reading" : "writing", addr);
1.1.1.12  root      432:        }
                    433: 
                    434:        if ((regs.spcflags & SPCFLAG_BUSERROR) == 0)    /* [NP] Check that the opcode has not already generated a read bus error */
                    435:        {
                    436:                BusErrorAddress = addr;                         /* Store for exception frame */
1.1.1.17  root      437:                bBusErrorReadWrite = bRead;
1.1.1.20  root      438: #if ENABLE_WINUAE_CPU
                    439:                if (currprefs.mmu_model) {
                    440:                        THROW(2);
                    441:                        return;
                    442:                }
                    443: #endif
1.1.1.12  root      444:                M68000_SetSpecial(SPCFLAG_BUSERROR);            /* The exception will be done in newcpu.c */
                    445:        }
1.1       root      446: }
                    447: 
1.1.1.3   root      448: 
                    449: /*-----------------------------------------------------------------------*/
1.1.1.12  root      450: /**
                    451:  * Exception handler
                    452:  */
1.1.1.13  root      453: void M68000_Exception(Uint32 ExceptionVector , int ExceptionSource)
1.1.1.12  root      454: {
                    455:        int exceptionNr = ExceptionVector/4;
                    456: 
1.1.1.16  root      457:        if ((ExceptionSource == M68000_EXC_SRC_AUTOVEC)
                    458:                && (exceptionNr>24 && exceptionNr<32))  /* 68k autovector interrupt? */
1.1.1.12  root      459:        {
                    460:                /* Handle autovector interrupts the UAE's way
                    461:                 * (see intlev() and do_specialties() in UAE CPU core) */
                    462:                /* In our case, this part is only called for HBL and VBL interrupts */
                    463:                int intnr = exceptionNr - 24;
                    464:                pendingInterrupts |= (1 << intnr);
                    465:                M68000_SetSpecial(SPCFLAG_INT);
                    466:        }
1.1.1.13  root      467: 
                    468:        else                                                    /* MFP or direct CPU exceptions */
1.1.1.12  root      469:        {
                    470:                Uint16 SR;
                    471: 
                    472:                /* Was the CPU stopped, i.e. by a STOP instruction? */
                    473:                if (regs.spcflags & SPCFLAG_STOP)
                    474:                {
                    475:                        regs.stopped = 0;
                    476:                        M68000_UnsetSpecial(SPCFLAG_STOP);    /* All is go,go,go! */
                    477:                }
                    478: 
                    479:                /* 68k exceptions are handled by Exception() of the UAE CPU core */
1.1.1.17  root      480: #if ENABLE_WINUAE_CPU
                    481:                Exception(exceptionNr, m68k_getpc(), ExceptionSource);
                    482: #else
1.1.1.12  root      483: #ifdef UAE_NEWCPU_H
1.1.1.13  root      484:                Exception(exceptionNr, m68k_getpc(), ExceptionSource);
1.1.1.12  root      485: #else
                    486:                Exception(exceptionNr, &regs, m68k_getpc(&regs));
                    487: #endif
1.1.1.17  root      488: #endif
1.1.1.12  root      489:                SR = M68000_GetSR();
                    490: 
                    491:                /* Set Status Register so interrupt can ONLY be stopped by another interrupt
                    492:                 * of higher priority! */
1.1.1.16  root      493:                if (ExceptionSource == M68000_EXC_SRC_INT_MFP)
1.1.1.12  root      494:                {
1.1.1.20  root      495:                        // FIXME : this test is useless, per design mfp.c will always give an address in the correct range
1.1.1.12  root      496:                        Uint32 MFPBaseVector = (unsigned int)(MFP_VR&0xf0)<<2;
                    497:                        if ( (ExceptionVector>=MFPBaseVector) && (ExceptionVector<=(MFPBaseVector+0x3c)) )
                    498:                                SR = (SR&SR_CLEAR_IPL)|0x0600; /* MFP, level 6 */
                    499:                }
1.1.1.16  root      500:                else if (ExceptionSource == M68000_EXC_SRC_INT_DSP)
                    501:                {
                    502:                        SR = (SR&SR_CLEAR_IPL)|0x0600;     /* DSP, level 6 */
                    503:                }
1.1.1.12  root      504: 
                    505:                M68000_SetSR(SR);
                    506:        }
1.1       root      507: }
                    508: 
1.1.1.8   root      509: 
                    510: /*-----------------------------------------------------------------------*/
1.1.1.12  root      511: /**
                    512:  * There seem to be wait states when a program accesses certain hardware
                    513:  * registers on the ST. Use this function to simulate these wait states.
                    514:  * [NP] with some instructions like CLR, we have a read then a write at the
                    515:  * same location, so we may have 2 wait states (read and write) to add
                    516:  * (nWaitStateCycles should be reset to 0 after the cycles were added).
                    517:  */
1.1.1.11  root      518: void M68000_WaitState(int nCycles)
1.1.1.8   root      519: {
1.1.1.12  root      520:        M68000_SetSpecial(SPCFLAG_EXTRA_CYCLES);
1.1.1.11  root      521: 
1.1.1.12  root      522:        nWaitStateCycles += nCycles;    /* add all the wait states for this instruction */
1.1.1.8   root      523: }
1.1.1.20  root      524: 
                    525: 
                    526: 
                    527: /*-----------------------------------------------------------------------*/
                    528: /**
                    529:  * Some components (HBL/VBL interrupts, access to the ACIA) require an
                    530:  * extra delay to be synchronized with the E Clock.
                    531:  * E Clock's frequency is 1/10th of the CPU, ie 0.8 MHz in an STF/STE
                    532:  * This delay is a multiple of 2 and will follow the pattern [ 0 8 6 4 2 ]
                    533:  */
                    534: 
                    535: int    M68000_WaitEClock ( void )
                    536: {
                    537:        int     CyclesToNextE;
                    538: 
                    539:        /* We must wait for the next multiple of 10 cycles to be synchronised with E Clock */
1.1.1.21! root      540:        CyclesToNextE = 10 - CyclesGlobalClockCounter % 10;
1.1.1.20  root      541:        if ( CyclesToNextE == 10 )              /* we're already synchronised with E Clock */
                    542:                CyclesToNextE = 0;
                    543:        return CyclesToNextE;
                    544: }
                    545: 
                    546: 
                    547: 

unix.superglobalmegacorp.com

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