|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * Custom chip emulation
5: *
6: * Copyright 1995-2002 Bernd Schmidt
7: * Copyright 1995 Alessandro Bissacco
1.1.1.5 root 8: * Copyright 2000-2014 Toni Wilen
1.1 root 9: */
10:
11: #include "sysconfig.h"
12: #include "sysdeps.h"
13: #include "compat.h"
14: #include "hatari-glue.h"
15: #include "options_cpu.h"
1.1.1.5 root 16: #include "events.h"
1.1 root 17: #include "custom.h"
18: #include "newcpu.h"
19: #include "main.h"
20: #include "cpummu.h"
21: #include "m68000.h"
22: #include "debugui.h"
23: #include "debugcpu.h"
1.1.1.5 root 24: #ifdef WINUAE_FOR_HATARI
25: #include "debug.h"
1.1.1.7 ! root 26: #include "blitter.h"
1.1.1.5 root 27: #endif
1.1 root 28:
29: #define WRITE_LOG_BUF_SIZE 4096
30:
1.1.1.3 root 31: /* TODO: move custom.c stuff declarations to custom.h? */
32:
1.1.1.5 root 33: #ifdef WINUAE_FOR_HATARI
34: /* declared in newcpu.c */
1.1 root 35: extern struct regstruct mmu_backup_regs;
1.1.1.5 root 36: /* declared in events.h */
37: unsigned long currcycle;
38: /* declared in savestate.h */
39: int savestate_state = 0;
40: #endif
1.1.1.3 root 41:
42:
1.1.1.5 root 43: uae_u16 dmacon;
1.1 root 44:
1.1.1.5 root 45: static int extra_cycle;
1.1 root 46:
1.1.1.5 root 47: #if 0
1.1 root 48: typedef struct _LARGE_INTEGER
49: {
50: union
51: {
52: struct
53: {
54: unsigned long LowPart;
55: long HighPart;
56: };
57: int64_t QuadPart;
58: };
59: } LARGE_INTEGER, *PLARGE_INTEGER;
1.1.1.5 root 60: #endif
1.1 root 61:
62:
1.1.1.5 root 63: #ifdef CPUEMU_13
1.1 root 64:
1.1.1.7 ! root 65: #ifndef WINUAE_FOR_HATARI
1.1.1.5 root 66: uae_u8 cycle_line[256 + 1];
1.1.1.2 root 67:
1.1.1.5 root 68: static void sync_ce020 (void)
69: {
70: unsigned long c;
71: int extra;
1.1.1.2 root 72:
1.1.1.5 root 73: c = get_cycles ();
74: extra = c & (CYCLE_UNIT - 1);
75: if (extra) {
76: extra = CYCLE_UNIT - extra;
77: do_cycles (extra);
78: }
1.1 root 79: }
80:
1.1.1.5 root 81: #define SETIFCHIP \
82: if (addr < 0xd80000) \
83: last_custom_value1 = v;
84: #endif /* WINUAE_FOR_HATARI */
85:
86: uae_u32 wait_cpu_cycle_read (uaecptr addr, int mode)
1.1 root 87: {
1.1.1.5 root 88: uae_u32 v = 0;
89: #ifndef WINUAE_FOR_HATARI
1.1 root 90: int hpos;
91:
92: hpos = dma_cycle ();
1.1.1.5 root 93: x_do_cycles_pre (CYCLE_UNIT);
94:
1.1 root 95: #ifdef DEBUGGER
1.1.1.5 root 96: struct dma_rec *dr = NULL;
1.1 root 97: if (debug_dma) {
1.1.1.5 root 98: int reg = 0x1000;
1.1 root 99: if (mode < 0)
100: reg |= 4;
101: else if (mode > 0)
102: reg |= 2;
103: else
104: reg |= 1;
1.1.1.5 root 105: dr = record_dma (reg, v, addr, hpos, vpos, DMARECORD_CPU);
1.1 root 106: checknasty (hpos, vpos);
107: }
108: #endif
1.1.1.5 root 109: if (mode < 0)
110: v = get_long (addr);
111: else if (mode > 0)
112: v = get_word (addr);
113: else if (mode == 0)
114: v = get_byte (addr);
115:
116: #ifdef DEBUGGER
117: if (debug_dma)
118: dr->dat = v;
119: #endif
120:
121: x_do_cycles_post (CYCLE_UNIT, v);
122:
123: regs.chipset_latch_rw = regs.chipset_latch_read = v;
124: SETIFCHIP
125:
126: #else /* WINUAE_FOR_HATARI */
1.1.1.6 root 127: // fprintf ( stderr , "mem read ce %x %d %lu %lu\n" , addr , mode ,currcycle / cpucycleunit , currcycle );
128: if ( ( ( CyclesGlobalClockCounter + currcycle*2/CYCLE_UNIT ) & 3 ) == 2 )
129: {
130: // fprintf ( stderr , "mem wait read %x %d %lu %lu\n" , addr , mode , currcycle / cpucycleunit , currcycle );
131: x_do_cycles (2*cpucycleunit);
132: // fprintf ( stderr , "mem wait read after %x %d %lu %lu\n" , addr , mode , currcycle / cpucycleunit , currcycle );
133: }
1.1 root 134:
135: if (mode < 0)
1.1.1.5 root 136: v = get_long (addr);
1.1 root 137: else if (mode > 0)
1.1.1.5 root 138: v = get_word (addr);
1.1 root 139: else if (mode == 0)
1.1.1.5 root 140: v = get_byte (addr);
141:
1.1.1.6 root 142: x_do_cycles_post (2*CYCLE_UNIT, v);
1.1.1.5 root 143: #endif /* WINUAE_FOR_HATARI */
1.1 root 144:
1.1.1.5 root 145: return v;
1.1 root 146: }
147:
148: uae_u32 wait_cpu_cycle_read_ce020 (uaecptr addr, int mode)
149: {
150: uae_u32 v = 0;
1.1.1.5 root 151: #ifndef WINUAE_FOR_HATARI
1.1 root 152: int hpos;
153:
1.1.1.5 root 154: sync_ce020 ();
1.1 root 155: hpos = dma_cycle ();
1.1.1.5 root 156: x_do_cycles_pre (CYCLE_UNIT);
1.1 root 157:
158: #ifdef DEBUGGER
1.1.1.5 root 159: struct dma_rec *dr = NULL;
1.1 root 160: if (debug_dma) {
161: int reg = 0x1000;
162: if (mode < 0)
163: reg |= 4;
164: else if (mode > 0)
165: reg |= 2;
166: else
167: reg |= 1;
168: dr = record_dma (reg, v, addr, hpos, vpos, DMARECORD_CPU);
169: checknasty (hpos, vpos);
170: }
171: #endif
172: if (mode < 0)
173: v = get_long (addr);
174: else if (mode > 0)
175: v = get_word (addr);
176: else if (mode == 0)
177: v = get_byte (addr);
178:
179: #ifdef DEBUGGER
180: if (debug_dma)
181: dr->dat = v;
182: #endif
1.1.1.5 root 183: if (currprefs.cpu_model == 68020)
184: x_do_cycles_post (CYCLE_UNIT / 2, v);
185:
186: regs.chipset_latch_rw = regs.chipset_latch_read = v;
187: SETIFCHIP
188:
189: #else /* WINUAE_FOR_HATARI */
1.1.1.7 ! root 190:
! 191: //fprintf ( stderr , "wait read ce020 glob %lu\n" , CyclesGlobalClockCounter );
! 192: //fprintf ( stderr , "wait read ce020 %lu %lu\n" , currcycle / cpucycleunit , currcycle );
! 193: int bus_pos = ( CyclesGlobalClockCounter + currcycle*2/CYCLE_UNIT ) & 3;
! 194: if ( ( bus_pos & 2 ) == 2 )
! 195: // if ( bus_pos )
! 196: {
! 197: // fprintf ( stderr , "mem wait read %x %d %lu %lu\n" , addr , mode , currcycle / cpucycleunit , currcycle );
! 198: x_do_cycles ((4-bus_pos)*cpucycleunit);
! 199: // fprintf ( stderr , "mem wait read after %x %d %lu %lu\n" , addr , mode , currcycle / cpucycleunit , currcycle );
! 200: }
! 201:
! 202: //fprintf ( stderr , "wait read2 ce020 %lu %lu\n" , currcycle / cpucycleunit , currcycle );
1.1.1.5 root 203:
204: if (mode < 0)
205: v = get_long (addr);
206: else if (mode > 0)
207: v = get_word (addr);
208: else if (mode == 0)
209: v = get_byte (addr);
210:
1.1.1.7 ! root 211: //fprintf ( stderr , "wait read3 ce020 %lu %lu\n" , currcycle / cpucycleunit , currcycle );
! 212: x_do_cycles_post (3*cpucycleunit, v);
! 213: //fprintf ( stderr , "wait read4 ce020 %lu %lu\n" , currcycle / cpucycleunit , currcycle );
! 214:
1.1.1.5 root 215: #endif /* WINUAE_FOR_HATARI */
1.1 root 216:
217: return v;
218: }
219:
1.1.1.5 root 220: void wait_cpu_cycle_write (uaecptr addr, int mode, uae_u32 v)
1.1 root 221: {
1.1.1.5 root 222: #ifndef WINUAE_FOR_HATARI
1.1 root 223: int hpos;
224:
225: hpos = dma_cycle ();
1.1.1.5 root 226: x_do_cycles_pre (CYCLE_UNIT);
1.1 root 227:
228: #ifdef DEBUGGER
229: if (debug_dma) {
1.1.1.5 root 230: int reg = 0x1100;
1.1 root 231: if (mode < 0)
232: reg |= 4;
233: else if (mode > 0)
234: reg |= 2;
235: else
236: reg |= 1;
1.1.1.5 root 237: record_dma (reg, v, addr, hpos, vpos, DMARECORD_CPU);
1.1 root 238: checknasty (hpos, vpos);
239: }
240: #endif
1.1.1.5 root 241:
1.1 root 242: if (mode < 0)
1.1.1.5 root 243: put_long (addr, v);
1.1 root 244: else if (mode > 0)
1.1.1.5 root 245: put_word (addr, v);
1.1 root 246: else if (mode == 0)
1.1.1.5 root 247: put_byte (addr, v);
1.1 root 248:
1.1.1.5 root 249: x_do_cycles_post (CYCLE_UNIT, v);
1.1 root 250:
1.1.1.5 root 251: regs.chipset_latch_rw = regs.chipset_latch_write = v;
252: SETIFCHIP
253:
254: #else /* WINUAE_FOR_HATARI */
1.1.1.6 root 255: // fprintf ( stderr , "mem write ce %x %d %lu %lu\n" , addr , mode ,currcycle / cpucycleunit , currcycle );
256: if ( ( ( CyclesGlobalClockCounter + currcycle*2/CYCLE_UNIT ) & 3 ) == 2 )
257: {
258: // fprintf ( stderr , "mem wait write %x %d %lu %lu\n" , addr , mode , currcycle / cpucycleunit , currcycle );
259: x_do_cycles (2*cpucycleunit);
260: // fprintf ( stderr , "mem wait write after %x %d %lu %lu\n" , addr , mode , currcycle / cpucycleunit , currcycle );
261: }
1.1.1.5 root 262:
263: if (mode < 0)
264: put_long (addr, v);
265: else if (mode > 0)
266: put_word (addr, v);
267: else if (mode == 0)
268: put_byte (addr, v);
269:
1.1.1.6 root 270: x_do_cycles_post (2*CYCLE_UNIT, v);
1.1.1.5 root 271: #endif /* WINUAE_FOR_HATARI */
1.1 root 272: }
273:
1.1.1.5 root 274: void wait_cpu_cycle_write_ce020 (uaecptr addr, int mode, uae_u32 v)
1.1 root 275: {
1.1.1.5 root 276: #ifndef WINUAE_FOR_HATARI
1.1 root 277: int hpos;
278:
1.1.1.5 root 279: sync_ce020 ();
1.1 root 280: hpos = dma_cycle ();
1.1.1.5 root 281: x_do_cycles_pre (CYCLE_UNIT);
1.1 root 282:
283: #ifdef DEBUGGER
284: if (debug_dma) {
285: int reg = 0x1100;
286: if (mode < 0)
287: reg |= 4;
288: else if (mode > 0)
289: reg |= 2;
290: else
291: reg |= 1;
292: record_dma (reg, v, addr, hpos, vpos, DMARECORD_CPU);
293: checknasty (hpos, vpos);
294: }
295: #endif
296:
297: if (mode < 0)
298: put_long (addr, v);
299: else if (mode > 0)
300: put_word (addr, v);
301: else if (mode == 0)
302: put_byte (addr, v);
303:
1.1.1.5 root 304: if (currprefs.cpu_model == 68020)
305: x_do_cycles_post (CYCLE_UNIT / 2, v);
306:
307: regs.chipset_latch_rw = regs.chipset_latch_write = v;
308: SETIFCHIP
309:
310: #else /* WINUAE_FOR_HATARI */
1.1.1.7 ! root 311:
! 312: //fprintf ( stderr , "wait read ce020 %lu %lu\n" , currcycle / cpucycleunit , currcycle );
! 313: int bus_pos = ( CyclesGlobalClockCounter + currcycle*2/CYCLE_UNIT ) & 3;
! 314: if ( ( bus_pos & 2 ) == 2 )
! 315: // if ( bus_pos )
! 316: {
! 317: // fprintf ( stderr , "mem wait read %x %d %lu %lu\n" , addr , mode , currcycle / cpucycleunit , currcycle );
! 318: x_do_cycles ((4-bus_pos)*cpucycleunit);
! 319: // fprintf ( stderr , "mem wait read after %x %d %lu %lu\n" , addr , mode , currcycle / cpucycleunit , currcycle );
! 320: }
! 321:
! 322: //fprintf ( stderr , "wait read2 ce020 %lu %lu\n" , currcycle / cpucycleunit , currcycle );
1.1.1.5 root 323:
324: if (mode < 0)
325: put_long (addr, v);
326: else if (mode > 0)
327: put_word (addr, v);
328: else if (mode == 0)
329: put_byte (addr, v);
330:
1.1.1.7 ! root 331: //fprintf ( stderr , "wait read3 ce020 %lu %lu\n" , currcycle / cpucycleunit , currcycle );
! 332: x_do_cycles_post (3*cpucycleunit, v);
! 333: //fprintf ( stderr , "wait read4 ce020 %lu %lu\n" , currcycle / cpucycleunit , currcycle );
! 334:
1.1.1.5 root 335: #endif /* WINUAE_FOR_HATARI */
1.1 root 336: }
337:
1.1.1.5 root 338: void do_cycles_ce (unsigned long cycles)
1.1 root 339: {
1.1.1.5 root 340: cycles += extra_cycle;
341: while (cycles >= CYCLE_UNIT) {
342: #ifndef WINUAE_FOR_HATARI
343: int hpos = current_hpos () + 1;
344: decide_line (hpos);
345: sync_copper (hpos);
346: decide_fetch_ce (hpos);
347: if (bltstate != BLT_done)
348: decide_blitter (hpos);
349: #endif /* WINUAE_FOR_HATARI */
350: do_cycles (1 * CYCLE_UNIT);
351: cycles -= CYCLE_UNIT;
352: }
353: extra_cycle = cycles;
1.1 root 354: }
355:
1.1.1.5 root 356:
1.1.1.7 ! root 357: #ifdef WINUAE_FOR_HATARI
! 358: /* Same as do_cycles_ce() with cycle exact blitter support */
! 359: void do_cycles_ce_hatari_blitter (unsigned long cycles)
! 360: {
! 361: cycles += extra_cycle;
! 362: while (cycles >= CYCLE_UNIT) {
! 363: #ifndef WINUAE_FOR_HATARI
! 364: int hpos = current_hpos () + 1;
! 365: decide_line (hpos);
! 366: sync_copper (hpos);
! 367: decide_fetch_ce (hpos);
! 368: if (bltstate != BLT_done)
! 369: decide_blitter (hpos);
! 370: #endif /* WINUAE_FOR_HATARI */
! 371: if ( Blitter_Check_Simultaneous_CPU() == 0 )
! 372: do_cycles (1 * CYCLE_UNIT);
! 373: Blitter_HOG_CPU_do_cycles_after ( 2 );
! 374:
! 375: cycles -= CYCLE_UNIT;
! 376: }
! 377: extra_cycle = cycles;
! 378: }
! 379: #endif
! 380:
! 381:
1.1.1.5 root 382: #ifndef WINUAE_FOR_HATARI
383: void do_cycles_ce020 (unsigned long cycles)
384: #else
385: /* [NP] : confusing, because same function name as in cpu_prefetch.h with do_cycles_ce020( int ), */
386: /* but here unsigned long parameter is already multiplied by cpucycleunit. */
387: /* Requires C++, so we rename to do_cycles_ce020_long() to keep C compatibility */
388: void do_cycles_ce020_long (unsigned long cycles)
389: #endif
1.1 root 390: {
1.1.1.5 root 391: unsigned long c;
392: #ifndef WINUAE_FOR_HATARI
393: int extra;
394: #else
395: unsigned long extra; /* remove warning "comparison between signed/unsigned" */
396: #endif
1.1 root 397:
1.1.1.5 root 398: if (!cycles)
1.1 root 399: return;
1.1.1.5 root 400: c = get_cycles ();
401: extra = c & (CYCLE_UNIT - 1);
402: //fprintf ( stderr , "do_cycles_ce020_long %d %d %d\n" , cycles , c , extra );
403: if (extra) {
404: extra = CYCLE_UNIT - extra;
405: if (extra >= cycles) {
406: do_cycles (cycles);
407: return;
408: }
409: do_cycles (extra);
410: cycles -= extra;
1.1 root 411: }
1.1.1.5 root 412: c = cycles;
413: while (c) {
414: #ifndef WINUAE_FOR_HATARI
415: int hpos = current_hpos () + 1;
416: decide_line (hpos);
417: sync_copper (hpos);
418: decide_fetch_ce (hpos);
419: if (bltstate != BLT_done)
420: decide_blitter (hpos);
421: #endif /* WINUAE_FOR_HATARI */
422: if (c < CYCLE_UNIT)
423: break;
424: do_cycles (1 * CYCLE_UNIT);
425: c -= CYCLE_UNIT;
426: }
427: if (c > 0)
428: do_cycles (c);
429: }
1.1 root 430:
1.1.1.5 root 431: int is_cycle_ce (void)
432: {
433: #ifndef WINUAE_FOR_HATARI
434: int hpos = current_hpos ();
435: return cycle_line[hpos] & CYCLE_MASK;
436:
437: #else /* WINUAE_FOR_HATARI */
438: return 0;
439: #endif /* WINUAE_FOR_HATARI */
440: }
441:
442: #endif
443:
444:
445:
446: void reset_frame_rate_hack (void)
447: {
448: #ifndef WINUAE_FOR_HATARI
449: jitcount = 0;
450: if (currprefs.m68k_speed >= 0)
451: return;
452:
453: rpt_did_reset = 1;
454: is_syncline = 0;
455: vsyncmintime = read_processor_time () + vsynctimebase;
456: write_log (_T("Resetting frame rate hack\n"));
457: #endif /* WINUAE_FOR_HATARI */
1.1 root 458: }
459:
460: /* Code taken from main.cpp */
461: void fixup_cpu (struct uae_prefs *p)
462: {
463: if (p->cpu_frequency == 1000000)
464: p->cpu_frequency = 0;
1.1.1.5 root 465:
466: #ifndef WINUAE_FOR_HATARI
467: if (p->cpu_model >= 68030 && p->address_space_24) {
468: error_log (_T("24-bit address space is not supported in 68030/040/060 configurations."));
469: p->address_space_24 = 0;
470: }
471: #else
472: /* Hatari : don't force address_space_24=0 for 68030, as the Falcon has a 68030 EC with only 24 bits */
473: #endif
474: if (p->cpu_model < 68020 && p->fpu_model && (p->cpu_compatible || p->cpu_cycle_exact)) {
475: error_log (_T("FPU is not supported in 68000/010 configurations."));
476: p->fpu_model = 0;
477: }
478:
1.1 root 479: switch (p->cpu_model)
480: {
481: case 68000:
482: p->address_space_24 = 1;
483: break;
484: case 68010:
485: p->address_space_24 = 1;
486: break;
487: case 68020:
488: break;
489: case 68030:
490: break;
491: case 68040:
492: if (p->fpu_model)
493: p->fpu_model = 68040;
494: break;
495: case 68060:
496: if (p->fpu_model)
497: p->fpu_model = 68060;
498: break;
499: }
1.1.1.5 root 500:
501: if (p->cpu_model < 68020 && p->cachesize) {
502: p->cachesize = 0;
503: error_log (_T("JIT requires 68020 or better CPU."));
504: }
505:
506: if (p->cpu_model >= 68040 && p->cachesize && p->cpu_compatible)
507: p->cpu_compatible = false;
508:
509: if ((p->cpu_model < 68030 || p->cachesize) && p->mmu_model) {
510: error_log (_T("MMU emulation requires 68030/040/060 and it is not JIT compatible."));
1.1 root 511: p->mmu_model = 0;
1.1.1.5 root 512: }
513:
514: if (p->cachesize && p->cpu_cycle_exact) {
515: error_log (_T("JIT and cycle-exact can't be enabled simultaneously."));
516: p->cachesize = 0;
517: }
518: if (p->cachesize && (p->fpu_no_unimplemented || p->int_no_unimplemented)) {
519: error_log (_T("JIT is not compatible with unimplemented CPU/FPU instruction emulation."));
520: p->fpu_no_unimplemented = p->int_no_unimplemented = false;
521: }
522:
523: #ifndef WINUAE_FOR_HATARI
524: /* [NP] In Hatari, don't change m68k_speed in CE mode */
525: if (p->cpu_cycle_exact && p->m68k_speed < 0)
526: p->m68k_speed = 0;
527: #endif
528:
529: #ifndef WINUAE_FOR_HATARI
530: if (p->immediate_blits && p->blitter_cycle_exact) {
531: error_log (_T("Cycle-exact and immediate blitter can't be enabled simultaneously.\n"));
532: p->immediate_blits = false;
533: }
534: if (p->immediate_blits && p->waiting_blits) {
535: error_log (_T("Immediate blitter and waiting blits can't be enabled simultaneously.\n"));
536: p->waiting_blits = 0;
537: }
538: #endif
539: if (p->cpu_cycle_exact)
540: p->cpu_compatible = true;
1.1 root 541: }
542:
1.1.1.5 root 543:
544: void custom_reset (bool hardreset, bool keyboardreset)
545: {
546: }
547:
548:
549: // TODO NP remove ?
550: #ifndef WINUAE_FOR_HATARI
1.1 root 551: /* Code taken from main.cpp*/
552: void uae_reset (int hardreset)
553: {
554: currprefs.quitstatefile[0] = changed_prefs.quitstatefile[0] = 0;
555:
1.1.1.7 ! root 556: if (uae_quit_program == 0) {
! 557: uae_quit_program = -UAE_RESET;
! 558: if (keyboardreset)
! 559: uae_quit_program = -UAE_RESET_KEYBOARD;
1.1 root 560: if (hardreset)
1.1.1.7 ! root 561: uae_quit_program = -UAE_RESET_HARD;
1.1 root 562: }
563: #endif
1.1.1.5 root 564:
1.1 root 565:
566: /* Code taken from win32.cpp*/
567: void fpux_restore (int *v)
568: {
569: /*#ifndef _WIN64
570: if (v)
571: _controlfp (*v, _MCW_IC | _MCW_RC | _MCW_PC);
572: else
573: _controlfp (fpucontrol, _MCW_IC | _MCW_RC | _MCW_PC);
574: #endif
575: */
576: }
577:
1.1.1.5 root 578: // TODO NP remove ?
1.1 root 579: /* Code taken from win32.cpp*/
580: void sleep_millis (int ms)
581: {
1.1.1.3 root 582: /* Laurent : may be coded later (DSL-Delay ?) */
1.1 root 583: }
584:
585:
586: /* Code just here to let newcpu.c link (original function is in inprec.cpp) */
587: int inprec_open(char *fname, int record)
588: {
589: return 0;
590: }
591:
1.1.1.5 root 592: // TODO NP remove ?
593: #ifndef WINUAE_FOR_HATARI
1.1 root 594: int current_hpos (void)
595: {
596: return (get_cycles () - eventtab[ev_hsync].oldcycles) / CYCLE_UNIT;
597: }
1.1.1.5 root 598: #endif
599:
600:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.