more vjaguar cleanup

This commit is contained in:
CasualPokePlayer 2022-09-28 03:24:48 -07:00
parent 80cf3a0c48
commit 6388e4a0a8
23 changed files with 67 additions and 35268 deletions

Binary file not shown.

View File

@ -356,7 +356,7 @@ EXPORT void GetRegisters(u32* regs)
{
for (u32 i = 0; i < 18; i++)
{
regs[i] = m68k_get_reg(NULL, (m68k_register_t)i);
regs[i] = m68k_get_reg((m68k_register_t)i);
}
memcpy(&regs[18], gpu_reg_bank_0, 128);
memcpy(&regs[50], gpu_reg_bank_1, 128);

View File

@ -336,7 +336,7 @@ static void ResetCallbacks(void)
static void LoadISRStub(void)
{
uint32_t isrAddr = m68k_get_reg(NULL, M68K_REG_A0);
uint32_t isrAddr = m68k_get_reg(M68K_REG_A0);
uint32_t addr = 0xF03010;
#define WRITE_GASM(x) do { GPUWriteWord(addr, x, M68K); addr += 2; } while (0)
@ -405,7 +405,7 @@ void CDHLEHook(uint32_t which)
static void CD_init(void)
{
fprintf(stderr, "CD_init called %08X\n", m68k_get_reg(NULL, M68K_REG_A0));
fprintf(stderr, "CD_init called %08X\n", m68k_get_reg(M68K_REG_A0));
LoadISRStub();
cd_initm = false;
}
@ -414,7 +414,7 @@ static void CD_mode(void)
{
// bit 0 = speed (0 = single, 1 = double)
// bit 1 = mode (0 = audio, 1 = data)
cd_mode = m68k_get_reg(NULL, M68K_REG_D0) & 3;
cd_mode = m68k_get_reg(M68K_REG_D0) & 3;
fprintf(stderr, "CD_mode mode = %d, speed = %d\n", cd_mode >> 1, cd_mode & 1);
NO_ERR();
}
@ -426,7 +426,7 @@ static void CD_ack(void)
static void CD_jeri(void)
{
bool njerry = m68k_get_reg(NULL, M68K_REG_D0) & 1;
bool njerry = m68k_get_reg(M68K_REG_D0) & 1;
if (cd_jerry ^ njerry)
{
fprintf(stderr, "changing jerry mode %d -> %d\n", cd_jerry, njerry);
@ -437,7 +437,7 @@ static void CD_jeri(void)
static void CD_spin(void)
{
fprintf(stderr, "CD_spin: new session %04X\n", m68k_get_reg(NULL, M68K_REG_D1) & 0xFFFF);
fprintf(stderr, "CD_spin: new session %04X\n", m68k_get_reg(M68K_REG_D1) & 0xFFFF);
NO_ERR();
}
@ -486,8 +486,8 @@ static void CD_upaus(void)
static void CD_read(void)
{
uint32_t dstStart = m68k_get_reg(NULL, M68K_REG_A0);
uint32_t dstEnd = m68k_get_reg(NULL, M68K_REG_A1);
uint32_t dstStart = m68k_get_reg(M68K_REG_A0);
uint32_t dstEnd = m68k_get_reg(M68K_REG_A1);
fprintf(stderr, "CD READ: dstStart %08X, dstEnd %08X\n", dstStart, dstEnd);
@ -498,7 +498,7 @@ static void CD_read(void)
return;
}
uint32_t timecode = m68k_get_reg(NULL, M68K_REG_D0);
uint32_t timecode = m68k_get_reg(M68K_REG_D0);
uint32_t frames = timecode & 0xFF;
uint32_t seconds = (timecode >> 8) & 0xFF;
@ -517,8 +517,8 @@ static void CD_read(void)
{
if (cd_initm)
{
uint32_t marker = m68k_get_reg(NULL, M68K_REG_D1);
uint32_t circBufSz = m68k_get_reg(NULL, M68K_REG_D2);
uint32_t marker = m68k_get_reg(M68K_REG_D1);
uint32_t circBufSz = m68k_get_reg(M68K_REG_D2);
fprintf(stderr, "cd_initm read: marker %04X, circBufSz %04X\n", marker, circBufSz);
uint32_t lba = (minutes * 60 + seconds) * 75 + frames - 150;
uint8_t buf2352[2352 + 128];
@ -630,7 +630,7 @@ static void CD_ptr(void)
static void CD_osamp(void)
{
cd_osamp = m68k_get_reg(NULL, M68K_REG_D0) & 3;
cd_osamp = m68k_get_reg(M68K_REG_D0) & 3;
NO_ERR();
}
@ -641,14 +641,14 @@ static void CD_getoc(void)
static void CD_initm(void)
{
fprintf(stderr, "CD_initm called %08X\n", m68k_get_reg(NULL, M68K_REG_A0));
fprintf(stderr, "CD_initm called %08X\n", m68k_get_reg(M68K_REG_A0));
LoadISRStub();
cd_initm = true;
}
static void CD_initf(void)
{
fprintf(stderr, "CD_initf called %08X\n", m68k_get_reg(NULL, M68K_REG_A0));
fprintf(stderr, "CD_initf called %08X\n", m68k_get_reg(M68K_REG_A0));
LoadISRStub();
cd_initm = false;
}

View File

@ -19,7 +19,6 @@
#include <stdlib.h>
#include "dac.h"
#include "gpu.h"
#include "jagdasm.h"
#include "jaguar.h"
#include "jerry.h"
#include "m68000/m68kinterface.h"

View File

@ -27,7 +27,6 @@
#include <stdlib.h>
#include <string.h>
#include "dsp.h"
#include "jagdasm.h"
#include "jaguar.h"
#include "m68000/m68kinterface.h"
#include "tom.h"

View File

@ -1,189 +0,0 @@
//
// Jaguar RISC Disassembly
//
// Originally by David Raingeard
// GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Carwin Jones (BeOS)
// Minor cleanups by James Hammons
// (C) 2012 Underground Software
//
// JLH = James Hammons <jlhamm@acm.org>
//
// Who When What
// --- ---------- -------------------------------------------------------------
// JLH 06/01/2012 Created this log (long overdue! ;-)
// JLH 01/23/2013 Beautifying of disassembly, including hex digits of opcodes
// and operands
//
#include "jagdasm.h"
#include <stdio.h>
#include "jaguar.h"
#define ROPCODE(a) JaguarReadWord(a)
uint8_t convert_zero[32] =
{ 32,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 };
const char * condition[32] =
{
"",
"nz,",
"z,",
"???,",
"nc,",
"nc nz,",
"nc z,",
"???,",
"c,",
"c nz,",
"c z,",
"???,",
"???,",
"???,",
"???,",
"???,",
"???,",
"???,",
"???,",
"???,",
"nn,",
"nn nz,",
"nn z,",
"???,",
"n,",
"n nz,",
"n z,",
"???,",
"???,",
"???,",
"???,",
"never,"
};
char * signed_16bit(int16_t val)
{
static char temp[10];
if (val < 0)
sprintf(temp, "-$%X", -val);
else
sprintf(temp, "$%X", val);
return temp;
}
unsigned dasmjag(int dsp_type, char * bufferOut, unsigned pc)
{
char buffer[64];
int op = ROPCODE(pc);
int reg1 = (op >> 5) & 31;
int reg2 = op & 31;
int size = 2;
pc += 2;
switch (op >> 10)
{
case 0: sprintf(buffer, "ADD R%02d,R%02d", reg1, reg2); break;
case 1: sprintf(buffer, "ADDC R%02d,R%02d", reg1, reg2); break;
case 2: sprintf(buffer, "ADDQ $%X,R%02d", convert_zero[reg1], reg2); break;
case 3: sprintf(buffer, "ADDQT $%X,R%02d", convert_zero[reg1], reg2); break;
case 4: sprintf(buffer, "SUB R%02d,R%02d", reg1, reg2); break;
case 5: sprintf(buffer, "SUBC R%02d,R%02d", reg1, reg2); break;
case 6: sprintf(buffer, "SUBQ $%X,R%02d", convert_zero[reg1], reg2); break;
case 7: sprintf(buffer, "SUBQT $%X,R%02d", convert_zero[reg1], reg2); break;
case 8: sprintf(buffer, "NEG R%02d", reg2); break;
case 9: sprintf(buffer, "AND R%02d,R%02d", reg1, reg2); break;
case 10: sprintf(buffer, "OR R%02d,R%02d", reg1, reg2); break;
case 11: sprintf(buffer, "XOR R%02d,R%02d", reg1, reg2); break;
case 12: sprintf(buffer, "NOT R%02d", reg2); break;
case 13: sprintf(buffer, "BTST $%X,R%02d", reg1, reg2); break;
case 14: sprintf(buffer, "BSET $%X,R%02d", reg1, reg2); break;
case 15: sprintf(buffer, "BCLR $%X,R%02d", reg1, reg2); break;
case 16: sprintf(buffer, "MULT R%02d,R%02d", reg1, reg2); break;
case 17: sprintf(buffer, "IMULT R%02d,R%02d", reg1, reg2); break;
case 18: sprintf(buffer, "IMULTN R%02d,R%02d", reg1, reg2); break;
case 19: sprintf(buffer, "RESMAC R%02d", reg2); break;
case 20: sprintf(buffer, "IMACN R%02d,R%02d", reg1, reg2); break;
case 21: sprintf(buffer, "DIV R%02d,R%02d", reg1, reg2); break;
case 22: sprintf(buffer, "ABS R%02d", reg2); break;
case 23: sprintf(buffer, "SH R%02d,R%02d", reg1, reg2); break;
case 24: sprintf(buffer, "SHLQ $%X,R%02d", 32 - reg1, reg2); break;
case 25: sprintf(buffer, "SHRQ $%X,R%02d", convert_zero[reg1], reg2); break;
case 26: sprintf(buffer, "SHA R%02d,R%02d", reg1, reg2); break;
case 27: sprintf(buffer, "SHARQ $%X,R%02d", convert_zero[reg1], reg2); break;
case 28: sprintf(buffer, "ROR R%02d,R%02d", reg1, reg2); break;
case 29: sprintf(buffer, "RORQ $%X,R%02d", convert_zero[reg1], reg2); break;
case 30: sprintf(buffer, "CMP R%02d,R%02d", reg1, reg2); break;
case 31: sprintf(buffer, "CMPQ %s,R%02d", signed_16bit((int16_t)(reg1 << 11) >> 11), reg2);break;
case 32: if (dsp_type == JAGUAR_GPU)
sprintf(buffer, "SAT8 R%02d", reg2);
else
sprintf(buffer, "SUBQMOD $%X,R%02d", convert_zero[reg1], reg2);
break;
case 33: if (dsp_type == JAGUAR_GPU)
sprintf(buffer, "SAT16 R%02d", reg2);
else
sprintf(buffer, "SAT16S R%02d", reg2);
break;
case 34: sprintf(buffer, "MOVE R%02d,R%02d", reg1, reg2); break;
case 35: sprintf(buffer, "MOVEQ %d,R%02d", reg1, reg2); break;
case 36: sprintf(buffer, "MOVETA R%02d,R%02d", reg1, reg2); break;
case 37: sprintf(buffer, "MOVEFA R%02d,R%02d", reg1, reg2); break;
case 38: sprintf(buffer, "MOVEI #$%X,R%02d", ROPCODE(pc) | (ROPCODE(pc+2)<<16), reg2); size = 6; break;
case 39: sprintf(buffer, "LOADB (R%02d),R%02d", reg1, reg2); break;
case 40: sprintf(buffer, "LOADW (R%02d),R%02d", reg1, reg2); break;
case 41: sprintf(buffer, "LOAD (R%02d),R%02d", reg1, reg2); break;
case 42: if (dsp_type == JAGUAR_GPU)
sprintf(buffer, "LOADP (R%02d),R%02d", reg1, reg2);
else
sprintf(buffer, "SAT32S R%02d", reg2);
break;
case 43: sprintf(buffer, "LOAD (R14+$%X),R%02d", convert_zero[reg1]*4, reg2);break;
case 44: sprintf(buffer, "LOAD (R15+$%X),R%02d", convert_zero[reg1]*4, reg2);break;
case 45: sprintf(buffer, "STOREB R%02d,(R%02d)", reg2, reg1); break;
case 46: sprintf(buffer, "STOREW R%02d,(R%02d)", reg2, reg1); break;
case 47: sprintf(buffer, "STORE R%02d,(R%02d)", reg2, reg1); break;
case 48: if (dsp_type == JAGUAR_GPU)
sprintf(buffer, "STOREP R%02d,(R%02d)", reg2, reg1);
else
sprintf(buffer, "MIRROR R%02d", reg2);
break;
case 49: sprintf(buffer, "STORE R%02d,(R14+$%X)", reg2, convert_zero[reg1]*4);break;
case 50: sprintf(buffer, "STORE R%02d,(R15+$%X)", reg2, convert_zero[reg1]*4);break;
case 51: sprintf(buffer, "MOVE PC,R%02d", reg2); break;
case 52: sprintf(buffer, "JUMP %s(R%02d)", condition[reg2], reg1); break;
case 53: sprintf(buffer, "JR %s$%X", condition[reg2], pc + ((int8_t)(reg1 << 3) >> 2)); break;
case 54: sprintf(buffer, "MMULT R%02d,R%02d", reg1, reg2); break;
case 55: sprintf(buffer, "MTOI R%02d,R%02d", reg1, reg2); break;
case 56: sprintf(buffer, "NORMI R%02d,R%02d", reg1, reg2); break;
case 57: sprintf(buffer, "NOP"); break;
case 58: sprintf(buffer, "LOAD (R14+R%02d),R%02d", reg1, reg2); break;
case 59: sprintf(buffer, "LOAD (R15+R%02d),R%02d", reg1, reg2); break;
case 60: sprintf(buffer, "STORE R%02d,(R14+R%02d)", reg2, reg1); break;
case 61: sprintf(buffer, "STORE R%02d,(R15+R%02d)", reg2, reg1); break;
case 62: if (dsp_type == JAGUAR_GPU)
sprintf(buffer, "SAT24 R%02d", reg2);
else
sprintf(buffer, "illegal [%d,%d]", reg1, reg2);
break;
case 63: if (dsp_type == JAGUAR_GPU)
sprintf(buffer, (reg1 ? "UNPACK R%02d" : "PACK R%02d"), reg2);
else
sprintf(buffer, "ADDQMOD $%X,R%02d", convert_zero[reg1], reg2);
break;
}
if (size == 2)
sprintf(bufferOut, "%04X %-24s", op, buffer);
else
{
uint16_t word1 = ROPCODE(pc), word2 = ROPCODE(pc + 2);
sprintf(bufferOut, "%04X %04X %04X %-24s", op, word1, word2, buffer);
}
return size;
}

View File

@ -1,9 +0,0 @@
#ifndef __JAGDASM__
#define __JAGDASM__
#define JAGUAR_GPU 0
#define JAGUAR_DSP 1
unsigned dasmjag(int dsp_type, char * buffer, unsigned pc);
#endif

View File

@ -57,12 +57,12 @@ void M68KInstructionHook(void)
{
if (jaguarCdInserted)
{
uint32_t pc = m68k_get_reg(NULL, M68K_REG_PC);
uint32_t pc = m68k_get_reg(M68K_REG_PC);
if (pc >= 0x3000 && pc <= 0x306C)
{
CDHLEHook((pc - 0x3000) / 6);
// return
uint32_t sp = m68k_get_reg(NULL, M68K_REG_SP);
uint32_t sp = m68k_get_reg(M68K_REG_SP);
m68k_set_reg(M68K_REG_PC, m68k_read_memory_32(sp));
m68k_set_reg(M68K_REG_SP, sp + 4);
}
@ -73,12 +73,12 @@ void M68KInstructionHook(void)
uint32_t regs[18];
for (uint32_t i = 0; i < 18; i++)
{
regs[i] = m68k_get_reg(NULL, (m68k_register_t)i);
regs[i] = m68k_get_reg((m68k_register_t)i);
}
CPUTraceCallback(regs);
}
MAYBE_CALLBACK(ExecuteCallback, m68k_get_reg(NULL, M68K_REG_PC));
MAYBE_CALLBACK(ExecuteCallback, m68k_get_reg(M68K_REG_PC));
}
//

View File

@ -70,8 +70,6 @@ extern struct regstruct regs, lastint_regs;
/* Possible exceptions sources for M68000_Exception() and Exception() */
#define M68000_EXC_SRC_CPU 1 /* Direct CPU exception */
#define M68000_EXC_SRC_AUTOVEC 2 /* Auto-vector exception (e.g. VBL) */
//#define M68000_EXC_SRC_INT_MFP 3 /* MFP interrupt exception */
//#define M68000_EXC_SRC_INT_DSP 4 /* DSP interrupt exception */
#define SET_CFLG(x) (CFLG = (x))
#define SET_NFLG(x) (NFLG = (x))

File diff suppressed because it is too large Load Diff

View File

@ -10,18 +10,16 @@
#include "cpudefs.h"
#include "inlines.h"
uint16_t last_op_for_exception_3;
uint32_t last_addr_for_exception_3;
uint32_t last_fault_for_exception_3;
uint16_t last_op_for_exception_3; // Opcode of faulting instruction
uint32_t last_addr_for_exception_3; // PC at fault time
uint32_t last_fault_for_exception_3; // Address that generated the exception
int OpcodeFamily; // Used by cpuemu.c...
int BusCyclePenalty = 0; // Used by cpuemu.c...
int OpcodeFamily;
int BusCyclePenalty = 0;
int CurrentInstrCycles;
struct regstruct regs;
//
// Make displacement effective address for 68000
//
@ -30,29 +28,12 @@ uint32_t get_disp_ea_000(uint32_t base, uint32_t dp)
int reg = (dp >> 12) & 0x0F;
int32_t regd = regs.regs[reg];
#if 1
if ((dp & 0x800) == 0)
regd = (int32_t)(int16_t)regd;
return base + (int8_t)dp + regd;
#else
/* Branch-free code... benchmark this again now that
* things are no longer inline.
*/
int32_t regd16;
uint32_t mask;
mask = ((dp & 0x800) >> 11) - 1;
regd16 = (int32_t)(int16_t)regd;
regd16 &= mask;
mask = ~mask;
base += (int8_t)dp;
regd &= mask;
regd |= regd16;
return base + regd;
#endif
}
//
// Create the Status Register from the flags
//
@ -62,7 +43,6 @@ void MakeSR(void)
| (GET_NFLG << 3) | (GET_ZFLG << 2) | (GET_VFLG << 1) | GET_CFLG);
}
//
// Set up the flags from Status Register
//
@ -91,107 +71,19 @@ void MakeFromSR(void)
m68k_areg(regs, 7) = regs.isp;
}
}
/* Pending interrupts can occur again after a write to the SR: */
//JLH: is this needed?
// set_special(SPCFLAG_DOINT);
}
//
// Rudimentary exception handling. This is really stripped down from what
// was in Hatari.
/*
NB: Seems that when an address exception occurs, it doesn't get handled properly
as per test1.cof. Need to figure out why it keeps going when it should wedge. :-P
*/
//
// Handle exceptions. We need a special case to handle MFP exceptions
// on Atari ST, because it's possible to change the MFP's vector base
// and get a conflict with 'normal' cpu exceptions.
//
#if 0
/*
This is the STOP # function. Dunno if exception handling occurs when it hits here or not, because don't know if the regs.s bit is set or not!
Seems to be...
SR-----------------
1111 11
5432 1098 7654 3210
---- ---- ---- ----
1 1
*/
unsigned long CPUFUNC(op_4e72_5)(uint32_t opcode) /* STOP */
{
OpcodeFamily = 44;
CurrentInstrCycles = 4;
if (!regs.s)
{
Exception(8, 0, M68000_EXC_SRC_CPU);
}
else
{
int16_t src = get_iword_prefetch(2);
regs.sr = src;
MakeFromSR();
m68k_setstopped(1);
m68k_incpc(4);
fill_prefetch_0();
}
return 4;
}
#endif
//tmp...
void WriteLog(const char * text, ...);
void Exception(int nr, uint32_t oldpc, int ExceptionSource)
{
uint32_t currpc = m68k_getpc(), newpc;
// Need to figure out how to report this stuff without using printf on stdout :-/
#if 0
char excNames[33][64] = {
"???", "???", "Bus Error", "Address Error",
"Illegal Instruction", "Zero Divide", "CHK", "TrapV",
"Privilege Violation", "Trace", "Line A", "Line F",
"???", "???", "Format Error", "Uninitialized Interrupt",
"???", "???", "???", "???",
"???", "???", "???", "???",
"Spurious/Autovector", "???", "???", "???",
"???", "???", "???", "???",
"Trap #"
};
WriteLog("Exception #%i occurred! (%s)\n", nr, (nr < 32 ? excNames[nr] : (nr < 48 ? "Trap #" : "????")));
WriteLog("Vector @ #%i = %08X\n", nr, m68k_read_memory_32(nr * 4));
//abort();
WriteLog("PC = $%08X\n", currpc);
WriteLog("A0 = $%08X A1 = $%08X A2 = $%08X A3 = $%08X\n", m68k_areg(regs, 0), m68k_areg(regs, 1), m68k_areg(regs, 2), m68k_areg(regs, 3));
WriteLog("A4 = $%08X A5 = $%08X A6 = $%08X A7 = $%08X\n", m68k_areg(regs, 4), m68k_areg(regs, 5), m68k_areg(regs, 6), m68k_areg(regs, 7));
WriteLog("D0 = $%08X D1 = $%08X D2 = $%08X D3 = $%08X\n", m68k_dreg(regs, 0), m68k_dreg(regs, 1), m68k_dreg(regs, 2), m68k_dreg(regs, 3));
WriteLog("D4 = $%08X D5 = $%08X D6 = $%08X D7 = $%08X\n", m68k_dreg(regs, 4), m68k_dreg(regs, 5), m68k_dreg(regs, 6), m68k_dreg(regs, 7));
WriteLog("\n");
uint32_t disPC = currpc - 10;
char buffer[128];
do
{
uint32_t oldpc = disPC;
disPC += m68k_disassemble(buffer, disPC, 0);
WriteLog("%s%08X: %s\n", (oldpc == currpc ? ">" : " "), oldpc, buffer);
}
while (disPC < (currpc + 10));
#endif
/*if( nr>=2 && nr<10 ) fprintf(stderr,"Exception (-> %i bombs)!\n",nr);*/
MakeSR();
// Change to supervisor mode if necessary
if (!regs.s)
{
regs.usp = m68k_areg(regs, 7);
@ -199,202 +91,15 @@ while (disPC < (currpc + 10));
regs.s = 1;
}
// Create 68000 style stack frame
m68k_areg(regs, 7) -= 4; // Push PC on stack
m68k_areg(regs, 7) -= 4;
m68k_write_memory_32(m68k_areg(regs, 7), currpc);
m68k_areg(regs, 7) -= 2; // Push SR on stack
m68k_areg(regs, 7) -= 2;
m68k_write_memory_16(m68k_areg(regs, 7), regs.sr);
// LOG_TRACE(TRACE_CPU_EXCEPTION, "cpu exception %d currpc %x buspc %x newpc %x fault_e3 %x op_e3 %hx addr_e3 %x\n",
// nr, currpc, BusErrorPC, get_long(4 * nr), last_fault_for_exception_3, last_op_for_exception_3, last_addr_for_exception_3);
#if 0
/* 68000 bus/address errors: */
if ((nr == 2 || nr == 3) && ExceptionSource == M68000_EXC_SRC_CPU)
{
uint16_t specialstatus = 1;
/* Special status word emulation isn't perfect yet... :-( */
if (regs.sr & 0x2000)
specialstatus |= 0x4;
m68k_areg(regs, 7) -= 8;
if (nr == 3) /* Address error */
{
specialstatus |= (last_op_for_exception_3 & (~0x1F)); /* [NP] unused bits of specialstatus are those of the last opcode ! */
put_word(m68k_areg(regs, 7), specialstatus);
put_long(m68k_areg(regs, 7) + 2, last_fault_for_exception_3);
put_word(m68k_areg(regs, 7) + 6, last_op_for_exception_3);
put_long(m68k_areg(regs, 7) + 10, last_addr_for_exception_3);
//JLH: Not now...
#if 0
if (bExceptionDebugging)
{
fprintf(stderr,"Address Error at address $%x, PC=$%x\n", last_fault_for_exception_3, currpc);
DebugUI();
}
#endif
}
else /* Bus error */
{
specialstatus |= (get_word(BusErrorPC) & (~0x1F)); /* [NP] unused bits of special status are those of the last opcode ! */
if (bBusErrorReadWrite)
specialstatus |= 0x10;
put_word(m68k_areg(regs, 7), specialstatus);
put_long(m68k_areg(regs, 7) + 2, BusErrorAddress);
put_word(m68k_areg(regs, 7) + 6, get_word(BusErrorPC)); /* Opcode */
/* [NP] PC stored in the stack frame is not necessarily pointing to the next instruction ! */
/* FIXME : we should have a proper model for this, in the meantime we handle specific cases */
if (get_word(BusErrorPC) == 0x21F8) /* move.l $0.w,$24.w (Transbeauce 2 loader) */
put_long(m68k_areg(regs, 7) + 10, currpc - 2); /* correct PC is 2 bytes less than usual value */
/* Check for double bus errors: */
if (regs.spcflags & SPCFLAG_BUSERROR)
{
fprintf(stderr, "Detected double bus error at address $%x, PC=$%lx => CPU halted!\n",
BusErrorAddress, (long)currpc);
unset_special(SPCFLAG_BUSERROR);
if (bExceptionDebugging)
DebugUI();
else
DlgAlert_Notice("Detected double bus error => CPU halted!\nEmulation needs to be reset.\n");
regs.intmask = 7;
m68k_setstopped(true);
return;
}
if (bExceptionDebugging && BusErrorAddress != 0xFF8A00)
{
fprintf(stderr,"Bus Error at address $%x, PC=$%lx\n", BusErrorAddress, (long)currpc);
DebugUI();
}
}
}
//Not now...
#if 0
/* Set PC and flags */
if (bExceptionDebugging && get_long(4 * nr) == 0)
{
write_log("Uninitialized exception handler #%i!\n", nr);
DebugUI();
}
#endif
newpc = get_long(4 * nr);
if (newpc & 1) /* check new pc is odd */
{
if (nr == 2 || nr == 3) /* address error during bus/address error -> stop emulation */
{
fprintf(stderr,"Address Error during exception 2/3, aborting new PC=$%x\n", newpc);
DebugUI();
}
else
{
fprintf(stderr,"Address Error during exception, new PC=$%x\n", newpc);
Exception(3, m68k_getpc(), M68000_EXC_SRC_CPU);
}
return;
}
#endif
m68k_setpc(m68k_read_memory_32(4 * nr));
fill_prefetch_0();
/* Handle trace flags depending on current state */
//JLH:no exception_trace(nr);
#if 0
/* Handle exception cycles (special case for MFP) */
// if (ExceptionSource == M68000_EXC_SRC_INT_MFP)
// {
// M68000_AddCycles(44 + 12); /* MFP interrupt, 'nr' can be in a different range depending on $fffa17 */
// }
// else
if (nr >= 24 && nr <= 31)
{
#if 0
if (nr == 26) /* HBL */
{
/* store current cycle pos when then interrupt was received (see video.c) */
LastCycleHblException = Cycles_GetCounter(CYCLES_COUNTER_VIDEO);
M68000_AddCycles(44 + 12); /* Video Interrupt */
}
else if (nr == 28) /* VBL */
M68000_AddCycles(44 + 12); /* Video Interrupt */
else
#endif
M68000_AddCycles(44 + 4); /* Other Interrupts */
}
else if (nr >= 32 && nr <= 47)
{
M68000_AddCycles(34 - 4); /* Trap (total is 34, but cpuemu.c already adds 4) */
}
else switch(nr)
{
case 2: M68000_AddCycles(50); break; /* Bus error */
case 3: M68000_AddCycles(50); break; /* Address error */
case 4: M68000_AddCycles(34); break; /* Illegal instruction */
case 5: M68000_AddCycles(38); break; /* Div by zero */
case 6: M68000_AddCycles(40); break; /* CHK */
case 7: M68000_AddCycles(34); break; /* TRAPV */
case 8: M68000_AddCycles(34); break; /* Privilege violation */
case 9: M68000_AddCycles(34); break; /* Trace */
case 10: M68000_AddCycles(34); break; /* Line-A - probably wrong */
case 11: M68000_AddCycles(34); break; /* Line-F - probably wrong */
default:
/* FIXME: Add right cycles value for MFP interrupts and copro exceptions ... */
if (nr < 64)
M68000_AddCycles(4); /* Coprocessor and unassigned exceptions (???) */
else
M68000_AddCycles(44 + 12); /* Must be a MFP or DSP interrupt */
break;
}
#endif
}
/*
The routines below take dividend and divisor as parameters.
They return 0 if division by zero, or exact number of cycles otherwise.
The number of cycles returned assumes a register operand.
Effective address time must be added if memory operand.
For 68000 only (not 68010, 68012, 68020, etc).
Probably valid for 68008 after adding the extra prefetch cycle.
Best and worst cases are for register operand:
(Note the difference with the documented range.)
DIVU:
Overflow (always): 10 cycles.
Worst case: 136 cycles.
Best case: 76 cycles.
DIVS:
Absolute overflow: 16-18 cycles.
Signed overflow is not detected prematurely.
Worst case: 156 cycles.
Best case without signed overflow: 122 cycles.
Best case with signed overflow: 120 cycles
*/
//
// DIVU
// Unsigned division
@ -408,7 +113,6 @@ STATIC_INLINE int getDivu68kCycles_2 (uint32_t dividend, uint16_t divisor)
if (divisor == 0)
return 0;
// Overflow
if ((dividend >> 16) >= divisor)
return (mcycles = 5) * 2;
@ -422,7 +126,6 @@ STATIC_INLINE int getDivu68kCycles_2 (uint32_t dividend, uint16_t divisor)
dividend <<= 1;
// If carry from shift
if ((int32_t)temp < 0)
dividend -= hdivisor;
else
@ -440,16 +143,12 @@ STATIC_INLINE int getDivu68kCycles_2 (uint32_t dividend, uint16_t divisor)
return mcycles * 2;
}
// This is called by cpuemu.c
int getDivu68kCycles(uint32_t dividend, uint16_t divisor)
{
int v = getDivu68kCycles_2(dividend, divisor) - 4;
// write_log ("U%d ", v);
return v;
}
//
// DIVS
// Signed division
@ -468,11 +167,9 @@ STATIC_INLINE int getDivs68kCycles_2(int32_t dividend, int16_t divisor)
if (dividend < 0)
mcycles++;
// Check for absolute overflow
if (((uint32_t)abs(dividend) >> 16) >= (uint16_t)abs(divisor))
return (mcycles + 2) * 2;
// Absolute quotient
aquot = (uint32_t)abs(dividend) / (uint16_t)abs(divisor);
mcycles += 55;
@ -485,8 +182,6 @@ STATIC_INLINE int getDivs68kCycles_2(int32_t dividend, int16_t divisor)
mcycles++;
}
// Count 15 msbits in absolute of quotient
for(i=0; i<15; i++)
{
if ((int16_t)aquot >= 0)
@ -498,12 +193,8 @@ STATIC_INLINE int getDivs68kCycles_2(int32_t dividend, int16_t divisor)
return mcycles * 2;
}
// This is called by cpuemu.c
int getDivs68kCycles(int32_t dividend, int16_t divisor)
{
int v = getDivs68kCycles_2(dividend, divisor) - 4;
// write_log ("S%d ", v);
return v;
}

View File

@ -12,15 +12,12 @@ struct cputbl
uint16_t opcode;
};
extern uint16_t last_op_for_exception_3; /* Opcode of faulting instruction */
extern uint32_t last_addr_for_exception_3; /* PC at fault time */
extern uint32_t last_fault_for_exception_3; /* Address that generated the exception */
extern uint16_t last_op_for_exception_3;
extern uint32_t last_addr_for_exception_3;
extern uint32_t last_fault_for_exception_3;
/* Family of the latest instruction executed (to check for pairing) */
extern int OpcodeFamily; /* see instrmnem in readcpu.h */
extern int OpcodeFamily;
/* How many cycles to add to the current instruction in case a "misaligned" bus access is made */
/* (used when addressing mode is d8(an,ix)) */
extern int BusCyclePenalty;
extern int CurrentInstrCycles;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -16,35 +16,32 @@ STATIC_INLINE 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 */
case 0: return 1;
case 1: return 0;
case 2: return !CFLG && !ZFLG;
case 3: return CFLG || ZFLG;
case 4: return !CFLG;
case 5: return CFLG;
case 6: return !ZFLG;
case 7: return ZFLG;
case 8: return !VFLG;
case 9: return VFLG;
case 10: return !NFLG;
case 11: return NFLG;
case 12: return NFLG == VFLG;
case 13: return NFLG != VFLG;
case 14: return !ZFLG && (NFLG == VFLG);
case 15: return ZFLG || (NFLG != VFLG);
}
abort();
return 0;
}
//no #define m68k_incpc(o) (regs.pc_p += (o))
#define m68k_incpc(o) (regs.pc += (o))
STATIC_INLINE void m68k_setpc(uint32_t newpc)
{
//This is only done here... (get_real_address())
// regs.pc_p = regs.pc_oldp = get_real_address(newpc);
regs.pc = newpc;
}
@ -52,29 +49,13 @@ STATIC_INLINE void m68k_setpc(uint32_t newpc)
STATIC_INLINE uint32_t m68k_getpc(void)
{
// return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp);
return regs.pc;
}
#if 0
STATIC_INLINE uint32_t m68k_getpc_p(uint8_t * p)
{
return regs.pc + ((char *)p - (char *)regs.pc_oldp);
}
#endif
STATIC_INLINE void m68k_setstopped(int stop)
{
regs.stopped = stop;
regs.remainingCycles = 0;
//But trace instructions are only on >68000 cpus, so this is bogus.
#if 0
/* A traced STOP instruction drops through immediately without
actually stopping. */
if (stop && (regs.spcflags & SPCFLAG_DOTRACE) == 0)
regs.spcflags |= SPCFLAG_STOP;
#endif
}
STATIC_INLINE void m68k_do_rts(void)
@ -97,103 +78,27 @@ STATIC_INLINE void m68k_do_jsr(uint32_t oldpc, uint32_t dest)
m68k_setpc(dest);
}
#if 0
//These do_get_mem_* functions are only used in newcpu...
//What it does is use a pointer to make instruction fetching quicker,
//though it probably leads to more problems than it solves. Something to
//decide using a profiler...
#define get_ibyte(o) do_get_mem_byte(regs.pc_p + (o) + 1)
#define get_iword(o) do_get_mem_word(regs.pc_p + (o))
#define get_ilong(o) do_get_mem_long(regs.pc_p + (o))
#else
// For now, we'll punt this crap...
// (Also, notice that the byte read is at address + 1...)
#define get_ibyte(o) m68k_read_memory_8(regs.pc + (o) + 1)
#define get_iword(o) m68k_read_memory_16(regs.pc + (o))
#define get_ilong(o) m68k_read_memory_32(regs.pc + (o))
#endif
// We don't use this crap, so let's comment out for now...
STATIC_INLINE void refill_prefetch(uint32_t currpc, uint32_t offs)
{
#if 0
uint32_t t = (currpc + offs) & ~1;
int32_t pc_p_offs = t - currpc;
uint8_t * ptr = regs.pc_p + pc_p_offs;
uint32_t r;
#ifdef UNALIGNED_PROFITABLE
r = *(uint32_t *)ptr;
regs.prefetch = r;
#else
r = do_get_mem_long(ptr);
do_put_mem_long(&regs.prefetch, r);
#endif
/* printf ("PC %lx T %lx PCPOFFS %d R %lx\n", currpc, t, pc_p_offs, r); */
regs.prefetch_pc = t;
#endif
}
STATIC_INLINE uint32_t get_ibyte_prefetch(int32_t o)
{
#if 0
uint32_t currpc = m68k_getpc();
uint32_t addr = currpc + o + 1;
uint32_t offs = addr - regs.prefetch_pc;
if (offs > 3)
{
refill_prefetch(currpc, o + 1);
offs = addr - regs.prefetch_pc;
}
uint32_t v = do_get_mem_byte(((uint8_t *)&regs.prefetch) + offs);
if (offs >= 2)
refill_prefetch(currpc, 2);
/* printf ("get_ibyte PC %lx ADDR %lx OFFS %lx V %lx\n", currpc, addr, offs, v); */
return v;
#else
return get_ibyte(o);
#endif
}
STATIC_INLINE uint32_t get_iword_prefetch(int32_t o)
{
#if 0
uint32_t currpc = m68k_getpc();
uint32_t addr = currpc + o;
uint32_t offs = addr - regs.prefetch_pc;
if (offs > 3)
{
refill_prefetch(currpc, o);
offs = addr - regs.prefetch_pc;
}
uint32_t v = do_get_mem_word(((uint8_t *)&regs.prefetch) + offs);
if (offs >= 2)
refill_prefetch(currpc, 2);
/* printf ("get_iword PC %lx ADDR %lx OFFS %lx V %lx\n", currpc, addr, offs, v); */
return v;
#else
return get_iword(o);
#endif
}
STATIC_INLINE uint32_t get_ilong_prefetch(int32_t o)
{
#if 0
uint32_t v = get_iword_prefetch(o);
v <<= 16;
v |= get_iword_prefetch(o + 2);
return v;
#else
return get_ilong(o);
#endif
}
STATIC_INLINE void fill_prefetch_0(void)

View File

@ -1,421 +0,0 @@
//
// m68kdasm.c: 68000 instruction disassembly
//
// Originally part of the UAE 68000 cpu core
// by Bernd Schmidt
//
// Adapted to Virtual Jaguar by James Hammons
//
// This file is distributed under the GNU Public License, version 3 or at your
// option any later version. Read the file GPLv3 for details.
//
#include <string.h>
#include "cpudefs.h"
#include "cpuextra.h"
#include "inlines.h"
#include "readcpu.h"
// Stuff from m68kinterface.c
extern unsigned long IllegalOpcode(uint32_t opcode);
extern cpuop_func * cpuFunctionTable[65536];
// Prototypes
void HandleMovem(char * output, uint16_t data, int direction);
// Local "global" variables
static long int m68kpc_offset;
#if 0
#define get_ibyte_1(o) get_byte(regs.pc + (regs.pc_p - regs.pc_oldp) + (o) + 1)
#define get_iword_1(o) get_word(regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
#define get_ilong_1(o) get_long(regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
#else
#define get_ibyte_1(o) m68k_read_memory_8(regs.pc + (o) + 1)
#define get_iword_1(o) m68k_read_memory_16(regs.pc + (o))
#define get_ilong_1(o) m68k_read_memory_32(regs.pc + (o))
#endif
//int32_t ShowEA(FILE * f, int reg, amodes mode, wordsizes size, char * buf)
int32_t ShowEA(int mnemonic, int reg, amodes mode, wordsizes size, char * buf)
{
uint16_t dp;
int8_t disp8;
int16_t disp16;
int r;
uint32_t dispreg;
uint32_t addr;
int32_t offset = 0;
char buffer[80];
switch (mode)
{
case Dreg:
sprintf(buffer,"D%d", reg);
break;
case Areg:
sprintf(buffer,"A%d", reg);
break;
case Aind:
sprintf(buffer,"(A%d)", reg);
break;
case Aipi:
sprintf(buffer,"(A%d)+", reg);
break;
case Apdi:
sprintf(buffer,"-(A%d)", reg);
break;
case Ad16:
disp16 = get_iword_1(m68kpc_offset); m68kpc_offset += 2;
addr = m68k_areg(regs,reg) + (int16_t)disp16;
sprintf(buffer,"(A%d,$%X) == $%lX", reg, disp16 & 0xFFFF,
(unsigned long)addr);
break;
case Ad8r:
dp = get_iword_1(m68kpc_offset); m68kpc_offset += 2;
disp8 = dp & 0xFF;
r = (dp & 0x7000) >> 12;
dispreg = (dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r));
if (!(dp & 0x800))
dispreg = (int32_t)(int16_t)(dispreg);
dispreg <<= (dp >> 9) & 3;
if (dp & 0x100)
{
int32_t outer = 0, disp = 0;
int32_t base = m68k_areg(regs,reg);
char name[10];
sprintf (name,"A%d, ",reg);
if (dp & 0x80) { base = 0; name[0] = 0; }
if (dp & 0x40) dispreg = 0;
if ((dp & 0x30) == 0x20) { disp = (int32_t)(int16_t)get_iword_1(m68kpc_offset); m68kpc_offset += 2; }
if ((dp & 0x30) == 0x30) { disp = get_ilong_1(m68kpc_offset); m68kpc_offset += 4; }
base += disp;
if ((dp & 0x3) == 0x2) { outer = (int32_t)(int16_t)get_iword_1(m68kpc_offset); m68kpc_offset += 2; }
if ((dp & 0x3) == 0x3) { outer = get_ilong_1(m68kpc_offset); m68kpc_offset += 4; }
if (!(dp & 4)) base += dispreg;
if (dp & 3) base = m68k_read_memory_32(base);
if (dp & 4) base += dispreg;
addr = base + outer;
sprintf(buffer,"(%s%c%d.%c*%d+%ld)+%ld == $%lX", name,
dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
1 << ((dp >> 9) & 3),
(long)disp, (long)outer, (unsigned long)addr);
}
else
{
addr = m68k_areg(regs,reg) + (int32_t)((int8_t)disp8) + dispreg;
sprintf (buffer,"(A%d, %c%d.%c*%d, $%X) == $%lX", reg,
dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
1 << ((dp >> 9) & 3), disp8, (unsigned long)addr);
}
break;
case PC16:
addr = m68k_getpc() + m68kpc_offset;
disp16 = get_iword_1(m68kpc_offset); m68kpc_offset += 2;
addr += (int16_t)disp16;
sprintf(buffer,"(PC, $%X) == $%lX", disp16 & 0xFFFF, (unsigned long)addr);
break;
case PC8r:
addr = m68k_getpc() + m68kpc_offset;
dp = get_iword_1(m68kpc_offset); m68kpc_offset += 2;
disp8 = dp & 0xFF;
r = (dp & 0x7000) >> 12;
dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r);
if (!(dp & 0x800))
dispreg = (int32_t)(int16_t)(dispreg);
dispreg <<= (dp >> 9) & 3;
if (dp & 0x100)
{
int32_t outer = 0,disp = 0;
int32_t base = addr;
char name[10];
sprintf (name,"PC, ");
if (dp & 0x80) { base = 0; name[0] = 0; }
if (dp & 0x40) dispreg = 0;
if ((dp & 0x30) == 0x20) { disp = (int32_t)(int16_t)get_iword_1(m68kpc_offset); m68kpc_offset += 2; }
if ((dp & 0x30) == 0x30) { disp = get_ilong_1(m68kpc_offset); m68kpc_offset += 4; }
base += disp;
if ((dp & 0x3) == 0x2)
{
outer = (int32_t)(int16_t)get_iword_1(m68kpc_offset);
m68kpc_offset += 2;
}
if ((dp & 0x3) == 0x3)
{
outer = get_ilong_1(m68kpc_offset);
m68kpc_offset += 4;
}
if (!(dp & 4)) base += dispreg;
if (dp & 3) base = m68k_read_memory_32(base);
if (dp & 4) base += dispreg;
addr = base + outer;
sprintf(buffer,"(%s%c%d.%c*%d+%ld)+%ld == $%lX", name,
dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
1 << ((dp >> 9) & 3), (long)disp, (long)outer, (unsigned long)addr);
}
else
{
addr += (int32_t)((int8_t)disp8) + dispreg;
sprintf(buffer,"(PC, %c%d.%c*%d, $%X) == $%lX", dp & 0x8000 ? 'A' : 'D',
(int)r, dp & 0x800 ? 'L' : 'W', 1 << ((dp >> 9) & 3),
disp8, (unsigned long)addr);
}
break;
case absw:
sprintf(buffer,"$%lX", (unsigned long)(int32_t)(int16_t)get_iword_1(m68kpc_offset));
m68kpc_offset += 2;
break;
case absl:
sprintf(buffer,"$%lX", (unsigned long)get_ilong_1(m68kpc_offset));
m68kpc_offset += 4;
break;
case imm:
switch (size)
{
case sz_byte:
sprintf(buffer,"#$%X", (unsigned int)(get_iword_1(m68kpc_offset) & 0xFF));
m68kpc_offset += 2;
break;
case sz_word:
sprintf(buffer,"#$%X", (unsigned int)(get_iword_1(m68kpc_offset) & 0xFFFF));
m68kpc_offset += 2;
break;
case sz_long:
sprintf(buffer,"#$%lX", (unsigned long)(get_ilong_1(m68kpc_offset)));
m68kpc_offset += 4;
break;
default:
break;
}
break;
case imm0:
offset = (int32_t)(int8_t)get_iword_1(m68kpc_offset);
m68kpc_offset += 2;
sprintf(buffer,"#$%X", (unsigned int)(offset & 0xFF));
break;
case imm1:
offset = (int32_t)(int16_t)get_iword_1(m68kpc_offset);
m68kpc_offset += 2;
if (mnemonic == i_MVMEL)
HandleMovem(buffer, offset, 0);
else if (mnemonic == i_MVMLE)
HandleMovem(buffer, offset, 1);
else
sprintf(buffer,"#$%X", (unsigned int)(offset & 0xFFFF));
break;
case imm2:
offset = (int32_t)get_ilong_1(m68kpc_offset);
m68kpc_offset += 4;
sprintf(buffer,"#$%lX", (unsigned long)(offset & 0xFFFFFFFF));
break;
case immi:
offset = (int32_t)(int8_t)(reg & 0xFF);
sprintf(buffer,"#$%lX", (unsigned long)(offset & 0xFFFFFFFF));
break;
default:
break;
}
// if (buf == 0)
// fprintf(f, "%s", buffer);
// else
strcat(buf, buffer);
return offset;
}
void HandleMovem(char * output, uint16_t data, int direction)
{
uint16_t ascending[16] = {
0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000 };
uint16_t descending[16] = {
0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, 0x0100,
0x0080, 0x0040, 0x0020, 0x0010, 0x0008, 0x0004, 0x0002, 0x0001 };
int i, j, first, runLength, firstPrint = 1;
char buf[16];
uint16_t * bitMask;
bitMask = (direction ? descending : ascending);
output[0] = 0;
// Handle D0-D7...
for(i=0; i<8; i++)
{
if (data & bitMask[i])
{
first = i;
runLength = 0;
for(j=i+1; j<8 && (data & bitMask[j]); j++)
runLength++;
i += runLength;
if (firstPrint)
firstPrint = 0;
else
strcat(output, "/");
sprintf(buf, "D%d", first);
strcat(output, buf);
if (runLength > 0)
{
sprintf(buf, "-D%d", first + runLength);
strcat(output, buf);
}
}
}
// Handle A0-A7...
for(i=0; i<8; i++)
{
if (data & bitMask[i + 8])
{
first = i;
runLength = 0;
for(j=i+1; j<8 && (data & bitMask[j+8]); j++)
runLength++;
i += runLength;
if (firstPrint)
firstPrint = 0;
else
strcat(output, "/");
sprintf(buf, "A%d", first);
strcat(output, buf);
if (runLength > 0)
{
sprintf(buf, "-A%d", first + runLength);
strcat(output, buf);
}
}
}
}
unsigned int M68KDisassemble(char * output, uint32_t addr)
{
char f[256], str[256];
char src[256], dst[256];
static const char * const ccnames[] =
{ "RA","RN","HI","LS","CC","CS","NE","EQ",
"VC","VS","PL","MI","GE","LT","GT","LE" };
str[0] = 0;
output[0] = 0;
uint32_t newpc = 0;
m68kpc_offset = addr - m68k_getpc();
long int pcOffsetSave = m68kpc_offset;
int opwords;
char instrname[20];
const struct mnemolookup * lookup;
uint32_t opcode = get_iword_1(m68kpc_offset);
m68kpc_offset += 2;
if (cpuFunctionTable[opcode] == IllegalOpcode)
opcode = 0x4AFC;
struct instr * dp = table68k + opcode;
for(lookup=lookuptab; lookup->mnemo!=dp->mnemo; lookup++)
;
strcpy(instrname, lookup->name);
char * ccpt = strstr(instrname, "cc");
if (ccpt)
strncpy(ccpt, ccnames[dp->cc], 2);
sprintf(f, "%s", instrname);
strcat(str, f);
switch (dp->size)
{
case sz_byte: strcat(str, ".B\t"); break;
case sz_word: strcat(str, ".W\t"); break;
case sz_long: strcat(str, ".L\t"); break;
default: strcat(str, "\t"); break;
}
// Get source and destination operands (if any)
src[0] = dst[0] = f[0] = 0;
if (dp->suse)
newpc = m68k_getpc() + m68kpc_offset
+ ShowEA(dp->mnemo, dp->sreg, dp->smode, dp->size, src);
if (dp->duse)
newpc = m68k_getpc() + m68kpc_offset
+ ShowEA(dp->mnemo, dp->dreg, dp->dmode, dp->size, dst);
// Handle execptions to the standard rules
if (dp->mnemo == i_BSR || dp->mnemo == i_Bcc)
sprintf(f, "$%lX", (long)newpc);
else if (dp->mnemo == i_DBcc)
sprintf(f, "%s, $%lX", src, (long)newpc);
else if (dp->mnemo == i_MVMEL)
sprintf(f, "%s, %s", dst, src);
else
sprintf(f, "%s%s%s", src, (dp->suse && dp->duse ? ", " : ""), dst);
strcat(str, f);
if (ccpt)
{
sprintf(f, " (%s)", (cctrue(dp->cc) ? "true" : "false"));
strcat(str, f);
}
// Add byte(s) display to front of disassembly
long int numberOfBytes = m68kpc_offset - pcOffsetSave;
for(opwords=0; opwords<5; opwords++)
{
if (((opwords + 1) * 2) <= numberOfBytes)
sprintf(f, "%04X ", get_iword_1(pcOffsetSave + opwords * 2));
else
sprintf(f, " ");
strcat(output, f);
}
strcat(output, str);
return numberOfBytes;
}
//
// Disassemble one instruction at pc and store in str_buff
//
unsigned int m68k_disassemble(char * str_buff, unsigned int pc, unsigned int cpu_type)
{
return M68KDisassemble(str_buff, pc);
}

View File

@ -12,7 +12,6 @@
//
#include "m68kinterface.h"
//#include <pthread.h>
#include "cpudefs.h"
#include "inlines.h"
#include "cpuextra.h"
@ -35,18 +34,8 @@
#define EXCEPTION_INTERRUPT_AUTOVECTOR 24
#define EXCEPTION_TRAP_BASE 32
// These are found in obj/cpustbl.c (generated by gencpu)
//extern const struct cputbl op_smalltbl_0_ff[]; /* 68040 */
//extern const struct cputbl op_smalltbl_1_ff[]; /* 68020 + 68881 */
//extern const struct cputbl op_smalltbl_2_ff[]; /* 68020 */
//extern const struct cputbl op_smalltbl_3_ff[]; /* 68010 */
extern const struct cputbl op_smalltbl_4_ff[]; /* 68000 */
extern const struct cputbl op_smalltbl_5_ff[]; /* 68000 slow but compatible. */
// Externs, supplied by the user...
//extern int irq_ack_handler(int);
// Function prototypes...
STATIC_INLINE void m68ki_check_interrupts(void);
void m68ki_exception_interrupt(uint32_t intLevel);
@ -60,158 +49,34 @@ void m68k_set_irq2(unsigned int intLevel);
static int32_t initialCycles;
cpuop_func * cpuFunctionTable[65536];
// By virtue of the fact that m68k_set_irq() can be called asychronously by
// another thread, we need something along the lines of this:
static int checkForIRQToHandle = 0;
//static pthread_mutex_t executionLock = PTHREAD_MUTEX_INITIALIZER;
static int IRQLevelToHandle = 0;
#if 0
#define ADD_CYCLES(A) m68ki_remaining_cycles += (A)
#define USE_CYCLES(A) m68ki_remaining_cycles -= (A)
#define SET_CYCLES(A) m68ki_remaining_cycles = A
#define GET_CYCLES() m68ki_remaining_cycles
#define USE_ALL_CYCLES() m68ki_remaining_cycles = 0
#define CPU_INT_LEVEL m68ki_cpu.int_level /* ASG: changed from CPU_INTS_PENDING */
#define CPU_INT_CYCLES m68ki_cpu.int_cycles /* ASG */
#define CPU_STOPPED m68ki_cpu.stopped
#define CPU_PREF_ADDR m68ki_cpu.pref_addr
#define CPU_PREF_DATA m68ki_cpu.pref_data
#define CPU_ADDRESS_MASK m68ki_cpu.address_mask
#define CPU_SR_MASK m68ki_cpu.sr_mask
#endif
#define CPU_DEBUG
void Dasm(uint32_t offset, uint32_t qt)
{
#ifdef CPU_DEBUG
// back up a few instructions...
//offset -= 100;
static char buffer[2048];//, mem[64];
int pc = offset, oldpc;
uint32_t i;
for(i=0; i<qt; i++)
{
/* oldpc = pc;
for(int j=0; j<64; j++)
mem[j^0x01] = jaguar_byte_read(pc + j);
pc += Dasm68000((char *)mem, buffer, 0);
WriteLog("%08X: %s\n", oldpc, buffer);//*/
oldpc = pc;
pc += m68k_disassemble(buffer, pc, 0);//M68K_CPU_TYPE_68000);
// WriteLog("%08X: %s\n", oldpc, buffer);//*/
printf("%08X: %s\n", oldpc, buffer);//*/
}
#endif
}
#ifdef CPU_DEBUG
void DumpRegisters(void)
{
uint32_t i;
for(i=0; i<16; i++)
{
printf("%s%i: %08X ", (i < 8 ? "D" : "A"), i & 0x7, regs.regs[i]);
if ((i & 0x03) == 3)
printf("\n");
}
}
#endif
void M68KDebugHalt(void)
{
regs.spcflags |= SPCFLAG_DEBUGGER;
}
void M68KDebugResume(void)
{
regs.spcflags &= ~SPCFLAG_DEBUGGER;
}
void m68k_set_cpu_type(unsigned int type)
{
}
// Pulse the RESET line on the CPU
void m68k_pulse_reset(void)
{
static uint32_t emulation_initialized = 0;
// The first call to this function initializes the opcode handler jump table
if (!emulation_initialized)
{
#if 0
m68ki_build_opcode_table();
m68k_set_int_ack_callback(NULL);
m68k_set_bkpt_ack_callback(NULL);
m68k_set_reset_instr_callback(NULL);
m68k_set_pc_changed_callback(NULL);
m68k_set_fc_callback(NULL);
m68k_set_instr_hook_callback(NULL);
#else
// Build opcode handler table here...
read_table68k();
do_merges();
BuildCPUFunctionTable();
#endif
emulation_initialized = 1;
}
// if (CPU_TYPE == 0) /* KW 990319 */
// m68k_set_cpu_type(M68K_CPU_TYPE_68000);
#if 0
/* Clear all stop levels and eat up all remaining cycles */
CPU_STOPPED = 0;
SET_CYCLES(0);
/* Turn off tracing */
FLAG_T1 = FLAG_T0 = 0;
m68ki_clear_trace();
/* Interrupt mask to level 7 */
FLAG_INT_MASK = 0x0700;
/* Reset VBR */
REG_VBR = 0;
/* Go to supervisor mode */
m68ki_set_sm_flag(SFLAG_SET | MFLAG_CLEAR);
/* Invalidate the prefetch queue */
#if M68K_EMULATE_PREFETCH
/* Set to arbitrary number since our first fetch is from 0 */
CPU_PREF_ADDR = 0x1000;
#endif /* M68K_EMULATE_PREFETCH */
/* Read the initial stack pointer and program counter */
m68ki_jump(0);
REG_SP = m68ki_read_imm_32();
REG_PC = m68ki_read_imm_32();
m68ki_jump(REG_PC);
#else
checkForIRQToHandle = 0;
regs.spcflags = 0;
regs.stopped = 0;
regs.remainingCycles = 0;
regs.intmask = 0x07;
regs.s = 1; // Supervisor mode ON
regs.s = 1;
// Read initial SP and PC
m68k_areg(regs, 7) = m68k_read_memory_32(0);
m68k_setpc(m68k_read_memory_32(4));
refill_prefetch(m68k_getpc(), 0);
#endif
}
@ -219,392 +84,124 @@ int m68k_execute(int num_cycles)
{
if (regs.stopped)
{
regs.remainingCycles = 0; // int32_t
regs.interruptCycles = 0; // uint32_t
regs.remainingCycles = 0;
regs.interruptCycles = 0;
return num_cycles;
}
#if 0
/* Set our pool of clock cycles available */
SET_CYCLES(num_cycles);
m68ki_initial_cycles = num_cycles;
/* ASG: update cycles */
USE_CYCLES(CPU_INT_CYCLES);
CPU_INT_CYCLES = 0;
/* Return point if we had an address error */
m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */
#else
regs.remainingCycles = num_cycles;
/*int32_t*/ initialCycles = num_cycles;
initialCycles = num_cycles;
regs.remainingCycles -= regs.interruptCycles;
regs.interruptCycles = 0;
#endif
/* Main loop. Keep going until we run out of clock cycles */
do
{
// This is so our debugging code can break in on a dime.
// Otherwise, this is just extra slow down :-P
if (regs.spcflags & SPCFLAG_DEBUGGER)
{
// Not sure this is correct... :-P
num_cycles = initialCycles - regs.remainingCycles;
regs.remainingCycles = 0; // int32_t
regs.interruptCycles = 0; // uint32_t
return num_cycles;
}
#if 0
/* Set tracing accodring to T1. (T0 is done inside instruction) */
m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */
/* Set the address space for reads */
m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */
/* Call external hook to peek at CPU */
m68ki_instr_hook(); /* auto-disable (see m68kcpu.h) */
/* Record previous program counter */
REG_PPC = REG_PC;
/* Read an instruction and call its handler */
REG_IR = m68ki_read_imm_16();
m68ki_instruction_jump_table[REG_IR]();
USE_CYCLES(CYC_INSTRUCTION[REG_IR]);
/* Trace m68k_exception, if necessary */
m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
#else
//Testing Hover Strike...
#if 0
//Dasm(regs.pc, 1);
static int hitCount = 0;
static int inRoutine = 0;
static int instSeen;
//if (regs.pc == 0x80340A)
if (regs.pc == 0x803416)
{
hitCount++;
inRoutine = 1;
instSeen = 0;
printf("%i: $80340A start. A0=%08X, A1=%08X ", hitCount, regs.regs[8], regs.regs[9]);
}
else if (regs.pc == 0x803422)
{
inRoutine = 0;
printf("(%i instructions)\n", instSeen);
}
if (inRoutine)
instSeen++;
#endif
// AvP testing... (problem was: 32 bit addresses on 24 bit address cpu--FIXED)
#if 0
static int go = 0;
if (regs.pc == 0x94BA)
{
go = 1;
printf("\n");
}
if (regs.pc == 0x94C6)
go = 0;
// if (regs.regs[10] == 0xFFFFFFFF && go)
if (go)
{
// printf("A2=-1, PC=%08X\n", regs.pc);
// go = 0;
// Dasm(regs.pc, 130);
Dasm(regs.pc, 1);
DumpRegisters();
}
//94BA: 2468 0000 MOVEA.L (A0,$0000) == $0002328A, A2
//94BE: 200A MOVE.L A2, D0
//94C0: 6A02 BPL.B $94C4
//94C2: 2452 MOVEA.L (A2), A2 ; <--- HERE
//94C4: 4283 CLR.L D3
#endif
// pthread_mutex_lock(&executionLock);
if (checkForIRQToHandle)
{
checkForIRQToHandle = 0;
m68k_set_irq2(IRQLevelToHandle);
}
#ifdef M68K_HOOK_FUNCTION
M68KInstructionHook();
#endif
uint32_t opcode = get_iword(0);
//if ((opcode & 0xFFF8) == 0x31C0)
//{
// printf("MOVE.W D%i, EA\n", opcode & 0x07);
//}
int32_t cycles = (int32_t)(*cpuFunctionTable[opcode])(opcode);
regs.remainingCycles -= cycles;
// pthread_mutex_unlock(&executionLock);
//printf("Executed opcode $%04X (%i cycles)...\n", opcode, cycles);
#endif
}
while (regs.remainingCycles > 0);
#if 0
/* set previous PC to current PC for the next entry into the loop */
REG_PPC = REG_PC;
/* ASG: update cycles */
USE_CYCLES(CPU_INT_CYCLES);
CPU_INT_CYCLES = 0;
/* return how many clocks we used */
return m68ki_initial_cycles - GET_CYCLES();
#else
regs.remainingCycles -= regs.interruptCycles;
regs.interruptCycles = 0;
// Return # of clock cycles used
return initialCycles - regs.remainingCycles;
#endif
}
void m68k_set_irq(unsigned int intLevel)
{
// We need to check for stopped state as well...
if (regs.stopped)
{
m68k_set_irq2(intLevel);
return;
}
// Since this can be called asynchronously, we need to fix it so that it
// doesn't fuck up the main execution loop.
IRQLevelToHandle = intLevel;
checkForIRQToHandle = 1;
}
/* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */
void m68k_set_irq2(unsigned int intLevel)
{
// pthread_mutex_lock(&executionLock);
// printf("m68k_set_irq: Could not get the lock!!!\n");
int oldLevel = regs.intLevel;
regs.intLevel = intLevel;
// A transition from < 7 to 7 always interrupts (NMI)
// Note: Level 7 can also level trigger like a normal IRQ
if (oldLevel != 0x07 && regs.intLevel == 0x07)
m68ki_exception_interrupt(7); // Edge triggered level 7 (NMI)
m68ki_exception_interrupt(7);
else
m68ki_check_interrupts(); // Level triggered (IRQ)
// pthread_mutex_unlock(&executionLock);
m68ki_check_interrupts();
}
// Check for interrupts
STATIC_INLINE void m68ki_check_interrupts(void)
{
#if 0
if(CPU_INT_LEVEL > FLAG_INT_MASK)
m68ki_exception_interrupt(CPU_INT_LEVEL>>8);
#else
if (regs.intLevel > regs.intmask)
m68ki_exception_interrupt(regs.intLevel);
#endif
}
// Service an interrupt request and start exception processing
void m68ki_exception_interrupt(uint32_t intLevel)
{
#if 0
uint vector;
uint sr;
uint new_pc;
/* Turn off the stopped state */
CPU_STOPPED &= ~STOP_LEVEL_STOP;
/* If we are halted, don't do anything */
if(CPU_STOPPED)
return;
/* Acknowledge the interrupt */
vector = m68ki_int_ack(int_level);
/* Get the interrupt vector */
if(vector == M68K_INT_ACK_AUTOVECTOR)
/* Use the autovectors. This is the most commonly used implementation */
vector = EXCEPTION_INTERRUPT_AUTOVECTOR+int_level;
else if(vector == M68K_INT_ACK_SPURIOUS)
/* Called if no devices respond to the interrupt acknowledge */
vector = EXCEPTION_SPURIOUS_INTERRUPT;
else if(vector > 255)
{
M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: Interrupt acknowledge returned invalid vector $%x\n",
m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC), vector));
return;
}
/* Start exception processing */
sr = m68ki_init_exception();
/* Set the interrupt mask to the level of the one being serviced */
FLAG_INT_MASK = int_level<<8;
/* Get the new PC */
new_pc = m68ki_read_data_32((vector<<2) + REG_VBR);
/* If vector is uninitialized, call the uninitialized interrupt vector */
if(new_pc == 0)
new_pc = m68ki_read_data_32((EXCEPTION_UNINITIALIZED_INTERRUPT<<2) + REG_VBR);
/* Generate a stack frame */
m68ki_stack_frame_0000(REG_PC, sr, vector);
if(FLAG_M && CPU_TYPE_IS_EC020_PLUS(CPU_TYPE))
{
/* Create throwaway frame */
m68ki_set_sm_flag(FLAG_S); /* clear M */
sr |= 0x2000; /* Same as SR in master stack frame except S is forced high */
m68ki_stack_frame_0001(REG_PC, sr, vector);
}
m68ki_jump(new_pc);
/* Defer cycle counting until later */
CPU_INT_CYCLES += CYC_EXCEPTION[vector];
#if !M68K_EMULATE_INT_ACK
/* Automatically clear IRQ if we are not using an acknowledge scheme */
CPU_INT_LEVEL = 0;
#endif /* M68K_EMULATE_INT_ACK */
#else
// Turn off the stopped state (N.B.: normal 68K behavior!)
regs.stopped = 0;
//JLH: need to add halt state?
// prolly, for debugging/alpine mode... :-/
// but then again, this should be handled already by the main execution loop :-P
// If we are halted, don't do anything
// if (regs.halted)
// return;
// Acknowledge the interrupt (NOTE: This is a user supplied function!)
uint32_t vector = irq_ack_handler(intLevel);
// Get the interrupt vector
if (vector == M68K_INT_ACK_AUTOVECTOR)
// Use the autovectors. This is the most commonly used implementation
vector = EXCEPTION_INTERRUPT_AUTOVECTOR + intLevel;
else if (vector == M68K_INT_ACK_SPURIOUS)
// Called if no devices respond to the interrupt acknowledge
vector = EXCEPTION_SPURIOUS_INTERRUPT;
else if (vector > 255)
{
// M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: Interrupt acknowledge returned invalid vector $%x\n",
// m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC), vector));
return;
}
// Start exception processing
uint32_t sr = m68ki_init_exception();
// Set the interrupt mask to the level of the one being serviced
regs.intmask = intLevel;
#if 0
extern int startM68KTracing;
if (startM68KTracing)
{
printf("IRQ: old PC=%06X, ", regs.pc);
}
#endif
// Get the new PC
uint32_t newPC = m68k_read_memory_32(vector << 2);
#if 0
if (startM68KTracing)
{
printf("new PC=%06X, vector=%u, ", newPC, vector);
}
#endif
// If vector is uninitialized, call the uninitialized interrupt vector
if (newPC == 0)
newPC = m68k_read_memory_32(EXCEPTION_UNINITIALIZED_INTERRUPT << 2);
// Generate a stack frame
m68ki_stack_frame_3word(regs.pc, sr);
m68k_setpc(newPC);
#if 0
if (startM68KTracing)
{
printf("(PC=%06X)\n", regs.pc);
}
#endif
// Defer cycle counting until later
regs.interruptCycles += 56; // NOT ACCURATE-- !!! FIX !!!
// CPU_INT_CYCLES += CYC_EXCEPTION[vector];
#endif
regs.interruptCycles += 56;
}
// Initiate exception processing
STATIC_INLINE uint32_t m68ki_init_exception(void)
{
#if 0
/* Save the old status register */
uint sr = m68ki_get_sr();
/* Turn off trace flag, clear pending traces */
FLAG_T1 = FLAG_T0 = 0;
m68ki_clear_trace();
/* Enter supervisor mode */
m68ki_set_s_flag(SFLAG_SET);
return sr;
#else
MakeSR();
uint32_t sr = regs.sr; // Save old status register
regs.s = 1; // Set supervisor mode
uint32_t sr = regs.sr;
regs.s = 1;
return sr;
#endif
}
// 3 word stack frame (68000 only)
STATIC_INLINE void m68ki_stack_frame_3word(uint32_t pc, uint32_t sr)
{
#if 0
m68ki_push_32(pc);
m68ki_push_16(sr);
#else
// Push PC on stack:
m68k_areg(regs, 7) -= 4;
m68k_write_memory_32(m68k_areg(regs, 7), pc);
// Push SR on stack:
m68k_areg(regs, 7) -= 2;
m68k_write_memory_16(m68k_areg(regs, 7), sr);
#endif
}
unsigned int m68k_get_reg(void * context, m68k_register_t reg)
unsigned int m68k_get_reg(m68k_register_t reg)
{
if (reg <= M68K_REG_A7)
return regs.regs[reg];
@ -621,7 +218,6 @@ unsigned int m68k_get_reg(void * context, m68k_register_t reg)
return 0;
}
void m68k_set_reg(m68k_register_t reg, unsigned int value)
{
if (reg <= M68K_REG_A7)
@ -637,7 +233,6 @@ void m68k_set_reg(m68k_register_t reg, unsigned int value)
regs.regs[15] = value;
}
//
// Check if the instruction is a valid one
//
@ -651,106 +246,54 @@ unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cp
return 1;
}
// Dummy functions, for now, until we prove the concept here. :-)
// Temp, while we're using the Musashi disassembler...
#if 0
unsigned int m68k_disassemble(char * str_buff, unsigned int pc, unsigned int cpu_type)
{
return 0;
}
#endif
int m68k_cycles_run(void) {} /* Number of cycles run so far */
int m68k_cycles_remaining(void) {} /* Number of cycles left */
//void m68k_modify_timeslice(int cycles) {} /* Modify cycles left */
//void m68k_end_timeslice(void) {} /* End timeslice now */
void m68k_modify_timeslice(int cycles)
{
regs.remainingCycles = cycles;
}
void m68k_end_timeslice(void)
{
#if 0
m68ki_initial_cycles = GET_CYCLES();
SET_CYCLES(0);
#else
initialCycles = regs.remainingCycles;
regs.remainingCycles = 0;
#endif
}
unsigned long IllegalOpcode(uint32_t opcode)
{
#if 0
uint32_t pc = m68k_getpc ();
#endif
if ((opcode & 0xF000) == 0xF000)
{
Exception(0x0B, 0, M68000_EXC_SRC_CPU); // LineF exception...
Exception(0x0B, 0, M68000_EXC_SRC_CPU);
return 4;
}
else if ((opcode & 0xF000) == 0xA000)
{
Exception(0x0A, 0, M68000_EXC_SRC_CPU); // LineA exception...
Exception(0x0A, 0, M68000_EXC_SRC_CPU);
return 4;
}
#if 0
write_log ("Illegal instruction: %04x at %08lx\n", opcode, (long)pc);
#endif
Exception(0x04, 0, M68000_EXC_SRC_CPU); // Illegal opcode exception...
Exception(0x04, 0, M68000_EXC_SRC_CPU);
return 4;
}
void BuildCPUFunctionTable(void)
{
int i;
unsigned long opcode;
// We're only using the "fast" 68000 emulation here, not the "compatible"
// ("fast" doesn't throw exceptions, so we're using "compatible" now :-P)
#if 0
const struct cputbl * tbl = (currprefs.cpu_compatible
? op_smalltbl_5_ff : op_smalltbl_4_ff);
#else
//let's try "compatible" and see what happens here...
// const struct cputbl * tbl = op_smalltbl_4_ff;
const struct cputbl * tbl = op_smalltbl_5_ff;
#endif
// Log_Printf(LOG_DEBUG, "Building CPU function table (%d %d %d).\n",
// currprefs.cpu_level, currprefs.cpu_compatible, currprefs.address_space_24);
// Set all instructions to Illegal...
for(opcode=0; opcode<65536; opcode++)
cpuFunctionTable[opcode] = IllegalOpcode;
// Move functions from compact table into our full function table...
for(i=0; tbl[i].handler!=NULL; i++)
cpuFunctionTable[tbl[i].opcode] = tbl[i].handler;
//JLH: According to readcpu.c, handler is set to -1 and never changes.
// Actually, it does read this crap in readcpu.c, do_merges() does it... :-P
// Again, seems like a build time thing could be done here...
#if 1
for(opcode=0; opcode<65536; opcode++)
{
// if (table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > currprefs.cpu_level)
if (table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > 0)
continue;
if (table68k[opcode].handler != -1)
{
//printf("Relocate: $%04X->$%04X\n", table68k[opcode].handler, opcode);
cpuop_func * f = cpuFunctionTable[table68k[opcode].handler];
if (f == IllegalOpcode)
@ -759,5 +302,4 @@ void BuildCPUFunctionTable(void)
cpuFunctionTable[opcode] = f;
}
}
#endif
}

View File

@ -69,7 +69,6 @@ typedef enum
*/
#define M68K_INT_ACK_SPURIOUS 0xFFFFFFFE
void m68k_set_cpu_type(unsigned int);
void m68k_pulse_reset(void);
int m68k_execute(int num_cycles);
void m68k_set_irq(unsigned int int_level);
@ -90,45 +89,24 @@ int irq_ack_handler(int);
// Convenience functions
// Uncomment this to have the emulated CPU call a hook function after every instruction
// NB: This must be implemented by the user!
#define M68K_HOOK_FUNCTION
#ifdef M68K_HOOK_FUNCTION
void M68KInstructionHook(void);
#endif
// Functions to allow debugging
void M68KDebugHalt(void);
void M68KDebugResume(void);
/* Peek at the internals of a CPU context. This can either be a context
* retrieved using m68k_get_context() or the currently running context.
* If context is NULL, the currently running CPU context will be used.
*/
unsigned int m68k_get_reg(void * context, m68k_register_t reg);
/* Peek at the internals of the currently running CPU context */
unsigned int m68k_get_reg(m68k_register_t reg);
/* Poke values into the internals of the currently running CPU context */
void m68k_set_reg(m68k_register_t reg, unsigned int value);
// Dummy functions, for now...
/* Check if an instruction is valid for the specified CPU type */
unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cpu_type);
/* Disassemble 1 instruction using the epecified CPU type at pc. Stores
* disassembly in str_buff and returns the size of the instruction in bytes.
*/
unsigned int m68k_disassemble(char * str_buff, unsigned int pc, unsigned int cpu_type);
/* These functions let you read/write/modify the number of cycles left to run
* while m68k_execute() is running.
* These are useful if the 68k accesses a memory-mapped port on another device
* that requires immediate processing by another CPU.
*/
int m68k_cycles_run(void); // Number of cycles run so far
int m68k_cycles_remaining(void); // Number of cycles left
void m68k_modify_timeslice(int cycles); // Modify cycles left
void m68k_end_timeslice(void); // End timeslice now
void m68k_modify_timeslice(int cycles);
void m68k_end_timeslice(void);
#ifdef __cplusplus
}

View File

@ -16,9 +16,6 @@
/* 2008/04/26 [NP] Handle sz_byte for Areg as a valid srcmode if current instruction is a MOVE */
/* (e.g. move.b a1,(a0) ($1089)) (fix Blood Money on Superior 65) */
//const char ReadCpu_fileid[] = "Hatari readcpu.c : " __DATE__ " " __TIME__;
#include <ctype.h>
#include <string.h>
@ -219,12 +216,6 @@ static void build_insn(int insn)
int flaglive = 0, flagdead = 0;
id = defs68k[insn];
/* Note: We treat anything with unknown flags as a jump. That
is overkill, but "the programmer" was lazy quite often, and
*this* programmer can't be bothered to work out what can and
can't trap. Usually, this will be overwritten with the gencomp
based information, anyway. */
for(j=0; j<5; j++)
{
switch (id.flaginfo[j].flagset)
@ -304,14 +295,12 @@ out1:
if (bitval[bitj] == 0)
bitval[bitj] = 8;
/* first check whether this one does not match after all */
if (bitval[bitz] == 3 || bitval[bitC] == 1)
continue;
if (bitcnt[bitI] && (bitval[bitI] == 0x00 || bitval[bitI] == 0xff))
continue;
/* bitI and bitC get copied to biti and bitc */
if (bitcnt[bitI])
{
bitval[biti] = bitval[bitI]; bitpos[biti] = bitpos[bitI];
@ -367,15 +356,12 @@ out1:
mnemonic[mnp] = 0;
/* now, we have read the mnemonic and the size */
while (opcstr[pos] && isspace((unsigned)opcstr[pos]))
pos++;
/* A goto a day keeps the D******a away. */
if (opcstr[pos] == 0)
goto endofline;
/* parse the source address */
usesrc = 1;
switch (opcstr[pos++])
{
@ -422,7 +408,6 @@ out1:
if (CPU_EMU_SIZE < 4)
{
/* Used for branch instructions */
srctype = 1;
srcgather = 1;
srcpos = bitpos[biti];
@ -434,7 +419,6 @@ out1:
if (CPU_EMU_SIZE < 3)
{
/* 1..8 for ADDQ/SUBQ and rotshi insns */
srcgather = 1;
srctype = 3;
srcpos = bitpos[bitj];
@ -446,7 +430,6 @@ out1:
if (CPU_EMU_SIZE < 5)
{
/* 0..15 */
srcgather = 1;
srctype = 2;
srcpos = bitpos[bitJ];
@ -469,7 +452,6 @@ out1:
if (CPU_EMU_SIZE < 5)
{
/* 0..15 */
srcgather = 1;
srctype = 5;
srcpos = bitpos[bitK];
@ -481,7 +463,6 @@ out1:
if (CPU_EMU_SIZE < 5)
{
/* 0..3 */
srcgather = 1;
srctype = 7;
srcpos = bitpos[bitp];
@ -514,7 +495,6 @@ out1:
if (opcstr[pos] == '!')
{
/* exclusion */
do
{
pos++;
@ -532,7 +512,6 @@ out1:
{
if (opcstr[pos + 4] == '-')
{
/* replacement */
if (mode_from_str(opcstr + pos) == srcmode)
srcmode = mode_from_str(opcstr + pos + 5);
else
@ -542,7 +521,6 @@ out1:
}
else
{
/* normal */
while(mode_from_str(opcstr + pos) != srcmode)
{
pos += 4;
@ -562,7 +540,6 @@ out1:
}
}
/* Some addressing modes are invalid as destination */
if (srcmode == imm || srcmode == PC16 || srcmode == PC8r)
goto nomatch;
@ -589,7 +566,6 @@ out1:
if (opcstr[pos] == '!')
{
/* exclusion */
do
{
pos++;
@ -607,7 +583,6 @@ out1:
{
if (opcstr[pos + 4] == '-')
{
/* replacement */
if (mode_from_str(opcstr + pos) == srcmode)
srcmode = mode_from_str(opcstr + pos + 5);
else
@ -617,7 +592,6 @@ out1:
}
else
{
/* normal */
while(mode_from_str(opcstr+pos) != srcmode)
{
pos += 4;
@ -639,7 +613,6 @@ out1:
default: abort();
}
/* safety check - might have changed */
if (srcmode != Areg && srcmode != Dreg && srcmode != Aind
&& srcmode != Ad16 && srcmode != Ad8r && srcmode != Aipi
&& srcmode != Apdi && srcmode != immi)
@ -647,8 +620,7 @@ out1:
srcgather = 0;
}
// if (srcmode == Areg && sz == sz_byte)
if (srcmode == Areg && sz == sz_byte && strcmp(mnemonic, "MOVE") != 0 ) // [NP] move.b is valid on 68000
if (srcmode == Areg && sz == sz_byte && strcmp(mnemonic, "MOVE") != 0 )
goto nomatch;
if (opcstr[pos] != ',')
@ -656,7 +628,6 @@ out1:
pos++;
/* parse the destination address */
usedst = 1;
switch (opcstr[pos++])
@ -736,7 +707,6 @@ out1:
if (opcstr[pos] == '!')
{
/* exclusion */
do
{
pos++;
@ -754,7 +724,6 @@ out1:
{
if (opcstr[pos+4] == '-')
{
/* replacement */
if (mode_from_str(opcstr + pos) == destmode)
destmode = mode_from_str(opcstr + pos + 5);
else
@ -764,7 +733,6 @@ out1:
}
else
{
/* normal */
while(mode_from_str(opcstr + pos) != destmode)
{
pos += 4;
@ -784,7 +752,6 @@ out1:
}
}
/* Some addressing modes are invalid as destination */
if (destmode == imm || destmode == PC16 || destmode == PC8r)
goto nomatch;
@ -810,7 +777,6 @@ out1:
if (opcstr[pos] == '!')
{
/* exclusion */
do
{
pos++;
@ -828,7 +794,6 @@ out1:
{
if (opcstr[pos+4] == '-')
{
/* replacement */
if (mode_from_str(opcstr + pos) == destmode)
destmode = mode_from_str(opcstr + pos + 5);
else
@ -838,7 +803,6 @@ out1:
}
else
{
/* normal */
while (mode_from_str(opcstr + pos) != destmode)
{
pos += 4;
@ -860,7 +824,6 @@ out1:
default: abort();
}
/* safety check - might have changed */
if (destmode != Areg && destmode != Dreg && destmode != Aind
&& destmode != Ad16 && destmode != Ad8r && destmode != Aipi
&& destmode != Apdi)
@ -870,13 +833,7 @@ out1:
if (destmode == Areg && sz == sz_byte)
goto nomatch;
#if 0
if (sz == sz_byte && (destmode == Aipi || destmode == Apdi)) {
dstgather = 0;
}
#endif
endofline:
/* now, we have a match */
if (table68k[opc].mnemo != i_ILLG)
fprintf(stderr, "Double match: %x: %s\n", opc, opcstr);
@ -921,22 +878,15 @@ endofline:
table68k[opc].stype = srctype;
table68k[opc].plev = id.plevel;
table68k[opc].clev = id.cpulevel;
#if 0
for (i = 0; i < 5; i++) {
table68k[opc].flaginfo[i].flagset = id.flaginfo[i].flagset;
table68k[opc].flaginfo[i].flaguse = id.flaginfo[i].flaguse;
}
#endif
table68k[opc].flagdead = flagdead;
table68k[opc].flaglive = flaglive;
table68k[opc].isjmp = isjmp;
nomatch:
/* FOO! */;
;
}
}
void read_table68k(void)
{
int i;
@ -952,21 +902,15 @@ void read_table68k(void)
build_insn(i);
}
static int mismatch;
static void handle_merges (long int opcode)
static void handle_merges(long int opcode)
{
uint16_t smsk;
uint16_t dmsk;
int sbitdst, dstend;
int srcreg, dstreg;
//0011 DDDd ddss sSSS:00:-NZ00:-----:12: MOVE.W s,d[!Areg]
//31C3 ->
//0011 0001 1100 0011 : DDD = 0, ddd = 7, sss = 0, SSS = 3
if (table68k[opcode].spos == -1)
{
sbitdst = 1;
@ -1019,9 +963,6 @@ static void handle_merges (long int opcode)
code = (code & ~smsk) | (srcreg << table68k[opcode].spos);
code = (code & ~dmsk) | (dstreg << table68k[opcode].dpos);
/* Check whether this is in fact the same instruction.
* The instructions should never differ, except for the
* Bcc.(BW) case. */
if (table68k[code].mnemo != table68k[opcode].mnemo
|| table68k[code].size != table68k[opcode].size
|| table68k[code].suse != table68k[opcode].suse
@ -1051,52 +992,11 @@ static void handle_merges (long int opcode)
if (code != opcode)
{
table68k[code].handler = opcode;
#if 0
if (opcode == 0x31C3 || code == 0x31C3)
{
printf("Relocate... ($%04X->$%04X)\n", (uint16_t)opcode, code);
printf(" handler: %08X\n", table68k[code].handler);
printf(" dreg: %i\n", table68k[code].dreg);
printf(" sreg: %i\n", table68k[code].sreg);
printf(" dpos: %i\n", table68k[code].dpos);
printf(" spos: %i\n", table68k[code].spos);
printf(" sduse: %i\n", table68k[code].sduse);
printf("flagdead: %i\n", table68k[code].flagdead);
printf("flaglive: %i\n", table68k[code].flaglive);
}
#endif
/*
long int handler;
unsigned char dreg;
unsigned char sreg;
signed char dpos;
signed char spos;
unsigned char sduse;
int flagdead:8, flaglive:8;
unsigned int mnemo:8;
unsigned int cc:4;
unsigned int plev:2;
unsigned int size:2;
unsigned int smode:5;
unsigned int stype:3;
unsigned int dmode:5;
unsigned int suse:1;
unsigned int duse:1;
unsigned int unused1:1;
unsigned int clev:3;
unsigned int isjmp:1;
unsigned int unused2:4;
*/
}
}
}
}
// What this really does is expand the # of handlers, which is why the
// opcode has to be passed into the opcode handler...
// E.g., $F620 maps into $F621-F627 as well; this code does this expansion.
void do_merges(void)
{
long int opcode;
@ -1115,9 +1015,7 @@ void do_merges(void)
nr_cpuop_funcs = nr;
}
int get_no_mismatches(void)
{
return mismatch;
}

View File

@ -11,7 +11,6 @@
#include "sysdeps.h"
ENUMDECL {
Dreg, Areg, Aind, Aipi, Apdi, Ad16, Ad8r,
absw, absl, PC16, PC8r, imm, imm0, imm1, imm2, immi, am_unknown, am_illg
@ -44,7 +43,7 @@ ENUMDECL {
i_CINVL, i_CINVP, i_CINVA, i_CPUSHL, i_CPUSHP, i_CPUSHA, i_MOVE16,
i_MMUOP,
MAX_OPCODE_FAMILY /* should always be last of the list */
MAX_OPCODE_FAMILY
} ENUMNAME (instrmnem);
extern const struct mnemolookup {

View File

@ -27,67 +27,11 @@
#include <assert.h>
#include <limits.h>
#ifndef __STDC__
#error "Your compiler is not ANSI. Get a real one."
#endif
#include <stdarg.h>
#include <stdint.h>
#if EEXIST == ENOTEMPTY
#define BROKEN_OS_PROBABLY_AIX
#endif
#ifdef __NeXT__
#define S_IRUSR S_IREAD
#define S_IWUSR S_IWRITE
#define S_IXUSR S_IEXEC
#define S_ISDIR(val) (S_IFDIR & val)
struct utimbuf
{
time_t actime;
time_t modtime;
};
#endif
#if defined(WARPUP)
#include "devices/timer.h"
#include "osdep/posixemu.h"
#define RETSIGTYPE
#define USE_ZFILE
#define strcasecmp stricmp
#define memcpy q_memcpy
#define memset q_memset
#define strdup my_strdup
#define random rand
#define creat(x,y) open("T:creat",O_CREAT|O_RDWR|O_TRUNC,777)
extern void * q_memset(void *, int, size_t);
extern void * q_memcpy(void *, const void *, size_t);
#endif
/* Acorn specific stuff */
#ifdef ACORN
#define S_IRUSR S_IREAD
#define S_IWUSR S_IWRITE
#define S_IXUSR S_IEXEC
#define strcasecmp stricmp
#endif
/* We can only rely on GNU C getting enums right. Mickeysoft VSC++ is known
* to have problems, and it's likely that other compilers choke too. */
#ifdef __GNUC__
#define ENUMDECL typedef enum
#define ENUMNAME(name) name
#else
#define ENUMDECL enum
#define ENUMNAME(name) ; typedef int name
#endif
/* When using GNU C, make abort more useful. */
#ifdef __GNUC__
@ -98,11 +42,6 @@ extern void * q_memcpy(void *, const void *, size_t);
} while (0)
#endif
#ifndef O_BINARY
#define O_BINARY 0
#endif
#ifndef STATIC_INLINE
#define STATIC_INLINE static __inline__
#endif

View File

@ -1,260 +0,0 @@
% 0: bit 0
% 1: bit 1
% c: condition code
% C: condition codes, except F
% f: direction
% i: immediate
% I: immediate, except 00 and ff
% j: immediate 1..8
% J: immediate 0..15
% k: immediate 0..7
% K: immediate 0..63
% p: immediate 0..3 (CINV and CPUSH: cache field)
% s: source mode
% S: source reg
% d: dest mode
% D: dest reg
% r: reg
% z: size
%
% Actually, a sssSSS may appear as a destination, and
% vice versa. The only difference between sssSSS and
% dddDDD are the valid addressing modes. There is
% no match for immediate and pc-rel. addressing modes
% in case of dddDDD.
%
% Arp: --> -(Ar)
% ArP: --> (Ar)+
% L: (xxx.L)
%
% Fields on a line:
% 16 chars bitpattern :
% CPU level / privilege level :
% CPU level 0: 68000
% 1: 68010
% 2: 68020
% privilege level 0: not privileged
% 1: unprivileged only on 68000 (check regs.s)
% 2: privileged (check regs.s)
% 3: privileged if size == word (check regs.s)
% Flags set by instruction: XNZVC :
% Flags used by instruction: XNZVC :
% - means flag unaffected / unused
% 0 means flag reset
% 1 means flag set
% ? means programmer was too lazy to check or instruction may trap
% + means instruction is conditional branch
% everything else means flag set/used
% / means instruction is unconditional branch/call
% x means flag is unknown and well-behaved programs shouldn't check it
% srcaddr status destaddr status :
% bitmasks of
% 1 means fetched
% 2 means stored
% 4 means jump offset
% 8 means jump address
% instruction
%
0000 0000 0011 1100:00:XNZVC:XNZVC:10: ORSR.B #1
0000 0000 0111 1100:02:?????:?????:10: ORSR.W #1
0000 0zz0 11ss sSSS:20:?????:?????:11: CHK2.z #1,s[!Dreg,Areg,Aipi,Apdi,Immd]
0000 0000 zzdd dDDD:00:-NZ00:-----:13: OR.z #z,d[!Areg]
0000 0010 0011 1100:00:XNZVC:XNZVC:10: ANDSR.B #1
0000 0010 0111 1100:02:?????:?????:10: ANDSR.W #1
0000 0010 zzdd dDDD:00:-NZ00:-----:13: AND.z #z,d[!Areg]
0000 0100 zzdd dDDD:00:XNZVC:-----:13: SUB.z #z,d[!Areg]
0000 0110 zzdd dDDD:00:XNZVC:-----:13: ADD.z #z,d[!Areg]
0000 0110 11ss sSSS:20:?????:?????:10: CALLM s[!Dreg,Areg,Aipi,Apdi,Immd]
0000 0110 11ss sSSS:20:?????:?????:10: RTM s[Dreg,Areg]
0000 1000 00ss sSSS:00:--Z--:-----:11: BTST #1,s[!Areg]
0000 1000 01ss sSSS:00:--Z--:-----:13: BCHG #1,s[!Areg,Immd]
0000 1000 10ss sSSS:00:--Z--:-----:13: BCLR #1,s[!Areg,Immd]
0000 1000 11ss sSSS:00:--Z--:-----:13: BSET #1,s[!Areg,Immd]
0000 1010 0011 1100:00:XNZVC:XNZVC:10: EORSR.B #1
0000 1010 0111 1100:02:?????:?????:10: EORSR.W #1
0000 1010 zzdd dDDD:00:-NZ00:-----:13: EOR.z #z,d[!Areg]
0000 1100 zzss sSSS:00:-NZVC:-----:11: CMP.z #z,s[!Areg,Immd]
0000 1010 11ss sSSS:20:?????:?????:13: CAS.B #1,s[!Dreg,Areg,Immd,PC8r,PC16]
0000 1100 11ss sSSS:20:?????:?????:13: CAS.W #1,s[!Dreg,Areg,Immd,PC8r,PC16]
0000 1100 1111 1100:20:?????:?????:10: CAS2.W #2
0000 1110 zzss sSSS:22:?????:?????:13: MOVES.z #1,s[!Dreg,Areg,Immd,PC8r,PC16]
0000 1110 11ss sSSS:20:?????:?????:13: CAS.L #1,s[!Dreg,Areg,Immd,PC8r,PC16]
0000 1110 1111 1100:20:?????:?????:10: CAS2.L #2
0000 rrr1 00dd dDDD:00:-----:-----:12: MVPMR.W d[Areg-Ad16],Dr
0000 rrr1 01dd dDDD:00:-----:-----:12: MVPMR.L d[Areg-Ad16],Dr
0000 rrr1 10dd dDDD:00:-----:-----:12: MVPRM.W Dr,d[Areg-Ad16]
0000 rrr1 11dd dDDD:00:-----:-----:12: MVPRM.L Dr,d[Areg-Ad16]
0000 rrr1 00ss sSSS:00:--Z--:-----:11: BTST Dr,s[!Areg]
0000 rrr1 01ss sSSS:00:--Z--:-----:13: BCHG Dr,s[!Areg,Immd]
0000 rrr1 10ss sSSS:00:--Z--:-----:13: BCLR Dr,s[!Areg,Immd]
0000 rrr1 11ss sSSS:00:--Z--:-----:13: BSET Dr,s[!Areg,Immd]
0001 DDDd ddss sSSS:00:-NZ00:-----:12: MOVE.B s,d[!Areg]
0010 DDDd ddss sSSS:00:-----:-----:12: MOVEA.L s,d[Areg]
0010 DDDd ddss sSSS:00:-NZ00:-----:12: MOVE.L s,d[!Areg]
0011 DDDd ddss sSSS:00:-----:-----:12: MOVEA.W s,d[Areg]
0011 DDDd ddss sSSS:00:-NZ00:-----:12: MOVE.W s,d[!Areg]
0100 0000 zzdd dDDD:00:XxZxC:X-Z--:30: NEGX.z d[!Areg]
0100 0000 11dd dDDD:01:?????:?????:10: MVSR2.W d[!Areg]
0100 0010 zzdd dDDD:00:-0100:-----:20: CLR.z d[!Areg]
0100 0010 11dd dDDD:10:?????:?????:10: MVSR2.B d[!Areg]
0100 0100 zzdd dDDD:00:XNZVC:-----:30: NEG.z d[!Areg]
0100 0100 11ss sSSS:00:XNZVC:-----:10: MV2SR.B s[!Areg]
0100 0110 zzdd dDDD:00:-NZ00:-----:30: NOT.z d[!Areg]
0100 0110 11ss sSSS:02:?????:?????:10: MV2SR.W s[!Areg]
0100 1000 0000 1rrr:20:-----:-----:31: LINK.L Ar,#2
0100 1000 00dd dDDD:00:X?Z?C:X-Z--:30: NBCD.B d[!Areg]
0100 1000 0100 1kkk:20:?????:?????:10: BKPT #k
0100 1000 01ss sSSS:00:-NZ00:-----:30: SWAP.W s[Dreg]
0100 1000 01ss sSSS:00:-----:-----:00: PEA.L s[!Dreg,Areg,Aipi,Apdi,Immd]
0100 1000 10dd dDDD:00:-NZ00:-----:30: EXT.W d[Dreg]
0100 1000 10dd dDDD:00:-----:-----:02: MVMLE.W #1,d[!Dreg,Areg,Aipi]
0100 1000 11dd dDDD:00:-NZ00:-----:30: EXT.L d[Dreg]
0100 1000 11dd dDDD:00:-----:-----:02: MVMLE.L #1,d[!Dreg,Areg,Aipi]
0100 1001 11dd dDDD:20:-NZ00:-----:30: EXT.B d[Dreg]
0100 1010 zzss sSSS:00:-NZ00:-----:10: TST.z s
0100 1010 11dd dDDD:00:?????:?????:30: TAS.B d[!Areg]
0100 1010 1111 1100:00:?????:?????:00: ILLEGAL
0100 1100 00ss sSSS:20:-NZVC:-----:13: MULL.L #1,s[!Areg]
0100 1100 01ss sSSS:20:?????:?????:13: DIVL.L #1,s[!Areg]
0100 1100 10ss sSSS:00:-----:-----:01: MVMEL.W #1,s[!Dreg,Areg,Apdi,Immd]
0100 1100 11ss sSSS:00:-----:-----:01: MVMEL.L #1,s[!Dreg,Areg,Apdi,Immd]
0100 1110 0100 JJJJ:00:-----:XNZVC:10: TRAP #J
0100 1110 0101 0rrr:00:-----:-----:31: LINK.W Ar,#1
0100 1110 0101 1rrr:00:-----:-----:30: UNLK.L Ar
0100 1110 0110 0rrr:02:-----:-----:10: MVR2USP.L Ar
0100 1110 0110 1rrr:02:-----:-----:20: MVUSP2R.L Ar
0100 1110 0111 0000:02:-----:-----:00: RESET
0100 1110 0111 0001:00:-----:-----:00: NOP
0100 1110 0111 0010:02:XNZVC:-----:10: STOP #1
0100 1110 0111 0011:02:XNZVC:-----:00: RTE
0100 1110 0111 0100:00:?????:?????:10: RTD #1
0100 1110 0111 0101:00:-----:-----:00: RTS
0100 1110 0111 0110:00:-----:XNZVC:00: TRAPV
0100 1110 0111 0111:00:XNZVC:-----:00: RTR
0100 1110 0111 1010:12:?????:?????:10: MOVEC2 #1
0100 1110 0111 1011:12:?????:?????:10: MOVE2C #1
0100 1110 10ss sSSS:00://///://///:80: JSR.L s[!Dreg,Areg,Aipi,Apdi,Immd]
0100 rrr1 00ss sSSS:20:?????:?????:11: CHK.L s[!Areg],Dr
0100 rrr1 10ss sSSS:00:?????:?????:11: CHK.W s[!Areg],Dr
0100 1110 11ss sSSS:00://///://///:80: JMP.L s[!Dreg,Areg,Aipi,Apdi,Immd]
0100 rrr1 11ss sSSS:00:-----:-----:02: LEA.L s[!Dreg,Areg,Aipi,Apdi,Immd],Ar
0101 jjj0 01dd dDDD:00:-----:-----:13: ADDA.W #j,d[Areg]
0101 jjj0 10dd dDDD:00:-----:-----:13: ADDA.L #j,d[Areg]
0101 jjj0 zzdd dDDD:00:XNZVC:-----:13: ADD.z #j,d[!Areg]
0101 jjj1 01dd dDDD:00:-----:-----:13: SUBA.W #j,d[Areg]
0101 jjj1 10dd dDDD:00:-----:-----:13: SUBA.L #j,d[Areg]
0101 jjj1 zzdd dDDD:00:XNZVC:-----:13: SUB.z #j,d[!Areg]
0101 cccc 1100 1rrr:00:-----:-++++:31: DBcc.W Dr,#1
0101 cccc 11dd dDDD:00:-----:-++++:20: Scc.B d[!Areg]
0101 cccc 1111 1010:20:?????:?????:10: TRAPcc #1
0101 cccc 1111 1011:20:?????:?????:10: TRAPcc #2
0101 cccc 1111 1100:20:?????:?????:00: TRAPcc
% Bxx.L is 68020 only, but setting the CPU level to 2 would give illegal
% instruction exceptions when compiling a 68000 only emulation, which isn't
% what we want either.
0110 0001 0000 0000:00://///://///:40: BSR.W #1
0110 0001 IIII IIII:00://///://///:40: BSR.B #i
0110 0001 1111 1111:00://///://///:40: BSR.L #2
0110 CCCC 0000 0000:00:-----:-++++:40: Bcc.W #1
0110 CCCC IIII IIII:00:-----:-++++:40: Bcc.B #i
0110 CCCC 1111 1111:00:-----:-++++:40: Bcc.L #2
0111 rrr0 iiii iiii:00:-NZ00:-----:12: MOVE.L #i,Dr
1000 rrr0 zzss sSSS:00:-NZ00:-----:13: OR.z s[!Areg],Dr
1000 rrr0 11ss sSSS:00:?????:?????:13: DIVU.W s[!Areg],Dr
1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:13: SBCD.B d[Dreg],Dr
1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:13: SBCD.B d[Areg-Apdi],Arp
1000 rrr1 zzdd dDDD:00:-NZ00:-----:13: OR.z Dr,d[!Areg,Dreg]
1000 rrr1 01dd dDDD:20:?????:?????:12: PACK d[Dreg],Dr
1000 rrr1 01dd dDDD:20:?????:?????:12: PACK d[Areg-Apdi],Arp
1000 rrr1 10dd dDDD:20:?????:?????:12: UNPK d[Dreg],Dr
1000 rrr1 10dd dDDD:20:?????:?????:12: UNPK d[Areg-Apdi],Arp
1000 rrr1 11ss sSSS:00:?????:?????:13: DIVS.W s[!Areg],Dr
1001 rrr0 zzss sSSS:00:XNZVC:-----:13: SUB.z s,Dr
1001 rrr0 11ss sSSS:00:-----:-----:13: SUBA.W s,Ar
1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:13: SUBX.z d[Dreg],Dr
1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:13: SUBX.z d[Areg-Apdi],Arp
1001 rrr1 zzdd dDDD:00:XNZVC:-----:13: SUB.z Dr,d[!Areg,Dreg]
1001 rrr1 11ss sSSS:00:-----:-----:13: SUBA.L s,Ar
1011 rrr0 zzss sSSS:00:-NZVC:-----:11: CMP.z s,Dr
1011 rrr0 11ss sSSS:00:-NZVC:-----:11: CMPA.W s,Ar
1011 rrr1 11ss sSSS:00:-NZVC:-----:11: CMPA.L s,Ar
1011 rrr1 zzdd dDDD:00:-NZVC:-----:11: CMPM.z d[Areg-Aipi],ArP
1011 rrr1 zzdd dDDD:00:-NZ00:-----:13: EOR.z Dr,d[!Areg]
1100 rrr0 zzss sSSS:00:-NZ00:-----:13: AND.z s[!Areg],Dr
1100 rrr0 11ss sSSS:00:-NZ00:-----:13: MULU.W s[!Areg],Dr
1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:13: ABCD.B d[Dreg],Dr
1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:13: ABCD.B d[Areg-Apdi],Arp
1100 rrr1 zzdd dDDD:00:-NZ00:-----:13: AND.z Dr,d[!Areg,Dreg]
1100 rrr1 01dd dDDD:00:-----:-----:33: EXG.L Dr,d[Dreg]
1100 rrr1 01dd dDDD:00:-----:-----:33: EXG.L Ar,d[Areg]
1100 rrr1 10dd dDDD:00:-----:-----:33: EXG.L Dr,d[Areg]
1100 rrr1 11ss sSSS:00:-NZ00:-----:13: MULS.W s[!Areg],Dr
1101 rrr0 zzss sSSS:00:XNZVC:-----:13: ADD.z s,Dr
1101 rrr0 11ss sSSS:00:-----:-----:13: ADDA.W s,Ar
1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:13: ADDX.z d[Dreg],Dr
1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:13: ADDX.z d[Areg-Apdi],Arp
1101 rrr1 zzdd dDDD:00:XNZVC:-----:13: ADD.z Dr,d[!Areg,Dreg]
1101 rrr1 11ss sSSS:00:-----:-----:13: ADDA.L s,Ar
1110 jjjf zz00 0RRR:00:XNZVC:-----:13: ASf.z #j,DR
1110 jjjf zz00 1RRR:00:XNZ0C:-----:13: LSf.z #j,DR
1110 jjjf zz01 0RRR:00:XNZ0C:X----:13: ROXf.z #j,DR
1110 jjjf zz01 1RRR:00:-NZ0C:-----:13: ROf.z #j,DR
1110 rrrf zz10 0RRR:00:XNZVC:X----:13: ASf.z Dr,DR
1110 rrrf zz10 1RRR:00:XNZ0C:X----:13: LSf.z Dr,DR
1110 rrrf zz11 0RRR:00:XNZ0C:X----:13: ROXf.z Dr,DR
1110 rrrf zz11 1RRR:00:-NZ0C:-----:13: ROf.z Dr,DR
1110 000f 11dd dDDD:00:XNZVC:-----:13: ASfW.W d[!Dreg,Areg]
1110 001f 11dd dDDD:00:XNZ0C:-----:13: LSfW.W d[!Dreg,Areg]
1110 010f 11dd dDDD:00:XNZ0C:X----:13: ROXfW.W d[!Dreg,Areg]
1110 011f 11dd dDDD:00:-NZ0C:-----:13: ROfW.W d[!Dreg,Areg]
1110 1000 11ss sSSS:20:?????:?????:11: BFTST #1,s[!Areg,Apdi,Aipi,Immd]
1110 1001 11ss sSSS:20:?????:?????:11: BFEXTU #1,s[!Areg,Apdi,Aipi,Immd]
1110 1010 11ss sSSS:20:?????:?????:13: BFCHG #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]
1110 1011 11ss sSSS:20:?????:?????:11: BFEXTS #1,s[!Areg,Apdi,Aipi,Immd]
1110 1100 11ss sSSS:20:?????:?????:13: BFCLR #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]
1110 1101 11ss sSSS:20:?????:?????:11: BFFFO #1,s[!Areg,Apdi,Aipi,Immd]
1110 1110 11ss sSSS:20:?????:?????:13: BFSET #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]
1110 1111 11ss sSSS:20:?????:?????:13: BFINS #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]
% floating point co processor
1111 0010 00ss sSSS:30:?????:?????:11: FPP #1,s
1111 0010 01ss sSSS:30:?????:?????:11: FDBcc #1,s[Areg-Dreg]
1111 0010 01ss sSSS:30:?????:?????:11: FScc #1,s[!Areg,Immd,PC8r,PC16]
1111 0010 0111 1010:30:?????:?????:10: FTRAPcc #1
1111 0010 0111 1011:30:?????:?????:10: FTRAPcc #2
1111 0010 0111 1100:30:?????:?????:00: FTRAPcc
1111 0010 10KK KKKK:30:?????:?????:11: FBcc #K,#1
1111 0010 11KK KKKK:30:?????:?????:11: FBcc #K,#2
1111 0011 00ss sSSS:32:?????:?????:20: FSAVE s[!Dreg,Areg,Aipi,Immd,PC8r,PC16]
1111 0011 01ss sSSS:32:?????:?????:10: FRESTORE s[!Dreg,Areg,Apdi,Immd]
1111 0101 iiii iSSS:40:?????:?????:11: MMUOP #i,s
% 68040 instructions
1111 0100 pp00 1rrr:42:-----:-----:02: CINVL #p,Ar
1111 0100 pp01 0rrr:42:-----:-----:02: CINVP #p,Ar
1111 0100 pp01 1rrr:42:-----:-----:00: CINVA #p
1111 0100 pp10 1rrr:42:-----:-----:02: CPUSHL #p,Ar
1111 0100 pp11 0rrr:42:-----:-----:02: CPUSHP #p,Ar
1111 0100 pp11 1rrr:42:-----:-----:00: CPUSHA #p
% destination register number is encoded in the following word
1111 0110 0010 0rrr:40:-----:-----:12: MOVE16 ArP,AxP
1111 0110 00ss sSSS:40:-----:-----:12: MOVE16 s[Dreg-Aipi],L
1111 0110 00dd dDDD:40:-----:-----:12: MOVE16 L,d[Areg-Aipi]
1111 0110 00ss sSSS:40:-----:-----:12: MOVE16 s[Aind],L
1111 0110 00dd dDDD:40:-----:-----:12: MOVE16 L,d[Aipi-Aind]