Annotation of previous_trunk/src/cycInt.c, revision 1.1

1.1     ! root        1: /*
        !             2:   Hatari - cycInt.c
        !             3: 
        !             4:   This file is distributed under the GNU Public License, version 2 or at
        !             5:   your option any later version. Read the file gpl.txt for details.
        !             6: 
        !             7:   This code handles our table with callbacks for cycle accurate program
        !             8:   interruption. We add any pending callback handler into a table so that we do
        !             9:   not need to test for every possible interrupt event. We then scan
        !            10:   the list if used entries in the table and copy the one with the least cycle
        !            11:   count into the global 'PendingInterrupt' variable. This is then
        !            12:   decremented by the execution loop - rather than decrement each and every
        !            13:   entry (as the others cannot occur before this one).
        !            14:   We support three time units: CPU cycles, ticks, and microseconds.
        !            15:   Ticks are bound to CPU cycles and run at TICK_RATE MHz. Microseconds are either
        !            16:   bound to the host CPU's performance counter in real-time mode or to the emulated
        !            17:   CPU cycles if non-realtime mode.
        !            18: */
        !            19: 
        !            20: const char CycInt_fileid[] = "Previous cycInt.c : " __DATE__ " " __TIME__;
        !            21: 
        !            22: #include <stdint.h>
        !            23: #include <assert.h>
        !            24: #include "main.h"
        !            25: #include "cycInt.h"
        !            26: #include "m68000.h"
        !            27: #include "screen.h"
        !            28: #include "video.h"
        !            29: #include "sysReg.h"
        !            30: #include "esp.h"
        !            31: #include "mo.h"
        !            32: #include "ethernet.h"
        !            33: #include "dma.h"
        !            34: #include "floppy.h"
        !            35: #include "snd.h"
        !            36: #include "printer.h"
        !            37: #include "kms.h"
        !            38: #include "configuration.h"
        !            39: #include "main.h"
        !            40: #include "nd_sdl.hpp"
        !            41: 
        !            42: void (*PendingInterruptFunction)(void);
        !            43: Sint64 PendingInterruptCounter;
        !            44: int    usCheckCycles;
        !            45: 
        !            46: Sint64 nCyclesOver;
        !            47: Sint64 nCyclesMainCounter;         /* Main cycles counter, counts emulated CPU cycles sind reset */
        !            48: 
        !            49: 
        !            50: /* List of possible interrupt handlers to be store in 'PendingInterruptTable',
        !            51:  * used for 'MemorySnapShot' */
        !            52: static void (* const pIntHandlerFunctions[MAX_INTERRUPTS])(void) =
        !            53: {
        !            54:        NULL,
        !            55:        Video_InterruptHandler_VBL,
        !            56:        Hardclock_InterruptHandler,
        !            57:     Mouse_Handler,
        !            58:     ESP_InterruptHandler,
        !            59:     ESP_IO_Handler,
        !            60:     M2MDMA_IO_Handler,
        !            61:     MO_InterruptHandler,
        !            62:     MO_IO_Handler,
        !            63:     ECC_IO_Handler,
        !            64:     ENET_IO_Handler,
        !            65:     FLP_IO_Handler,
        !            66:     SND_Out_Handler,
        !            67:     SND_In_Handler,
        !            68:     Printer_IO_Handler,
        !            69:     Main_EventHandlerInterrupt,
        !            70:     nd_vbl_handler,
        !            71:     nd_video_vbl_handler,
        !            72: };
        !            73: 
        !            74: static INTERRUPTHANDLER InterruptHandlers[MAX_INTERRUPTS];
        !            75: INTERRUPTHANDLER        PendingInterrupt;
        !            76: static int              ActiveInterrupt=0;
        !            77: 
        !            78: static void CycInt_SetNewInterrupt(void);
        !            79: 
        !            80: extern Uint8 NEXTRom[0x20000];
        !            81: 
        !            82: /*-----------------------------------------------------------------------*/
        !            83: /**
        !            84:  * Reset interrupts, handlers
        !            85:  */
        !            86: void CycInt_Reset(void) {
        !            87:        int i;
        !            88: 
        !            89:        /* Reset counts */
        !            90:     PendingInterrupt.time = 0;
        !            91:        ActiveInterrupt       = 0;
        !            92:        nCyclesOver           = 0;
        !            93:     nCyclesMainCounter    = 0;
        !            94:     usCheckCycles         = 0;
        !            95:         
        !            96:        /* Reset interrupt table */
        !            97:        for (i=0; i<MAX_INTERRUPTS; i++) {
        !            98:                InterruptHandlers[i].type      = CYC_INT_NONE;
        !            99:                InterruptHandlers[i].time      = INT64_MAX;
        !           100:                InterruptHandlers[i].pFunction = pIntHandlerFunctions[i];
        !           101:        }
        !           102: }
        !           103: 
        !           104: /*-----------------------------------------------------------------------*/
        !           105: /**
        !           106:  * Find next interrupt to occur, and store to global variables for decrement
        !           107:  * in instruction decode loop.
        !           108:  * (SC) Microseconf interrupts are skipped here and handled in the decode loop.
        !           109:  */
        !           110: static void CycInt_SetNewInterrupt(void) {
        !           111:        Sint64       LowestCycleCount = INT64_MAX;
        !           112:        interrupt_id LowestInterrupt  = INTERRUPT_NULL;
        !           113:     
        !           114:        /* Find next interrupt to go off */
        !           115:        for(int i = INTERRUPT_NULL+1; i < MAX_INTERRUPTS; i++) {
        !           116:         /* Is interrupt pending? */
        !           117:         if(InterruptHandlers[i].type == CYC_INT_CPU && InterruptHandlers[i].time < LowestCycleCount) {
        !           118:             LowestCycleCount = InterruptHandlers[i].time;
        !           119:             LowestInterrupt  = i;
        !           120:         }
        !           121:        }
        !           122: 
        !           123:        /* Set new counts, active interrupt */
        !           124:     PendingInterrupt = InterruptHandlers[LowestInterrupt];
        !           125:        ActiveInterrupt  = LowestInterrupt;
        !           126: }
        !           127: 
        !           128: /*-----------------------------------------------------------------------*/
        !           129: /**
        !           130:  * Adjust all interrupt timings, MUST call CycInt_SetNewInterrupt after this.
        !           131:  */
        !           132: static void CycInt_UpdateInterrupt(void) {
        !           133:        int i;
        !           134: 
        !           135:        /* Adjust table by subtracting cycles that have passed since last update */
        !           136:        for (i = 0; i < MAX_INTERRUPTS; i++) {
        !           137:                if (InterruptHandlers[i].type == CYC_INT_CPU)
        !           138:                        InterruptHandlers[i].time -= nCyclesOver;
        !           139:        }
        !           140:     nCyclesOver = 0;
        !           141: }
        !           142: 
        !           143: /*-----------------------------------------------------------------------*/
        !           144: /**
        !           145:  * Check all microsecond interrupt timings
        !           146:  */
        !           147: bool CycInt_SetNewInterruptUs(void) {
        !           148:     Sint64 now = host_time_us();
        !           149:     if (ConfigureParams.System.bRealtime) {
        !           150:         for(int i = 0; i < MAX_INTERRUPTS; i++) {
        !           151:             if (InterruptHandlers[i].type == CYC_INT_US && now > InterruptHandlers[i].time) {
        !           152:                 PendingInterrupt = InterruptHandlers[i];
        !           153:                 PendingInterrupt.time = -1;
        !           154:                 ActiveInterrupt       = i;
        !           155:                 return true;
        !           156:             }
        !           157:         }
        !           158:     }
        !           159:     return false;
        !           160: }
        !           161: 
        !           162: /*-----------------------------------------------------------------------*/
        !           163: /**
        !           164:  * Adjust all interrupt timings as 'ActiveInterrupt' has occured, and
        !           165:  * remove from active list.
        !           166:  */
        !           167: void CycInt_AcknowledgeInterrupt(void) {
        !           168:        /* Update list cycle counts */
        !           169:        CycInt_UpdateInterrupt();
        !           170: 
        !           171:        /* Disable interrupt entry which has just occured */
        !           172:        InterruptHandlers[ActiveInterrupt].type = CYC_INT_NONE;
        !           173: 
        !           174:        /* Set new */
        !           175:        CycInt_SetNewInterrupt();
        !           176: }
        !           177: 
        !           178: /*-----------------------------------------------------------------------*/
        !           179: /**
        !           180:  * Add interrupt to occur from now.
        !           181:  */
        !           182: void CycInt_AddRelativeInterruptCycles(Sint64 CycleTime, interrupt_id Handler) {
        !           183:        assert(CycleTime >= 0);
        !           184: 
        !           185:        /* Update list cycle counts with current PendingInterruptCount before adding a new int, */
        !           186:        /* because CycInt_SetNewInterrupt can change the active int / PendingInterruptCount */
        !           187:        if ( ActiveInterrupt > 0 )
        !           188:                CycInt_UpdateInterrupt();
        !           189: 
        !           190:        InterruptHandlers[Handler].type = CYC_INT_CPU;
        !           191:        InterruptHandlers[Handler].time = CycleTime;
        !           192: 
        !           193:        /* Set new active int and compute a new value for PendingInterruptCount*/
        !           194:        CycInt_SetNewInterrupt();
        !           195: }
        !           196: 
        !           197: /*-----------------------------------------------------------------------*/
        !           198: /**
        !           199:  * Add interrupt to occur us microsencods from now
        !           200:  * Use usreal if we are in realtime mode
        !           201:  */
        !           202: void CycInt_AddRelativeInterruptUs(Sint64 us, Sint64 usreal, interrupt_id Handler) {
        !           203:     assert(us >= 0);
        !           204:     
        !           205:     if(ConfigureParams.System.bRealtime) {
        !           206:         /* Update list cycle counts with current PendingInterruptCount before adding a new int, */
        !           207:         /* because CycInt_SetNewInterrupt can change the active int / PendingInterruptCount */
        !           208:         if ( ActiveInterrupt > 0 ) CycInt_UpdateInterrupt();
        !           209:         
        !           210:         if ( usreal > 0 ) us = usreal;
        !           211:         
        !           212:         InterruptHandlers[Handler].type = CYC_INT_US;
        !           213:         InterruptHandlers[Handler].time = host_time_us() + us;
        !           214:         
        !           215:         /* Set new active int and compute a new value for PendingInterruptCount*/
        !           216:         CycInt_SetNewInterrupt();
        !           217:     } else {
        !           218:         CycInt_AddRelativeInterruptCycles(us * ConfigureParams.System.nCpuFreq, Handler);
        !           219:     }
        !           220: }
        !           221: 
        !           222: /*-----------------------------------------------------------------------*/
        !           223: /**
        !           224:  * Add interrupt to occur microseconds from now. Convert to cycles.
        !           225:  * Use UsTimeFast if we are in realtime mode.
        !           226:  */
        !           227: void CycInt_AddRelativeInterruptUsCycles(Sint64 us, Sint64 usreal, interrupt_id Handler) {
        !           228:     
        !           229:     if (ConfigureParams.System.bRealtime && usreal > 0) {
        !           230:        us = usreal;
        !           231:     }
        !           232: 
        !           233:     CycInt_AddRelativeInterruptCycles(us * ConfigureParams.System.nCpuFreq, Handler);
        !           234: }
        !           235: 
        !           236: /*-----------------------------------------------------------------------*/
        !           237: /**
        !           238:  * Remove a pending interrupt from our table
        !           239:  */
        !           240: void CycInt_RemovePendingInterrupt(interrupt_id Handler) {
        !           241:        /* Update list cycle counts, including the handler we want to remove */
        !           242:        /* to be able to resume it later */
        !           243:        CycInt_UpdateInterrupt();
        !           244: 
        !           245:        /* Stop interrupt after CycInt_UpdateInterrupt */
        !           246:        InterruptHandlers[Handler].type = CYC_INT_NONE;
        !           247: 
        !           248:        /* Set new */
        !           249:        CycInt_SetNewInterrupt();
        !           250: }
        !           251: 
        !           252: 
        !           253: /*-----------------------------------------------------------------------*/
        !           254: /**
        !           255:  * Return true if interrupt is active in list
        !           256:  */
        !           257: bool CycInt_InterruptActive(interrupt_id Handler)
        !           258: {
        !           259:     return InterruptHandlers[Handler].type != CYC_INT_NONE;
        !           260: }

unix.superglobalmegacorp.com

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