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