|
|
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 ! 8: * Copyright 2000-2010 Toni Wilen ! 9: */ ! 10: ! 11: #include "sysconfig.h" ! 12: #include "sysdeps.h" ! 13: #include "compat.h" ! 14: #include "hatari-glue.h" ! 15: #include "options_cpu.h" ! 16: #include "custom.h" ! 17: #include "newcpu.h" ! 18: #include "main.h" ! 19: #include "cpummu.h" ! 20: #include "cpu_prefetch.h" ! 21: #include "m68000.h" ! 22: #include "debugui.h" ! 23: #include "debugcpu.h" ! 24: ! 25: #define WRITE_LOG_BUF_SIZE 4096 ! 26: ! 27: extern struct regstruct mmu_backup_regs; ! 28: static uae_u32 mmu_struct, mmu_callback, mmu_regs; ! 29: static uae_u32 mmu_fault_bank_addr, mmu_fault_addr; ! 30: static int mmu_fault_size, mmu_fault_rw; ! 31: static int mmu_slots; ! 32: static struct regstruct mmur; ! 33: static int userdtsc = 0; ! 34: int qpcdivisor = 0; ! 35: volatile frame_time_t vsyncmintime; ! 36: ! 37: void do_cycles_ce (long cycles); ! 38: ! 39: unsigned long int event_cycles, nextevent, is_lastline, currcycle; ! 40: uae_u32 wait_cpu_cycle_read (uaecptr addr, int mode); ! 41: void wait_cpu_cycle_write (uaecptr addr, int mode, uae_u32 v); ! 42: void wait_cpu_cycle_write_ce020 (uaecptr addr, int mode, uae_u32 v); ! 43: uae_u32 wait_cpu_cycle_read_ce020 (uaecptr addr, int mode); ! 44: frame_time_t read_processor_time_qpf (void); ! 45: frame_time_t read_processor_time_rdtsc (void); ! 46: ! 47: ! 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; ! 60: ! 61: uae_u16 dmacon; ! 62: uae_u8 cycle_line[256]; ! 63: ! 64: struct ev eventtab[ev_max]; ! 65: ! 66: void do_cycles_ce (long cycles) ! 67: { ! 68: static int extra_cycle; ! 69: ! 70: cycles += extra_cycle; ! 71: /* ! 72: while (cycles >= CYCLE_UNIT) { ! 73: int hpos = current_hpos () + 1; ! 74: sync_copper (hpos); ! 75: decide_line (hpos); ! 76: decide_fetch_ce (hpos); ! 77: if (bltstate != BLT_done) ! 78: decide_blitter (hpos); ! 79: do_cycles (1 * CYCLE_UNIT); ! 80: cycles -= CYCLE_UNIT; ! 81: } ! 82: */ ! 83: extra_cycle = cycles; ! 84: } ! 85: ! 86: void wait_cpu_cycle_write_ce020 (uaecptr addr, int mode, uae_u32 v) ! 87: { ! 88: int hpos; ! 89: ! 90: /* ! 91: hpos = dma_cycle (); ! 92: do_cycles_ce (CYCLE_UNIT); ! 93: */ ! 94: #ifdef DEBUGGER ! 95: if (debug_dma) { ! 96: int reg = 0x1100; ! 97: if (mode < 0) ! 98: reg |= 4; ! 99: else if (mode > 0) ! 100: reg |= 2; ! 101: else ! 102: reg |= 1; ! 103: record_dma (reg, v, addr, hpos, vpos, DMARECORD_CPU); ! 104: checknasty (hpos, vpos); ! 105: } ! 106: #endif ! 107: ! 108: if (mode < 0) ! 109: put_long (addr, v); ! 110: else if (mode > 0) ! 111: put_word (addr, v); ! 112: else if (mode == 0) ! 113: put_byte (addr, v); ! 114: ! 115: regs.ce020memcycles -= CYCLE_UNIT; ! 116: } ! 117: ! 118: uae_u32 wait_cpu_cycle_read_ce020 (uaecptr addr, int mode) ! 119: { ! 120: uae_u32 v = 0; ! 121: int hpos; ! 122: struct dma_rec *dr; ! 123: ! 124: /* ! 125: hpos = dma_cycle (); ! 126: do_cycles_ce (CYCLE_UNIT); ! 127: */ ! 128: ! 129: #ifdef DEBUGGER ! 130: if (debug_dma) { ! 131: int reg = 0x1000; ! 132: if (mode < 0) ! 133: reg |= 4; ! 134: else if (mode > 0) ! 135: reg |= 2; ! 136: else ! 137: reg |= 1; ! 138: dr = record_dma (reg, v, addr, hpos, vpos, DMARECORD_CPU); ! 139: checknasty (hpos, vpos); ! 140: } ! 141: #endif ! 142: if (mode < 0) ! 143: v = get_long (addr); ! 144: else if (mode > 0) ! 145: v = get_word (addr); ! 146: else if (mode == 0) ! 147: v = get_byte (addr); ! 148: ! 149: #ifdef DEBUGGER ! 150: if (debug_dma) ! 151: dr->dat = v; ! 152: #endif ! 153: ! 154: regs.ce020memcycles -= CYCLE_UNIT; ! 155: return v; ! 156: } ! 157: ! 158: uae_u32 wait_cpu_cycle_read (uaecptr addr, int mode) ! 159: { ! 160: uae_u32 v = 0; ! 161: int hpos; ! 162: struct dma_rec *dr; ! 163: ! 164: /* ! 165: hpos = dma_cycle (); ! 166: do_cycles_ce (CYCLE_UNIT); ! 167: */ ! 168: ! 169: #ifdef DEBUGGER ! 170: if (debug_dma) { ! 171: int reg = 0x1000; ! 172: if (mode < 0) ! 173: reg |= 4; ! 174: else if (mode > 0) ! 175: reg |= 2; ! 176: else ! 177: reg |= 1; ! 178: dr = record_dma (reg, v, addr, hpos, vpos, DMARECORD_CPU); ! 179: checknasty (hpos, vpos); ! 180: } ! 181: #endif ! 182: if (mode < 0) ! 183: v = get_long (addr); ! 184: else if (mode > 0) ! 185: v = get_word (addr); ! 186: else if (mode == 0) ! 187: v = get_byte (addr); ! 188: ! 189: #ifdef DEBUGGER ! 190: if (debug_dma) ! 191: dr->dat = v; ! 192: #endif ! 193: ! 194: do_cycles_ce (CYCLE_UNIT); ! 195: return v; ! 196: } ! 197: ! 198: void wait_cpu_cycle_write (uaecptr addr, int mode, uae_u32 v) ! 199: { ! 200: int hpos; ! 201: ! 202: /* ! 203: hpos = dma_cycle (); ! 204: do_cycles_ce (CYCLE_UNIT); ! 205: */ ! 206: ! 207: #ifdef DEBUGGER ! 208: if (debug_dma) { ! 209: int reg = 0x1100; ! 210: if (mode < 0) ! 211: reg |= 4; ! 212: else if (mode > 0) ! 213: reg |= 2; ! 214: else ! 215: reg |= 1; ! 216: record_dma (reg, v, addr, hpos, vpos, DMARECORD_CPU); ! 217: checknasty (hpos, vpos); ! 218: } ! 219: #endif ! 220: ! 221: if (mode < 0) ! 222: put_long (addr, v); ! 223: else if (mode > 0) ! 224: put_word (addr, v); ! 225: else if (mode == 0) ! 226: put_byte (addr, v); ! 227: do_cycles_ce (CYCLE_UNIT); ! 228: ! 229: } ! 230: ! 231: int is_cycle_ce (void) ! 232: { ! 233: int hpos = current_hpos (); ! 234: return cycle_line[hpos]; ! 235: } ! 236: ! 237: void reset_frame_rate_hack (void) ! 238: { ! 239: /* Laurent : should it be adapted or removed ? ! 240: if (currprefs.m68k_speed != -1) ! 241: return; ! 242: ! 243: if (! rpt_available) { ! 244: currprefs.m68k_speed = 0; ! 245: return; ! 246: } ! 247: ! 248: rpt_did_reset = 1; ! 249: is_lastline = 0; ! 250: vsyncmintime = read_processor_time () + vsynctime; ! 251: write_log ("Resetting frame rate hack\n"); ! 252: */ ! 253: } ! 254: ! 255: /* Code taken from main.cpp */ ! 256: void fixup_cpu (struct uae_prefs *p) ! 257: { ! 258: if (p->cpu_frequency == 1000000) ! 259: p->cpu_frequency = 0; ! 260: switch (p->cpu_model) ! 261: { ! 262: case 68000: ! 263: p->address_space_24 = 1; ! 264: if (p->cpu_compatible || p->cpu_cycle_exact) ! 265: p->fpu_model = 0; ! 266: break; ! 267: case 68010: ! 268: p->address_space_24 = 1; ! 269: if (p->cpu_compatible || p->cpu_cycle_exact) ! 270: p->fpu_model = 0; ! 271: break; ! 272: case 68020: ! 273: break; ! 274: case 68030: ! 275: p->address_space_24 = 0; ! 276: break; ! 277: case 68040: ! 278: p->address_space_24 = 0; ! 279: if (p->fpu_model) ! 280: p->fpu_model = 68040; ! 281: break; ! 282: case 68060: ! 283: p->address_space_24 = 0; ! 284: if (p->fpu_model) ! 285: p->fpu_model = 68060; ! 286: break; ! 287: } ! 288: if (p->cpu_model != 68040) ! 289: p->mmu_model = 0; ! 290: } ! 291: ! 292: /* Code taken from main.cpp*/ ! 293: void uae_reset (int hardreset) ! 294: { ! 295: currprefs.quitstatefile[0] = changed_prefs.quitstatefile[0] = 0; ! 296: ! 297: if (quit_program == 0) { ! 298: quit_program = -2; ! 299: if (hardreset) ! 300: quit_program = -3; ! 301: } ! 302: ! 303: } ! 304: ! 305: /* Code taken from debug.cpp*/ ! 306: void mmu_do_hit (void) ! 307: { ! 308: int i; ! 309: uaecptr p; ! 310: uae_u32 pc; ! 311: ! 312: mmu_triggered = 0; ! 313: pc = m68k_getpc (); ! 314: p = mmu_regs + 18 * 4; ! 315: put_long (p, pc); ! 316: regs = mmu_backup_regs; ! 317: regs.intmask = 7; ! 318: regs.t0 = regs.t1 = 0; ! 319: if (!regs.s) { ! 320: regs.usp = m68k_areg (regs, 7); ! 321: if (currprefs.cpu_model >= 68020) ! 322: m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp; ! 323: else ! 324: m68k_areg (regs, 7) = regs.isp; ! 325: regs.s = 1; ! 326: } ! 327: MakeSR (); ! 328: m68k_setpc (mmu_callback); ! 329: fill_prefetch_slow (); ! 330: ! 331: if (currprefs.cpu_model > 68000) { ! 332: for (i = 0 ; i < 9; i++) { ! 333: m68k_areg (regs, 7) -= 4; ! 334: put_long (m68k_areg (regs, 7), 0); ! 335: } ! 336: m68k_areg (regs, 7) -= 4; ! 337: put_long (m68k_areg (regs, 7), mmu_fault_addr); ! 338: m68k_areg (regs, 7) -= 2; ! 339: put_word (m68k_areg (regs, 7), 0); /* WB1S */ ! 340: m68k_areg (regs, 7) -= 2; ! 341: put_word (m68k_areg (regs, 7), 0); /* WB2S */ ! 342: m68k_areg (regs, 7) -= 2; ! 343: put_word (m68k_areg (regs, 7), 0); /* WB3S */ ! 344: m68k_areg (regs, 7) -= 2; ! 345: put_word (m68k_areg (regs, 7), ! 346: (mmu_fault_rw ? 0 : 0x100) | (mmu_fault_size << 5)); /* SSW */ ! 347: m68k_areg (regs, 7) -= 4; ! 348: put_long (m68k_areg (regs, 7), mmu_fault_bank_addr); ! 349: m68k_areg (regs, 7) -= 2; ! 350: put_word (m68k_areg (regs, 7), 0x7002); ! 351: } ! 352: m68k_areg (regs, 7) -= 4; ! 353: put_long (m68k_areg (regs, 7), get_long (p - 4)); ! 354: m68k_areg (regs, 7) -= 2; ! 355: put_word (m68k_areg (regs, 7), mmur.sr); ! 356: #ifdef JIT ! 357: set_special(SPCFLAG_END_COMPILE); ! 358: #endif ! 359: } ! 360: ! 361: /* Code taken from win32.cpp*/ ! 362: void fpux_restore (int *v) ! 363: { ! 364: /*#ifndef _WIN64 ! 365: if (v) ! 366: _controlfp (*v, _MCW_IC | _MCW_RC | _MCW_PC); ! 367: else ! 368: _controlfp (fpucontrol, _MCW_IC | _MCW_RC | _MCW_PC); ! 369: #endif ! 370: */ ! 371: } ! 372: ! 373: /* Code taken from win32.cpp*/ ! 374: frame_time_t read_processor_time (void) ! 375: { ! 376: #if 0 ! 377: static int cnt; ! 378: ! 379: cnt++; ! 380: if (cnt > 1000000) { ! 381: write_log(L"**************\n"); ! 382: cnt = 0; ! 383: } ! 384: #endif ! 385: if (userdtsc) ! 386: return read_processor_time_rdtsc (); ! 387: else ! 388: return read_processor_time_qpf (); ! 389: } ! 390: ! 391: /* Code taken from win32.cpp*/ ! 392: frame_time_t read_processor_time_qpf (void) ! 393: { ! 394: /* Laurent : may be coded later ! 395: LARGE_INTEGER counter; ! 396: QueryPerformanceCounter (&counter); ! 397: if (qpcdivisor == 0) ! 398: return (frame_time_t)(counter.LowPart); ! 399: return (frame_time_t)(counter.QuadPart >> qpcdivisor); ! 400: */ ! 401: } ! 402: ! 403: /* Code taken from win32.cpp*/ ! 404: frame_time_t read_processor_time_rdtsc (void) ! 405: { ! 406: frame_time_t foo = 0; ! 407: #if defined(X86_MSVC_ASSEMBLY) ! 408: frame_time_t bar; ! 409: __asm ! 410: { ! 411: rdtsc ! 412: mov foo, eax ! 413: mov bar, edx ! 414: } ! 415: /* very high speed CPU's RDTSC might overflow without this.. */ ! 416: foo >>= 6; ! 417: foo |= bar << 26; ! 418: #endif ! 419: return foo; ! 420: } ! 421: ! 422: /* Code taken from win32.cpp*/ ! 423: void sleep_millis (int ms) ! 424: { ! 425: /* Laurent : may be coded later (DSL-Delay ?) ! 426: unsigned int TimerEvent; ! 427: int start; ! 428: int cnt; ! 429: ! 430: start = read_processor_time (); ! 431: EnterCriticalSection (&cs_time); ! 432: cnt = timehandlecounter++; ! 433: if (timehandlecounter >= MAX_TIMEHANDLES) ! 434: timehandlecounter = 0; ! 435: LeaveCriticalSection (&cs_time); ! 436: TimerEvent = timeSetEvent (ms, 0, (LPTIMECALLBACK)timehandle[cnt], 0, TIME_ONESHOT | TIME_CALLBACK_EVENT_SET); ! 437: WaitForSingleObject (timehandle[cnt], ms); ! 438: ResetEvent (timehandle[cnt]); ! 439: timeKillEvent (TimerEvent); ! 440: idletime += read_processor_time () - start; ! 441: */ ! 442: } ! 443: ! 444: ! 445: /* Code just here to let newcpu.c link (original function is in inprec.cpp) */ ! 446: int inprec_open(char *fname, int record) ! 447: { ! 448: return 0; ! 449: } ! 450: ! 451: int current_hpos (void) ! 452: { ! 453: return (get_cycles () - eventtab[ev_hsync].oldcycles) / CYCLE_UNIT; ! 454: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.