📄 newcpu.c
字号:
/***************************************************************************** XCopilotThis code is part of XCopilot, a port of copilot Portions of this code are Copyright (C) 1997 Ivan A. Curtis icurtis@radlogic.com.auThe original MS-Windows95 copilot emulator was written by Greg Hewgill.The following copyright notice appeared on the original copilot sources: Copyright (c) 1996 Greg Hewgill MC68000 Emulation code is from Bernd Schmidt's Unix Amiga Emulator. The following copyright notice appeared in those files: Original UAE code Copyright (c) 1995 Bernd SchmidtThis code must not be distributed without these copyright notices intact.**************************************************************************************************************************************************************Filename: newcpu.cDescription: MC68000 emulationUpdate History: (most recent first) Ian Goldberg 10-Apr-97 16:53 -- added support for logging flow traces I. Curtis 26-Feb-97 15:00 -- modified from win95 version******************************************************************************/#include <assert.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include "sysdeps.h"#include "shared.h"#include "memory.h"#include "custom.h"#include "newcpu.h"#include "dragonball.h"int areg_byteinc[] = { 1,1,1,1,1,1,1,2 };int imm8_table[] = { 8,1,2,3,4,5,6,7 };UWORD *InstructionStart_p;shared_img *Shptr;int exectrace = 0;#ifdef COUNT_INSTRSstatic unsigned long int instrcount[65536];static UWORD opcodenums[65536];int compfn(const void *el1, const void *el2){ return instrcount[*(const UWORD *)el1] < instrcount[*(const UWORD *)el2];}void dump_counts(void){ FILE *f = fopen("insncount", "w"); unsigned long int total = 0; int i; for(i=0; i < 65536; i++) { opcodenums[i] = i; total += instrcount[i]; } qsort(opcodenums, 65536, sizeof(UWORD), compfn); fprintf(f, "Total: %ld\n", total); for(i=0; i < 65536; i++) { unsigned long int cnt = instrcount[opcodenums[i]]; if (!cnt) break; fprintf(f, "%04x: %ld\n", opcodenums[i], cnt); } fclose(f);}#endif#ifdef INTEL_FLAG_OPTunion flagu intel_flag_lookup[256];#endifvoid fatal(char *file, int line){ if (file) { fprintf(stderr, "Fatal(%s,%d)\n", file, line); return; } Shptr->CpuReq = cpuExit; exit(1);}UWORD nextiword(void){ UWORD r = *(Shptr->regs).pc_p++; return r;}ULONG nextilong(void){ ULONG r = *(Shptr->regs).pc_p++; r = (r << 16) + *(Shptr->regs).pc_p++; return r;}void MC68000_setpc(CPTR newpc){ if (!get_real_address(newpc)) { fprintf(stderr, "FATAL: weird setpc(%08lx) at %08lx!\n", (unsigned long)newpc, MC68000_getpc()); abort(); } if (Shptr->logF) { fprintf(Shptr->logF, "setpc %08lx -> %08lx\n", MC68000_getpc(), (unsigned long)newpc); } (Shptr->regs).pc = newpc; (Shptr->regs).pc_p = (Shptr->regs).pc_oldp = get_real_address(newpc);}CPTR MC68000_getpc(void){ return (Shptr->regs).pc + ((char *)(Shptr->regs).pc_p - (char *)(Shptr->regs).pc_oldp);}void MC68000_setstopped(int stop){ (Shptr->regs).stopped = stop; if (stop) specialflags |= SPCFLAG_STOP;}int cctrue(const int cc){ switch(cc) { case 0: return 1; /* T */ case 1: return 0; /* F */ case 2: return !CFLG && !ZFLG; /* HI */ case 3: return CFLG || ZFLG; /* LS */ case 4: return !CFLG; /* CC */ case 5: return CFLG; /* CS */ case 6: return !ZFLG; /* NE */ case 7: return ZFLG; /* EQ */ case 8: return !VFLG; /* VC */ case 9: return VFLG; /* VS */ case 10:return !NFLG; /* PL */ case 11:return NFLG; /* MI */ case 12:return NFLG == VFLG; /* GE */ case 13:return NFLG != VFLG; /* LT */ case 14:return !ZFLG && (NFLG == VFLG); /* GT */ case 15:return ZFLG || (NFLG != VFLG); /* LE */ } fatal(NULL, 0); return 0;}extern ULONG get_disp_ea (ULONG base, UWORD dp){ int reg = (dp >> 12) & 7; LONG regd; if (dp & 0x8000) regd = (Shptr->regs).a[reg]; else regd = (Shptr->regs).d[reg]; if (!(dp & 0x800)) regd = (LONG)(WORD)regd; return base + (BYTE)(dp) + regd;}void MC68000_setshare(shared_img *shptr){ Shptr = shptr;}void MC68000_init(shared_img *shptr){ Shptr = shptr;#ifdef COUNT_INSTRS memset(instrcount, 0, sizeof instrcount);#endif#ifdef INTEL_FLAG_OPT for (i = 0; i < 256; i++) { intel_flag_lookup[i].flags.c = !!(i & 1); intel_flag_lookup[i].flags.z = !!(i & 64); intel_flag_lookup[i].flags.n = !!(i & 128); intel_flag_lookup[i].flags.v = 0; }#endif /* printf("Building CPU table...\n"); read_table68k (); do_merges (); for (opcode = 0; opcode < 65536; opcode++) cpufunctbl[opcode] = op_illg; for (i = 0; smallcputbl[i].handler != NULL; i++) { if (!smallcputbl[i].specific) cpufunctbl[smallcputbl[i].opcode] = smallcputbl[i].handler; } for (opcode = 0; opcode < 65536; opcode++) { cpuop_func *f; if (table68k[opcode].mnemo == i_ILLG) continue; if (table68k[opcode].handler != -1) { f = cpufunctbl[table68k[opcode].handler]; if (f == op_illg) fatal(NULL, 0); cpufunctbl[opcode] = f; } } for (i = 0; smallcputbl[i].handler != NULL; i++) { if (smallcputbl[i].specific) cpufunctbl[smallcputbl[i].opcode] = smallcputbl[i].handler; }*/}/************ these two moved into shared_imgstruct regstruct regs;union flagu regflags;********************************************/#if CPU_LEVEL > 1ULONG get_disp_ea (ULONG base, UWORD dp){ int reg = (dp >> 12) & 7; LONG regd; if (dp & 0x8000) regd = (Shptr->regs).a[reg]; else regd = (Shptr->regs).d[reg]; if (!(dp & 0x800)) regd = (LONG)(WORD)regd; if (dp & 0x100) { LONG extraind = 0; printf("020\n"); regd <<= (dp >> 9) & 3; if (dp & 0x80) base = 0; if (dp & 0x40) regd = 0; if ((dp & 0x30) == 0x20) base += (LONG)(WORD)nextiword(); if ((dp & 0x30) == 0x30) base += nextilong(); if ((dp & 0x3) == 0x2) extraind = (LONG)(WORD)nextiword(); if ((dp & 0x3) == 0x3) extraind = nextilong(); if (!(dp & 4)) base += regd; if (dp & 3) base = get_long (base); if (dp & 4) base += regd; return base + extraind; /* Yikes, that's complicated */ } else { return base + (BYTE)(dp) + regd; }}#endifvoid MakeSR(void){#if 0 assert((NFLG & 1) == NFLG); assert(((Shptr->regs).s & 1) == (Shptr->regs).s); assert(((Shptr->regs).x & 1) == (Shptr->regs).x); assert((CFLG & 1) == CFLG); assert((VFLG & 1) == VFLG); assert((ZFLG & 1) == ZFLG);#endif (Shptr->regs).sr = (((Shptr->regs).t << 15) | ((Shptr->regs).s << 13) | ((Shptr->regs).intmask << 8) | ((Shptr->regs).x << 4) | (NFLG << 3) | (ZFLG << 2) | (VFLG << 1) | CFLG);}void MakeFromSR(void){ int olds = (Shptr->regs).s; (Shptr->regs).t = ((Shptr->regs).sr >> 15) & 1; (Shptr->regs).s = ((Shptr->regs).sr >> 13) & 1; (Shptr->regs).intmask = ((Shptr->regs).sr >> 8) & 7; (Shptr->regs).x = ((Shptr->regs).sr >> 4) & 1; NFLG = ((Shptr->regs).sr >> 3) & 1; ZFLG = ((Shptr->regs).sr >> 2) & 1; VFLG = ((Shptr->regs).sr >> 1) & 1; CFLG = (Shptr->regs).sr & 1; if (olds != (Shptr->regs).s) { CPTR temp = (Shptr->regs).usp; (Shptr->regs).usp = (Shptr->regs).a[7]; (Shptr->regs).a[7] = temp; } specialflags |= SPCFLAG_INT; if ((Shptr->regs).t) specialflags |= SPCFLAG_TRACE; else specialflags &= ~(SPCFLAG_TRACE | SPCFLAG_DOTRACE);}void MC68000_exception(int nr){ if (nr < 48 && Shptr->ExceptionFlags[nr] && InstructionStart_p) { (Shptr->regs).pc_p = InstructionStart_p; Shptr->CpuState = cpuException + nr; return; } if (nr == 32 + 0xF && do_api(*(Shptr->regs).pc_p)) { nextiword(); return; } MakeSR(); if (!(Shptr->regs).s) { CPTR temp = (Shptr->regs).usp; (Shptr->regs).usp = (Shptr->regs).a[7]; (Shptr->regs).a[7] = temp; (Shptr->regs).s = 1; } if (CPU_LEVEL > 0) { (Shptr->regs).a[7] -= 2; put_word ((Shptr->regs).a[7], nr * 4); } (Shptr->regs).a[7] -= 4; put_long ((Shptr->regs).a[7], MC68000_getpc ()); (Shptr->regs).a[7] -= 2; put_word ((Shptr->regs).a[7], (Shptr->regs).sr); MC68000_setpc(get_long(4*nr)); (Shptr->regs).t = 0; specialflags &= ~(SPCFLAG_TRACE | SPCFLAG_DOTRACE);}static void MC68000_interrupt(int nr){ assert(nr < 8 && nr >= 0); MC68000_exception(nr + intbase()); (Shptr->regs).intmask = nr; specialflags |= SPCFLAG_INT;}void MC68000_reset(void){ (Shptr->regs).a[7] = get_long(0x10c00000); MC68000_setpc(get_long(0x10c00004)); (Shptr->regs).s = 1; (Shptr->regs).stopped = 0; (Shptr->regs).t = 0; specialflags = 0; Shptr->CpuState = cpuStopped; (Shptr->regs).intmask = 7; customreset();}void op_illg(ULONG opcode){ (Shptr->regs).pc_p--; if ((opcode & 0xF000) == 0xF000) { if ((opcode & 0xE00) == 0x200) MC68000_exception(0xB); else switch (opcode & 0x1FF) { case 0x17: (Shptr->regs).pc_p+=2; break; default: (Shptr->regs).pc_p++; } return; } if ((opcode & 0xF000) == 0xA000) { MC68000_exception(0xA); return; } if (opcode == 0x4AFC) { /* breakpoint */ Shptr->CpuState = cpuBreakpoint; /* * fprintf(stderr, "I - CpuState = cpuBreakpoint\n"); * fflush(stderr); */ return; } fprintf(stderr, "Illegal instruction: %04x\n", (unsigned int)opcode);fprintf(stderr, "ILL at 0x%x\n", (Shptr->regs).pc);exit(1); MC68000_exception(4);}void updateisr();void maybe_updateisr();#ifndef DEFPILOTLOG#define DEFPILOTLOG "xcopilot.log"#endifvoid MC68000_run(void){ UWORD opcode; int i; Shptr->CpuState = cpuRunning; /* start running */ for(;;) {// fprintf(stderr, "."); fflush(stderr); if (Shptr->CpuReq != cpuNone) { /* check for a request */// fprintf(stderr, "not None %d\n", Shptr->CpuReq); fflush(stderr); return; /* bail out if requested */ } if (Shptr->dolog == !Shptr->logF) { /* We need to turn logging on or off */ if (Shptr->dolog) { char *pilotdir = getenv("XCOPILOTDIR"); char *fname = getenv("XCOPILOTLOG"); char *fbuf = NULL; if (!fname) fname = DEFPILOTLOG; if (fname[0] != '/' && pilotdir) { fbuf = malloc(strlen(pilotdir)+strlen(fname)+2); if (fbuf) { sprintf("%s/%s", pilotdir, fname); fname = fbuf; } } Shptr->logF = fopen(fname, "a"); if (fbuf) { free(fbuf); fbuf = NULL; } } else { fclose(Shptr->logF); Shptr->logF = NULL; } } InstructionStart_p = (Shptr->regs).pc_p; if (exectrace || check_break(MC68000_getpc())) {#if 1 // def GDB_VERBOSE fprintf(stderr,"GDB Break\n");#endif exectrace = gdb_break(MC68000_getpc(), (Shptr->regs).sr, (Shptr->regs).a, (Shptr->regs).d);#if 1 // def GDB_VERBOSE fprintf(stderr,"GDB %s\n",exectrace ? "step" : "restart"); fflush(stderr);#endif } opcode = nextiword(); (*cpufunctbl[opcode])(opcode); maybe_updateisr();if (buserr) { /* DAVIDM */ int i, j; fprintf(stderr, "BUSERR at 0x%x\n\r", MC68000_getpc()); fprintf(stderr, "SR 0x%.8x\n\r", (Shptr->regs).sr); for (i=0;i<8;i++) fprintf(stderr,"A%d[0x%.8x] ",i,(Shptr->regs).a[i]); fprintf(stderr,"\n\r"); for (i=0;i<8;i++) fprintf(stderr,"D%d[0x%.8x] ",i,(Shptr->regs).d[i]); fprintf(stderr,"\n\r"); for (i = 0; i < 128; ) { fprintf(stderr, "0x%8x: ", (Shptr->regs).a[7] + i); for (j = 0; i < 128 && j < 4; j++, i += 4) if (valid_address((Shptr->regs).a[7] + i, 4)) fprintf(stderr, "0x%8x ", get_long((Shptr->regs).a[7] + i)); else fprintf(stderr, "%10.10s ", "-"); fprintf(stderr, "\n\r"); } kill(0, 1); exit(1);}#ifndef NO_EXCEPTION_3 if (buserr) { MC68000_exception(3); buserr = 0; }#endif InstructionStart_p = NULL; do_cycles(0); if (specialflags) { if (specialflags & SPCFLAG_DOTRACE) { MC68000_exception(9); } while (specialflags & SPCFLAG_STOP) { usleep(100); maybe_updateisr(); do_cycles(1); if (specialflags & (SPCFLAG_INT | SPCFLAG_DOINT)){ int intr = intlev(); specialflags &= ~(SPCFLAG_INT | SPCFLAG_DOINT); if (intr != -1 && intr > (Shptr->regs).intmask) { MC68000_interrupt(intr); (Shptr->regs).stopped = 0; specialflags &= ~SPCFLAG_STOP; } } if (Shptr->CpuState > cpuRunning || Shptr->CpuReq != cpuNone) {// fprintf(stderr, "not None 2 %d, %d\n", Shptr->CpuReq, Shptr->CpuState); fflush(stderr); return; } } if (specialflags & SPCFLAG_TRACE) { specialflags &= ~SPCFLAG_TRACE; specialflags |= SPCFLAG_DOTRACE; } if (specialflags & SPCFLAG_DOINT) { int intr = intlev(); specialflags &= ~(SPCFLAG_INT | SPCFLAG_DOINT); if (intr != -1 && intr > (Shptr->regs).intmask) { MC68000_interrupt(intr); (Shptr->regs).stopped = 0; } } if (specialflags & SPCFLAG_INT) { specialflags &= ~SPCFLAG_INT; specialflags |= SPCFLAG_DOINT; } if (specialflags & SPCFLAG_BRK) { specialflags &= ~SPCFLAG_BRK; return; } } if (Shptr->CpuState > cpuRunning) {// fprintf(stderr, "not None 3 %d\n", Shptr->CpuState); fflush(stderr); return; } }}void MC68000_step(void){ specialflags |= SPCFLAG_BRK; MC68000_run();}void MC68000_skip(CPTR nextpc){ specialflags |= SPCFLAG_BRK; do { MC68000_step(); } while (nextpc != MC68000_getpc()); Shptr->CpuState = cpuStopped;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -