Annotation of previous/src/cycInt.c, revision 1.1.1.5

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
1.1.1.5 ! root       11:   count into the global 'PendingInterrupt' variable. This is then
1.1       root       12:   decremented by the execution loop - rather than decrement each and every
                     13:   entry (as the others cannot occur before this one).
1.1.1.5 ! root       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.
1.1       root       18: */
                     19: 
1.1.1.5 ! root       20: const char CycInt_fileid[] = "Previous cycInt.c : " __DATE__ " " __TIME__;
1.1       root       21: 
                     22: #include <stdint.h>
                     23: #include <assert.h>
                     24: #include "main.h"
                     25: #include "cycInt.h"
                     26: #include "m68000.h"
1.1.1.2   root       27: #include "screen.h"
1.1       root       28: #include "video.h"
1.1.1.3   root       29: #include "sysReg.h"
1.1.1.4   root       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"
1.1.1.5 ! root       38: #include "configuration.h"
        !            39: #include "main.h"
        !            40: #include "nd_sdl.h"
1.1       root       41: 
                     42: void (*PendingInterruptFunction)(void);
1.1.1.5 ! root       43: Sint64 PendingInterruptCounter;
        !            44: int    usCheckCycles;
        !            45: 
        !            46: Sint64 nCyclesOver;
        !            47: Sint64 nCyclesMainCounter;         /* Main cycles counter, counts emulated CPU cycles sind reset */
1.1       root       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,
1.1.1.2   root       55:        Video_InterruptHandler_VBL,
1.1.1.4   root       56:        Hardclock_InterruptHandler,
                     57:     Mouse_Handler,
                     58:     ESP_InterruptHandler,
                     59:     ESP_IO_Handler,
1.1.1.5 ! root       60:     M2MDMA_IO_Handler,
1.1.1.4   root       61:     MO_InterruptHandler,
                     62:     MO_IO_Handler,
                     63:     ECC_IO_Handler,
                     64:     ENET_IO_Handler,
                     65:     FLP_IO_Handler,
1.1.1.5 ! root       66:     SND_Out_Handler,
        !            67:     SND_In_Handler,
        !            68:     Printer_IO_Handler,
        !            69:     Main_EventHandlerInterrupt,
        !            70:     nd_vbl_handler,
        !            71:     nd_video_vbl_handler,
1.1       root       72: };
                     73: 
                     74: static INTERRUPTHANDLER InterruptHandlers[MAX_INTERRUPTS];
1.1.1.5 ! root       75: INTERRUPTHANDLER        PendingInterrupt;
        !            76: static int              ActiveInterrupt=0;
1.1       root       77: 
                     78: static void CycInt_SetNewInterrupt(void);
                     79: 
1.1.1.5 ! root       80: extern Uint8 NEXTRom[0x20000];
        !            81: 
1.1       root       82: /*-----------------------------------------------------------------------*/
                     83: /**
                     84:  * Reset interrupts, handlers
                     85:  */
1.1.1.5 ! root       86: void CycInt_Reset(void) {
1.1       root       87:        int i;
                     88: 
                     89:        /* Reset counts */
1.1.1.5 ! root       90:     PendingInterrupt.time = 0;
        !            91:        ActiveInterrupt       = 0;
        !            92:        nCyclesOver           = 0;
        !            93:     nCyclesMainCounter    = 0;
        !            94:     usCheckCycles         = 0;
        !            95:         
1.1       root       96:        /* Reset interrupt table */
1.1.1.5 ! root       97:        for (i=0; i<MAX_INTERRUPTS; i++) {
        !            98:                InterruptHandlers[i].type      = CYC_INT_NONE;
        !            99:                InterruptHandlers[i].time      = INT64_MAX;
1.1       root      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.
1.1.1.5 ! root      108:  * (SC) Microseconf interrupts are skipped here and handled in the decode loop.
1.1       root      109:  */
1.1.1.5 ! root      110: static void CycInt_SetNewInterrupt(void) {
        !           111:        Sint64       LowestCycleCount = INT64_MAX;
        !           112:        interrupt_id LowestInterrupt  = INTERRUPT_NULL;
        !           113:     
1.1       root      114:        /* Find next interrupt to go off */
1.1.1.5 ! root      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:         }
1.1       root      121:        }
                    122: 
                    123:        /* Set new counts, active interrupt */
1.1.1.5 ! root      124:     PendingInterrupt = InterruptHandlers[LowestInterrupt];
        !           125:        ActiveInterrupt  = LowestInterrupt;
1.1       root      126: }
                    127: 
                    128: /*-----------------------------------------------------------------------*/
                    129: /**
                    130:  * Adjust all interrupt timings, MUST call CycInt_SetNewInterrupt after this.
                    131:  */
1.1.1.5 ! root      132: static void CycInt_UpdateInterrupt(void) {
1.1       root      133:        int i;
                    134: 
1.1.1.5 ! root      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;
1.1       root      141: }
                    142: 
1.1.1.5 ! root      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: }
1.1       root      161: 
                    162: /*-----------------------------------------------------------------------*/
                    163: /**
                    164:  * Adjust all interrupt timings as 'ActiveInterrupt' has occured, and
                    165:  * remove from active list.
                    166:  */
1.1.1.5 ! root      167: void CycInt_AcknowledgeInterrupt(void) {
1.1       root      168:        /* Update list cycle counts */
                    169:        CycInt_UpdateInterrupt();
                    170: 
                    171:        /* Disable interrupt entry which has just occured */
1.1.1.5 ! root      172:        InterruptHandlers[ActiveInterrupt].type = CYC_INT_NONE;
1.1       root      173: 
                    174:        /* Set new */
                    175:        CycInt_SetNewInterrupt();
                    176: }
                    177: 
                    178: /*-----------------------------------------------------------------------*/
                    179: /**
1.1.1.5 ! root      180:  * Add interrupt to occur from now.
1.1       root      181:  */
1.1.1.5 ! root      182: void CycInt_AddRelativeInterruptCycles(Sint64 CycleTime, interrupt_id Handler) {
1.1       root      183:        assert(CycleTime >= 0);
                    184: 
1.1.1.2   root      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 )
1.1       root      188:                CycInt_UpdateInterrupt();
                    189: 
1.1.1.5 ! root      190:        InterruptHandlers[Handler].type = CYC_INT_CPU;
        !           191:        InterruptHandlers[Handler].time = CycleTime;
1.1       root      192: 
1.1.1.2   root      193:        /* Set new active int and compute a new value for PendingInterruptCount*/
1.1       root      194:        CycInt_SetNewInterrupt();
                    195: }
                    196: 
                    197: /*-----------------------------------------------------------------------*/
                    198: /**
1.1.1.5 ! root      199:  * Add interrupt to occur us microsencods from now
        !           200:  * Use usreal if we are in realtime mode
1.1       root      201:  */
1.1.1.5 ! root      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:     }
1.1       root      220: }
                    221: 
                    222: /*-----------------------------------------------------------------------*/
                    223: /**
1.1.1.5 ! root      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:     }
1.1       root      232: 
1.1.1.5 ! root      233:     CycInt_AddRelativeInterruptCycles(us * ConfigureParams.System.nCpuFreq, Handler);
1.1       root      234: }
                    235: 
                    236: /*-----------------------------------------------------------------------*/
                    237: /**
                    238:  * Remove a pending interrupt from our table
                    239:  */
1.1.1.5 ! root      240: void CycInt_RemovePendingInterrupt(interrupt_id Handler) {
1.1       root      241:        /* Update list cycle counts, including the handler we want to remove */
1.1.1.5 ! root      242:        /* to be able to resume it later */
1.1       root      243:        CycInt_UpdateInterrupt();
                    244: 
1.1.1.5 ! root      245:        /* Stop interrupt after CycInt_UpdateInterrupt */
        !           246:        InterruptHandlers[Handler].type = CYC_INT_NONE;
1.1       root      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: {
1.1.1.5 ! root      259:     return InterruptHandlers[Handler].type != CYC_INT_NONE;
1.1       root      260: }

unix.superglobalmegacorp.com

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