|
|
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: */
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). */
18: /* 2008/04/14 [NP] Take nWaitStateCycles into account when computing the value of */
19: /* Cycles_GetCounterOnReadAccess and Cycles_GetCounterOnWriteAccess*/
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.2 ! 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) */
! 26:
1.1 root 27:
28:
29: const char Cycles_fileid[] = "Hatari cycles.c : " __DATE__ " " __TIME__;
30:
31: #include "main.h"
32: #include "m68000.h"
33: #include "memorySnapShot.h"
34: #include "cycles.h"
35:
36:
37: int nCyclesMainCounter; /* Main cycles counter */
38:
39: static int nCyclesCounter[CYCLES_COUNTER_MAX]; /* Array with all counters */
40:
41: int CurrentInstrCycles;
42:
43:
44:
45: /*-----------------------------------------------------------------------*/
46: /**
47: * Save/Restore snapshot of local variables ('MemorySnapShot_Store' handles type)
48: */
49: void Cycles_MemorySnapShot_Capture(bool bSave)
50: {
51: /* Save/Restore details */
52: MemorySnapShot_Store(&nCyclesMainCounter, sizeof(nCyclesMainCounter));
53: MemorySnapShot_Store(nCyclesCounter, sizeof(nCyclesCounter));
54: MemorySnapShot_Store(&CurrentInstrCycles, sizeof(CurrentInstrCycles));
55: }
56:
57:
58: /*-----------------------------------------------------------------------*/
59: /**
60: * Update all cycles counters with the current value of nCyclesMainCounter.
61: */
62: static void Cycles_UpdateCounters(void)
63: {
64: int i;
65:
66: for (i = 0; i < CYCLES_COUNTER_MAX; i++)
67: {
68: nCyclesCounter[i] += nCyclesMainCounter;
69: }
70:
71: nCyclesMainCounter = 0;
72: }
73:
74:
75: /*-----------------------------------------------------------------------*/
76: /**
77: * Set a counter to a new value.
78: */
79: void Cycles_SetCounter(int nId, int nValue)
80: {
81: /* Update counters first (nCyclesMainCounter must be 0 afterwards) */
82: Cycles_UpdateCounters();
83:
84: /* Now set the new value: */
85: nCyclesCounter[nId] = nValue;
86: }
87:
88:
89: /*-----------------------------------------------------------------------*/
90: /**
91: * Read a counter.
92: */
93: int Cycles_GetCounter(int nId)
94: {
95: /* Update counters first so we read an up-to-date value */
96: Cycles_UpdateCounters();
97:
98: return nCyclesCounter[nId];
99: }
100:
101:
102: /*-----------------------------------------------------------------------*/
103: /**
104: * Read a counter on CPU memory read access by taking care of the instruction
105: * type (add the needed amount of additional cycles).
106: */
107: int Cycles_GetCounterOnReadAccess(int nId)
108: {
109: int nAddCycles;
1.1.1.2 ! root 110: int Opcode;
1.1 root 111:
112: /* Update counters first so we read an up-to-date value */
113: Cycles_UpdateCounters();
114:
115: if ( BusMode == BUS_MODE_BLITTER )
116: {
117: nAddCycles = 4 + nWaitStateCycles;
118: }
119: else /* BUS_MODE_CPU */
120: {
121: /* TODO: Find proper cycles count depending on the type of the current instruction */
122: /* (e.g. movem is not correctly handled) */
1.1.1.2 ! root 123: Opcode = get_word(BusErrorPC);
! 124: //fprintf ( stderr , "opcode=%x\n" , Opcode );
! 125:
! 126: /* Assume we use 'move src,dst' : access cycle depends on dst mode */
! 127: if ( Opcode == 0x11f8 ) /* move.b xxx.w,xxx.w (eg MOVE.B $ffff8209.w,$26.w in Bird Mad Girl Show) */
! 128: nAddCycles = CurrentInstrCycles + nWaitStateCycles - 8; /* read is effective before the 8 write cycles for dst */
! 129: else
! 130: nAddCycles = CurrentInstrCycles + nWaitStateCycles; /* assume dest is reg : read is effective at the end of the instr */
1.1 root 131: }
132:
133: return nCyclesCounter[nId] + nAddCycles;
134: }
135:
136:
137: /*-----------------------------------------------------------------------*/
138: /**
139: * Read a counter on CPU memory write access by taking care of the instruction
140: * type (add the needed amount of additional cycles).
141: */
142: int Cycles_GetCounterOnWriteAccess(int nId)
143: {
144: int nAddCycles;
145:
146: /* Update counters first so we read an up-to-date value */
147: Cycles_UpdateCounters();
148:
149: if ( BusMode == BUS_MODE_BLITTER )
150: {
151: nAddCycles = 4 + nWaitStateCycles;
152: }
153: else /* BUS_MODE_CPU */
154: {
155: /* TODO: Find proper cycles count depending on the type of the current instruction */
156: /* (e.g. movem is not correctly handled) */
157: nAddCycles = CurrentInstrCycles + nWaitStateCycles;
158:
159: /* assume the behaviour of a 'move' (since this is the most */
160: /* common instr used when requiring cycle precise writes) */
161: if ( nAddCycles >= 8 )
162: nAddCycles -= 4; /* last 4 cycles are for prefetch */
163: }
164:
165: return nCyclesCounter[nId] + nAddCycles;
166: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.