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