Update Musashi to 3.32 (MAME version 0.128)

This commit is contained in:
Barry Harris 2014-11-09 17:15:57 +00:00
parent a63d902eb7
commit 5292cab48d
12 changed files with 2047 additions and 835 deletions

View File

@ -114,7 +114,7 @@ psikyo_tile_func.h = $(srcdir)dep/generated/psikyo_tile_func.h
pgm_sprite.h = $(srcdir)dep/generated/pgm_sprite.h
build_details.h = $(srcdir)dep/generated/build_details.h
allobj = $(objdir)cpu/m68k/m68kcpu.o $(objdir)cpu/m68k/m68kopnz.o $(objdir)cpu/m68k/m68kopdm.o $(objdir)cpu/m68k/m68kopac.o $(objdir)cpu/m68k/m68kops.o \
allobj = $(objdir)cpu/m68k/m68kcpu.o $(objdir)cpu/m68k/m68kops.o \
$(foreach file,$(autobj:.o=.c), \
$(foreach dir,$(alldir),$(subst $(srcdir),$(objdir), \
$(firstword $(subst .c,.o,$(wildcard $(srcdir)$(dir)/$(file))))))) \

View File

@ -127,7 +127,7 @@ psikyo_tile_func.h = $(srcdir)dep/generated/psikyo_tile_func.h
pgm_sprite.h = $(srcdir)dep/generated/pgm_sprite.h
build_details.h = $(srcdir)dep/generated/build_details.h
allobj = $(objdir)cpu/m68k/m68kcpu.o $(objdir)cpu/m68k/m68kopnz.o $(objdir)cpu/m68k/m68kopdm.o $(objdir)cpu/m68k/m68kopac.o $(objdir)cpu/m68k/m68kops.o \
allobj = $(objdir)cpu/m68k/m68kcpu.o $(objdir)cpu/m68k/m68kops.o \
$(foreach file,$(autobj:.o=.c), \
$(foreach dir,$(alldir),$(subst $(srcdir),$(objdir), \
$(firstword $(subst .c,.o,$(wildcard $(srcdir)$(dir)/$(file))))))) \

View File

@ -229,7 +229,7 @@ cave_sprite_func.h = $(srcdir)depend/generated/cave_sprite_func.h
psikyo_tile_func.h = $(srcdir)depend/generated/psikyo_tile_func.h
pgm_sprite.h = $(srcdir)depend/generated/pgm_sprite.h
allobj = $(objdir)cpu/m68k/m68kcpu.o $(objdir)cpu/m68k/m68kopnz.o $(objdir)cpu/m68k/m68kopdm.o $(objdir)cpu/m68k/m68kopac.o $(objdir)cpu/m68k/m68kops.o \
allobj = $(objdir)cpu/m68k/m68kcpu.o $(objdir)cpu/m68k/m68kops.o \
$(foreach file,$(autobj:.o=.c), \
$(foreach dir,$(alldir),$(subst $(srcdir),$(objdir), \
$(firstword $(subst .c,.o,$(wildcard $(srcdir)$(dir)/$(file))))))) \

View File

@ -128,7 +128,7 @@ psikyo_tile_func.h = $(srcdir)dep/generated/psikyo_tile_func.h
pgm_sprite.h = $(srcdir)dep/generated/pgm_sprite.h
build_details.h = $(srcdir)dep/generated/build_details.h
allobj = $(objdir)cpu/m68k/m68kcpu.o $(objdir)cpu/m68k/m68kopnz.o $(objdir)cpu/m68k/m68kopdm.o $(objdir)cpu/m68k/m68kopac.o $(objdir)cpu/m68k/m68kops.o $(objdir)burner/win32/resource.res \
allobj = $(objdir)cpu/m68k/m68kcpu.o $(objdir)cpu/m68k/m68kops.o $(objdir)burner/win32/resource.res \
$(foreach file,$(autobj:.o=.c), \
$(foreach dir,$(alldir),$(subst $(srcdir),$(objdir), \
$(firstword $(subst .c,.o,$(wildcard $(srcdir)$(dir)/$(file))))))) \

View File

@ -107,7 +107,7 @@ inline static void CheckBreakpoint_W(UINT32 a, const UINT32 m)
}
}
inline static void CheckBreakpoint_PC()
inline static void CheckBreakpoint_PC(unsigned int /*pc*/)
{
for (INT32 i = 0; BreakpointFetch[i].address; i++) {
if (BreakpointFetch[i].address == (UINT32)SekGetPC(-1)) {
@ -122,7 +122,7 @@ inline static void CheckBreakpoint_PC()
}
}
inline static void SingleStep_PC()
inline static void SingleStep_PC(unsigned int /*pc*/)
{
#ifdef EMU_A68K
UpdateA68KContext();
@ -512,7 +512,7 @@ struct A68KContext* SekRegs[SEK_MAX] = { NULL, };
#endif
struct A68KInter {
void (__fastcall *DebugCallback) ();
void (__fastcall *DebugCallback) (unsigned int pc);
UINT8 (__fastcall *Read8) (UINT32 a);
UINT16 (__fastcall *Read16)(UINT32 a);
UINT32 (__fastcall *Read32)(UINT32 a);
@ -556,8 +556,8 @@ void __fastcall A68KWrite16(UINT32 a,UINT16 d) { WriteWord(a,d);}
void __fastcall A68KWrite32(UINT32 a,UINT32 d) { WriteLong(a,d);}
#if defined (FBA_DEBUG)
void __fastcall A68KCheckBreakpoint() { CheckBreakpoint_PC(); }
void __fastcall A68KSingleStep() { SingleStep_PC(); }
void __fastcall A68KCheckBreakpoint(unsigned int pc) { CheckBreakpoint_PC(pc); }
void __fastcall A68KSingleStep(unsigned int pc) { SingleStep_PC(pc); }
#endif
#ifdef EMU_A68K
@ -592,8 +592,8 @@ void __fastcall M68KWriteByteBP(UINT32 a, UINT32 d) { WriteByteBP(a, d); }
void __fastcall M68KWriteWordBP(UINT32 a, UINT32 d) { WriteWordBP(a, d); }
void __fastcall M68KWriteLongBP(UINT32 a, UINT32 d) { WriteLongBP(a, d); }
void M68KCheckBreakpoint() { CheckBreakpoint_PC(); }
void M68KSingleStep() { SingleStep_PC(); }
void M68KCheckBreakpoint(unsigned int pc) { CheckBreakpoint_PC(pc); }
void M68KSingleStep(unsigned int pc) { SingleStep_PC(pc); }
UINT32 (__fastcall *M68KReadByteDebug)(UINT32);
UINT32 (__fastcall *M68KReadWordDebug)(UINT32);

View File

@ -10,23 +10,24 @@
/* ======================================================================== */
/*
* MUSASHI
* Version 3.3
* Version 3.32
*
* A portable Motorola M680x0 processor emulation engine.
* Copyright 1998-2001 Karl Stenerud. All rights reserved.
* Copyright Karl Stenerud. All rights reserved.
*
* This code may be freely used for non-commercial purposes as long as this
* copyright notice remains unaltered in the source code and any binary files
* containing this code in compiled form.
*
* All other lisencing terms must be negotiated with the author
* All other licensing terms must be negotiated with the author
* (Karl Stenerud).
*
* The latest version of this code can be obtained at:
* http://kstenerud.cjb.net
*/
/* ======================================================================== */
/* ============================ GENERAL DEFINES =========================== */
/* ======================================================================== */
@ -76,7 +77,7 @@ enum
};
/* Registers used by m68k_get_reg() and m68k_set_reg() */
typedef enum
enum _m68k_register_t
{
/* Real registers */
M68K_REG_D0, /* Data registers */
@ -109,8 +110,8 @@ typedef enum
/* Assumed registers */
/* These are cheat registers which emulate the 1-longword prefetch
* present in the 68000 and 68010.
*/
* present in the 68000 and 68010.
*/
M68K_REG_PREF_ADDR, /* Last prefetch address */
M68K_REG_PREF_DATA, /* Last prefetch data */
@ -118,7 +119,10 @@ typedef enum
M68K_REG_PPC, /* Previous value in the program counter */
M68K_REG_IR, /* Instruction register */
M68K_REG_CPU_TYPE /* Type of CPU being run */
} m68k_register_t;
};
typedef enum _m68k_register_t m68k_register_t;
/* ======================================================================== */
/* ====================== FUNCTIONS CALLED BY THE CPU ===================== */
@ -236,6 +240,14 @@ void m68k_set_cmpild_instr_callback(void (*callback)(unsigned int val, int reg)
*/
void m68k_set_rte_instr_callback(void (*callback)(void));
/* Set the callback for the TAS instruction.
* You must enable M68K_TAS_HAS_CALLBACK in m68kconf.h.
* The CPU calls this callback every time it encounters a TAS instruction.
* Default behavior: return 1, allow writeback.
*/
void m68k_set_tas_instr_callback(int (*callback)(void));
/* Set the callback for informing of a large PC change.
* You must enable M68K_MONITOR_PC in m68kconf.h.
@ -262,7 +274,7 @@ void m68k_set_fc_callback(void (*callback)(unsigned int new_fc));
* instruction cycle.
* Default behavior: do nothing.
*/
void m68k_set_instr_hook_callback(void (*callback)(void));
void m68k_set_instr_hook_callback(void (*callback)(unsigned int pc));
@ -308,6 +320,12 @@ void m68k_end_timeslice(void); /* End timeslice now */
*/
void m68k_set_irq(unsigned int int_level);
/* Set the virtual irq lines, where the highest level
* active line is automatically selected. If you use this function,
* do not use m68k_set_irq.
*/
void m68k_set_virq(unsigned int level, unsigned int active);
unsigned int m68k_get_virq(unsigned int level);
/* Halt the CPU as if you pulsed the HALT pin. */
void m68k_pulse_halt(void);
@ -325,7 +343,7 @@ unsigned int m68k_get_context(void* dst);
void m68k_set_context(void* dst);
/* Register the CPU state information */
void m68k_state_register(const char *type);
void m68k_state_register(const char *type, int index);
/* Peek at the internals of a CPU context. This can either be a context
@ -345,6 +363,11 @@ unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cp
*/
unsigned int m68k_disassemble(char* str_buff, unsigned int pc, unsigned int cpu_type);
/* Same as above but accepts raw opcode data directly rather than fetching
* via the read/write interfaces.
*/
unsigned int m68k_disassemble_raw(char* str_buff, unsigned int pc, const unsigned char* opdata, const unsigned char* argdata, unsigned int cpu_type);
/* ======================================================================== */
/* ============================= CONFIGURATION ============================ */

File diff suppressed because it is too large Load Diff

View File

@ -3,16 +3,16 @@
/* ======================================================================== */
/*
* MUSASHI
* Version 3.3
* Version 3.32
*
* A portable Motorola M680x0 processor emulation engine.
* Copyright 1998-2001 Karl Stenerud. All rights reserved.
* Copyright Karl Stenerud. All rights reserved.
*
* This code may be freely used for non-commercial purposes as long as this
* copyright notice remains unaltered in the source code and any binary files
* containing this code in compiled form.
*
* All other lisencing terms must be negotiated with the author
* All other licensing terms must be negotiated with the author
* (Karl Stenerud).
*
* The latest version of this code can be obtained at:
@ -20,6 +20,7 @@
*/
#pragma once
#ifndef M68KCONF__HEADER
#define M68KCONF__HEADER
@ -37,6 +38,26 @@
#define OPT_SPECIFY_HANDLER 2
/* ======================================================================== */
/* ============================== MAME STUFF ============================== */
/* ======================================================================== */
/* If you're compiling this for MAME, only change M68K_COMPILE_FOR_MAME
* to OPT_ON and use m68kmame.h to configure the 68k core.
*/
#ifndef M68K_COMPILE_FOR_MAME
#define M68K_COMPILE_FOR_MAME OPT_ON
#endif /* M68K_COMPILE_FOR_MAME */
#if M68K_COMPILE_FOR_MAME == OPT_OFF
#define FALSE 0
#define TRUE 1
#include "driver.h"
/* ======================================================================== */
/* ============================= CONFIGURATION ============================ */
/* ======================================================================== */
@ -46,6 +67,7 @@
#define M68K_EMULATE_010 OPT_ON
#define M68K_EMULATE_EC020 OPT_ON
#define M68K_EMULATE_020 OPT_OFF
#define M68K_EMULATE_040 OPT_OFF
/* If ON, the CPU will call m68k_read_immediate_xx() for immediate addressing
@ -93,15 +115,19 @@
* instruction.
*/
#define M68K_CMPILD_HAS_CALLBACK OPT_SPECIFY_HANDLER
//#define M68K_CMPILD_CALLBACK(v,r) your_cmpild_handler_function(v,r)
#define M68K_CMPILD_CALLBACK(v, r) M68KcmpildCallback(v, r)
/* If ON, CPU will call the callback when it encounters a rte
* instruction.
*/
#define M68K_RTE_HAS_CALLBACK OPT_SPECIFY_HANDLER
//#define M68K_RTE_CALLBACK() your_rte_handler_function()
#define M68K_RTE_CALLBACK() M68KRTECallback()
#define M68K_RTE_CALLBACK() M68KRTECallback()
/* If ON, CPU will call the callback when it encounters a tas
* instruction.
*/
#define M68K_TAS_HAS_CALLBACK OPT_ON
#define M68K_TAS_CALLBACK() your_tas_handler_function()
/* If ON, CPU will call the set fc callback on every memory access to
@ -260,6 +286,8 @@ void __fastcall M68KWriteLong(unsigned int a, unsigned int d);
#define m68k_write_memory_32(address, value) M68KWriteLong(address, value)
#endif /* FBA_DEBUG */
#endif /* M68K_COMPILE_FOR_MAME */
/* ======================================================================== */
/* ============================== END OF FILE ============================= */

View File

@ -3,17 +3,17 @@
/* ======================================================================== */
#if 1
static const char* copyright_notice =
static const char copyright_notice[] =
"MUSASHI\n"
"Version 3.3 (2001-01-29)\n"
"Version 3.32 (2007-12-15)\n"
"A portable Motorola M680x0 processor emulation engine.\n"
"Copyright 1998-2001 Karl Stenerud. All rights reserved.\n"
"Copyright Karl Stenerud. All rights reserved.\n"
"\n"
"This code may be freely used for non-commercial purpooses as long as this\n"
"copyright notice remains unaltered in the source code and any binary files\n"
"containing this code in compiled form.\n"
"\n"
"All other lisencing terms must be negotiated with the author\n"
"All other licensing terms must be negotiated with the author\n"
"(Karl Stenerud).\n"
"\n"
"The latest version of this code can be obtained at:\n"
@ -32,8 +32,12 @@ static const char* copyright_notice =
/* ================================ INCLUDES ============================== */
/* ======================================================================== */
extern void m68040_fpu_op0(void);
extern void m68040_fpu_op1(void);
#include "m68kops.h"
#include "m68kcpu.h"
#include "m68kfpu.c"
/* ======================================================================== */
/* ================================= DATA ================================= */
@ -45,7 +49,7 @@ uint m68ki_tracing = 0;
uint m68ki_address_space;
#ifdef M68K_LOG_ENABLE
const char* m68ki_cpu_names[] =
const char *const m68ki_cpu_names[] =
{
"Invalid CPU",
"M68000",
@ -79,7 +83,7 @@ uint m68ki_aerr_write_mode;
uint m68ki_aerr_fc;
/* Used by shift & rotate instructions */
uint8 m68ki_shift_8_table[65] =
const uint8 m68ki_shift_8_table[65] =
{
0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
@ -88,7 +92,7 @@ uint8 m68ki_shift_8_table[65] =
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff
};
uint16 m68ki_shift_16_table[65] =
const uint16 m68ki_shift_16_table[65] =
{
0x0000, 0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff, 0xffff,
@ -99,7 +103,7 @@ uint16 m68ki_shift_16_table[65] =
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff
};
uint m68ki_shift_32_table[65] =
const uint m68ki_shift_32_table[65] =
{
0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000,
0xfc000000, 0xfe000000, 0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
@ -118,7 +122,7 @@ uint m68ki_shift_32_table[65] =
/* Number of clock cycles to use for exception processing.
* I used 4 for any vectors that are undocumented for processing times.
*/
uint8 m68ki_exception_cycle_table[3][256] =
const uint8 m68ki_exception_cycle_table[4][256] =
{
{ /* 000 */
4, /* 0: Reset - Initial Stack Pointer */
@ -338,10 +342,83 @@ uint8 m68ki_exception_cycle_table[3][256] =
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
},
{ /* 040 */ // TODO: these values are not correct
4, /* 0: Reset - Initial Stack Pointer */
4, /* 1: Reset - Initial Program Counter */
50, /* 2: Bus Error (unemulated) */
50, /* 3: Address Error (unemulated) */
20, /* 4: Illegal Instruction */
38, /* 5: Divide by Zero */
40, /* 6: CHK */
20, /* 7: TRAPV */
34, /* 8: Privilege Violation */
25, /* 9: Trace */
20, /* 10: 1010 */
20, /* 11: 1111 */
4, /* 12: RESERVED */
4, /* 13: Coprocessor Protocol Violation (unemulated) */
4, /* 14: Format Error */
30, /* 15: Uninitialized Interrupt */
4, /* 16: RESERVED */
4, /* 17: RESERVED */
4, /* 18: RESERVED */
4, /* 19: RESERVED */
4, /* 20: RESERVED */
4, /* 21: RESERVED */
4, /* 22: RESERVED */
4, /* 23: RESERVED */
30, /* 24: Spurious Interrupt */
30, /* 25: Level 1 Interrupt Autovector */
30, /* 26: Level 2 Interrupt Autovector */
30, /* 27: Level 3 Interrupt Autovector */
30, /* 28: Level 4 Interrupt Autovector */
30, /* 29: Level 5 Interrupt Autovector */
30, /* 30: Level 6 Interrupt Autovector */
30, /* 31: Level 7 Interrupt Autovector */
20, /* 32: TRAP #0 */
20, /* 33: TRAP #1 */
20, /* 34: TRAP #2 */
20, /* 35: TRAP #3 */
20, /* 36: TRAP #4 */
20, /* 37: TRAP #5 */
20, /* 38: TRAP #6 */
20, /* 39: TRAP #7 */
20, /* 40: TRAP #8 */
20, /* 41: TRAP #9 */
20, /* 42: TRAP #10 */
20, /* 43: TRAP #11 */
20, /* 44: TRAP #12 */
20, /* 45: TRAP #13 */
20, /* 46: TRAP #14 */
20, /* 47: TRAP #15 */
4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
4, /* 49: FP Inexact Result (unemulated) */
4, /* 50: FP Divide by Zero (unemulated) */
4, /* 51: FP Underflow (unemulated) */
4, /* 52: FP Operand Error (unemulated) */
4, /* 53: FP Overflow (unemulated) */
4, /* 54: FP Signaling NAN (unemulated) */
4, /* 55: FP Unimplemented Data Type (unemulated) */
4, /* 56: MMU Configuration Error (unemulated) */
4, /* 57: MMU Illegal Operation Error (unemulated) */
4, /* 58: MMU Access Level Violation Error (unemulated) */
4, /* 59: RESERVED */
4, /* 60: RESERVED */
4, /* 61: RESERVED */
4, /* 62: RESERVED */
4, /* 63: RESERVED */
/* 64-255: User Defined */
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
}
};
uint8 m68ki_ea_idx_cycle_table[64] =
const uint8 m68ki_ea_idx_cycle_table[64] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, /* ..01.000 no memory indirect, base NULL */
@ -402,6 +479,12 @@ static void default_rte_instr_callback(void)
{
}
/* Called when a tas instruction is executed */
static int default_tas_instr_callback(void)
{
return 1; // allow writeback
}
/* Called when the program counter changed by a large value */
static unsigned int default_pc_changed_callback_data;
static void default_pc_changed_callback(unsigned int new_pc)
@ -417,7 +500,7 @@ static void default_set_fc_callback(unsigned int new_fc)
}
/* Called every instruction cycle prior to execution */
static void default_instr_hook_callback(void)
static void default_instr_hook_callback(unsigned int pc)
{
}
@ -487,11 +570,11 @@ unsigned int m68k_get_reg(void* context, m68k_register_t regnum)
case CPU_TYPE_010: return (unsigned int)M68K_CPU_TYPE_68010;
case CPU_TYPE_EC020: return (unsigned int)M68K_CPU_TYPE_68EC020;
case CPU_TYPE_020: return (unsigned int)M68K_CPU_TYPE_68020;
case CPU_TYPE_040: return (unsigned int)M68K_CPU_TYPE_68040;
}
return M68K_CPU_TYPE_INVALID;
default: return 0;
}
return 0;
}
void m68k_set_reg(m68k_register_t regnum, unsigned int value)
@ -571,6 +654,11 @@ void m68k_set_rte_instr_callback(void (*callback)(void))
CALLBACK_RTE_INSTR = callback ? callback : default_rte_instr_callback;
}
void m68k_set_tas_instr_callback(int (*callback)(void))
{
CALLBACK_TAS_INSTR = callback ? callback : default_tas_instr_callback;
}
void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc))
{
CALLBACK_PC_CHANGED = callback ? callback : default_pc_changed_callback;
@ -581,7 +669,7 @@ void m68k_set_fc_callback(void (*callback)(unsigned int new_fc))
CALLBACK_SET_FC = callback ? callback : default_set_fc_callback;
}
void m68k_set_instr_hook_callback(void (*callback)(void))
void m68k_set_instr_hook_callback(void (*callback)(unsigned int pc))
{
CALLBACK_INSTR_HOOK = callback ? callback : default_instr_hook_callback;
}
@ -607,7 +695,7 @@ void m68k_set_cpu_type(unsigned int cpu_type)
CYC_MOVEM_L = 3;
CYC_SHIFT = 1;
CYC_RESET = 132;
break;
return;
case M68K_CPU_TYPE_68008:
CPU_TYPE = CPU_TYPE_008;
CPU_ADDRESS_MASK = 0x003fffff;
@ -623,7 +711,7 @@ void m68k_set_cpu_type(unsigned int cpu_type)
CYC_MOVEM_L = 3;
CYC_SHIFT = 1;
CYC_RESET = 132;
break;
return;
case M68K_CPU_TYPE_68010:
CPU_TYPE = CPU_TYPE_010;
CPU_ADDRESS_MASK = 0x00ffffff;
@ -639,7 +727,7 @@ void m68k_set_cpu_type(unsigned int cpu_type)
CYC_MOVEM_L = 3;
CYC_SHIFT = 1;
CYC_RESET = 130;
break;
return;
case M68K_CPU_TYPE_68EC020:
CPU_TYPE = CPU_TYPE_EC020;
CPU_ADDRESS_MASK = 0x00ffffff;
@ -655,7 +743,7 @@ void m68k_set_cpu_type(unsigned int cpu_type)
CYC_MOVEM_L = 2;
CYC_SHIFT = 0;
CYC_RESET = 518;
break;
return;
case M68K_CPU_TYPE_68020:
CPU_TYPE = CPU_TYPE_020;
CPU_ADDRESS_MASK = 0xffffffff;
@ -671,27 +759,40 @@ void m68k_set_cpu_type(unsigned int cpu_type)
CYC_MOVEM_L = 2;
CYC_SHIFT = 0;
CYC_RESET = 518;
break;
return;
case M68K_CPU_TYPE_68040: // TODO: these values are not correct
CPU_TYPE = CPU_TYPE_040;
CPU_ADDRESS_MASK = 0xffffffff;
CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
CYC_INSTRUCTION = m68ki_cycles[2];
CYC_EXCEPTION = m68ki_exception_cycle_table[2];
CYC_BCC_NOTAKE_B = -2;
CYC_BCC_NOTAKE_W = 0;
CYC_DBCC_F_NOEXP = 0;
CYC_DBCC_F_EXP = 4;
CYC_SCC_R_TRUE = 0;
CYC_MOVEM_W = 2;
CYC_MOVEM_L = 2;
CYC_SHIFT = 0;
CYC_RESET = 518;
return;
}
m68ki_build_opcode_table(CPU_TYPE_IS_000(CPU_TYPE));
}
/* Execute some instructions until we use up num_cycles clock cycles */
/* ASG: removed per-instruction interrupt checks */
int m68k_execute(int num_cycles)
{
/* Set our pool of clock cycles available */
SET_CYCLES(num_cycles);
m68ki_initial_cycles = num_cycles;
/* See if interrupts came in */
m68ki_check_interrupts();
/* Make sure we're not stopped */
if(!CPU_STOPPED)
{
/* 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) */
@ -705,7 +806,7 @@ int m68k_execute(int num_cycles)
m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */
/* Call external hook to peek at CPU */
m68ki_instr_hook(); /* auto-disable (see m68kcpu.h) */
m68ki_instr_hook(REG_PC); /* auto-disable (see m68kcpu.h) */
/* Record previous program counter */
REG_PPC = REG_PC;
@ -721,20 +822,12 @@ int m68k_execute(int num_cycles)
/* 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
SET_CYCLES(0);
/* We get here if the CPU is stopped or halted */
SET_CYCLES(0);
CPU_INT_CYCLES = 0;
return num_cycles;
/* return how many clocks we used */
return m68ki_initial_cycles - GET_CYCLES();
}
@ -758,7 +851,7 @@ void m68k_modify_timeslice(int cycles)
void m68k_end_timeslice(void)
{
m68ki_initial_cycles -= GET_CYCLES();
m68ki_initial_cycles = GET_CYCLES();
SET_CYCLES(0);
}
@ -775,9 +868,29 @@ void m68k_set_irq(unsigned int int_level)
/* A transition from < 7 to 7 always interrupts (NMI) */
/* Note: Level 7 can also level trigger like a normal IRQ */
if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700)
m68ki_exception_interrupt(7); /* Edge triggered level 7 (NMI) */
m68ki_cpu.nmi_pending = TRUE;
}
void m68k_set_virq(unsigned int level, unsigned int active)
{
uint state = m68ki_cpu.virq_state;
uint blevel;
if(active)
state |= 1 << level;
else
m68ki_check_interrupts(); /* Level triggered (IRQ) */
state &= ~(1 << level);
m68ki_cpu.virq_state = state;
for(blevel = 7; blevel > 0; blevel--)
if(state & (1 << blevel))
break;
m68k_set_irq(blevel);
}
unsigned int m68k_get_virq(unsigned int level)
{
return (m68ki_cpu.virq_state & (1 << level)) ? 1 : 0;
}
void m68k_init(void)
@ -787,7 +900,7 @@ void m68k_init(void)
/* The first call to this function initializes the opcode handler jump table */
if(!emulation_initialized)
{
m68ki_build_opcode_table(CPU_TYPE_IS_000(CPU_TYPE));
m68ki_build_opcode_table();
emulation_initialized = 1;
}
@ -796,6 +909,7 @@ void m68k_init(void)
m68k_set_reset_instr_callback(NULL);
m68k_set_cmpild_instr_callback(NULL);
m68k_set_rte_instr_callback(NULL);
m68k_set_tas_instr_callback(NULL);
m68k_set_pc_changed_callback(NULL);
m68k_set_fc_callback(NULL);
m68k_set_instr_hook_callback(NULL);
@ -815,6 +929,8 @@ void m68k_pulse_reset(void)
m68ki_clear_trace();
/* Interrupt mask to level 7 */
FLAG_INT_MASK = 0x0700;
CPU_INT_LEVEL = 0;
m68ki_cpu.virq_state = 0;
/* Reset VBR */
REG_VBR = 0;
/* Go to supervisor mode */
@ -868,22 +984,22 @@ void m68k_set_context(void* src)
#if M68K_COMPILE_FOR_MAME == OPT_ON
#include "state.h"
#include "deprecat.h"
static struct {
UINT16 sr;
int stopped;
int halted;
UINT8 stopped;
UINT8 halted;
} m68k_substate;
static void m68k_prepare_substate(void)
static void m68k_prepare_substate(running_machine *machine, void *param)
{
m68k_substate.sr = m68ki_get_sr();
m68k_substate.stopped = (CPU_STOPPED & STOP_LEVEL_STOP) != 0;
m68k_substate.halted = (CPU_STOPPED & STOP_LEVEL_HALT) != 0;
}
static void m68k_post_load(void)
static void m68k_post_load(running_machine *machine, void *param)
{
m68ki_set_sr_noint_nosp(m68k_substate.sr);
CPU_STOPPED = m68k_substate.stopped ? STOP_LEVEL_STOP : 0
@ -891,31 +1007,28 @@ static void m68k_post_load(void)
m68ki_jump(REG_PC);
}
void m68k_state_register(const char *type)
void m68k_state_register(const char *type, int index)
{
int cpu = cpu_getactivecpu();
state_save_register_UINT32(type, cpu, "D" , REG_D, 8);
state_save_register_UINT32(type, cpu, "A" , REG_A, 8);
state_save_register_UINT32(type, cpu, "PPC" , &REG_PPC, 1);
state_save_register_UINT32(type, cpu, "PC" , &REG_PC, 1);
state_save_register_UINT32(type, cpu, "USP" , &REG_USP, 1);
state_save_register_UINT32(type, cpu, "ISP" , &REG_ISP, 1);
state_save_register_UINT32(type, cpu, "MSP" , &REG_MSP, 1);
state_save_register_UINT32(type, cpu, "VBR" , &REG_VBR, 1);
state_save_register_UINT32(type, cpu, "SFC" , &REG_SFC, 1);
state_save_register_UINT32(type, cpu, "DFC" , &REG_DFC, 1);
state_save_register_UINT32(type, cpu, "CACR" , &REG_CACR, 1);
state_save_register_UINT32(type, cpu, "CAAR" , &REG_CAAR, 1);
state_save_register_UINT16(type, cpu, "SR" , &m68k_substate.sr, 1);
state_save_register_UINT32(type, cpu, "INT_LEVEL" , &CPU_INT_LEVEL, 1);
state_save_register_UINT32(type, cpu, "INT_CYCLES", &CPU_INT_CYCLES, 1);
state_save_register_int (type, cpu, "STOPPED" , &m68k_substate.stopped);
state_save_register_int (type, cpu, "HALTED" , &m68k_substate.halted);
state_save_register_UINT32(type, cpu, "PREF_ADDR" , &CPU_PREF_ADDR, 1);
state_save_register_UINT32(type, cpu, "PREF_DATA" , &CPU_PREF_DATA, 1);
state_save_register_func_presave(m68k_prepare_substate);
state_save_register_func_postload(m68k_post_load);
/* Note, D covers A because the dar array is common, REG_A=REG_D+8 */
state_save_register_item_array(type, index, REG_D);
state_save_register_item(type, index, REG_PPC);
state_save_register_item(type, index, REG_PC);
state_save_register_item(type, index, REG_USP);
state_save_register_item(type, index, REG_ISP);
state_save_register_item(type, index, REG_MSP);
state_save_register_item(type, index, REG_VBR);
state_save_register_item(type, index, REG_SFC);
state_save_register_item(type, index, REG_DFC);
state_save_register_item(type, index, REG_CACR);
state_save_register_item(type, index, REG_CAAR);
state_save_register_item(type, index, m68k_substate.sr);
state_save_register_item(type, index, CPU_INT_LEVEL);
state_save_register_item(type, index, m68k_substate.stopped);
state_save_register_item(type, index, m68k_substate.halted);
state_save_register_item(type, index, CPU_PREF_ADDR);
state_save_register_item(type, index, CPU_PREF_DATA);
state_save_register_presave(Machine, m68k_prepare_substate, NULL);
state_save_register_postload(Machine, m68k_post_load, NULL);
}
#endif /* M68K_COMPILE_FOR_MAME */

View File

@ -4,16 +4,16 @@
/* ======================================================================== */
/*
* MUSASHI
* Version 3.3
* Version 3.32
*
* A portable Motorola M680x0 processor emulation engine.
* Copyright 1998-2001 Karl Stenerud. All rights reserved.
* Copyright Karl Stenerud. All rights reserved.
*
* This code may be freely used for non-commercial purposes as long as this
* copyright notice remains unaltered in the source code and any binary files
* containing this code in compiled form.
*
* All other lisencing terms must be negotiated with the author
* All other licensing terms must be negotiated with the author
* (Karl Stenerud).
*
* The latest version of this code can be obtained at:
@ -21,7 +21,7 @@
*/
#pragma once
#ifndef M68KCPU__HEADER
#define M68KCPU__HEADER
@ -58,10 +58,10 @@
#define sint8 signed char /* ASG: changed from char to signed char */
#define sint16 signed short
#define sint32 signed int
#define sint32 signed int /* AWJ: changed from long to int */
#define uint8 unsigned char
#define uint16 unsigned short
#define uint32 unsigned int
#define uint32 unsigned int /* AWJ: changed from long to int */
/* signed and unsigned int must be at least 32 bits wide */
#define sint signed int
@ -159,6 +159,7 @@
#define CPU_TYPE_010 4
#define CPU_TYPE_EC020 8
#define CPU_TYPE_020 16
#define CPU_TYPE_040 32
/* Different ways to stop the CPU */
#define STOP_LEVEL_STOP 1
@ -264,8 +265,8 @@
#define LSL_32(A, C) ((A) << (C))
#else
/* We have to do this because the morons at ANSI decided that shifts
* by >= data size are undefined.
*/
* by >= data size are undefined.
*/
#define LSR_32(A, C) ((C) < 32 ? (A) >> (C) : 0)
#define LSL_32(A, C) ((C) < 32 ? (A) << (C) : 0)
#endif /* M68K_INT_GT_32_BIT */
@ -315,6 +316,11 @@
#define REG_CAAR m68ki_cpu.caar
#define REG_IR m68ki_cpu.ir
#define REG_FP m68ki_cpu.fpr
#define REG_FPCR m68ki_cpu.fpcr
#define REG_FPSR m68ki_cpu.fpsr
#define REG_FPIAR m68ki_cpu.fpiar
#define FLAG_T1 m68ki_cpu.t1_flag
#define FLAG_T0 m68ki_cpu.t0_flag
#define FLAG_S m68ki_cpu.s_flag
@ -327,7 +333,6 @@
#define FLAG_INT_MASK m68ki_cpu.int_mask
#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
@ -354,6 +359,7 @@
#define CALLBACK_RESET_INSTR m68ki_cpu.reset_instr_callback
#define CALLBACK_CMPILD_INSTR m68ki_cpu.cmpild_instr_callback
#define CALLBACK_RTE_INSTR m68ki_cpu.rte_instr_callback
#define CALLBACK_TAS_INSTR m68ki_cpu.tas_instr_callback
#define CALLBACK_PC_CHANGED m68ki_cpu.pc_changed_callback
#define CALLBACK_SET_FC m68ki_cpu.set_fc_callback
#define CALLBACK_INSTR_HOOK m68ki_cpu.instr_hook_callback
@ -365,8 +371,16 @@
/* These defines are dependant on the configuration defines in m68kconf.h */
/* Disable certain comparisons if we're not using all CPU types */
#if M68K_EMULATE_040
#define CPU_TYPE_IS_040_PLUS(A) ((A) & CPU_TYPE_040)
#define CPU_TYPE_IS_040_LESS(A) 1
#else
#define CPU_TYPE_IS_040_PLUS(A) 0
#define CPU_TYPE_IS_040_LESS(A) 1
#endif
#if M68K_EMULATE_020
#define CPU_TYPE_IS_020_PLUS(A) ((A) & CPU_TYPE_020)
#define CPU_TYPE_IS_020_PLUS(A) ((A) & (CPU_TYPE_020 | CPU_TYPE_040))
#define CPU_TYPE_IS_020_LESS(A) 1
#else
#define CPU_TYPE_IS_020_PLUS(A) 0
@ -374,7 +388,7 @@
#endif
#if M68K_EMULATE_EC020
#define CPU_TYPE_IS_EC020_PLUS(A) ((A) & (CPU_TYPE_EC020 | CPU_TYPE_020))
#define CPU_TYPE_IS_EC020_PLUS(A) ((A) & (CPU_TYPE_EC020 | CPU_TYPE_020 | CPU_TYPE_040))
#define CPU_TYPE_IS_EC020_LESS(A) ((A) & (CPU_TYPE_000 | CPU_TYPE_008 | CPU_TYPE_010 | CPU_TYPE_EC020))
#else
#define CPU_TYPE_IS_EC020_PLUS(A) CPU_TYPE_IS_020_PLUS(A)
@ -383,7 +397,7 @@
#if M68K_EMULATE_010
#define CPU_TYPE_IS_010(A) ((A) == CPU_TYPE_010)
#define CPU_TYPE_IS_010_PLUS(A) ((A) & (CPU_TYPE_010 | CPU_TYPE_EC020 | CPU_TYPE_020))
#define CPU_TYPE_IS_010_PLUS(A) ((A) & (CPU_TYPE_010 | CPU_TYPE_EC020 | CPU_TYPE_020 | CPU_TYPE_040))
#define CPU_TYPE_IS_010_LESS(A) ((A) & (CPU_TYPE_000 | CPU_TYPE_008 | CPU_TYPE_010))
#else
#define CPU_TYPE_IS_010(A) 0
@ -397,7 +411,7 @@
#define CPU_TYPE_IS_020_VARIANT(A) 0
#endif
#if M68K_EMULATE_020 || M68K_EMULATE_EC020 || M68K_EMULATE_010
#if M68K_EMULATE_040 || M68K_EMULATE_020 || M68K_EMULATE_EC020 || M68K_EMULATE_010
#define CPU_TYPE_IS_000(A) ((A) == CPU_TYPE_000 || (A) == CPU_TYPE_008)
#else
#define CPU_TYPE_IS_000(A) 1
@ -466,14 +480,25 @@
#define m68ki_rte_callback()
#endif /* M68K_RTE_HAS_CALLBACK */
#if M68K_INSTRUCTION_HOOK
#if M68K_INSTRUCTION_HOOK == OPT_SPECIFY_HANDLER
#define m68ki_instr_hook() M68K_INSTRUCTION_CALLBACK()
#if M68K_TAS_HAS_CALLBACK
#if M68K_TAS_HAS_CALLBACK == OPT_SPECIFY_HANDLER
#define m68ki_tas_callback() M68K_TAS_CALLBACK()
#else
#define m68ki_instr_hook() CALLBACK_INSTR_HOOK()
#define m68ki_tas_callback() CALLBACK_TAS_INSTR()
#endif
#else
#define m68ki_instr_hook()
#define m68ki_tas_callback()
#endif /* M68K_TAS_HAS_CALLBACK */
#if M68K_INSTRUCTION_HOOK
#if M68K_INSTRUCTION_HOOK == OPT_SPECIFY_HANDLER
#define m68ki_instr_hook(pc) M68K_INSTRUCTION_CALLBACK(pc)
#else
#define m68ki_instr_hook(pc) CALLBACK_INSTR_HOOK(pc)
#endif
#else
#define m68ki_instr_hook(pc)
#endif /* M68K_INSTRUCTION_HOOK */
#if M68K_MONITOR_PC
@ -536,7 +561,6 @@
if(CPU_STOPPED) \
{ \
SET_CYCLES(0); \
CPU_INT_CYCLES = 0; \
return m68ki_initial_cycles; \
} \
}
@ -549,16 +573,23 @@
m68ki_aerr_fc = FC; \
longjmp(m68ki_aerr_trap, 1); \
}
#define m68ki_check_address_error_010_less(ADDR, WRITE_MODE, FC) \
if (CPU_TYPE_IS_010_LESS(CPU_TYPE)) \
{ \
m68ki_check_address_error(ADDR, WRITE_MODE, FC) \
}
#else
#define m68ki_set_address_error_trap()
#define m68ki_check_address_error(ADDR, WRITE_MODE, FC)
#define m68ki_check_address_error_010_less(ADDR, WRITE_MODE, FC)
#endif /* M68K_ADDRESS_ERROR */
/* Logging */
#if M68K_LOG_ENABLE
#include <stdio.h>
extern FILE* M68K_LOG_FILEHANDLE
extern char* m68ki_cpu_names[];
extern const char *const m68ki_cpu_names[];
#define M68K_DO_LOG(A) if(M68K_LOG_FILEHANDLE) fprintf A
#if M68K_LOG_1010_1111
@ -807,7 +838,16 @@
/* =============================== PROTOTYPES ============================= */
/* ======================================================================== */
typedef struct
typedef union _fp_reg fp_reg;
union _fp_reg
{
uint64 i;
double f;
};
typedef struct _m68ki_cpu_core m68ki_cpu_core;
struct _m68ki_cpu_core
{
uint cpu_type; /* CPU Type: 68000, 68008, 68010, 68EC020, or 68020 */
uint dar[16]; /* Data and Address Registers */
@ -820,6 +860,10 @@ typedef struct
uint cacr; /* Cache Control Register (m68020, unemulated) */
uint caar; /* Cache Address Register (m68020, unemulated) */
uint ir; /* Instruction Register */
fp_reg fpr[8]; /* FPU Data Register (m68040) */
uint fpiar; /* FPU Instruction Address Register (m68040) */
uint fpsr; /* FPU Status Register (m68040) */
uint fpcr; /* FPU Control Register (m68040) */
uint t1_flag; /* Trace 1 */
uint t0_flag; /* Trace 0 */
uint s_flag; /* Supervisor */
@ -831,7 +875,6 @@ typedef struct
uint c_flag; /* Carry */
uint int_mask; /* I0-I2 */
uint int_level; /* State of interrupt pins IPL0-IPL2 -- ASG: changed from ints_pending */
uint int_cycles; /* ASG: extra cycles from generated interrupts */
uint stopped; /* Stopped state */
uint pref_addr; /* Last prefetch address */
uint pref_data; /* Data in the prefetch queue */
@ -850,8 +893,13 @@ typedef struct
uint cyc_movem_l;
uint cyc_shift;
uint cyc_reset;
uint8* cyc_instruction;
uint8* cyc_exception;
/* Virtual IRQ lines state */
uint virq_state;
uint nmi_pending;
const uint8* cyc_instruction;
const uint8* cyc_exception;
/* Callbacks to host */
int (*int_ack_callback)(int int_line); /* Interrupt Acknowledge */
@ -859,22 +907,23 @@ typedef struct
void (*reset_instr_callback)(void); /* Called when a RESET instruction is encountered */
void (*cmpild_instr_callback)(unsigned int, int); /* Called when a CMPI.L #v, Dn instruction is encountered */
void (*rte_instr_callback)(void); /* Called when a RTE instruction is encountered */
int (*tas_instr_callback)(void); /* Called when a TAS instruction is encountered, allows / disallows writeback */
void (*pc_changed_callback)(unsigned int new_pc); /* Called when the PC changes by a large amount */
void (*set_fc_callback)(unsigned int new_fc); /* Called when the CPU function code changes */
void (*instr_hook_callback)(void); /* Called every instruction cycle prior to execution */
void (*instr_hook_callback)(unsigned int pc); /* Called every instruction cycle prior to execution */
} m68ki_cpu_core;
};
extern m68ki_cpu_core m68ki_cpu;
extern sint m68ki_remaining_cycles;
extern uint m68ki_tracing;
extern uint8 m68ki_shift_8_table[];
extern uint16 m68ki_shift_16_table[];
extern uint m68ki_shift_32_table[];
extern uint8 m68ki_exception_cycle_table[][256];
extern const uint8 m68ki_shift_8_table[];
extern const uint16 m68ki_shift_16_table[];
extern const uint m68ki_shift_32_table[];
extern const uint8 m68ki_exception_cycle_table[][256];
extern uint m68ki_address_space;
extern uint8 m68ki_ea_idx_cycle_table[];
extern const uint8 m68ki_ea_idx_cycle_table[];
extern uint m68ki_aerr_address;
extern uint m68ki_aerr_write_mode;
@ -1015,13 +1064,19 @@ INLINE uint m68ki_read_imm_16(void)
m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */
m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */
#if M68K_EMULATE_PREFETCH
if(MASK_OUT_BELOW_2(REG_PC) != CPU_PREF_ADDR)
{
uint result;
if(REG_PC != CPU_PREF_ADDR)
{
CPU_PREF_ADDR = MASK_OUT_BELOW_2(REG_PC);
CPU_PREF_DATA = m68k_read_immediate_32(ADDRESS_68K(CPU_PREF_ADDR));
CPU_PREF_ADDR = REG_PC;
CPU_PREF_DATA = m68k_read_immediate_16(ADDRESS_68K(CPU_PREF_ADDR));
}
result = MASK_OUT_ABOVE_16(CPU_PREF_DATA);
REG_PC += 2;
return MASK_OUT_ABOVE_16(CPU_PREF_DATA >> ((2-((REG_PC-2)&2))<<3));
CPU_PREF_ADDR = REG_PC;
CPU_PREF_DATA = m68k_read_immediate_16(ADDRESS_68K(CPU_PREF_ADDR));
return result;
}
#else
REG_PC += 2;
return m68k_read_immediate_16(ADDRESS_68K(REG_PC-2));
@ -1034,20 +1089,21 @@ INLINE uint m68ki_read_imm_32(void)
m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */
m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */
if(MASK_OUT_BELOW_2(REG_PC) != CPU_PREF_ADDR)
if(REG_PC != CPU_PREF_ADDR)
{
CPU_PREF_ADDR = MASK_OUT_BELOW_2(REG_PC);
CPU_PREF_DATA = m68k_read_immediate_32(ADDRESS_68K(CPU_PREF_ADDR));
CPU_PREF_ADDR = REG_PC;
CPU_PREF_DATA = m68k_read_immediate_16(ADDRESS_68K(CPU_PREF_ADDR));
}
temp_val = CPU_PREF_DATA;
temp_val = MASK_OUT_ABOVE_16(CPU_PREF_DATA);
REG_PC += 2;
if(MASK_OUT_BELOW_2(REG_PC) != CPU_PREF_ADDR)
{
CPU_PREF_ADDR = MASK_OUT_BELOW_2(REG_PC);
CPU_PREF_DATA = m68k_read_immediate_32(ADDRESS_68K(CPU_PREF_ADDR));
temp_val = MASK_OUT_ABOVE_32((temp_val << 16) | (CPU_PREF_DATA >> 16));
}
CPU_PREF_ADDR = REG_PC;
CPU_PREF_DATA = m68k_read_immediate_16(ADDRESS_68K(CPU_PREF_ADDR));
temp_val = MASK_OUT_ABOVE_32((temp_val << 16) | MASK_OUT_ABOVE_16(CPU_PREF_DATA));
REG_PC += 2;
CPU_PREF_ADDR = REG_PC;
CPU_PREF_DATA = m68k_read_immediate_16(ADDRESS_68K(CPU_PREF_ADDR));
return temp_val;
#else
@ -1076,13 +1132,13 @@ INLINE uint m68ki_read_8_fc(uint address, uint fc)
INLINE uint m68ki_read_16_fc(uint address, uint fc)
{
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
m68ki_check_address_error(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */
m68ki_check_address_error_010_less(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */
return m68k_read_memory_16(ADDRESS_68K(address));
}
INLINE uint m68ki_read_32_fc(uint address, uint fc)
{
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
m68ki_check_address_error(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */
m68ki_check_address_error_010_less(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */
return m68k_read_memory_32(ADDRESS_68K(address));
}
@ -1094,13 +1150,13 @@ INLINE void m68ki_write_8_fc(uint address, uint fc, uint value)
INLINE void m68ki_write_16_fc(uint address, uint fc, uint value)
{
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
m68ki_check_address_error(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */
m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */
m68k_write_memory_16(ADDRESS_68K(address), value);
}
INLINE void m68ki_write_32_fc(uint address, uint fc, uint value)
{
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
m68ki_check_address_error(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */
m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */
m68k_write_memory_32(ADDRESS_68K(address), value);
}
@ -1108,7 +1164,7 @@ INLINE void m68ki_write_32_fc(uint address, uint fc, uint value)
INLINE void m68ki_write_32_pd_fc(uint address, uint fc, uint value)
{
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
m68ki_check_address_error(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */
m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */
m68k_write_memory_32_pd(ADDRESS_68K(address), value);
}
#endif
@ -1550,10 +1606,10 @@ INLINE void m68ki_stack_frame_buserr(uint sr)
m68ki_push_16(REG_IR);
m68ki_push_32(m68ki_aerr_address); /* access address */
/* 0 0 0 0 0 0 0 0 0 0 0 R/W I/N FC
* R/W 0 = write, 1 = read
* I/N 0 = instruction, 1 = not
* FC 3-bit function code
*/
* R/W 0 = write, 1 = read
* I/N 0 = instruction, 1 = not
* FC 3-bit function code
*/
m68ki_push_16(m68ki_aerr_write_mode | CPU_INSTR_MODE | m68ki_aerr_fc);
}
@ -1563,9 +1619,9 @@ INLINE void m68ki_stack_frame_buserr(uint sr)
void m68ki_stack_frame_1000(uint pc, uint sr, uint vector)
{
/* VERSION
* NUMBER
* INTERNAL INFORMATION, 16 WORDS
*/
* NUMBER
* INTERNAL INFORMATION, 16 WORDS
*/
m68ki_fake_push_32();
m68ki_fake_push_32();
m68ki_fake_push_32();
@ -1883,12 +1939,12 @@ INLINE void m68ki_exception_address_error(void)
uint sr = m68ki_init_exception();
/* If we were processing a bus error, address error, or reset,
* this is a catastrophic failure.
* Halt the CPU
*/
* this is a catastrophic failure.
* Halt the CPU
*/
if(CPU_RUN_MODE == RUN_MODE_BERR_AERR_RESET)
{
m68k_read_memory_8(0x00ffff01);
m68k_read_memory_8(0x00ffff01);
CPU_STOPPED = STOP_LEVEL_HALT;
return;
}
@ -1968,7 +2024,7 @@ void m68ki_exception_interrupt(uint int_level)
m68ki_jump(new_pc);
/* Defer cycle counting until later */
CPU_INT_CYCLES += CYC_EXCEPTION[vector];
USE_CYCLES(CYC_EXCEPTION[vector]);
#if !M68K_EMULATE_INT_ACK
/* Automatically clear IRQ if we are not using an acknowledge scheme */
@ -1980,7 +2036,12 @@ void m68ki_exception_interrupt(uint int_level)
/* ASG: Check for interrupts */
INLINE void m68ki_check_interrupts(void)
{
if(CPU_INT_LEVEL > FLAG_INT_MASK)
if(m68ki_cpu.nmi_pending)
{
m68ki_cpu.nmi_pending = FALSE;
m68ki_exception_interrupt(7);
}
else if(CPU_INT_LEVEL > FLAG_INT_MASK)
m68ki_exception_interrupt(CPU_INT_LEVEL>>8);
}

828
src/cpu/m68k/m68kfpu.c Normal file
View File

@ -0,0 +1,828 @@
#define fatalerror printf
#define FPCC_N 0x08000000
#define FPCC_Z 0x04000000
#define FPCC_I 0x02000000
#define FPCC_NAN 0x01000000
#define DOUBLE_INFINITY U64(0x7ff0000000000000)
#define DOUBLE_EXPONENT U64(0x7ff0000000000000)
#define DOUBLE_MANTISSA U64(0x000fffffffffffff)
INLINE void SET_CONDITION_CODES(fp_reg reg)
{
REG_FPSR &= ~(FPCC_N|FPCC_Z|FPCC_I|FPCC_NAN);
// sign flag
if (reg.i & U64(0x8000000000000000))
{
REG_FPSR |= FPCC_N;
}
// zero flag
if ((reg.i & U64(0x7fffffffffffffff)) == 0)
{
REG_FPSR |= FPCC_Z;
}
// infinity flag
if ((reg.i & U64(0x7fffffffffffffff)) == DOUBLE_INFINITY)
{
REG_FPSR |= FPCC_I;
}
// NaN flag
if (((reg.i & DOUBLE_EXPONENT) == DOUBLE_EXPONENT) && ((reg.i & DOUBLE_MANTISSA) != 0))
{
REG_FPSR |= FPCC_NAN;
}
}
INLINE int TEST_CONDITION(int condition)
{
int n = (REG_FPSR & FPCC_N) != 0;
int z = (REG_FPSR & FPCC_Z) != 0;
int nan = (REG_FPSR & FPCC_NAN) != 0;
int r = 0;
switch (condition)
{
case 0x00: return 0; // False
case 0x01: return (z); // Equal
case 0x0e: return (!z); // Not Equal
case 0x0f: return 1; // True
case 0x12: return (!(nan || z || n)); // Greater Than
case 0x13: return (z || !(nan || n)); // Greater or Equal
case 0x14: return (n && !(nan || z)); // Less Than
case 0x15: return (z || (n && !nan)); // Less Than or Equal
case 0x1a: return (nan || !(n || z)); // Not Less Than or Equal
case 0x1b: return (nan || z || !n); // Not Less Than
case 0x1c: return (nan || (n && !z)); // Not Greater or Equal Than
case 0x1d: return (nan || z || n); // Not Greater Than
default: fatalerror("M68040: test_condition: unhandled condition %02X\n", condition);
}
return r;
}
static UINT8 READ_EA_8(int ea)
{
int mode = (ea >> 3) & 0x7;
int reg = (ea & 0x7);
switch (mode)
{
case 0: // Dn
{
return REG_D[reg];
}
case 5: // (d16, An)
{
UINT32 ea = EA_AY_DI_8();
return m68ki_read_8(ea);
}
case 6: // (An) + (Xn) + d8
{
UINT32 ea = EA_AY_IX_8();
return m68ki_read_8(ea);
}
case 7:
{
switch (reg)
{
case 1: // (xxx).L
{
UINT32 d1 = OPER_I_16();
UINT32 d2 = OPER_I_16();
UINT32 ea = (d1 << 16) | d2;
return m68ki_read_8(ea);
}
case 4: // #<data>
{
return OPER_I_8();
}
default: fatalerror("MC68040: READ_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
}
break;
}
default: fatalerror("MC68040: READ_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
}
return 0;
}
static UINT16 READ_EA_16(int ea)
{
int mode = (ea >> 3) & 0x7;
int reg = (ea & 0x7);
switch (mode)
{
case 0: // Dn
{
return (UINT16)(REG_D[reg]);
}
case 2: // (An)
{
UINT32 ea = REG_A[reg];
return m68ki_read_16(ea);
}
case 5: // (d16, An)
{
UINT32 ea = EA_AY_DI_16();
return m68ki_read_16(ea);
}
case 6: // (An) + (Xn) + d8
{
UINT32 ea = EA_AY_IX_16();
return m68ki_read_16(ea);
}
case 7:
{
switch (reg)
{
case 1: // (xxx).L
{
UINT32 d1 = OPER_I_16();
UINT32 d2 = OPER_I_16();
UINT32 ea = (d1 << 16) | d2;
return m68ki_read_16(ea);
}
case 4: // #<data>
{
return OPER_I_16();
}
default: fatalerror("MC68040: READ_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
}
break;
}
default: fatalerror("MC68040: READ_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
}
return 0;
}
static UINT32 READ_EA_32(int ea)
{
int mode = (ea >> 3) & 0x7;
int reg = (ea & 0x7);
switch (mode)
{
case 0: // Dn
{
return REG_D[reg];
}
case 2: // (An)
{
UINT32 ea = REG_A[reg];
return m68ki_read_32(ea);
}
case 3: // (An)+
{
UINT32 ea = EA_AY_PI_32();
return m68ki_read_32(ea);
}
case 5: // (d16, An)
{
UINT32 ea = EA_AY_DI_32();
return m68ki_read_32(ea);
}
case 6: // (An) + (Xn) + d8
{
UINT32 ea = EA_AY_IX_32();
return m68ki_read_32(ea);
}
case 7:
{
switch (reg)
{
case 1: // (xxx).L
{
UINT32 d1 = OPER_I_16();
UINT32 d2 = OPER_I_16();
UINT32 ea = (d1 << 16) | d2;
return m68ki_read_32(ea);
}
case 2: // (d16, PC)
{
UINT32 ea = EA_PCDI_32();
return m68ki_read_32(ea);
}
case 4: // #<data>
{
return OPER_I_32();
}
default: fatalerror("MC68040: READ_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
}
break;
}
default: fatalerror("MC68040: READ_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
}
return 0;
}
static void WRITE_EA_32(int ea, UINT32 data)
{
int mode = (ea >> 3) & 0x7;
int reg = (ea & 0x7);
switch (mode)
{
case 0: // Dn
{
REG_D[reg] = data;
break;
}
case 2: // (An)
{
UINT32 ea = REG_A[reg];
m68ki_write_32(ea, data);
break;
}
case 3: // (An)+
{
UINT32 ea = EA_AY_PI_32();
m68ki_write_32(ea, data);
break;
}
case 4: // -(An)
{
UINT32 ea = EA_AY_PD_32();
m68ki_write_32(ea, data);
break;
}
case 5: // (d16, An)
{
UINT32 ea = EA_AY_DI_32();
m68ki_write_32(ea, data);
break;
}
case 6: // (An) + (Xn) + d8
{
UINT32 ea = EA_AY_IX_32();
m68ki_write_32(ea, data);
break;
}
case 7:
{
switch (reg)
{
case 1: // (xxx).L
{
UINT32 d1 = OPER_I_16();
UINT32 d2 = OPER_I_16();
UINT32 ea = (d1 << 16) | d2;
m68ki_write_32(ea, data);
break;
}
case 2: // (d16, PC)
{
UINT32 ea = EA_PCDI_32();
m68ki_write_32(ea, data);
break;
}
default: fatalerror("MC68040: WRITE_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
}
break;
}
default: fatalerror("MC68040: WRITE_EA_32: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC);
}
}
static UINT64 READ_EA_64(int ea)
{
int mode = (ea >> 3) & 0x7;
int reg = (ea & 0x7);
UINT32 h1, h2;
switch (mode)
{
case 2: // (An)
{
UINT32 ea = REG_A[reg];
h1 = m68ki_read_32(ea+0);
h2 = m68ki_read_32(ea+4);
return (UINT64)(h1) << 32 | (UINT64)(h2);
}
case 3: // (An)+
{
UINT32 ea = REG_A[reg];
REG_A[reg] += 8;
h1 = m68ki_read_32(ea+0);
h2 = m68ki_read_32(ea+4);
return (UINT64)(h1) << 32 | (UINT64)(h2);
}
case 5: // (d16, An)
{
UINT32 ea = EA_AY_DI_32();
h1 = m68ki_read_32(ea+0);
h2 = m68ki_read_32(ea+4);
return (UINT64)(h1) << 32 | (UINT64)(h2);
}
case 7:
{
switch (reg)
{
case 4: // #<data>
{
h1 = OPER_I_32();
h2 = OPER_I_32();
return (UINT64)(h1) << 32 | (UINT64)(h2);
}
case 2: // (d16, PC)
{
UINT32 ea = EA_PCDI_32();
h1 = m68ki_read_32(ea+0);
h2 = m68ki_read_32(ea+4);
return (UINT64)(h1) << 32 | (UINT64)(h2);
}
default: fatalerror("MC68040: READ_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
}
break;
}
default: fatalerror("MC68040: READ_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
}
return 0;
}
static void WRITE_EA_64(int ea, UINT64 data)
{
int mode = (ea >> 3) & 0x7;
int reg = (ea & 0x7);
switch (mode)
{
case 2: // (An)
{
UINT32 ea = REG_A[reg];
m68ki_write_32(ea, (UINT32)(data >> 32));
m68ki_write_32(ea, (UINT32)(data));
break;
}
case 4: // -(An)
{
UINT32 ea;
REG_A[reg] -= 8;
ea = REG_A[reg];
m68ki_write_32(ea+0, (UINT32)(data >> 32));
m68ki_write_32(ea+4, (UINT32)(data));
break;
}
case 5: // (d16, An)
{
UINT32 ea = EA_AY_DI_32();
m68ki_write_32(ea+0, (UINT32)(data >> 32));
m68ki_write_32(ea+4, (UINT32)(data));
break;
}
default: fatalerror("MC68040: WRITE_EA_64: unhandled mode %d, reg %d, data %08X%08X at %08X\n", mode, reg, (UINT32)(data >> 32), (UINT32)(data), REG_PC);
}
}
static fp_reg READ_EA_FPE(int ea)
{
fp_reg r;
int mode = (ea >> 3) & 0x7;
int reg = (ea & 0x7);
// TODO: convert to extended floating-point!
switch (mode)
{
case 3: // (An)+
{
UINT32 d1,d2,d3;
UINT32 ea = REG_A[reg];
REG_A[reg] += 12;
d1 = m68ki_read_32(ea+0);
d2 = m68ki_read_32(ea+4);
d3 = m68ki_read_32(ea+8);
r.i = (UINT64)(d1) << 32 | (UINT64)(d2);
break;
}
default: fatalerror("MC68040: READ_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC);
}
return r;
}
static void WRITE_EA_FPE(int ea, fp_reg fpr)
{
int mode = (ea >> 3) & 0x7;
int reg = (ea & 0x7);
// TODO: convert to extended floating-point!
switch (mode)
{
case 4: // -(An)
{
UINT32 ea;
REG_A[reg] -= 12;
ea = REG_A[reg];
m68ki_write_32(ea+0, (UINT32)(fpr.i >> 32));
m68ki_write_32(ea+4, (UINT32)(fpr.i));
m68ki_write_32(ea+8, 0);
break;
}
default: fatalerror("MC68040: WRITE_EA_FPE: unhandled mode %d, reg %d, data %f at %08X\n", mode, reg, fpr.f, REG_PC);
}
}
static void fpgen_rm_reg(UINT16 w2)
{
int ea = REG_IR & 0x3f;
int rm = (w2 >> 14) & 0x1;
int src = (w2 >> 10) & 0x7;
int dst = (w2 >> 7) & 0x7;
int opmode = w2 & 0x7f;
double source;
if (rm)
{
switch (src)
{
case 0: // Long-Word Integer
{
INT32 d = READ_EA_32(ea);
source = (double)(d);
break;
}
case 1: // Single-precision Real
{
UINT32 d = READ_EA_32(ea);
source = (double)(*(float*)&d);
break;
}
case 2: // Extended-precision Real
{
fatalerror("fpgen_rm_reg: extended-precision real load unimplemented at %08X\n", REG_PC-4);
break;
}
case 3: // Packed-decimal Real
{
fatalerror("fpgen_rm_reg: packed-decimal real load unimplemented at %08X\n", REG_PC-4);
break;
}
case 4: // Word Integer
{
INT16 d = READ_EA_16(ea);
source = (double)(d);
break;
}
case 5: // Double-precision Real
{
UINT64 d = READ_EA_64(ea);
source = *(double*)&d;
break;
}
case 6: // Byte Integer
{
INT8 d = READ_EA_8(ea);
source = (double)(d);
break;
}
default: fatalerror("fmove_rm_reg: invalid source specifier at %08X\n", REG_PC-4);
}
}
else
{
source = REG_FP[src].f;
}
switch (opmode)
{
case 0x00: // FMOVE
{
REG_FP[dst].f = source;
USE_CYCLES(4);
break;
}
case 0x04: // FSQRT
{
REG_FP[dst].f = sqrt(source);
SET_CONDITION_CODES(REG_FP[dst]);
USE_CYCLES(109);
break;
}
case 0x18: // FABS
{
REG_FP[dst].f = fabs(source);
SET_CONDITION_CODES(REG_FP[dst]);
USE_CYCLES(3);
break;
}
case 0x1a: // FNEG
{
REG_FP[dst].f = -source;
SET_CONDITION_CODES(REG_FP[dst]);
USE_CYCLES(3);
break;
}
case 0x20: // FDIV
{
REG_FP[dst].f /= source;
USE_CYCLES(43);
break;
}
case 0x22: // FADD
{
REG_FP[dst].f += source;
SET_CONDITION_CODES(REG_FP[dst]);
USE_CYCLES(9);
break;
}
case 0x23: // FMUL
{
REG_FP[dst].f *= source;
SET_CONDITION_CODES(REG_FP[dst]);
USE_CYCLES(11);
break;
}
case 0x28: // FSUB
{
REG_FP[dst].f -= source;
SET_CONDITION_CODES(REG_FP[dst]);
USE_CYCLES(9);
break;
}
case 0x38: // FCMP
{
fp_reg res;
res.f = REG_FP[dst].f - source;
SET_CONDITION_CODES(res);
USE_CYCLES(7);
break;
}
case 0x3a: // FTST
{
fp_reg res;
res.f = source;
SET_CONDITION_CODES(res);
USE_CYCLES(7);
break;
}
default: fatalerror("fpgen_rm_reg: unimplemented opmode %02X at %08X\n", opmode, REG_PC-4);
}
}
static void fmove_reg_mem(UINT16 w2)
{
int ea = REG_IR & 0x3f;
int src = (w2 >> 7) & 0x7;
int dst = (w2 >> 10) & 0x7;
//int kfactor = w2 & 0x7f;
switch (dst)
{
case 0: // Long-Word Integer
{
INT32 d = (INT32)(REG_FP[src].f);
WRITE_EA_32(ea, d);
break;
}
case 1: // Single-precision Real
{
float f = (float)(REG_FP[src].f);
UINT32 d = *(UINT32 *)&f;
WRITE_EA_32(ea, d);
break;
}
case 2: // Extended-precision Real
{
fatalerror("fmove_reg_mem: extended-precision real store unimplemented at %08X\n", REG_PC-4);
break;
}
case 3: // Packed-decimal Real with Static K-factor
{
fatalerror("fmove_reg_mem: packed-decimal real store unimplemented at %08X\n", REG_PC-4);
break;
}
case 4: // Word Integer
{
fatalerror("fmove_reg_mem: word integer store unimplemented at %08X\n", REG_PC-4);
break;
}
case 5: // Double-precision Real
{
UINT64 d = REG_FP[src].i;
WRITE_EA_64(ea, d);
break;
}
case 6: // Byte Integer
{
fatalerror("fmove_reg_mem: byte integer store unimplemented at %08X\n", REG_PC-4);
break;
}
case 7: // Packed-decimal Real with Dynamic K-factor
{
fatalerror("fmove_reg_mem: packed-decimal real store unimplemented at %08X\n", REG_PC-4);
break;
}
}
USE_CYCLES(12);
}
static void fmove_fpcr(UINT16 w2)
{
int ea = REG_IR & 0x3f;
int dir = (w2 >> 13) & 0x1;
int reg = (w2 >> 10) & 0x7;
if (dir) // From system control reg to <ea>
{
switch (reg)
{
case 1: WRITE_EA_32(ea, REG_FPIAR); break;
case 2: WRITE_EA_32(ea, REG_FPSR); break;
case 4: WRITE_EA_32(ea, REG_FPCR); break;
default: fatalerror("fmove_fpcr: unknown reg %d, dir %d\n", reg, dir);
}
}
else // From <ea> to system control reg
{
switch (reg)
{
case 1: REG_FPIAR = READ_EA_32(ea); break;
case 2: REG_FPSR = READ_EA_32(ea); break;
case 4: REG_FPCR = READ_EA_32(ea); break;
default: fatalerror("fmove_fpcr: unknown reg %d, dir %d\n", reg, dir);
}
}
USE_CYCLES(10);
}
static void fmovem(UINT16 w2)
{
int i;
int ea = REG_IR & 0x3f;
int dir = (w2 >> 13) & 0x1;
int mode = (w2 >> 11) & 0x3;
int reglist = w2 & 0xff;
if (dir) // From FP regs to mem
{
switch (mode)
{
case 0: // Static register list, predecrement addressing mode
{
for (i=0; i < 8; i++)
{
if (reglist & (1 << i))
{
WRITE_EA_FPE(ea, REG_FP[i]);
USE_CYCLES(2);
}
}
break;
}
default: fatalerror("040fpu0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC-4);
}
}
else // From mem to FP regs
{
switch (mode)
{
case 2: // Static register list, postincrement addressing mode
{
for (i=0; i < 8; i++)
{
if (reglist & (1 << i))
{
REG_FP[7-i] = READ_EA_FPE(ea);
USE_CYCLES(2);
}
}
break;
}
default: fatalerror("040fpu0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC-4);
}
}
}
static void fbcc16(void)
{
INT32 offset;
int condition = REG_IR & 0x3f;
offset = (INT16)(OPER_I_16());
// TODO: condition and jump!!!
if (TEST_CONDITION(condition))
{
m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
m68ki_branch_16(offset-2);
}
USE_CYCLES(7);
}
static void fbcc32(void)
{
INT32 offset;
int condition = REG_IR & 0x3f;
offset = OPER_I_32();
// TODO: condition and jump!!!
if (TEST_CONDITION(condition))
{
m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
m68ki_branch_32(offset-4);
}
USE_CYCLES(7);
}
void m68040_fpu_op0(void)
{
switch ((REG_IR >> 6) & 0x3)
{
case 0:
{
UINT16 w2 = OPER_I_16();
switch ((w2 >> 13) & 0x7)
{
case 0x0: // FPU ALU FP, FP
case 0x2: // FPU ALU ea, FP
{
fpgen_rm_reg(w2);
break;
}
case 0x3: // FMOVE FP, ea
{
fmove_reg_mem(w2);
break;
}
case 0x4: // FMOVE ea, FPCR
case 0x5: // FMOVE FPCR, ea
{
fmove_fpcr(w2);
break;
}
case 0x6: // FMOVEM ea, list
case 0x7: // FMOVEM list, ea
{
fmovem(w2);
break;
}
default: fatalerror("m68040_fpu_op0: unimplemented subop %d at %08X\n", (w2 >> 13) & 0x7, REG_PC-4);
}
break;
}
case 2: // FBcc disp16
{
fbcc16();
break;
}
case 3: // FBcc disp32
{
fbcc32();
break;
}
default: fatalerror("m68040_fpu_op0: unimplemented main op %d\n", (REG_IR >> 6) & 0x3);
}
}
void m68040_fpu_op1(void)
{
int ea = REG_IR & 0x3f;
switch ((REG_IR >> 6) & 0x3)
{
case 0: // FSAVE <ea>
{
WRITE_EA_32(ea, 0x00000000);
// TODO: correct state frame
break;
}
case 1: // FRESTORE <ea>
{
READ_EA_32(ea);
// TODO: correct state frame
break;
}
default: fatalerror("m68040_fpu_op1: unimplemented op %d at %08X\n", (REG_IR >> 6) & 0x3, REG_PC-2);
}
}

View File

@ -3,16 +3,16 @@
/* ======================================================================== */
/*
* MUSASHI
* Version 3.3
* Version 3.32
*
* A portable Motorola M680x0 processor emulation engine.
* Copyright 1998-2001 Karl Stenerud. All rights reserved.
* Copyright Karl Stenerud. All rights reserved.
*
* This code may be freely used for non-commercial purposes as long as this
* copyright notice remains unaltered in the source code and any binary files
* containing this code in compiled form.
*
* All other lisencing terms must be negotiated with the author
* All other licensing terms must be negotiated with the author
* (Karl Stenerud).
*
* The latest version of this code can be obtained at:
@ -52,7 +52,7 @@
*/
const char* g_version = "3.3";
static const char g_version[] = "3.32";
/* ======================================================================== */
/* =============================== INCLUDES =============================== */
@ -88,9 +88,6 @@ const char* g_version = "3.3";
#define FILENAME_INPUT "m68k_in.c"
#define FILENAME_PROTOTYPE "m68kops.h"
#define FILENAME_TABLE "m68kops.c"
#define FILENAME_OPS_AC "m68kopac.c"
#define FILENAME_OPS_DM "m68kopdm.c"
#define FILENAME_OPS_NZ "m68kopnz.c"
/* Identifier sequences recognized by this program */
@ -130,10 +127,12 @@ const char* g_version = "3.3";
/* ============================== PROTOTYPES ============================== */
/* ======================================================================== */
enum {
enum
{
CPU_TYPE_000 = 0,
CPU_TYPE_010,
CPU_TYPE_020,
CPU_TYPE_040,
NUM_CPUS
};
@ -229,7 +228,6 @@ int extract_opcode_info(char* src, char* name, int* size, char* spec_proc, char*
void add_replace_string(replace_struct* replace, const char* search_str, const char* replace_str);
void write_body(FILE* filep, body_struct* body, replace_struct* replace);
void get_base_name(char* base_name, opcode_struct* op);
void write_prototype(FILE* filep, char* base_name);
void write_function_name(FILE* filep, char* base_name);
void add_opcode_output_table_entry(opcode_struct* op, char* name);
static int DECL_SPEC compare_nof_true_bits(const void* aptr, const void* bptr);
@ -239,7 +237,7 @@ void set_opcode_struct(opcode_struct* src, opcode_struct* dst, int ea_mode);
void generate_opcode_handler(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* opinfo, int ea_mode);
void generate_opcode_ea_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op);
void generate_opcode_cc_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op_in, int offset);
void process_opcode_handlers(void);
void process_opcode_handlers(FILE* filep);
void populate_table(void);
void read_insert(char* insert);
@ -256,9 +254,6 @@ char g_input_filename[M68K_MAX_PATH] = FILENAME_INPUT;
FILE* g_input_file = NULL;
FILE* g_prototype_file = NULL;
FILE* g_table_file = NULL;
FILE* g_ops_ac_file = NULL;
FILE* g_ops_dm_file = NULL;
FILE* g_ops_nz_file = NULL;
int g_num_functions = 0; /* Number of functions processed */
int g_num_primitives = 0; /* Number of function primitives read */
@ -270,7 +265,7 @@ opcode_struct g_opcode_input_table[MAX_OPCODE_INPUT_TABLE_LENGTH];
opcode_struct g_opcode_output_table[MAX_OPCODE_OUTPUT_TABLE_LENGTH];
int g_opcode_output_table_length = 0;
ea_info_struct g_ea_info_table[13] =
const ea_info_struct g_ea_info_table[13] =
{/* fname ea mask match */
{"", "", 0x00, 0x00}, /* EA_MODE_NONE */
{"ai", "AY_AI", 0x38, 0x10}, /* EA_MODE_AI */
@ -288,7 +283,7 @@ ea_info_struct g_ea_info_table[13] =
};
const char* g_cc_table[16][2] =
const char *const g_cc_table[16][2] =
{
{ "t", "T"}, /* 0000 */
{ "f", "F"}, /* 0001 */
@ -309,7 +304,7 @@ const char* g_cc_table[16][2] =
};
/* size to index translator (0 -> 0, 8 and 16 -> 1, 32 -> 2) */
int g_size_select_table[33] =
const int g_size_select_table[33] =
{
0, /* unsized */
0, 0, 0, 0, 0, 0, 0, 1, /* 8 */
@ -318,25 +313,26 @@ int g_size_select_table[33] =
};
/* Extra cycles required for certain EA modes */
int g_ea_cycle_table[13][NUM_CPUS][3] =
{/* 000 010 020 */
{{ 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}}, /* EA_MODE_NONE */
{{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}}, /* EA_MODE_AI */
{{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}}, /* EA_MODE_PI */
{{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}}, /* EA_MODE_PI7 */
{{ 0, 6, 10}, { 0, 6, 10}, { 0, 5, 5}}, /* EA_MODE_PD */
{{ 0, 6, 10}, { 0, 6, 10}, { 0, 5, 5}}, /* EA_MODE_PD7 */
{{ 0, 8, 12}, { 0, 8, 12}, { 0, 5, 5}}, /* EA_MODE_DI */
{{ 0, 10, 14}, { 0, 10, 14}, { 0, 7, 7}}, /* EA_MODE_IX */
{{ 0, 8, 12}, { 0, 8, 12}, { 0, 4, 4}}, /* EA_MODE_AW */
{{ 0, 12, 16}, { 0, 12, 16}, { 0, 4, 4}}, /* EA_MODE_AL */
{{ 0, 8, 12}, { 0, 8, 12}, { 0, 5, 5}}, /* EA_MODE_PCDI */
{{ 0, 10, 14}, { 0, 10, 14}, { 0, 7, 7}}, /* EA_MODE_PCIX */
{{ 0, 4, 8}, { 0, 4, 8}, { 0, 2, 4}}, /* EA_MODE_I */
/* TODO: correct timings for 040 */
const int g_ea_cycle_table[13][NUM_CPUS][3] =
{/* 000 010 020 040 */
{{ 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}}, /* EA_MODE_NONE */
{{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_AI */
{{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_PI */
{{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_PI7 */
{{ 0, 6, 10}, { 0, 6, 10}, { 0, 5, 5}, { 0, 5, 5}}, /* EA_MODE_PD */
{{ 0, 6, 10}, { 0, 6, 10}, { 0, 5, 5}, { 0, 5, 5}}, /* EA_MODE_PD7 */
{{ 0, 8, 12}, { 0, 8, 12}, { 0, 5, 5}, { 0, 5, 5}}, /* EA_MODE_DI */
{{ 0, 10, 14}, { 0, 10, 14}, { 0, 7, 7}, { 0, 7, 7}}, /* EA_MODE_IX */
{{ 0, 8, 12}, { 0, 8, 12}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_AW */
{{ 0, 12, 16}, { 0, 12, 16}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_AL */
{{ 0, 8, 12}, { 0, 8, 12}, { 0, 5, 5}, { 0, 5, 5}}, /* EA_MODE_PCDI */
{{ 0, 10, 14}, { 0, 10, 14}, { 0, 7, 7}, { 0, 7, 7}}, /* EA_MODE_PCIX */
{{ 0, 4, 8}, { 0, 4, 8}, { 0, 2, 4}, { 0, 2, 4}}, /* EA_MODE_I */
};
/* Extra cycles for JMP instruction (000, 010) */
int g_jmp_cycle_table[13] =
const int g_jmp_cycle_table[13] =
{
0, /* EA_MODE_NONE */
4, /* EA_MODE_AI */
@ -354,7 +350,7 @@ int g_jmp_cycle_table[13] =
};
/* Extra cycles for JSR instruction (000, 010) */
int g_jsr_cycle_table[13] =
const int g_jsr_cycle_table[13] =
{
0, /* EA_MODE_NONE */
4, /* EA_MODE_AI */
@ -372,7 +368,7 @@ int g_jsr_cycle_table[13] =
};
/* Extra cycles for LEA instruction (000, 010) */
int g_lea_cycle_table[13] =
const int g_lea_cycle_table[13] =
{
0, /* EA_MODE_NONE */
4, /* EA_MODE_AI */
@ -390,7 +386,7 @@ int g_lea_cycle_table[13] =
};
/* Extra cycles for PEA instruction (000, 010) */
int g_pea_cycle_table[13] =
const int g_pea_cycle_table[13] =
{
0, /* EA_MODE_NONE */
6, /* EA_MODE_AI */
@ -408,7 +404,7 @@ int g_pea_cycle_table[13] =
};
/* Extra cycles for MOVEM instruction (000, 010) */
int g_movem_cycle_table[13] =
const int g_movem_cycle_table[13] =
{
0, /* EA_MODE_NONE */
0, /* EA_MODE_AI */
@ -426,7 +422,7 @@ int g_movem_cycle_table[13] =
};
/* Extra cycles for MOVES instruction (010) */
int g_moves_cycle_table[13][3] =
const int g_moves_cycle_table[13][3] =
{
{ 0, 0, 0}, /* EA_MODE_NONE */
{ 0, 4, 6}, /* EA_MODE_AI */
@ -444,7 +440,7 @@ int g_moves_cycle_table[13][3] =
};
/* Extra cycles for CLR instruction (010) */
int g_clr_cycle_table[13][3] =
const int g_clr_cycle_table[13][3] =
{
{ 0, 0, 0}, /* EA_MODE_NONE */
{ 0, 4, 6}, /* EA_MODE_AI */
@ -479,9 +475,6 @@ void error_exit(const char* fmt, ...)
if(g_prototype_file) fclose(g_prototype_file);
if(g_table_file) fclose(g_table_file);
if(g_ops_ac_file) fclose(g_ops_ac_file);
if(g_ops_dm_file) fclose(g_ops_dm_file);
if(g_ops_nz_file) fclose(g_ops_nz_file);
if(g_input_file) fclose(g_input_file);
exit(EXIT_FAILURE);
@ -498,9 +491,6 @@ void perror_exit(const char* fmt, ...)
if(g_prototype_file) fclose(g_prototype_file);
if(g_table_file) fclose(g_table_file);
if(g_ops_ac_file) fclose(g_ops_ac_file);
if(g_ops_dm_file) fclose(g_ops_dm_file);
if(g_ops_nz_file) fclose(g_ops_nz_file);
if(g_input_file) fclose(g_input_file);
exit(EXIT_FAILURE);
@ -788,16 +778,10 @@ void get_base_name(char* base_name, opcode_struct* op)
sprintf(base_name+strlen(base_name), "_%s", op->spec_ea);
}
/* Write the prototype of an opcode handler function */
void write_prototype(FILE* filep, char* base_name)
{
fprintf(filep, "void %s(void);\n", base_name);
}
/* Write the name of an opcode handler function */
void write_function_name(FILE* filep, char* base_name)
{
fprintf(filep, "void %s(void)\n", base_name);
fprintf(filep, "static void %s(void)\n", base_name);
}
void add_opcode_output_table_entry(opcode_struct* op, char* name)
@ -880,7 +864,6 @@ void generate_opcode_handler(FILE* filep, body_struct* body, replace_struct* rep
/* Set the opcode structure and write the tables, prototypes, etc */
set_opcode_struct(opinfo, op, ea_mode);
get_base_name(str, op);
write_prototype(g_prototype_file, str);
add_opcode_output_table_entry(op, str);
write_function_name(filep, str);
@ -999,10 +982,9 @@ void generate_opcode_cc_variants(FILE* filep, body_struct* body, replace_struct*
}
/* Process the opcode handlers section of the input file */
void process_opcode_handlers(void)
void process_opcode_handlers(FILE* filep)
{
FILE* input_file = g_input_file;
FILE* output_file;
char func_name[MAX_LINE_LENGTH+1];
char oper_name[MAX_LINE_LENGTH+1];
int oper_size;
@ -1012,9 +994,6 @@ void process_opcode_handlers(void)
replace_struct* replace = malloc(sizeof(replace_struct));
body_struct* body = malloc(sizeof(body_struct));
output_file = g_ops_ac_file;
for(;;)
{
/* Find the first line of the function */
@ -1057,23 +1036,17 @@ void process_opcode_handlers(void)
if(opinfo == NULL)
error_exit("Unable to find matching table entry for %s", func_name);
/* Change output files if we pass 'c' or 'n' */
if(output_file == g_ops_ac_file && oper_name[0] > 'c')
output_file = g_ops_dm_file;
else if(output_file == g_ops_dm_file && oper_name[0] > 'm')
output_file = g_ops_nz_file;
replace->length = 0;
/* Generate opcode variants */
if(strcmp(opinfo->name, "bcc") == 0 || strcmp(opinfo->name, "scc") == 0)
generate_opcode_cc_variants(output_file, body, replace, opinfo, 1);
generate_opcode_cc_variants(filep, body, replace, opinfo, 1);
else if(strcmp(opinfo->name, "dbcc") == 0)
generate_opcode_cc_variants(output_file, body, replace, opinfo, 2);
generate_opcode_cc_variants(filep, body, replace, opinfo, 2);
else if(strcmp(opinfo->name, "trapcc") == 0)
generate_opcode_cc_variants(output_file, body, replace, opinfo, 4);
generate_opcode_cc_variants(filep, body, replace, opinfo, 4);
else
generate_opcode_ea_variants(output_file, body, replace, opinfo);
generate_opcode_ea_variants(filep, body, replace, opinfo);
}
free(replace);
@ -1246,7 +1219,9 @@ int main(int argc, char **argv)
/* Inserts */
char temp_insert[MAX_INSERT_LENGTH+1];
char prototype_footer_insert[MAX_INSERT_LENGTH+1];
char table_header_insert[MAX_INSERT_LENGTH+1];
char table_footer_insert[MAX_INSERT_LENGTH+1];
char ophandler_header_insert[MAX_INSERT_LENGTH+1];
char ophandler_footer_insert[MAX_INSERT_LENGTH+1];
/* Flags if we've processed certain parts already */
int prototype_header_read = 0;
@ -1258,8 +1233,8 @@ int main(int argc, char **argv)
int table_body_read = 0;
int ophandler_body_read = 0;
printf("\n\t\tMusashi v%s 68000, 68008, 68010, 68EC020, 68020 emulator\n", g_version);
printf("\t\tCopyright 1998-2000 Karl Stenerud (karl@mame.net)\n\n");
printf("\n\tMusashi v%s 68000, 68008, 68010, 68EC020, 68020, 68040 emulator\n", g_version);
printf("\tCopyright Karl Stenerud (karl@mame.net)\n\n");
/* Check if output path and source for the input file are given */
if(argc > 1)
@ -1291,18 +1266,6 @@ int main(int argc, char **argv)
if((g_table_file = fopen(filename, "w")) == NULL)
perror_exit("Unable to create table file (%s)\n", filename);
sprintf(filename, "%s%s", output_path, FILENAME_OPS_AC);
if((g_ops_ac_file = fopen(filename, "w")) == NULL)
perror_exit("Unable to create ops ac file (%s)\n", filename);
sprintf(filename, "%s%s", output_path, FILENAME_OPS_DM);
if((g_ops_dm_file = fopen(filename, "w")) == NULL)
perror_exit("Unable to create ops dm file (%s)\n", filename);
sprintf(filename, "%s%s", output_path, FILENAME_OPS_NZ);
if((g_ops_nz_file = fopen(filename, "w")) == NULL)
perror_exit("Unable to create ops nz file (%s)\n", filename);
if((g_input_file=fopen(g_input_filename, "r")) == NULL)
perror_exit("can't open %s for input", g_input_filename);
@ -1318,18 +1281,6 @@ int main(int argc, char **argv)
if((g_table_file = fopen(filename, "wt")) == NULL)
perror_exit("Unable to create table file (%s)\n", filename);
sprintf(filename, "%s%s", output_path, FILENAME_OPS_AC);
if((g_ops_ac_file = fopen(filename, "wt")) == NULL)
perror_exit("Unable to create ops ac file (%s)\n", filename);
sprintf(filename, "%s%s", output_path, FILENAME_OPS_DM);
if((g_ops_dm_file = fopen(filename, "wt")) == NULL)
perror_exit("Unable to create ops dm file (%s)\n", filename);
sprintf(filename, "%s%s", output_path, FILENAME_OPS_NZ);
if((g_ops_nz_file = fopen(filename, "wt")) == NULL)
perror_exit("Unable to create ops nz file (%s)\n", filename);
if((g_input_file=fopen(g_input_filename, "rt")) == NULL)
perror_exit("can't open %s for input", g_input_filename);
@ -1358,18 +1309,14 @@ int main(int argc, char **argv)
{
if(table_header_read)
error_exit("Duplicate table header");
read_insert(temp_insert);
fprintf(g_table_file, "%s", temp_insert);
read_insert(table_header_insert);
table_header_read = 1;
}
else if(strcmp(section_id, ID_OPHANDLER_HEADER) == 0)
{
if(ophandler_header_read)
error_exit("Duplicate opcode handler header");
read_insert(temp_insert);
fprintf(g_ops_ac_file, "%s\n\n", temp_insert);
fprintf(g_ops_dm_file, "%s\n\n", temp_insert);
fprintf(g_ops_nz_file, "%s\n\n", temp_insert);
read_insert(ophandler_header_insert);
ophandler_header_read = 1;
}
else if(strcmp(section_id, ID_PROTOTYPE_FOOTER) == 0)
@ -1422,7 +1369,9 @@ int main(int argc, char **argv)
if(ophandler_body_read)
error_exit("Duplicate opcode handler section");
process_opcode_handlers();
fprintf(g_table_file, "%s\n\n", ophandler_header_insert);
process_opcode_handlers(g_table_file);
fprintf(g_table_file, "%s\n\n", ophandler_footer_insert);
ophandler_body_read = 1;
}
@ -1446,13 +1395,11 @@ int main(int argc, char **argv)
if(!ophandler_body_read)
error_exit("Missing opcode handler body");
fprintf(g_table_file, "%s\n\n", table_header_insert);
print_opcode_output_table(g_table_file);
fprintf(g_table_file, "%s\n\n", table_footer_insert);
fprintf(g_prototype_file, "%s\n\n", prototype_footer_insert);
fprintf(g_table_file, "%s\n\n", table_footer_insert);
fprintf(g_ops_ac_file, "%s\n\n", ophandler_footer_insert);
fprintf(g_ops_dm_file, "%s\n\n", ophandler_footer_insert);
fprintf(g_ops_nz_file, "%s\n\n", ophandler_footer_insert);
break;
}
@ -1465,9 +1412,6 @@ int main(int argc, char **argv)
/* Close all files and exit */
fclose(g_prototype_file);
fclose(g_table_file);
fclose(g_ops_ac_file);
fclose(g_ops_dm_file);
fclose(g_ops_nz_file);
fclose(g_input_file);
printf("Generated %d opcode handlers from %d primitives\n", g_num_functions, g_num_primitives);