Annotation of previous_trunk/src/cycInt.c, revision 1.1.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.