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

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"
1.1.1.6 ! root       40: #include "nd_sdl.hpp"
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.6 ! root      108:  * (SC) Microsecond 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.