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