|
|
1.1 root 1: /*
2: Hatari - cycles.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: Here we take care of cycle counters. For performance reasons we don't increase
8: all counters after each 68k instruction, but only one main counter.
9: When we need to read one of the normal counters (currently only for video
10: and sound cycles), we simply update these counters with the main counter
11: before returning the current counter value.
12: */
1.1.1.2 root 13:
14:
15: /* 2007/03/xx [NP] Use 'CurrentInstrCycles' to get a good approximation for */
16: /* Cycles_GetCounterOnReadAccess and Cycles_GetCounterOnWriteAccess*/
17: /* (this should work correctly with 'move' instruction). */
1.1.1.3 root 18: /* 2008/04/14 [NP] Take nWaitStateCycles into account when computing the value of */
19: /* Cycles_GetCounterOnReadAccess and Cycles_GetCounterOnWriteAccess*/
1.1.1.4 root 20: /* 2008/12/21 [NP] Use BusMode to adjust Cycles_GetCounterOnReadAccess and */
21: /* Cycles_GetCounterOnWriteAccess depending on who is owning the */
22: /* bus (cpu, blitter). */
1.1.1.6 root 23: /* 2011/03/26 [NP] In Cycles_GetCounterOnReadAccess, add a special case for opcode */
24: /* $11f8 'move.b xxx.w,xxx.w' (fix MOVE.B $ffff8209.w,$26.w in */
25: /* 'Bird Mad Girl Show' demo's loader/protection) */
1.1.1.2 root 26:
27:
1.1.1.4 root 28: const char Cycles_fileid[] = "Hatari cycles.c : " __DATE__ " " __TIME__;
1.1 root 29:
30: #include "main.h"
1.1.1.3 root 31: #include "m68000.h"
1.1.1.5 root 32: #include "memorySnapShot.h"
1.1 root 33: #include "cycles.h"
34:
35:
1.1.1.5 root 36: int nCyclesMainCounter; /* Main cycles counter */
1.1 root 37:
1.1.1.5 root 38: static int nCyclesCounter[CYCLES_COUNTER_MAX]; /* Array with all counters */
1.1 root 39:
1.1.1.2 root 40: int CurrentInstrCycles;
1.1.1.7 ! root 41: int MovepByteNbr; /* Number of the byte currently transferred in a movep (1..2 or 1..4) */
! 42:
1.1.1.2 root 43:
1.1 root 44:
1.1.1.5 root 45:
46: /*-----------------------------------------------------------------------*/
47: /**
48: * Save/Restore snapshot of local variables ('MemorySnapShot_Store' handles type)
49: */
50: void Cycles_MemorySnapShot_Capture(bool bSave)
51: {
52: /* Save/Restore details */
53: MemorySnapShot_Store(&nCyclesMainCounter, sizeof(nCyclesMainCounter));
54: MemorySnapShot_Store(nCyclesCounter, sizeof(nCyclesCounter));
55: MemorySnapShot_Store(&CurrentInstrCycles, sizeof(CurrentInstrCycles));
56: }
57:
58:
1.1 root 59: /*-----------------------------------------------------------------------*/
1.1.1.2 root 60: /**
61: * Update all cycles counters with the current value of nCyclesMainCounter.
62: */
1.1 root 63: static void Cycles_UpdateCounters(void)
64: {
65: int i;
66:
67: for (i = 0; i < CYCLES_COUNTER_MAX; i++)
68: {
69: nCyclesCounter[i] += nCyclesMainCounter;
70: }
71:
72: nCyclesMainCounter = 0;
73: }
74:
75:
76: /*-----------------------------------------------------------------------*/
1.1.1.2 root 77: /**
78: * Set a counter to a new value.
79: */
1.1 root 80: void Cycles_SetCounter(int nId, int nValue)
81: {
82: /* Update counters first (nCyclesMainCounter must be 0 afterwards) */
83: Cycles_UpdateCounters();
84:
85: /* Now set the new value: */
86: nCyclesCounter[nId] = nValue;
87: }
88:
89:
90: /*-----------------------------------------------------------------------*/
1.1.1.2 root 91: /**
92: * Read a counter.
93: */
1.1 root 94: int Cycles_GetCounter(int nId)
95: {
96: /* Update counters first so we read an up-to-date value */
97: Cycles_UpdateCounters();
98:
99: return nCyclesCounter[nId];
100: }
101:
102:
103: /*-----------------------------------------------------------------------*/
1.1.1.2 root 104: /**
105: * Read a counter on CPU memory read access by taking care of the instruction
106: * type (add the needed amount of additional cycles).
107: */
1.1 root 108: int Cycles_GetCounterOnReadAccess(int nId)
109: {
110: int nAddCycles;
1.1.1.6 root 111: int Opcode;
1.1 root 112:
113: /* Update counters first so we read an up-to-date value */
114: Cycles_UpdateCounters();
115:
1.1.1.4 root 116: if ( BusMode == BUS_MODE_BLITTER )
117: {
118: nAddCycles = 4 + nWaitStateCycles;
119: }
120: else /* BUS_MODE_CPU */
121: {
122: /* TODO: Find proper cycles count depending on the type of the current instruction */
123: /* (e.g. movem is not correctly handled) */
1.1.1.6 root 124: Opcode = get_word(BusErrorPC);
125: //fprintf ( stderr , "opcode=%x\n" , Opcode );
126:
127: /* Assume we use 'move src,dst' : access cycle depends on dst mode */
128: if ( Opcode == 0x11f8 ) /* move.b xxx.w,xxx.w (eg MOVE.B $ffff8209.w,$26.w in Bird Mad Girl Show) */
129: nAddCycles = CurrentInstrCycles + nWaitStateCycles - 8; /* read is effective before the 8 write cycles for dst */
1.1.1.7 ! root 130: else if ( OpcodeFamily == i_MVPRM ) /* eg movep.l d0,$ffc3(a1) in E605 (STE) */
! 131: nAddCycles = 12 + MovepByteNbr * 4; /* [NP] FIXME, it works with E605 but gives 20-32 cycles instead of 16-28 */
! 132: /* something must be wrong in video.c */
1.1.1.6 root 133: else
134: nAddCycles = CurrentInstrCycles + nWaitStateCycles; /* assume dest is reg : read is effective at the end of the instr */
1.1.1.4 root 135: }
1.1 root 136:
137: return nCyclesCounter[nId] + nAddCycles;
138: }
139:
140:
141: /*-----------------------------------------------------------------------*/
1.1.1.2 root 142: /**
143: * Read a counter on CPU memory write access by taking care of the instruction
144: * type (add the needed amount of additional cycles).
145: */
1.1 root 146: int Cycles_GetCounterOnWriteAccess(int nId)
147: {
148: int nAddCycles;
149:
150: /* Update counters first so we read an up-to-date value */
151: Cycles_UpdateCounters();
152:
1.1.1.4 root 153: if ( BusMode == BUS_MODE_BLITTER )
154: {
155: nAddCycles = 4 + nWaitStateCycles;
156: }
157: else /* BUS_MODE_CPU */
158: {
159: /* TODO: Find proper cycles count depending on the type of the current instruction */
160: /* (e.g. movem is not correctly handled) */
161: nAddCycles = CurrentInstrCycles + nWaitStateCycles;
162:
1.1.1.7 ! root 163: if ( OpcodeFamily == i_CLR ) /* should also be the case for add, sub, and, or, eor, neg, not */
! 164: ; /* Do nothing, the write is done during the last 4 cycles */
! 165: /* (e.g bottom border removal in No Scroll / Delirious Demo 4) */
! 166: else
! 167: {
! 168: /* assume the behaviour of a 'move' (since this is the most */
! 169: /* common instr used when requiring cycle precise writes) */
! 170: if ( nAddCycles >= 8 )
! 171: nAddCycles -= 4; /* last 4 cycles are for prefetch */
! 172: }
1.1.1.4 root 173: }
1.1 root 174:
175: return nCyclesCounter[nId] + nAddCycles;
176: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.